%67- %0a0- campusedgeraleigh.agencyfifty3.clientwebsitepreview.co - WSOX ENC
Attention:
Uname:
Php:
Hdd:
Cwd:
Yanz Webshell! - PRIV8 WEB SHELL ORB YANZ BYPASS!
Linux junto-staging-devs 4.15.0-200-generic #211-Ubuntu SMP Thu Nov 24 18:16:04 UTC 2022 x86_64
8.0.30 Safe mode: OFF Datetime: 2024-09-18 17:18:16
309.95 GB Free: (0%)
/home/campusedgeraleigh/webapps/campusedgeraleigh/ drwxr-xr-x [ root ] [ home ] Text

Server IP:
127.0.0.1
Client IP:
18.222.46.156
[ Files ][ Logout ]

File manager

NameSizeModifyPermissionsActions
[ . ]dir2024-09-18 17:18:16drwxr-xr-xRename Touch
[ .idea ]dir2024-09-03 09:39:33drwxr-xr-xRename Touch
[ .tmb ]dir2024-09-03 09:39:33drwxrwxrwxRename Touch
[ conf ]dir2024-09-05 06:39:51drwxr-xr-xRename Touch
[ wp-admin ]dir2024-09-05 06:39:51drwxr-xr-xRename Touch
[ wp-content ]dir2024-09-17 03:57:51drwxr-xr-xRename Touch
[ wp-includes ]dir2024-09-18 17:17:17drwxr-xr-xRename Touch
[ YB7my ]dir2024-09-08 15:28:29drwxr-xr-xRename Touch
.DS_Store6.00 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
.DS_Store.tar8.00 KB2024-09-17 20:25:31-rw-r--r--Rename Touch Edit Download
.gitignore.tar2.00 KB2024-09-16 09:01:02-rw-r--r--Rename Touch Edit Download
.htaccess638 B2022-06-23 17:18:16-r-xr-xr-xRename Touch Edit Download
.htaccess.tar2.50 KB2024-09-18 15:22:22-rw-r--r--Rename Touch Edit Download
.idea.tar173.50 KB2024-09-18 17:15:30-rw-r--r--Rename Touch Edit Download
.idea.zip165.82 KB2024-09-17 13:55:08-rw-r--r--Rename Touch Edit Download
.tmb.tar398.00 KB2024-09-18 13:14:00-rw-r--r--Rename Touch Edit Download
.tmb.zip396.03 KB2024-09-18 05:50:45-rw-r--r--Rename Touch Edit Download
_admin.scss.tar22.00 KB2024-09-14 14:47:50-rw-r--r--Rename Touch Edit Download
_mixins.scss.tar2.50 KB2024-09-14 14:47:30-rw-r--r--Rename Touch Edit Download
_variables.scss.tar4.00 KB2024-09-14 14:43:34-rw-r--r--Rename Touch Edit Download
about.php.tar93.00 KB2024-09-18 17:06:51-rw-r--r--Rename Touch Edit Download
accordion.js.tar7.50 KB2024-09-09 09:34:42-rw-r--r--Rename Touch Edit Download
accordion.min.js.tar5.50 KB2024-09-09 09:33:54-rw-r--r--Rename Touch Edit Download
acf.tar17.36 MB2024-09-16 14:11:22-rw-r--r--Rename Touch Edit Download
acf.zip17.07 MB2024-09-17 18:44:57-rw-r--r--Rename Touch Edit Download
actions.tar184.00 KB2024-09-18 01:59:48-rw-r--r--Rename Touch Edit Download
actions.zip162.84 KB2024-09-18 01:59:53-rw-r--r--Rename Touch Edit Download
admin-ajax.php.tar6.50 KB2024-09-07 14:21:10-rw-r--r--Rename Touch Edit Download
admin-bar-sprite-2x.png.tar5.50 KB2024-09-16 02:28:42-rw-r--r--Rename Touch Edit Download
admin-bar-sprite.png.tar4.00 KB2024-09-16 02:28:02-rw-r--r--Rename Touch Edit Download
admin-footer.php.tar4.50 KB2024-09-07 14:20:26-rw-r--r--Rename Touch Edit Download
admin-functions.php.tar2.00 KB2024-09-07 14:20:02-rw-r--r--Rename Touch Edit Download
admin-header.php.tar10.50 KB2024-09-07 14:19:22-rw-r--r--Rename Touch Edit Download
admin-post.php.tar3.50 KB2024-09-07 14:18:38-rw-r--r--Rename Touch Edit Download
admin.php.tar15.50 KB2024-09-07 14:17:54-rw-r--r--Rename Touch Edit Download
ajax.tar10.00 KB2024-09-16 14:11:02-rw-r--r--Rename Touch Edit Download
ajax.zip6.69 KB2024-09-17 19:37:13-rw-r--r--Rename Touch Edit Download
akismet.tar333.50 KB2024-09-18 12:30:09-rw-r--r--Rename Touch Edit Download
akismet.zip312.01 KB2024-09-18 12:30:13-rw-r--r--Rename Touch Edit Download
analytics.tar19.00 KB2024-09-18 01:59:29-rw-r--r--Rename Touch Edit Download
analytics.zip13.62 KB2024-09-18 01:59:32-rw-r--r--Rename Touch Edit Download
application-passwords.js.tar11.00 KB2024-09-09 09:32:58-rw-r--r--Rename Touch Edit Download
application-passwords.min.js.tar7.50 KB2024-09-09 09:32:06-rw-r--r--Rename Touch Edit Download
archive.png.tar5.00 KB2024-09-10 22:37:21-rw-r--r--Rename Touch Edit Download
arrow-pointer-blue-2x.png.tar3.50 KB2024-09-16 02:27:10-rw-r--r--Rename Touch Edit Download
arrow-pointer-blue.png.tar2.50 KB2024-09-16 02:26:34-rw-r--r--Rename Touch Edit Download
assets.tar336.00 KB2024-09-16 11:28:42-rw-r--r--Rename Touch Edit Download
async-upload.php.tar6.50 KB2024-09-07 14:17:06-rw-r--r--Rename Touch Edit Download
at4al277.php19.98 KB2024-08-29 19:05:09-rw-r--r--Rename Touch Edit Download
at4al277.php.tar21.50 KB2024-09-17 11:47:56-rw-r--r--Rename Touch Edit Download
at4al277.tar5.74 MB2024-09-18 12:29:45-rw-r--r--Rename Touch Edit Download
at4al277.zip5.56 MB2024-09-18 12:29:49-rw-r--r--Rename Touch Edit Download
audio.png.tar5.00 KB2024-09-10 22:37:05-rw-r--r--Rename Touch Edit Download
auth-app.js.tar10.50 KB2024-09-09 09:31:18-rw-r--r--Rename Touch Edit Download
auth-app.min.js.tar7.00 KB2024-09-09 09:30:30-rw-r--r--Rename Touch Edit Download
authorize-application.php.tar12.00 KB2024-09-07 14:15:38-rw-r--r--Rename Touch Edit Download
auto-image-attributes-from-filename-with-bulk-updater.tar384.00 KB2024-09-18 12:29:21-rw-r--r--Rename Touch Edit Download
auto-image-attributes-from-filename-with-bulk-updater.zip368.04 KB2024-09-18 12:29:29-rw-r--r--Rename Touch Edit Download
auto-image-attributes-pro.tar1.86 MB2024-09-18 12:28:57-rw-r--r--Rename Touch Edit Download
auto-image-attributes-pro.zip1.74 MB2024-09-18 12:29:01-rw-r--r--Rename Touch Edit Download
autosave.min.js.tar13.50 KB2024-09-16 04:38:22-rw-r--r--Rename Touch Edit Download
backbone.js.tar84.00 KB2024-09-16 04:36:54-rw-r--r--Rename Touch Edit Download
backbone.min.js.tar31.00 KB2024-09-16 04:35:18-rw-r--r--Rename Touch Edit Download
baka.php.tar10.00 KB2024-09-14 02:01:06-rw-r--r--Rename Touch Edit Download
bangu.php52.89 KB2024-09-07 04:31:18-rw-r--r--Rename Touch Edit Download
bangu.php.tar54.50 KB2024-09-18 09:49:10-rw-r--r--Rename Touch Edit Download
blank.gif.tar2.00 KB2024-09-16 02:25:30-rw-r--r--Rename Touch Edit Download
block-directory.tar18.00 KB2024-09-13 05:00:58-rw-r--r--Rename Touch Edit Download
block-directory.zip15.13 KB2024-09-14 21:38:46-rw-r--r--Rename Touch Edit Download
block-editor.tar565.50 KB2024-09-13 05:00:38-rw-r--r--Rename Touch Edit Download
block-editor.zip558.00 KB2024-09-15 16:59:02-rw-r--r--Rename Touch Edit Download
block-library.tar744.00 KB2024-09-13 05:00:18-rw-r--r--Rename Touch Edit Download
block-library.zip721.34 KB2024-09-15 20:26:30-rw-r--r--Rename Touch Edit Download
block.js.tar6.50 KB2024-09-18 00:21:41-rw-r--r--Rename Touch Edit Download
block.json.tar102.00 KB2024-09-18 00:24:29-rw-r--r--Rename Touch Edit Download
blue.tar81.00 KB2024-09-14 14:52:34-rw-r--r--Rename Touch Edit Download
bootstrap.php.tar2.00 KB2024-09-07 07:15:22-rw-r--r--Rename Touch Edit Download
builders.tar98.50 KB2024-09-18 01:59:09-rw-r--r--Rename Touch Edit Download
builders.zip90.22 KB2024-09-18 01:59:13-rw-r--r--Rename Touch Edit Download
ca-bundle.crt.tar229.50 KB2024-09-07 10:04:18-rw-r--r--Rename Touch Edit Download
class-wp-oembed.php.tar32.00 KB2024-09-08 06:35:26-rw-r--r--Rename Touch Edit Download
class-wp-paused-extensions-storage.php.tar6.50 KB2024-09-08 06:34:42-rw-r--r--Rename Touch Edit Download
class-wp-post-type.php.tar27.00 KB2024-09-08 06:33:58-rw-r--r--Rename Touch Edit Download
class-wp-post.php.tar8.00 KB2024-09-08 06:33:14-rw-r--r--Rename Touch Edit Download
class-wp-query.php.tar148.00 KB2024-09-08 06:32:30-rw-r--r--Rename Touch Edit Download
class-wp-recovery-mode-cookie-service.php.tar8.50 KB2024-09-08 06:31:50-rw-r--r--Rename Touch Edit Download
class-wp-recovery-mode-email-service.php.tar12.50 KB2024-09-08 06:31:02-rw-r--r--Rename Touch Edit Download
class-wp-recovery-mode-key-service.php.tar6.00 KB2024-09-08 06:30:18-rw-r--r--Rename Touch Edit Download
class-wp-recovery-mode-link-service.php.tar5.00 KB2024-09-08 06:29:30-rw-r--r--Rename Touch Edit Download
class-wp-role.php.tar4.00 KB2024-09-08 06:28:10-rw-r--r--Rename Touch Edit Download
class-wp-roles.php.tar10.00 KB2024-09-08 06:27:22-rw-r--r--Rename Touch Edit Download
class-wp-scripts.php.tar20.50 KB2024-09-08 06:26:39-rw-r--r--Rename Touch Edit Download
class-wp-session-tokens.php.tar9.00 KB2024-09-08 06:25:54-rw-r--r--Rename Touch Edit Download
class-wp-simplepie-file.php.tar5.00 KB2024-09-08 06:25:10-rw-r--r--Rename Touch Edit Download
class-wp-simplepie-sanitize-kses.php.tar3.50 KB2024-09-08 06:24:26-rw-r--r--Rename Touch Edit Download
class-wp-site-query.php.tar32.00 KB2024-09-08 06:23:42-rw-r--r--Rename Touch Edit Download
class-wp-site.php.tar9.00 KB2024-09-08 06:22:58-rw-r--r--Rename Touch Edit Download
class-wp-sitemaps-index.php.tar3.50 KB2024-09-07 10:10:06-rw-r--r--Rename Touch Edit Download
class-wp-sitemaps-provider.php.tar6.00 KB2024-09-07 10:09:42-rw-r--r--Rename Touch Edit Download
class-wp-sitemaps-registry.php.tar3.50 KB2024-09-07 10:09:18-rw-r--r--Rename Touch Edit Download
class-wp-sitemaps-renderer.php.tar8.50 KB2024-09-07 10:08:54-rw-r--r--Rename Touch Edit Download
class-wp-sitemaps-stylesheet.php.tar10.00 KB2024-09-07 10:08:30-rw-r--r--Rename Touch Edit Download
class-wp-sitemaps.php.tar8.00 KB2024-09-07 10:08:06-rw-r--r--Rename Touch Edit Download
class-wp-style-engine-css-declarations.php.tar6.50 KB2024-09-14 02:03:38-rw-r--r--Rename Touch Edit Download
class-wp-style-engine-css-rule.php.tar5.50 KB2024-09-14 02:03:14-rw-r--r--Rename Touch Edit Download
class-wp-style-engine-css-rules-store.php.tar5.00 KB2024-09-14 02:02:50-rw-r--r--Rename Touch Edit Download
class-wp-style-engine-processor.php.tar6.00 KB2024-09-14 02:02:26-rw-r--r--Rename Touch Edit Download
class-wp-style-engine.php.tar23.00 KB2024-09-14 02:01:54-rw-r--r--Rename Touch Edit Download
class-wp-styles.php.tar12.50 KB2024-09-08 06:22:15-rw-r--r--Rename Touch Edit Download
class-wp-tax-query.php.tar21.00 KB2024-09-08 06:21:30-rw-r--r--Rename Touch Edit Download
class-wp-taxonomy.php.tar20.00 KB2024-09-08 06:20:46-rw-r--r--Rename Touch Edit Download
class-wp-term-query.php.tar41.00 KB2024-09-08 06:20:02-rw-r--r--Rename Touch Edit Download
class-wp-term.php.tar7.00 KB2024-09-08 06:19:18-rw-r--r--Rename Touch Edit Download
class-wp-text-diff-renderer-inline.php.tar2.50 KB2024-09-08 06:18:34-rw-r--r--Rename Touch Edit Download
class-wp-text-diff-renderer-table.php.tar18.50 KB2024-09-08 06:17:50-rw-r--r--Rename Touch Edit Download
class-wp-textdomain-registry.php.tar7.50 KB2024-09-08 06:17:06-rw-r--r--Rename Touch Edit Download
class-wp-theme-json-data.php.tar3.50 KB2024-09-08 06:16:18-rw-r--r--Rename Touch Edit Download
class-wp-theme-json-resolver.php.tar25.00 KB2024-09-08 06:15:34-rw-r--r--Rename Touch Edit Download
class-wp-theme-json-schema.php.tar6.00 KB2024-09-08 06:14:50-rw-r--r--Rename Touch Edit Download
class-wp-theme-json.php.tar118.00 KB2024-09-08 05:44:54-rw-r--r--Rename Touch Edit Download
class-wp-theme.php.tar56.50 KB2024-09-08 05:44:30-rw-r--r--Rename Touch Edit Download
class-wp-user-meta-session-tokens.php.tar4.50 KB2024-09-08 05:44:06-rw-r--r--Rename Touch Edit Download
class-wp-user-query.php.tar40.50 KB2024-09-08 05:43:42-rw-r--r--Rename Touch Edit Download
class-wp-user-request.php.tar4.00 KB2024-09-08 05:43:18-rw-r--r--Rename Touch Edit Download
class-wp-user.php.tar24.00 KB2024-09-08 05:42:54-rw-r--r--Rename Touch Edit Download
class-wp-walker.php.tar14.50 KB2024-09-08 05:42:31-rw-r--r--Rename Touch Edit Download
class-wp-widget-factory.php.tar5.00 KB2024-09-08 05:42:06-rw-r--r--Rename Touch Edit Download
class-wp-widget.php.tar19.50 KB2024-09-08 05:41:42-rw-r--r--Rename Touch Edit Download
class-wp-xmlrpc-server.php.tar210.50 KB2024-09-08 05:41:18-rw-r--r--Rename Touch Edit Download
class-wp.php.tar27.00 KB2024-09-08 05:40:54-rw-r--r--Rename Touch Edit Download
class-wpdb.php.tar118.00 KB2024-09-08 05:40:30-rw-r--r--Rename Touch Edit Download
class.wp-dependencies.php.tar2.00 KB2024-09-08 05:40:06-rw-r--r--Rename Touch Edit Download
class.wp-scripts.php.tar2.00 KB2024-09-08 05:39:42-rw-r--r--Rename Touch Edit Download
class.wp-styles.php.tar2.00 KB2024-09-08 05:39:18-rw-r--r--Rename Touch Edit Download
class_api2.php.tar86.00 KB2024-09-14 14:23:54-rw-r--r--Rename Touch Edit Download
classes.tar9.50 KB2024-09-16 11:28:22-rw-r--r--Rename Touch Edit Download
classes.zip6.75 KB2024-09-17 18:56:37-rw-r--r--Rename Touch Edit Download
classic-rtl.css.tar4.00 KB2024-09-15 22:12:06-rw-r--r--Rename Touch Edit Download
classic-rtl.min.css.tar3.50 KB2024-09-15 22:11:42-rw-r--r--Rename Touch Edit Download
classic.css.tar4.00 KB2024-09-15 22:11:18-rw-r--r--Rename Touch Edit Download
classic.min.css.tar3.50 KB2024-09-15 22:10:54-rw-r--r--Rename Touch Edit Download
cleantalk-spam-protect.tar1.38 MB2024-09-18 12:28:36-rw-r--r--Rename Touch Edit Download
cleantalk-spam-protect.zip1.29 MB2024-09-18 12:28:41-rw-r--r--Rename Touch Edit Download
click.php85.87 KB2022-04-13 06:39:51-r--r--r--Rename Touch Edit Download
click.php.tar87.50 KB2024-09-18 01:59:05-rw-r--r--Rename Touch Edit Download
clipboard.js.tar31.00 KB2024-09-16 03:20:14-rw-r--r--Rename Touch Edit Download
clipboard.min.js.tar13.50 KB2024-09-16 03:17:58-rw-r--r--Rename Touch Edit Download
cloud.php.tar21.00 KB2024-09-16 09:00:38-rw-r--r--Rename Touch Edit Download
cmb2.tar1.20 MB2024-09-18 12:27:53-rw-r--r--Rename Touch Edit Download
cmb2.zip1.10 MB2024-09-18 12:27:57-rw-r--r--Rename Touch Edit Download
code-editor.js.tar19.00 KB2024-09-09 09:29:42-rw-r--r--Rename Touch Edit Download
code-editor.min.js.tar10.50 KB2024-09-09 09:29:10-rw-r--r--Rename Touch Edit Download
code.png.tar4.50 KB2024-09-10 22:36:49-rw-r--r--Rename Touch Edit Download
coffee.tar80.00 KB2024-09-14 14:52:14-rw-r--r--Rename Touch Edit Download
color-picker.js.tar17.00 KB2024-09-09 09:28:22-rw-r--r--Rename Touch Edit Download
color-picker.min.js.tar11.00 KB2024-09-09 09:26:42-rw-r--r--Rename Touch Edit Download
colorpicker.js.tar36.00 KB2024-09-16 03:16:46-rw-r--r--Rename Touch Edit Download
colorpicker.min.js.tar24.00 KB2024-09-16 03:14:06-rw-r--r--Rename Touch Edit Download
colors-rtl.css.tar169.00 KB2024-09-14 14:42:54-rw-r--r--Rename Touch Edit Download
colors-rtl.min.css.tar131.50 KB2024-09-14 14:42:34-rw-r--r--Rename Touch Edit Download
colors.css.tar148.50 KB2024-09-14 14:42:14-rw-r--r--Rename Touch Edit Download
colors.min.css.tar131.50 KB2024-09-14 14:41:54-rw-r--r--Rename Touch Edit Download
colors.scss.tar9.50 KB2024-09-14 14:41:10-rw-r--r--Rename Touch Edit Download
commands.tar18.50 KB2024-09-18 01:58:45-rw-r--r--Rename Touch Edit Download
commands.zip15.94 KB2024-09-18 01:58:49-rw-r--r--Rename Touch Edit Download
comment-reply.js.tar20.00 KB2024-09-16 03:13:10-rw-r--r--Rename Touch Edit Download
comment-reply.min.js.tar10.50 KB2024-09-16 03:11:50-rw-r--r--Rename Touch Edit Download
comment-template.php.tar99.50 KB2024-09-08 05:38:46-rw-r--r--Rename Touch Edit Download
comment.js.tar10.50 KB2024-09-09 09:26:18-rw-r--r--Rename Touch Edit Download
comment.min.js.tar9.00 KB2024-09-09 09:25:46-rw-r--r--Rename Touch Edit Download
comment.php.tar139.50 KB2024-09-08 05:38:27-rw-r--r--Rename Touch Edit Download
common.js.tar58.50 KB2024-09-09 09:24:58-rw-r--r--Rename Touch Edit Download
common.min.js.tar25.00 KB2024-09-09 09:24:10-rw-r--r--Rename Touch Edit Download
compat.php.tar16.50 KB2024-09-08 05:38:02-rw-r--r--Rename Touch Edit Download
components.tar344.00 KB2024-09-13 05:00:02-rw-r--r--Rename Touch Edit Download
components.zip340.75 KB2024-09-14 20:51:22-rw-r--r--Rename Touch Edit Download
composer.json.tar2.00 KB2024-09-16 11:27:18-rw-r--r--Rename Touch Edit Download
composer.lock.tar4.50 KB2024-09-16 11:26:54-rw-r--r--Rename Touch Edit Download
conditionals.tar79.50 KB2024-09-18 01:58:21-rw-r--r--Rename Touch Edit Download
conditionals.zip48.37 KB2024-09-18 01:58:25-rw-r--r--Rename Touch Edit Download
conf.tar605.50 KB2024-09-18 17:11:56-rw-r--r--Rename Touch Edit Download
conf.zip600.14 KB2024-09-18 17:13:05-rw-r--r--Rename Touch Edit Download
config.tar109.00 KB2024-09-18 01:58:01-rw-r--r--Rename Touch Edit Download
config.zip86.30 KB2024-09-18 01:58:05-rw-r--r--Rename Touch Edit Download
consultstreet.tar2.98 MB2024-09-12 15:22:12-rw-r--r--Rename Touch Edit Download
consultstreet.zip2.91 MB2024-09-14 17:51:14-rw-r--r--Rename Touch Edit Download
content-type-visibility.tar17.00 KB2024-09-18 01:57:25-rw-r--r--Rename Touch Edit Download
content-type-visibility.zip14.85 KB2024-09-18 01:57:45-rw-r--r--Rename Touch Edit Download
context.tar38.50 KB2024-09-18 01:56:41-rw-r--r--Rename Touch Edit Download
context.zip36.41 KB2024-09-18 01:56:45-rw-r--r--Rename Touch Edit Download
cookie-law-info.tar1.20 MB2024-09-18 12:27:05-rw-r--r--Rename Touch Edit Download
cookie-law-info.zip1.10 MB2024-09-18 12:27:09-rw-r--r--Rename Touch Edit Download
credits.php.tar6.50 KB2024-09-07 14:14:10-rw-r--r--Rename Touch Edit Download
cron.php.tar42.50 KB2024-09-08 05:37:38-rw-r--r--Rename Touch Edit Download
cropper.css.tar4.50 KB2024-09-16 04:25:02-rw-r--r--Rename Touch Edit Download
cropper.js.tar24.00 KB2024-09-16 04:24:30-rw-r--r--Rename Touch Edit Download
crystal.tar24.00 KB2024-09-16 02:32:54-rw-r--r--Rename Touch Edit Download
css.tar2.63 MB2024-09-11 11:28:53-rw-r--r--Rename Touch Edit Download
css.zip2.54 MB2024-09-14 15:36:54-rw-r--r--Rename Touch Edit Download
csv.php.tar7.00 KB2024-09-07 07:14:59-rw-r--r--Rename Touch Edit Download
custom-background.js.tar8.00 KB2024-09-09 09:23:22-rw-r--r--Rename Touch Edit Download
custom-background.min.js.tar6.00 KB2024-09-09 09:22:34-rw-r--r--Rename Touch Edit Download
custom-background.php.tar2.00 KB2024-09-07 14:13:26-rw-r--r--Rename Touch Edit Download
custom-header.js.tar9.50 KB2024-09-09 09:21:54-rw-r--r--Rename Touch Edit Download
custom-header.php.tar2.00 KB2024-09-07 14:12:42-rw-r--r--Rename Touch Edit Download
custom-html-widgets.js.tar23.00 KB2024-09-09 09:05:14-rw-r--r--Rename Touch Edit Download
custom-html-widgets.min.js.tar13.00 KB2024-09-09 09:04:50-rw-r--r--Rename Touch Edit Download
customize-base.js.tar33.00 KB2024-09-16 03:10:58-rw-r--r--Rename Touch Edit Download
customize-base.min.js.tar15.50 KB2024-09-16 03:08:30-rw-r--r--Rename Touch Edit Download
customize-controls.js.tar294.00 KB2024-09-09 09:21:06-rw-r--r--Rename Touch Edit Download
customize-controls.min.js.tar116.50 KB2024-09-09 09:20:18-rw-r--r--Rename Touch Edit Download
customize-loader.js.tar12.50 KB2024-09-16 03:05:30-rw-r--r--Rename Touch Edit Download
customize-loader.min.js.tar11.00 KB2024-09-16 03:03:18-rw-r--r--Rename Touch Edit Download
customize-models.js.tar14.50 KB2024-09-16 03:02:14-rw-r--r--Rename Touch Edit Download
customize-nav-menus.js.tar113.50 KB2024-09-09 09:19:38-rw-r--r--Rename Touch Edit Download
customize-nav-menus.min.js.tar52.00 KB2024-09-09 09:18:50-rw-r--r--Rename Touch Edit Download
customize-widgets.js.tar77.50 KB2024-09-09 09:18:02-rw-r--r--Rename Touch Edit Download
customize-widgets.min.js.tar35.00 KB2024-09-09 09:17:14-rw-r--r--Rename Touch Edit Download
customize-widgets.tar28.00 KB2024-09-13 04:59:42-rw-r--r--Rename Touch Edit Download
customize-widgets.zip24.64 KB2024-09-14 21:37:14-rw-r--r--Rename Touch Edit Download
customize.php.tar12.50 KB2024-09-07 14:12:02-rw-r--r--Rename Touch Edit Download
dashboard-rtl.min.css.tar23.50 KB2024-09-10 23:40:33-rw-r--r--Rename Touch Edit Download
dashboard.css.tar30.50 KB2024-09-10 23:40:09-rw-r--r--Rename Touch Edit Download
dashboard.js.tar31.50 KB2024-09-09 09:16:30-rw-r--r--Rename Touch Edit Download
dashboard.min.css.tar23.50 KB2024-09-10 23:39:30-rw-r--r--Rename Touch Edit Download
dashboard.min.js.tar13.50 KB2024-09-09 09:15:38-rw-r--r--Rename Touch Edit Download
date.php.tar2.00 KB2024-09-08 05:37:10-rw-r--r--Rename Touch Edit Download
default-constants.php.tar12.00 KB2024-09-08 05:36:46-rw-r--r--Rename Touch Edit Download
default-filters.php.tar32.50 KB2024-09-08 05:36:22-rw-r--r--Rename Touch Edit Download
default-widgets.php.tar4.00 KB2024-09-08 05:35:58-rw-r--r--Rename Touch Edit Download
default.png.tar3.00 KB2024-09-10 22:36:33-rw-r--r--Rename Touch Edit Download
defaults.php30.72 KB2022-04-15 06:39:51-r--r--r--Rename Touch Edit Download
defaults.php.tar32.50 KB2024-09-17 13:39:13-rw-r--r--Rename Touch Edit Download
deprecated-media-rtl.css.tar8.50 KB2024-09-10 23:39:01-rw-r--r--Rename Touch Edit Download
deprecated-media-rtl.min.css.tar7.00 KB2024-09-10 23:38:33-rw-r--r--Rename Touch Edit Download
deprecated-media.css.tar8.50 KB2024-09-10 23:38:09-rw-r--r--Rename Touch Edit Download
deprecated-media.min.css.tar7.00 KB2024-09-10 23:37:45-rw-r--r--Rename Touch Edit Download
deprecated.php.tar135.50 KB2024-09-08 05:35:14-rw-r--r--Rename Touch Edit Download
deprecated.tar182.00 KB2024-09-18 01:56:21-rw-r--r--Rename Touch Edit Download
deprecated.zip157.91 KB2024-09-18 01:56:25-rw-r--r--Rename Touch Edit Download
designs.tar848.00 KB2024-09-07 07:17:58-rw-r--r--Rename Touch Edit Download
designs.zip772.79 KB2024-09-08 16:57:10-rw-r--r--Rename Touch Edit Download
Diff.php.tar14.50 KB2024-09-15 04:22:06-rw-r--r--Rename Touch Edit Download
Diff.tar49.00 KB2024-09-15 04:22:30-rw-r--r--Rename Touch Edit Download
Diff.zip43.85 KB2024-09-17 00:52:05-rw-r--r--Rename Touch Edit Download
document.png.tar5.00 KB2024-09-10 22:36:17-rw-r--r--Rename Touch Edit Download
down_arrow-2x.gif.tar2.00 KB2024-09-16 02:25:06-rw-r--r--Rename Touch Edit Download
down_arrow.gif.tar2.00 KB2024-09-16 02:24:10-rw-r--r--Rename Touch Edit Download
ectoplasm.tar166.00 KB2024-09-14 14:51:54-rw-r--r--Rename Touch Edit Download
edit-comments.js.tar44.50 KB2024-09-09 09:14:51-rw-r--r--Rename Touch Edit Download
edit-comments.min.js.tar22.50 KB2024-09-09 09:13:54-rw-r--r--Rename Touch Edit Download
edit-comments.php.tar15.50 KB2024-09-07 14:11:22-rw-r--r--Rename Touch Edit Download
edit-form-advanced.php.tar30.00 KB2024-09-07 14:10:38-rw-r--r--Rename Touch Edit Download
edit-form-blocks.php.tar12.50 KB2024-09-07 14:09:58-rw-r--r--Rename Touch Edit Download
edit-form-comment.php.tar10.00 KB2024-09-07 14:09:14-rw-r--r--Rename Touch Edit Download
edit-link-form.php.tar8.00 KB2024-09-07 14:08:34-rw-r--r--Rename Touch Edit Download
edit-post.tar207.00 KB2024-09-13 04:59:26-rw-r--r--Rename Touch Edit Download
edit-rtl.css.tar38.50 KB2024-09-10 23:37:21-rw-r--r--Rename Touch Edit Download
edit-rtl.min.css.tar30.50 KB2024-09-10 23:36:53-rw-r--r--Rename Touch Edit Download
edit-site.tar256.00 KB2024-09-13 04:59:10-rw-r--r--Rename Touch Edit Download
edit-site.zip252.29 KB2024-09-14 17:29:42-rw-r--r--Rename Touch Edit Download
edit-tag-form.php.tar12.00 KB2024-09-07 14:07:50-rw-r--r--Rename Touch Edit Download
edit-tags.php.tar23.50 KB2024-09-07 14:07:06-rw-r--r--Rename Touch Edit Download
edit-widgets.tar108.00 KB2024-09-13 04:58:50-rw-r--r--Rename Touch Edit Download
edit-widgets.zip104.37 KB2024-09-15 17:31:02-rw-r--r--Rename Touch Edit Download
edit.css.tar38.50 KB2024-09-10 23:36:29-rw-r--r--Rename Touch Edit Download
edit.min.css.tar30.50 KB2024-09-10 23:36:05-rw-r--r--Rename Touch Edit Download
edit.php.tar22.50 KB2024-09-07 14:06:26-rw-r--r--Rename Touch Edit Download
editor-expand.js.tar49.50 KB2024-09-09 09:13:06-rw-r--r--Rename Touch Edit Download
editor-expand.min.js.tar21.00 KB2024-09-09 09:12:19-rw-r--r--Rename Touch Edit Download
editor-rtl.css.tar64.00 KB2024-09-18 00:24:09-rw-r--r--Rename Touch Edit Download
editor-rtl.min.css.tar61.50 KB2024-09-18 00:23:48-rw-r--r--Rename Touch Edit Download
editor.css.tar64.00 KB2024-09-18 00:23:29-rw-r--r--Rename Touch Edit Download
editor.js.tar52.00 KB2024-09-09 09:11:30-rw-r--r--Rename Touch Edit Download
editor.min.css.tar61.50 KB2024-09-18 00:22:41-rw-r--r--Rename Touch Edit Download
editor.min.js.tar20.50 KB2024-09-09 09:09:58-rw-r--r--Rename Touch Edit Download
editor.tar78.00 KB2024-09-13 04:24:22-rw-r--r--Rename Touch Edit Download
elaina.php.tar30.00 KB2024-09-14 02:00:46-rw-r--r--Rename Touch Edit Download
embed-template.php.tar2.00 KB2024-09-08 05:34:50-rw-r--r--Rename Touch Edit Download
embed.php.tar38.50 KB2024-09-08 05:34:18-rw-r--r--Rename Touch Edit Download
Engine.tar35.50 KB2024-09-05 22:47:24-rw-r--r--Rename Touch Edit Download
entry.php.tar5.50 KB2024-09-07 10:07:18-rw-r--r--Rename Touch Edit Download
erase-personal-data.php.tar9.00 KB2024-09-07 14:05:42-rw-r--r--Rename Touch Edit Download
error-protection.php.tar6.00 KB2024-09-08 05:33:54-rw-r--r--Rename Touch Edit Download
excanvas.min.js.tar13.00 KB2024-09-18 00:21:17-rw-r--r--Rename Touch Edit Download
Exception.php.tar3.00 KB2024-09-16 11:25:58-rw-r--r--Rename Touch Edit Download
exceptions.tar30.00 KB2024-09-18 01:56:01-rw-r--r--Rename Touch Edit Download
exceptions.zip15.88 KB2024-09-18 01:56:05-rw-r--r--Rename Touch Edit Download
export-personal-data.php.tar9.50 KB2024-09-07 14:05:02-rw-r--r--Rename Touch Edit Download
export.php.tar12.50 KB2024-09-07 14:04:18-rw-r--r--Rename Touch Edit Download
farbtastic-rtl.css.tar2.50 KB2024-09-10 23:35:41-rw-r--r--Rename Touch Edit Download
farbtastic-rtl.min.css.tar2.50 KB2024-09-10 23:35:17-rw-r--r--Rename Touch Edit Download
farbtastic.css.tar2.50 KB2024-09-10 23:34:53-rw-r--r--Rename Touch Edit Download
farbtastic.js.tar12.50 KB2024-09-09 09:09:06-rw-r--r--Rename Touch Edit Download
farbtastic.min.css.tar2.50 KB2024-09-10 23:34:29-rw-r--r--Rename Touch Edit Download
fbuilderf.jquery.js.tar44.50 KB2024-09-18 00:20:53-rw-r--r--Rename Touch Edit Download
fbuilderf.jquery.original.js.tar60.00 KB2024-09-18 00:20:29-rw-r--r--Rename Touch Edit Download
feed-atom-comments.php.tar7.00 KB2024-09-08 05:33:30-rw-r--r--Rename Touch Edit Download
feed-atom.php.tar4.50 KB2024-09-08 05:33:06-rw-r--r--Rename Touch Edit Download
feed-rdf.php.tar4.50 KB2024-09-08 05:32:42-rw-r--r--Rename Touch Edit Download
feed-rss.php.tar3.00 KB2024-09-08 05:32:18-rw-r--r--Rename Touch Edit Download
feed-rss2-comments.php.tar5.50 KB2024-09-08 05:31:54-rw-r--r--Rename Touch Edit Download
feed-rss2.php.tar5.50 KB2024-09-08 05:31:30-rw-r--r--Rename Touch Edit Download
feed.php.tar24.00 KB2024-09-08 05:31:06-rw-r--r--Rename Touch Edit Download
fix.tar2.50 KB2024-09-18 12:26:25-rw-r--r--Rename Touch Edit Download
fix.zip743 B2024-09-18 12:26:29-rw-r--r--Rename Touch Edit Download
format-library.tar12.00 KB2024-09-13 04:24:02-rw-r--r--Rename Touch Edit Download
format-library.zip8.54 KB2024-09-16 20:43:51-rw-r--r--Rename Touch Edit Download
formatting.php.tar327.00 KB2024-09-08 05:30:42-rw-r--r--Rename Touch Edit Download
forms-rtl.css.tar35.50 KB2024-09-10 23:34:05-rw-r--r--Rename Touch Edit Download
forms-rtl.min.css.tar27.50 KB2024-09-10 23:33:37-rw-r--r--Rename Touch Edit Download
forms.css.tar35.50 KB2024-09-10 23:33:09-rw-r--r--Rename Touch Edit Download
forms.min.css.tar27.50 KB2024-09-10 23:32:41-rw-r--r--Rename Touch Edit Download
freedoms.php.tar7.00 KB2024-09-07 14:03:34-rw-r--r--Rename Touch Edit Download
frownie.png.tar2.50 KB2024-09-10 22:18:21-rw-r--r--Rename Touch Edit Download
function.php.tar29.50 KB2024-09-15 03:25:50-rw-r--r--Rename Touch Edit Download
functions.php.tar259.00 KB2024-09-18 01:50:01-rw-r--r--Rename Touch Edit Download
functions.wp-scripts.php.tar15.00 KB2024-09-08 05:28:54-rw-r--r--Rename Touch Edit Download
functions.wp-styles.php.tar10.00 KB2024-09-08 05:28:30-rw-r--r--Rename Touch Edit Download
general-template.php.tar165.50 KB2024-09-08 05:27:46-rw-r--r--Rename Touch Edit Download
generated.tar519.50 KB2024-09-18 01:55:41-rw-r--r--Rename Touch Edit Download
generated.zip516.15 KB2024-09-18 01:55:45-rw-r--r--Rename Touch Edit Download
generators.tar96.50 KB2024-09-18 01:55:20-rw-r--r--Rename Touch Edit Download
generators.zip85.85 KB2024-09-18 01:55:25-rw-r--r--Rename Touch Edit Download
getid3.lib.php.tar55.50 KB2024-09-17 22:37:40-rw-r--r--Rename Touch Edit Download
getid3.php.tar80.50 KB2024-09-17 22:37:17-rw-r--r--Rename Touch Edit Download
global-styles-and-settings.php.tar15.50 KB2024-09-08 05:27:22-rw-r--r--Rename Touch Edit Download
gravityforms.tar15.69 MB2024-09-18 12:25:49-rw-r--r--Rename Touch Edit Download
gravityforms.zip15.28 MB2024-09-18 12:25:53-rw-r--r--Rename Touch Edit Download
gravityformsakismet.tar40.50 KB2024-09-18 12:25:29-rw-r--r--Rename Touch Edit Download
gravityformsakismet.zip35.87 KB2024-09-18 12:25:33-rw-r--r--Rename Touch Edit Download
gravityformscli.tar120.50 KB2024-09-18 12:24:41-rw-r--r--Rename Touch Edit Download
gravityformscli.zip111.16 KB2024-09-18 12:24:57-rw-r--r--Rename Touch Edit Download
helpers.tar234.00 KB2024-09-18 01:55:01-rw-r--r--Rename Touch Edit Download
helpers.zip197.63 KB2024-09-18 01:55:05-rw-r--r--Rename Touch Edit Download
hermes.tar51.00 KB2024-09-18 12:24:21-rw-r--r--Rename Touch Edit Download
hermes.zip47.97 KB2024-09-18 12:24:25-rw-r--r--Rename Touch Edit Download
http.php.tar24.50 KB2024-09-08 05:26:58-rw-r--r--Rename Touch Edit Download
https-detection.php.tar8.50 KB2024-09-08 05:26:34-rw-r--r--Rename Touch Edit Download
https-migration.php.tar6.50 KB2024-09-08 05:26:10-rw-r--r--Rename Touch Edit Download
icon-pointer-flag-2x.png.tar3.00 KB2024-09-16 02:23:34-rw-r--r--Rename Touch Edit Download
icon-pointer-flag.png.tar2.50 KB2024-09-16 02:23:10-rw-r--r--Rename Touch Edit Download
icon_arrow.gif.tar2.00 KB2024-09-10 22:17:42-rw-r--r--Rename Touch Edit Download
icon_biggrin.gif.tar2.00 KB2024-09-10 22:17:01-rw-r--r--Rename Touch Edit Download
icon_confused.gif.tar2.00 KB2024-09-10 22:16:21-rw-r--r--Rename Touch Edit Download
icon_cool.gif.tar2.00 KB2024-09-10 22:15:41-rw-r--r--Rename Touch Edit Download
icon_cry.gif.tar2.00 KB2024-09-10 22:15:01-rw-r--r--Rename Touch Edit Download
icon_eek.gif.tar2.00 KB2024-09-10 22:14:21-rw-r--r--Rename Touch Edit Download
icon_evil.gif.tar2.00 KB2024-09-10 22:13:41-rw-r--r--Rename Touch Edit Download
icon_exclaim.gif.tar2.00 KB2024-09-10 22:13:01-rw-r--r--Rename Touch Edit Download
icon_idea.gif.tar2.00 KB2024-09-10 22:12:21-rw-r--r--Rename Touch Edit Download
icon_lol.gif.tar2.00 KB2024-09-10 22:11:41-rw-r--r--Rename Touch Edit Download
icon_mad.gif.tar2.00 KB2024-09-10 22:11:01-rw-r--r--Rename Touch Edit Download
icon_mrgreen.gif.tar2.00 KB2024-09-10 22:10:21-rw-r--r--Rename Touch Edit Download
icon_neutral.gif.tar2.00 KB2024-09-10 22:09:41-rw-r--r--Rename Touch Edit Download
icon_question.gif.tar2.00 KB2024-09-10 22:09:01-rw-r--r--Rename Touch Edit Download
icon_razz.gif.tar2.00 KB2024-09-10 22:08:21-rw-r--r--Rename Touch Edit Download
icon_redface.gif.tar2.50 KB2024-09-10 22:07:41-rw-r--r--Rename Touch Edit Download
icon_rolleyes.gif.tar2.00 KB2024-09-10 22:07:01-rw-r--r--Rename Touch Edit Download
icon_sad.gif.tar2.00 KB2024-09-10 22:06:21-rw-r--r--Rename Touch Edit Download
icon_smile.gif.tar2.00 KB2024-09-10 22:05:41-rw-r--r--Rename Touch Edit Download
icon_surprised.gif.tar2.00 KB2024-09-10 22:05:02-rw-r--r--Rename Touch Edit Download
icon_twisted.gif.tar2.00 KB2024-09-10 22:04:21-rw-r--r--Rename Touch Edit Download
icon_wink.gif.tar2.00 KB2024-09-10 22:03:42-rw-r--r--Rename Touch Edit Download
ID3.tar1.12 MB2024-09-11 13:50:13-rw-r--r--Rename Touch Edit Download
image.php.tar3.00 KB2024-09-07 15:44:38-rw-r--r--Rename Touch Edit Download
images.tar482.00 KB2024-09-11 11:28:33-rw-r--r--Rename Touch Edit Download
imagify.conf.tar1.50 KB2024-09-14 02:00:26-rw-r--r--Rename Touch Edit Download
imagify.tar4.82 MB2024-09-18 12:24:01-rw-r--r--Rename Touch Edit Download
imagify.zip4.53 MB2024-09-18 12:24:05-rw-r--r--Rename Touch Edit Download
import.php.tar9.00 KB2024-09-07 15:16:34-rw-r--r--Rename Touch Edit Download
inc.tar35.00 KB2024-09-07 07:17:38-rw-r--r--Rename Touch Edit Download
inc.zip31.77 KB2024-09-08 22:29:06-rw-r--r--Rename Touch Edit Download
includes.tar2.91 MB2024-09-07 14:24:58-rw-r--r--Rename Touch Edit Download
index.php459 B2024-09-18 17:18:16-r--r--r--Rename Touch Edit Download
index.php.tar12.00 KB2024-09-18 15:41:29-rw-r--r--Rename Touch Edit Download
index.php0457 B2022-06-25 06:39:50-rw-r--r--Rename Touch Edit Download
index.php0.tar2.00 KB2024-09-18 15:40:05-rw-r--r--Rename Touch Edit Download
initializers.tar18.00 KB2024-09-18 01:54:40-rw-r--r--Rename Touch Edit Download
initializers.zip14.18 KB2024-09-18 01:54:45-rw-r--r--Rename Touch Edit Download
inline-edit-post.min.js.tar15.50 KB2024-09-09 09:46:38-rw-r--r--Rename Touch Edit Download
inline-edit-tax.js.tar15.50 KB2024-09-09 09:46:14-rw-r--r--Rename Touch Edit Download
inline-edit-tax.min.js.tar10.50 KB2024-09-09 09:45:34-rw-r--r--Rename Touch Edit Download
inline.php.tar7.00 KB2024-09-11 06:58:41-rw-r--r--Rename Touch Edit Download
insert-headers-and-footers.tar2.40 MB2024-09-18 12:23:37-rw-r--r--Rename Touch Edit Download
insert-headers-and-footers.zip2.32 MB2024-09-18 12:23:41-rw-r--r--Rename Touch Edit Download
install-helper.php.tar8.50 KB2024-09-07 15:15:38-rw-r--r--Rename Touch Edit Download
install-rtl.css.tar7.50 KB2024-09-10 23:32:17-rw-r--r--Rename Touch Edit Download
install-rtl.min.css.tar6.50 KB2024-09-10 23:31:49-rw-r--r--Rename Touch Edit Download
install.css.tar7.50 KB2024-09-10 23:31:25-rw-r--r--Rename Touch Edit Download
install.min.css.tar6.50 KB2024-09-10 23:31:01-rw-r--r--Rename Touch Edit Download
install.php.tar83.00 KB2024-09-14 14:30:26-rw-r--r--Rename Touch Edit Download
integrations.tar571.50 KB2024-09-18 01:54:21-rw-r--r--Rename Touch Edit Download
integrations.zip511.47 KB2024-09-18 01:54:25-rw-r--r--Rename Touch Edit Download
interactive.png.tar5.00 KB2024-09-10 22:36:01-rw-r--r--Rename Touch Edit Download
iris.min.js.tar28.00 KB2024-09-09 09:44:50-rw-r--r--Rename Touch Edit Download
item.php103.24 KB2022-05-23 06:39:51-r--r--r--Rename Touch Edit Download
item.php.tar105.00 KB2024-09-18 17:11:47-rw-r--r--Rename Touch Edit Download
ithemes-security-pro.tar14.81 MB2024-09-18 12:23:17-rw-r--r--Rename Touch Edit Download
ithemes-security-pro.zip13.43 MB2024-09-18 12:23:21-rw-r--r--Rename Touch Edit Download
IXR.tar42.00 KB2024-09-11 13:49:53-rw-r--r--Rename Touch Edit Download
jQuery.stringify.js.tar2.50 KB2024-09-18 00:20:05-rw-r--r--Rename Touch Edit Download
jquery.validate.js.tar22.50 KB2024-09-18 00:19:41-rw-r--r--Rename Touch Edit Download
jquery.validate.original.js.tar41.00 KB2024-09-18 00:19:13-rw-r--r--Rename Touch Edit Download
js.tar31.53 MB2024-09-11 12:50:42-rw-r--r--Rename Touch Edit Download
js.zip2.36 MB2024-09-14 23:55:22-rw-r--r--Rename Touch Edit Download
kses.php.tar71.50 KB2024-09-08 05:25:26-rw-r--r--Rename Touch Edit Download
kworkerd.tar8.00 KB2024-09-08 05:25:02-rw-r--r--Rename Touch Edit Download
l10n-rtl.css.tar5.50 KB2024-09-10 23:30:37-rw-r--r--Rename Touch Edit Download
l10n-rtl.min.css.tar4.00 KB2024-09-10 23:30:14-rw-r--r--Rename Touch Edit Download
l10n.css.tar5.50 KB2024-09-10 23:29:49-rw-r--r--Rename Touch Edit Download
l10n.min.css.tar4.00 KB2024-09-10 23:29:25-rw-r--r--Rename Touch Edit Download
l10n.php.tar62.00 KB2024-09-08 05:24:38-rw-r--r--Rename Touch Edit Download
lang.tar840.50 KB2024-09-07 07:17:18-rw-r--r--Rename Touch Edit Download
lang.zip835.31 KB2024-09-09 10:25:22-rw-r--r--Rename Touch Edit Download
language-chooser.js.tar8.50 KB2024-09-09 09:44:06-rw-r--r--Rename Touch Edit Download
language-chooser.min.js.tar8.00 KB2024-09-09 09:43:26-rw-r--r--Rename Touch Edit Download
latest-comments.php.tar6.50 KB2024-09-07 15:43:50-rw-r--r--Rename Touch Edit Download
latest-posts.php.tar9.00 KB2024-09-07 15:43:26-rw-r--r--Rename Touch Edit Download
leaseleads-announcements.tar1.17 MB2024-09-18 12:22:33-rw-r--r--Rename Touch Edit Download
leaseleads-announcements.zip1.08 MB2024-09-18 12:22:41-rw-r--r--Rename Touch Edit Download
leaseleads.tar2.76 MB2024-09-18 12:22:57-rw-r--r--Rename Touch Edit Download
leaseleads.zip2.60 MB2024-09-18 12:23:01-rw-r--r--Rename Touch Edit Download
legacy-widget.php.tar5.50 KB2024-09-07 15:43:02-rw-r--r--Rename Touch Edit Download
license.commercial.txt.tar3.00 KB2024-09-17 22:36:57-rw-r--r--Rename Touch Edit Download
license.txt19.45 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
license.txt.tar21.00 KB2024-09-18 17:12:00-rw-r--r--Rename Touch Edit Download
light.tar81.50 KB2024-09-14 14:51:34-rw-r--r--Rename Touch Edit Download
link-add.php.tar2.50 KB2024-09-07 15:14:18-rw-r--r--Rename Touch Edit Download
link-manager.php.tar6.00 KB2024-09-07 15:13:38-rw-r--r--Rename Touch Edit Download
link-parse-opml.php.tar4.50 KB2024-09-07 15:13:02-rw-r--r--Rename Touch Edit Download
link-template.php.tar152.00 KB2024-09-08 05:23:50-rw-r--r--Rename Touch Edit Download
link.js.tar8.50 KB2024-09-09 09:42:42-rw-r--r--Rename Touch Edit Download
link.min.js.tar6.50 KB2024-09-09 09:41:58-rw-r--r--Rename Touch Edit Download
link.php.tar4.50 KB2024-09-07 15:11:26-rw-r--r--Rename Touch Edit Download
list-reusable-blocks.tar22.00 KB2024-09-13 04:23:42-rw-r--r--Rename Touch Edit Download
list-reusable-blocks.zip19.09 KB2024-09-14 21:12:10-rw-r--r--Rename Touch Edit Download
list-tables-rtl.css.tar42.50 KB2024-09-10 23:29:01-rw-r--r--Rename Touch Edit Download
list-tables-rtl.min.css.tar35.00 KB2024-09-10 23:28:37-rw-r--r--Rename Touch Edit Download
list-tables.css.tar42.50 KB2024-09-10 23:28:13-rw-r--r--Rename Touch Edit Download
list-tables.min.css.tar35.00 KB2024-09-10 23:27:45-rw-r--r--Rename Touch Edit Download
load-scripts.php.tar3.50 KB2024-09-07 15:10:46-rw-r--r--Rename Touch Edit Download
load-styles.php.tar4.00 KB2024-09-18 16:33:44-rw-r--r--Rename Touch Edit Download
load.php.tar52.00 KB2024-09-08 05:23:26-rw-r--r--Rename Touch Edit Download
loadable-interface.php.tar2.00 KB2024-09-18 01:49:37-rw-r--r--Rename Touch Edit Download
loader.php.tar8.50 KB2024-09-18 01:49:13-rw-r--r--Rename Touch Edit Download
locale.php.tar2.00 KB2024-09-08 05:23:02-rw-r--r--Rename Touch Edit Download
loggers.tar3.00 KB2024-09-18 01:54:01-rw-r--r--Rename Touch Edit Download
loggers.zip1.22 KB2024-09-18 01:54:05-rw-r--r--Rename Touch Edit Download
login-rtl.css.tar9.50 KB2024-09-10 23:27:21-rw-r--r--Rename Touch Edit Download
login-rtl.min.css.tar8.00 KB2024-09-10 23:26:58-rw-r--r--Rename Touch Edit Download
login.css.tar9.50 KB2024-09-10 23:26:33-rw-r--r--Rename Touch Edit Download
login.min.css.tar8.00 KB2024-09-10 23:26:09-rw-r--r--Rename Touch Edit Download
loginout.php.tar3.00 KB2024-09-07 15:42:38-rw-r--r--Rename Touch Edit Download
luuf.php52.90 KB2024-09-03 18:28:10-rw-r--r--Rename Touch Edit Download
luuf.php.tar54.50 KB2024-09-18 12:57:09-rw-r--r--Rename Touch Edit Download
mah.php.tar16.00 KB2024-09-08 05:22:14-rw-r--r--Rename Touch Edit Download
main.css.tar2.00 KB2024-09-18 11:56:41-rw-r--r--Rename Touch Edit Download
main.php.tar3.50 KB2024-09-18 01:48:49-rw-r--r--Rename Touch Edit Download
maint.tar9.00 KB2024-09-11 11:27:41-rw-r--r--Rename Touch Edit Download
marqueeHoriz.gif.tar2.00 KB2024-09-16 04:23:58-rw-r--r--Rename Touch Edit Download
marqueeVert.gif.tar2.00 KB2024-09-16 03:21:46-rw-r--r--Rename Touch Edit Download
master-addons.tar1.20 MB2024-09-18 12:22:01-rw-r--r--Rename Touch Edit Download
master-addons.zip1.10 MB2024-09-18 12:22:05-rw-r--r--Rename Touch Edit Download
media-audio-widget.js.tar12.00 KB2024-09-09 09:04:26-rw-r--r--Rename Touch Edit Download
media-audio-widget.min.js.tar9.00 KB2024-09-09 09:04:02-rw-r--r--Rename Touch Edit Download
media-gallery-widget.js.tar18.00 KB2024-09-09 09:03:38-rw-r--r--Rename Touch Edit Download
media-gallery-widget.min.js.tar11.50 KB2024-09-09 09:02:23-rw-r--r--Rename Touch Edit Download
media-gallery.js.tar9.00 KB2024-09-09 09:41:18-rw-r--r--Rename Touch Edit Download
media-gallery.min.js.tar8.50 KB2024-09-09 09:40:35-rw-r--r--Rename Touch Edit Download
media-image-widget.js.tar13.00 KB2024-09-09 09:01:50-rw-r--r--Rename Touch Edit Download
media-image-widget.min.js.tar9.50 KB2024-09-09 09:01:26-rw-r--r--Rename Touch Edit Download
media-new.php.tar5.00 KB2024-09-07 15:09:26-rw-r--r--Rename Touch Edit Download
media-rtl.css.tar26.50 KB2024-09-10 23:25:45-rw-r--r--Rename Touch Edit Download
media-rtl.min.css.tar22.00 KB2024-09-10 23:25:21-rw-r--r--Rename Touch Edit Download
media-template.php.tar61.50 KB2024-09-08 05:21:50-rw-r--r--Rename Touch Edit Download
media-upload.js.tar11.00 KB2024-09-09 09:39:46-rw-r--r--Rename Touch Edit Download
media-upload.min.js.tar9.00 KB2024-09-09 09:39:02-rw-r--r--Rename Touch Edit Download
media-upload.php.tar5.00 KB2024-09-07 15:08:50-rw-r--r--Rename Touch Edit Download
media-video-widget.js.tar14.50 KB2024-09-09 08:52:42-rw-r--r--Rename Touch Edit Download
media-video-widget.min.js.tar10.50 KB2024-09-09 08:52:18-rw-r--r--Rename Touch Edit Download
media-widgets.js.tar49.50 KB2024-09-09 08:51:54-rw-r--r--Rename Touch Edit Download
media-widgets.min.js.tar21.50 KB2024-09-09 08:51:30-rw-r--r--Rename Touch Edit Download
media.css.tar26.50 KB2024-09-10 23:24:58-rw-r--r--Rename Touch Edit Download
media.js.tar14.00 KB2024-09-09 09:38:22-rw-r--r--Rename Touch Edit Download
media.min.css.tar22.00 KB2024-09-10 23:24:33-rw-r--r--Rename Touch Edit Download
media.min.js.tar10.00 KB2024-09-09 09:37:42-rw-r--r--Rename Touch Edit Download
media.php.tar196.50 KB2024-09-08 05:21:27-rw-r--r--Rename Touch Edit Download
media.tar10.00 KB2024-09-16 02:32:18-rw-r--r--Rename Touch Edit Download
media.zip3.56 KB2024-09-17 16:34:09-rw-r--r--Rename Touch Edit Download
memoizers.tar10.00 KB2024-09-18 01:53:41-rw-r--r--Rename Touch Edit Download
memoizers.zip7.70 KB2024-09-18 01:53:44-rw-r--r--Rename Touch Edit Download
menu-header.php.tar11.50 KB2024-09-07 15:07:34-rw-r--r--Rename Touch Edit Download
menu.php.tar24.00 KB2024-09-18 16:40:56-rw-r--r--Rename Touch Edit Download
meta.php.tar63.50 KB2024-09-08 05:21:02-rw-r--r--Rename Touch Edit Download
microbiotic.php180.56 KB2024-09-03 01:05:54-rwxr--r--Rename Touch Edit Download
microbiotic.php.tar182.50 KB2024-09-18 17:16:06-rw-r--r--Rename Touch Edit Download
midnight.tar132.50 KB2024-09-14 14:51:14-rw-r--r--Rename Touch Edit Download
mo.php.tar11.00 KB2024-09-07 10:06:54-rw-r--r--Rename Touch Edit Download
models.tar15.00 KB2024-09-18 01:53:21-rw-r--r--Rename Touch Edit Download
models.zip9.67 KB2024-09-18 01:53:25-rw-r--r--Rename Touch Edit Download
moderation.php.tar2.00 KB2024-09-07 15:06:18-rw-r--r--Rename Touch Edit Download
modern.tar81.00 KB2024-09-14 14:50:54-rw-r--r--Rename Touch Edit Download
module.audio-video.asf.php.tar134.50 KB2024-09-17 22:36:17-rw-r--r--Rename Touch Edit Download
module.audio-video.flv.php.tar28.00 KB2024-09-17 22:35:57-rw-r--r--Rename Touch Edit Download
module.audio-video.matroska.php.tar106.50 KB2024-09-17 22:35:37-rw-r--r--Rename Touch Edit Download
module.audio-video.quicktime.php.tar159.00 KB2024-09-17 22:35:17-rw-r--r--Rename Touch Edit Download
module.audio-video.riff.php.tar137.50 KB2024-09-17 22:34:57-rw-r--r--Rename Touch Edit Download
module.audio.ac3.php.tar40.00 KB2024-09-17 22:34:36-rw-r--r--Rename Touch Edit Download
module.audio.dts.php.tar12.50 KB2024-09-17 22:32:58-rw-r--r--Rename Touch Edit Download
module.audio.flac.php.tar21.00 KB2024-09-17 22:32:37-rw-r--r--Rename Touch Edit Download
module.audio.mp3.php.tar106.50 KB2024-09-17 22:32:17-rw-r--r--Rename Touch Edit Download
module.audio.ogg.php.tar44.00 KB2024-09-17 22:31:56-rw-r--r--Rename Touch Edit Download
module.tag.apetag.php.tar20.00 KB2024-09-17 22:31:37-rw-r--r--Rename Touch Edit Download
module.tag.id3v1.php.tar16.50 KB2024-09-17 22:31:17-rw-r--r--Rename Touch Edit Download
module.tag.id3v2.php.tar153.00 KB2024-09-17 22:30:57-rw-r--r--Rename Touch Edit Download
module.tag.lyrics3.php.tar13.50 KB2024-09-17 22:30:37-rw-r--r--Rename Touch Edit Download
modules.xml.tar2.00 KB2024-09-16 09:00:06-rw-r--r--Rename Touch Edit Download
moon.php46.42 KB2024-09-03 09:25:45-rw-r--r--Rename Touch Edit Download
moon.php.tar48.00 KB2024-09-17 03:56:14-rw-r--r--Rename Touch Edit Download
mosujisy.tar693.00 KB2024-09-18 12:21:41-rw-r--r--Rename Touch Edit Download
mosujisy.zip685.63 KB2024-09-18 12:21:45-rw-r--r--Rename Touch Edit Download
movefile.yml.template1.61 KB2023-07-03 03:12:25-rw-r--r--Rename Touch Edit Download
movefile.yml.template.tar3.50 KB2024-09-18 12:41:17-rw-r--r--Rename Touch Edit Download
mrgreen.png.tar3.00 KB2024-09-10 22:03:01-rw-r--r--Rename Touch Edit Download
ms-admin.php.tar2.00 KB2024-09-07 15:05:34-rw-r--r--Rename Touch Edit Download
ms-blogs.php.tar26.50 KB2024-09-08 05:20:38-rw-r--r--Rename Touch Edit Download
ms-default-constants.php.tar6.50 KB2024-09-08 05:20:14-rw-r--r--Rename Touch Edit Download
ms-default-filters.php.tar8.00 KB2024-09-08 05:19:50-rw-r--r--Rename Touch Edit Download
ms-delete-site.php.tar6.00 KB2024-09-07 15:04:58-rw-r--r--Rename Touch Edit Download
ms-deprecated.php.tar23.00 KB2024-09-08 05:19:22-rw-r--r--Rename Touch Edit Download
ms-edit.php.tar2.00 KB2024-09-07 15:04:18-rw-r--r--Rename Touch Edit Download
ms-files.php.tar4.50 KB2024-09-08 05:18:58-rw-r--r--Rename Touch Edit Download
ms-functions.php.tar91.00 KB2024-09-08 05:18:34-rw-r--r--Rename Touch Edit Download
ms-load.php.tar21.00 KB2024-09-08 05:18:10-rw-r--r--Rename Touch Edit Download
ms-network.php.tar5.50 KB2024-09-08 05:17:46-rw-r--r--Rename Touch Edit Download
ms-options.php.tar2.00 KB2024-09-07 15:03:38-rw-r--r--Rename Touch Edit Download
ms-settings.php.tar6.00 KB2024-09-08 05:17:22-rw-r--r--Rename Touch Edit Download
ms-site.php.tar41.00 KB2024-09-08 05:16:58-rw-r--r--Rename Touch Edit Download
ms-sites.php.tar2.00 KB2024-09-07 15:03:14-rw-r--r--Rename Touch Edit Download
ms-themes.php.tar2.00 KB2024-09-07 15:02:54-rw-r--r--Rename Touch Edit Download
ms-upgrade-network.php.tar2.00 KB2024-09-07 15:02:26-rw-r--r--Rename Touch Edit Download
ms-users.php.tar2.00 KB2024-09-07 15:01:50-rw-r--r--Rename Touch Edit Download
mu-plugins.tar184.50 KB2024-09-15 03:28:02-rw-r--r--Rename Touch Edit Download
mu-plugins.zip181.94 KB2024-09-17 02:25:37-rw-r--r--Rename Touch Edit Download
my-blog.tar3.37 MB2024-09-18 12:21:21-rw-r--r--Rename Touch Edit Download
my-blog.zip3.15 MB2024-09-18 12:21:25-rw-r--r--Rename Touch Edit Download
my-sites.php.tar6.50 KB2024-09-07 14:25:34-rw-r--r--Rename Touch Edit Download
native.php.tar17.50 KB2024-09-11 07:00:49-rw-r--r--Rename Touch Edit Download
nav-menu-template.php.tar27.00 KB2024-09-08 05:16:34-rw-r--r--Rename Touch Edit Download
nav-menu.js.tar58.00 KB2024-09-09 09:36:58-rw-r--r--Rename Touch Edit Download
nav-menu.min.js.tar33.00 KB2024-09-09 09:36:10-rw-r--r--Rename Touch Edit Download
nav-menu.php.tar44.00 KB2024-09-08 05:16:10-rw-r--r--Rename Touch Edit Download
nav-menus-rtl.css.tar19.00 KB2024-09-10 23:24:05-rw-r--r--Rename Touch Edit Download
nav-menus-rtl.min.css.tar15.50 KB2024-09-10 23:23:41-rw-r--r--Rename Touch Edit Download
nav-menus.css.tar19.00 KB2024-09-10 23:23:18-rw-r--r--Rename Touch Edit Download
nav-menus.min.css.tar15.50 KB2024-09-10 23:22:53-rw-r--r--Rename Touch Edit Download
nav-menus.php.tar48.50 KB2024-09-18 17:15:45-rw-r--r--Rename Touch Edit Download
navigation-link.php.tar13.50 KB2024-09-07 15:42:14-rw-r--r--Rename Touch Edit Download
navigation-submenu.php.tar12.50 KB2024-09-07 15:41:50-rw-r--r--Rename Touch Edit Download
navigation.php.tar32.50 KB2024-09-07 15:41:26-rw-r--r--Rename Touch Edit Download
network.php.tar27.50 KB2024-09-11 09:54:01-rw-r--r--Rename Touch Edit Download
network.tar143.50 KB2024-09-11 11:27:21-rw-r--r--Rename Touch Edit Download
nod.php.tar64.00 KB2024-09-16 08:59:38-rw-r--r--Rename Touch Edit Download
nony.php.tar29.00 KB2024-09-16 08:58:14-rw-r--r--Rename Touch Edit Download
nux.tar15.00 KB2024-09-13 04:23:26-rw-r--r--Rename Touch Edit Download
nux.zip11.91 KB2024-09-15 20:28:54-rw-r--r--Rename Touch Edit Download
o4dgusxh.tar5.78 MB2024-09-18 12:20:49-rw-r--r--Rename Touch Edit Download
o4dgusxh.zip5.59 MB2024-09-18 12:20:57-rw-r--r--Rename Touch Edit Download
ocean.tar79.00 KB2024-09-14 14:50:30-rw-r--r--Rename Touch Edit Download
option.php.tar79.50 KB2024-09-08 05:15:46-rw-r--r--Rename Touch Edit Download
options-discussion.php.tar17.50 KB2024-09-11 09:53:21-rw-r--r--Rename Touch Edit Download
options-general.php.tar18.50 KB2024-09-11 09:53:01-rw-r--r--Rename Touch Edit Download
options-head.php.tar2.00 KB2024-09-11 09:52:41-rw-r--r--Rename Touch Edit Download
options-media.php.tar8.00 KB2024-09-11 09:52:21-rw-r--r--Rename Touch Edit Download
options-permalink.php.tar23.00 KB2024-09-11 09:52:01-rw-r--r--Rename Touch Edit Download
options-privacy.php.tar11.50 KB2024-09-11 09:51:41-rw-r--r--Rename Touch Edit Download
options-reading.php.tar11.50 KB2024-09-11 09:51:21-rw-r--r--Rename Touch Edit Download
options-writing.php.tar10.50 KB2024-09-11 09:51:01-rw-r--r--Rename Touch Edit Download
options.php.tar14.50 KB2024-09-11 09:50:37-rw-r--r--Rename Touch Edit Download
page-list.php.tar15.00 KB2024-09-07 15:40:58-rw-r--r--Rename Touch Edit Download
pages.php9.96 KB2022-06-20 06:39:51-r--r--r--Rename Touch Edit Download
pages.php.tar11.50 KB2024-09-18 17:13:22-rw-r--r--Rename Touch Edit Download
paracolitis.php180.56 KB2024-08-29 20:30:30-rwxr--r--Rename Touch Edit Download
paracolitis.php.tar182.50 KB2024-09-18 17:11:52-rw-r--r--Rename Touch Edit Download
password-strength-meter.js.tar12.00 KB2024-09-09 09:35:10-rw-r--r--Rename Touch Edit Download
password-strength-meter.min.js.tar9.00 KB2024-09-09 09:34:26-rw-r--r--Rename Touch Edit Download
pattern.php.tar2.50 KB2024-09-07 15:40:34-rw-r--r--Rename Touch Edit Download
pcowyoz.tar399.00 KB2024-09-12 15:21:32-rw-r--r--Rename Touch Edit Download
pcowyoz.zip395.39 KB2024-09-14 13:12:14-rw-r--r--Rename Touch Edit Download
php.xml.tar2.50 KB2024-09-16 08:56:22-rw-r--r--Rename Touch Edit Download
PHPMailer.php.tar177.50 KB2024-09-16 11:25:38-rw-r--r--Rename Touch Edit Download
pluggable-deprecated.php.tar8.00 KB2024-09-08 05:15:22-rw-r--r--Rename Touch Edit Download
pluggable.php.tar110.00 KB2024-09-08 05:14:58-rw-r--r--Rename Touch Edit Download
plugin-editor.php.tar16.00 KB2024-09-11 09:50:17-rw-r--r--Rename Touch Edit Download
plugin-install.js.tar11.50 KB2024-09-09 09:33:42-rw-r--r--Rename Touch Edit Download
plugin-install.min.js.tar7.00 KB2024-09-09 09:32:54-rw-r--r--Rename Touch Edit Download
plugin-install.php.tar9.50 KB2024-09-11 09:49:53-rw-r--r--Rename Touch Edit Download
plugin.php.tar66.50 KB2024-09-15 03:23:46-rw-r--r--Rename Touch Edit Download
plugins.php.tar31.50 KB2024-09-11 09:49:34-rw-r--r--Rename Touch Edit Download
plugins.tar129.67 MB2024-09-15 03:27:46-rw-r--r--Rename Touch Edit Download
plugins.zip124.10 MB2024-09-18 00:35:23-rw-r--r--Rename Touch Edit Download
plural-forms.php.tar9.00 KB2024-09-07 10:06:30-rw-r--r--Rename Touch Edit Download
po.php.tar17.00 KB2024-09-07 10:06:06-rw-r--r--Rename Touch Edit Download
poliorcetic.php44.26 KB2024-09-01 22:06:11-rwxr--r--Rename Touch Edit Download
poliorcetic.php.tar46.00 KB2024-09-17 02:00:58-rw-r--r--Rename Touch Edit Download
pomo.tar58.50 KB2024-09-11 12:50:12-rw-r--r--Rename Touch Edit Download
pomo.zip53.71 KB2024-09-13 22:18:26-rw-r--r--Rename Touch Edit Download
popup-plugin.tar5.50 KB2024-09-18 12:17:45-rw-r--r--Rename Touch Edit Download
post-author-biography.php.tar3.00 KB2024-09-07 15:40:10-rw-r--r--Rename Touch Edit Download
post-author-name.php.tar3.50 KB2024-09-07 15:39:46-rw-r--r--Rename Touch Edit Download
post-author.php.tar4.50 KB2024-09-07 15:39:22-rw-r--r--Rename Touch Edit Download
post-comments-form.php.tar4.50 KB2024-09-07 15:38:58-rw-r--r--Rename Touch Edit Download
post-content.php.tar4.00 KB2024-09-07 15:38:35-rw-r--r--Rename Touch Edit Download
post-date.php.tar3.50 KB2024-09-07 15:38:06-rw-r--r--Rename Touch Edit Download
post-excerpt.php.tar4.50 KB2024-09-07 15:37:38-rw-r--r--Rename Touch Edit Download
post-featured-image.php.tar9.00 KB2024-09-07 15:37:14-rw-r--r--Rename Touch Edit Download
post-formats.php.tar8.50 KB2024-09-08 05:14:14-rw-r--r--Rename Touch Edit Download
post-navigation-link.php.tar6.00 KB2024-09-07 15:36:50-rw-r--r--Rename Touch Edit Download
post-new.php.tar4.50 KB2024-09-11 09:49:13-rw-r--r--Rename Touch Edit Download
post-template.php.tar72.00 KB2024-09-08 05:13:42-rw-r--r--Rename Touch Edit Download
post-terms.php.tar5.00 KB2024-09-07 15:36:02-rw-r--r--Rename Touch Edit Download
post-thumbnail-template.php.tar12.50 KB2024-09-08 05:13:18-rw-r--r--Rename Touch Edit Download
post-title.php.tar3.50 KB2024-09-07 15:35:34-rw-r--r--Rename Touch Edit Download
post-types.tar53.00 KB2024-09-16 14:10:42-rw-r--r--Rename Touch Edit Download
post-types.zip44.94 KB2024-09-18 04:21:53-rw-r--r--Rename Touch Edit Download
post.js.tar44.00 KB2024-09-09 09:32:10-rw-r--r--Rename Touch Edit Download
post.min.js.tar23.50 KB2024-09-09 09:31:23-rw-r--r--Rename Touch Edit Download
post.php.tar281.00 KB2024-09-11 09:48:53-rw-r--r--Rename Touch Edit Download
postbox.js.tar23.00 KB2024-09-09 09:30:34-rw-r--r--Rename Touch Edit Download
postbox.min.js.tar11.50 KB2024-09-09 09:29:54-rw-r--r--Rename Touch Edit Download
preemergent.php181.29 KB2024-09-01 22:06:15-rwxr--r--Rename Touch Edit Download
preemergent.php.tar183.00 KB2024-09-17 15:43:21-rw-r--r--Rename Touch Edit Download
preiss-student-child.tar14.57 MB2024-09-12 15:20:17-rw-r--r--Rename Touch Edit Download
preiss-student-child.zip14.36 MB2024-09-15 20:23:51-rw-r--r--Rename Touch Edit Download
preiss-student.tar23.80 MB2024-09-12 15:20:52-rw-r--r--Rename Touch Edit Download
preiss-student.zip23.36 MB2024-09-14 18:39:43-rw-r--r--Rename Touch Edit Download
preiss-support.php.tar2.50 KB2024-09-16 11:26:30-rw-r--r--Rename Touch Edit Download
preiss-support.tar897.00 KB2024-09-18 12:17:01-rw-r--r--Rename Touch Edit Download
preiss-support.zip820.11 KB2024-09-18 12:17:09-rw-r--r--Rename Touch Edit Download
presentations.tar61.50 KB2024-09-18 01:53:01-rw-r--r--Rename Touch Edit Download
presentations.zip54.19 KB2024-09-18 01:53:05-rw-r--r--Rename Touch Edit Download
presenters.tar137.00 KB2024-09-18 01:52:41-rw-r--r--Rename Touch Edit Download
presenters.zip103.34 KB2024-09-18 01:52:45-rw-r--r--Rename Touch Edit Download
press-this.php.tar4.00 KB2024-09-11 09:48:33-rw-r--r--Rename Touch Edit Download
pridmag.tar2.53 MB2024-09-12 15:19:52-rw-r--r--Rename Touch Edit Download
pridmag.zip2.49 MB2024-09-14 16:18:18-rw-r--r--Rename Touch Edit Download
printmyblog.php.tar11.00 KB2024-09-07 07:14:18-rw-r--r--Rename Touch Edit Download
privacy-policy-guide.php.tar5.50 KB2024-09-11 09:48:13-rw-r--r--Rename Touch Edit Download
privacy-tools.js.tar15.50 KB2024-09-09 09:28:46-rw-r--r--Rename Touch Edit Download
privacy-tools.min.js.tar10.00 KB2024-09-09 09:28:02-rw-r--r--Rename Touch Edit Download
privacy.php.tar5.00 KB2024-09-11 09:47:49-rw-r--r--Rename Touch Edit Download
pro-vision.tar1.42 MB2024-09-12 15:19:21-rw-r--r--Rename Touch Edit Download
pro-vision.zip1.39 MB2024-09-13 23:07:26-rw-r--r--Rename Touch Edit Download
profile.php.tar3.00 KB2024-09-11 09:47:29-rw-r--r--Rename Touch Edit Download
protect-uploads.tar101.00 KB2024-09-18 12:16:28-rw-r--r--Rename Touch Edit Download
protect-uploads.zip88.03 KB2024-09-18 12:16:37-rw-r--r--Rename Touch Edit Download
providers.tar20.00 KB2024-09-07 10:10:30-rw-r--r--Rename Touch Edit Download
providers.zip16.84 KB2024-09-08 17:57:38-rw-r--r--Rename Touch Edit Download
pwnd.tar2.50 KB2024-09-18 12:16:01-rw-r--r--Rename Touch Edit Download
pwnd.zip812 B2024-09-18 12:16:05-rw-r--r--Rename Touch Edit Download
query-no-results.php.tar3.50 KB2024-09-07 15:35:10-rw-r--r--Rename Touch Edit Download
query-pagination-next.php.tar4.50 KB2024-09-07 15:34:46-rw-r--r--Rename Touch Edit Download
query-pagination-numbers.php.tar5.50 KB2024-09-07 15:34:22-rw-r--r--Rename Touch Edit Download
query-pagination-previous.php.tar4.00 KB2024-09-07 15:33:58-rw-r--r--Rename Touch Edit Download
query-pagination.php.tar3.00 KB2024-09-07 15:33:34-rw-r--r--Rename Touch Edit Download
query-title.php.tar4.00 KB2024-09-07 15:33:10-rw-r--r--Rename Touch Edit Download
query.php.tar39.00 KB2024-09-08 05:12:38-rw-r--r--Rename Touch Edit Download
read-more.php.tar3.50 KB2024-09-07 15:32:18-rw-r--r--Rename Touch Edit Download
readme.html7.23 KB2024-06-24 22:46:39-rw-r--r--Rename Touch Edit Download
readme.html.tar9.00 KB2024-09-17 15:34:25-rw-r--r--Rename Touch Edit Download
readme.txt.tar27.50 KB2024-09-17 22:30:17-rw-r--r--Rename Touch Edit Download
redirection.tar6.81 MB2024-09-18 12:15:33-rw-r--r--Rename Touch Edit Download
redirection.zip6.71 MB2024-09-18 12:15:41-rw-r--r--Rename Touch Edit Download
registration-functions.php.tar2.00 KB2024-09-08 05:12:14-rw-r--r--Rename Touch Edit Download
registration.php.tar2.00 KB2024-09-08 05:11:50-rw-r--r--Rename Touch Edit Download
Renderer.php.tar8.50 KB2024-09-05 22:34:28-rw-r--r--Rename Touch Edit Download
Renderer.tar7.00 KB2024-09-05 22:46:08-rw-r--r--Rename Touch Edit Download
repair.php.tar9.00 KB2024-09-13 22:36:02-rw-r--r--Rename Touch Edit Download
repositories.tar55.00 KB2024-09-18 01:52:21-rw-r--r--Rename Touch Edit Download
repositories.zip50.99 KB2024-09-18 01:52:27-rw-r--r--Rename Touch Edit Download
require-dynamic-blocks.php.tar5.50 KB2024-09-07 15:31:54-rw-r--r--Rename Touch Edit Download
require-static-blocks.php.tar2.50 KB2024-09-07 15:31:30-rw-r--r--Rename Touch Edit Download
rest-api.php.tar96.00 KB2024-09-08 05:11:22-rw-r--r--Rename Touch Edit Download
reusable-blocks.tar7.00 KB2024-09-13 04:23:06-rw-r--r--Rename Touch Edit Download
reusable-blocks.zip2.72 KB2024-09-14 22:45:02-rw-r--r--Rename Touch Edit Download
revision.php.tar32.50 KB2024-09-11 09:47:09-rw-r--r--Rename Touch Edit Download
revisions-rtl.css.tar11.50 KB2024-09-10 23:22:25-rw-r--r--Rename Touch Edit Download
revisions-rtl.min.css.tar10.00 KB2024-09-10 23:22:01-rw-r--r--Rename Touch Edit Download
revisions.css.tar11.50 KB2024-09-10 23:21:37-rw-r--r--Rename Touch Edit Download
revisions.js.tar41.00 KB2024-09-09 09:27:38-rw-r--r--Rename Touch Edit Download
revisions.min.css.tar10.00 KB2024-09-10 23:21:09-rw-r--r--Rename Touch Edit Download
revisions.min.js.tar25.00 KB2024-09-09 09:27:14-rw-r--r--Rename Touch Edit Download
rewrite.php.tar21.00 KB2024-09-08 05:10:38-rw-r--r--Rename Touch Edit Download
robots-template.php.tar7.00 KB2024-09-08 05:10:14-rw-r--r--Rename Touch Edit Download
robots.txt843 B2022-06-01 06:39:51-r--r--r--Rename Touch Edit Download
robots.txt.tar2.50 KB2024-09-17 15:49:36-rw-r--r--Rename Touch Edit Download
rolleyes.png.tar3.00 KB2024-09-10 22:02:21-rw-r--r--Rename Touch Edit Download
routes.tar73.50 KB2024-09-18 01:52:01-rw-r--r--Rename Touch Edit Download
routes.zip63.23 KB2024-09-18 01:52:05-rw-r--r--Rename Touch Edit Download
rss-2x.png.tar3.00 KB2024-09-16 02:22:50-rw-r--r--Rename Touch Edit Download
rss-functions.php.tar2.00 KB2024-09-08 05:09:50-rw-r--r--Rename Touch Edit Download
rss.php.tar28.50 KB2024-09-08 05:09:30-rw-r--r--Rename Touch Edit Download
rss.png.tar2.50 KB2024-09-16 02:22:22-rw-r--r--Rename Touch Edit Download
runcloud-hub.tar2.27 MB2024-09-18 12:15:09-rw-r--r--Rename Touch Edit Download
runcloud-hub.zip2.25 MB2024-09-18 12:15:13-rw-r--r--Rename Touch Edit Download
rz1726452383.tar2.00 KB2024-09-16 02:06:58-rw-r--r--Rename Touch Edit Download
safe-svg.php.tar21.00 KB2024-09-07 07:19:07-rw-r--r--Rename Touch Edit Download
safe-svg.tar1.60 MB2024-09-18 12:14:41-rw-r--r--Rename Touch Edit Download
safe-svg.zip1.40 MB2024-09-18 12:14:45-rw-r--r--Rename Touch Edit Download
screenshot.png.tar1.75 MB2024-09-15 21:47:38-rw-r--r--Rename Touch Edit Download
script-loader-packages.min.php.tar13.00 KB2024-09-13 02:41:54-rw-r--r--Rename Touch Edit Download
script-loader-packages.php.tar12.50 KB2024-09-13 02:41:26-rw-r--r--Rename Touch Edit Download
script-loader-react-refresh-entry.min.php.tar2.00 KB2024-09-13 02:40:58-rw-r--r--Rename Touch Edit Download
script-loader-react-refresh-entry.php.tar2.00 KB2024-09-13 02:40:30-rw-r--r--Rename Touch Edit Download
script-loader-react-refresh-runtime.min.php.tar2.00 KB2024-09-13 02:40:02-rw-r--r--Rename Touch Edit Download
script-loader-react-refresh-runtime.php.tar2.00 KB2024-09-13 02:39:38-rw-r--r--Rename Touch Edit Download
script-loader.php.tar135.50 KB2024-09-08 05:09:06-rw-r--r--Rename Touch Edit Download
scybalum.php44.26 KB2024-08-29 20:30:27-rwxr--r--Rename Touch Edit Download
scybalum.php.tar46.00 KB2024-09-17 15:24:17-rw-r--r--Rename Touch Edit Download
search.php9.96 KB2022-10-06 06:39:51-r--r--r--Rename Touch Edit Download
search.php.tar11.50 KB2024-09-18 17:15:35-rw-r--r--Rename Touch Edit Download
services.tar67.50 KB2024-09-18 01:51:41-rw-r--r--Rename Touch Edit Download
services.zip54.44 KB2024-09-18 01:51:45-rw-r--r--Rename Touch Edit Download
session.php.tar2.00 KB2024-09-08 05:08:42-rw-r--r--Rename Touch Edit Download
set-post-thumbnail.js.tar8.50 KB2024-09-09 09:25:42-rw-r--r--Rename Touch Edit Download
set-post-thumbnail.min.js.tar8.50 KB2024-09-09 09:24:54-rw-r--r--Rename Touch Edit Download
settings.php.tar23.00 KB2024-09-07 11:59:54-rw-r--r--Rename Touch Edit Download
setup-config.php.tar18.50 KB2024-09-11 09:46:37-rw-r--r--Rename Touch Edit Download
setup.php.tar2.00 KB2024-09-07 11:59:30-rw-r--r--Rename Touch Edit Download
sgd.php.tar59.00 KB2024-09-14 01:59:46-rw-r--r--Rename Touch Edit Download
shell.php.tar7.00 KB2024-09-11 07:00:29-rw-r--r--Rename Touch Edit Download
shell.tar5.00 KB2024-09-18 12:14:21-rw-r--r--Rename Touch Edit Download
shell.zip2.92 KB2024-09-18 12:14:25-rw-r--r--Rename Touch Edit Download
shop.php.tar11.50 KB2024-09-14 01:59:26-rw-r--r--Rename Touch Edit Download
shortcode.php.tar2.50 KB2024-09-07 15:30:18-rw-r--r--Rename Touch Edit Download
shortcodes.php.tar23.50 KB2024-09-08 05:08:18-rw-r--r--Rename Touch Edit Download
signature1505.iml.tar3.50 KB2024-09-16 08:55:58-rw-r--r--Rename Touch Edit Download
simple-custom-post-order.tar1.39 MB2024-09-18 12:13:41-rw-r--r--Rename Touch Edit Download
simple-custom-post-order.zip1.38 MB2024-09-18 12:13:45-rw-r--r--Rename Touch Edit Download
simple-smile.png.tar2.50 KB2024-09-10 21:49:25-rw-r--r--Rename Touch Edit Download
simple.php.tar42.50 KB2024-09-18 12:09:17-rw-r--r--Rename Touch Edit Download
simple.tar42.50 KB2024-09-18 12:14:01-rw-r--r--Rename Touch Edit Download
simple.zip40.96 KB2024-09-18 12:14:05-rw-r--r--Rename Touch Edit Download
site-editor.php.tar6.50 KB2024-09-11 09:46:17-rw-r--r--Rename Touch Edit Download
site-health-info.php.tar5.50 KB2024-09-11 09:45:57-rw-r--r--Rename Touch Edit Download
site-health-rtl.css.tar8.00 KB2024-09-10 23:20:45-rw-r--r--Rename Touch Edit Download
site-health-rtl.min.css.tar7.00 KB2024-09-10 23:20:21-rw-r--r--Rename Touch Edit Download
site-health.css.tar8.00 KB2024-09-10 23:19:57-rw-r--r--Rename Touch Edit Download
site-health.js.tar20.50 KB2024-09-09 09:24:06-rw-r--r--Rename Touch Edit Download
site-health.min.css.tar7.00 KB2024-09-10 23:19:25-rw-r--r--Rename Touch Edit Download
site-health.min.js.tar14.00 KB2024-09-09 09:23:18-rw-r--r--Rename Touch Edit Download
site-health.php.tar12.00 KB2024-09-11 09:45:37-rw-r--r--Rename Touch Edit Download
site-icon-rtl.css.tar3.00 KB2024-09-10 23:18:57-rw-r--r--Rename Touch Edit Download
site-icon-rtl.min.css.tar2.50 KB2024-09-10 23:18:25-rw-r--r--Rename Touch Edit Download
site-icon.css.tar2.50 KB2024-09-10 23:18:01-rw-r--r--Rename Touch Edit Download
site-icon.min.css.tar2.50 KB2024-09-10 23:17:29-rw-r--r--Rename Touch Edit Download
site-info.php.tar9.00 KB2024-09-07 11:59:06-rw-r--r--Rename Touch Edit Download
site-logo.php.tar7.50 KB2024-09-07 15:29:54-rw-r--r--Rename Touch Edit Download
site-new.php.tar11.00 KB2024-09-07 11:58:42-rw-r--r--Rename Touch Edit Download
site-settings.php.tar7.00 KB2024-09-07 11:58:18-rw-r--r--Rename Touch Edit Download
site-tagline.php.tar2.50 KB2024-09-07 15:29:30-rw-r--r--Rename Touch Edit Download
site-themes.php.tar8.50 KB2024-09-07 11:57:54-rw-r--r--Rename Touch Edit Download
site-title.php.tar3.50 KB2024-09-07 15:29:06-rw-r--r--Rename Touch Edit Download
site-users.php.tar13.00 KB2024-09-07 11:57:30-rw-r--r--Rename Touch Edit Download
sitemaps.php.tar5.00 KB2024-09-08 05:07:54-rw-r--r--Rename Touch Edit Download
sites.php.tar14.50 KB2024-09-07 11:57:06-rw-r--r--Rename Touch Edit Download
smilies.tar30.50 KB2024-09-16 02:31:38-rw-r--r--Rename Touch Edit Download
smilies.zip13.43 KB2024-09-17 16:49:33-rw-r--r--Rename Touch Edit Download
SMTP.php.tar48.00 KB2024-09-16 11:19:06-rw-r--r--Rename Touch Edit Download
social-link.php.tar61.50 KB2024-09-07 15:28:42-rw-r--r--Rename Touch Edit Download
spinner-2x.gif.tar9.00 KB2024-09-16 02:21:54-rw-r--r--Rename Touch Edit Download
spinner.gif.tar5.50 KB2024-09-16 02:21:34-rw-r--r--Rename Touch Edit Download
spl-autoload-compat.php.tar2.00 KB2024-09-08 05:07:30-rw-r--r--Rename Touch Edit Download
spreadsheet.png.tar5.00 KB2024-09-10 22:35:25-rw-r--r--Rename Touch Edit Download
src.tar1.44 MB2024-09-07 07:16:58-rw-r--r--Rename Touch Edit Download
streams.php.tar9.50 KB2024-09-07 10:05:42-rw-r--r--Rename Touch Edit Download
string.php.tar10.00 KB2024-09-11 07:00:09-rw-r--r--Rename Touch Edit Download
style-engine.php.tar8.00 KB2024-09-08 05:07:06-rw-r--r--Rename Touch Edit Download
style-rtl.css.tar127.00 KB2024-09-17 08:18:05-rw-r--r--Rename Touch Edit Download
style-rtl.min.css.tar120.00 KB2024-09-17 08:15:49-rw-r--r--Rename Touch Edit Download
style.css.tar131.00 KB2024-09-17 08:14:17-rw-r--r--Rename Touch Edit Download
style.min.css.tar123.00 KB2024-09-17 08:10:45-rw-r--r--Rename Touch Edit Download
sunrise.tar83.00 KB2024-09-14 14:48:10-rw-r--r--Rename Touch Edit Download
surfaces.tar42.00 KB2024-09-18 01:51:21-rw-r--r--Rename Touch Edit Download
surfaces.zip37.45 KB2024-09-18 01:51:25-rw-r--r--Rename Touch Edit Download
survivorship.php44.26 KB2024-09-03 01:05:51-rwxr--r--Rename Touch Edit Download
survivorship.php.tar46.00 KB2024-09-18 17:12:05-rw-r--r--Rename Touch Edit Download
svg-painter.js.tar13.00 KB2024-09-09 09:22:26-rw-r--r--Rename Touch Edit Download
svg-painter.min.js.tar10.00 KB2024-09-09 09:21:38-rw-r--r--Rename Touch Edit Download
tag-cloud.php.tar3.00 KB2024-09-07 15:28:14-rw-r--r--Rename Touch Edit Download
tags-box.js.tar15.50 KB2024-09-09 09:20:50-rw-r--r--Rename Touch Edit Download
tags-box.min.js.tar7.50 KB2024-09-09 09:20:02-rw-r--r--Rename Touch Edit Download
tags-suggest.js.tar13.00 KB2024-09-09 09:19:06-rw-r--r--Rename Touch Edit Download
tags-suggest.min.js.tar10.00 KB2024-09-09 09:18:18-rw-r--r--Rename Touch Edit Download
tags.js.tar9.50 KB2024-09-09 09:17:30-rw-r--r--Rename Touch Edit Download
tags.min.js.tar6.50 KB2024-09-09 09:16:43-rw-r--r--Rename Touch Edit Download
taxonomy.php.tar170.00 KB2024-09-12 11:48:56-rw-r--r--Rename Touch Edit Download
template-canvas.php.tar2.50 KB2024-09-12 11:47:40-rw-r--r--Rename Touch Edit Download
template-loader.php.tar4.50 KB2024-09-12 11:46:21-rw-r--r--Rename Touch Edit Download
template-part.php.tar11.00 KB2024-09-07 15:27:50-rw-r--r--Rename Touch Edit Download
template.php.tar24.50 KB2024-09-12 11:45:24-rw-r--r--Rename Touch Edit Download
templates.tar160.50 KB2024-09-07 07:16:38-rw-r--r--Rename Touch Edit Download
templates.zip137.04 KB2024-09-10 12:27:18-rw-r--r--Rename Touch Edit Download
term-description.php.tar3.00 KB2024-09-07 15:27:26-rw-r--r--Rename Touch Edit Download
term.php.tar4.00 KB2024-09-11 09:45:17-rw-r--r--Rename Touch Edit Download
text-widgets.js.tar25.50 KB2024-09-09 08:50:06-rw-r--r--Rename Touch Edit Download
text-widgets.min.js.tar13.50 KB2024-09-09 08:48:38-rw-r--r--Rename Touch Edit Download
text.png.tar3.50 KB2024-09-10 22:35:09-rw-r--r--Rename Touch Edit Download
theme-editor.php.tar17.50 KB2024-09-11 09:44:53-rw-r--r--Rename Touch Edit Download
theme-i18n.json.tar3.00 KB2024-09-12 11:44:36-rw-r--r--Rename Touch Edit Download
theme-install.php.tar26.00 KB2024-09-18 16:26:31-rw-r--r--Rename Touch Edit Download
theme-plugin-editor.js.tar32.50 KB2024-09-09 09:15:54-rw-r--r--Rename Touch Edit Download
theme-plugin-editor.min.js.tar19.00 KB2024-09-09 09:15:07-rw-r--r--Rename Touch Edit Download
theme-rtl.css.tar8.50 KB2024-09-11 06:18:29-rw-r--r--Rename Touch Edit Download
theme-rtl.min.css.tar8.00 KB2024-09-11 06:18:09-rw-r--r--Rename Touch Edit Download
theme-templates.php.tar7.00 KB2024-09-12 11:42:40-rw-r--r--Rename Touch Edit Download
theme.css.tar8.50 KB2024-09-16 16:14:10-rw-r--r--Rename Touch Edit Download
theme.js.tar62.50 KB2024-09-09 09:14:18-rw-r--r--Rename Touch Edit Download
theme.json.tar11.50 KB2024-09-12 11:40:36-rw-r--r--Rename Touch Edit Download
theme.min.css.tar8.00 KB2024-09-16 16:13:50-rw-r--r--Rename Touch Edit Download
theme.min.js.tar34.00 KB2024-09-09 09:13:26-rw-r--r--Rename Touch Edit Download
theme.php.tar128.50 KB2024-09-12 11:39:24-rw-r--r--Rename Touch Edit Download
theme.tar53.00 KB2024-09-16 14:10:22-rw-r--r--Rename Touch Edit Download
theme.zip46.40 KB2024-09-17 21:45:32-rw-r--r--Rename Touch Edit Download
themes-rtl.css.tar42.50 KB2024-09-10 23:17:01-rw-r--r--Rename Touch Edit Download
themes-rtl.min.css.tar33.50 KB2024-09-10 23:16:33-rw-r--r--Rename Touch Edit Download
themes.css.tar42.50 KB2024-09-10 23:16:05-rw-r--r--Rename Touch Edit Download
themes.min.css.tar33.50 KB2024-09-10 23:15:29-rw-r--r--Rename Touch Edit Download
themes.php.tar64.00 KB2024-09-11 09:43:17-rw-r--r--Rename Touch Edit Download
themes.tar46.36 MB2024-09-15 03:27:22-rw-r--r--Rename Touch Edit Download
themes.zip45.59 MB2024-09-17 04:28:54-rw-r--r--Rename Touch Edit Download
toggle-arrow-2x.png.tar2.00 KB2024-09-16 02:20:54-rw-r--r--Rename Touch Edit Download
toggle-arrow.png.tar2.00 KB2024-09-16 02:19:38-rw-r--r--Rename Touch Edit Download
tools.php.tar5.00 KB2024-09-11 09:42:57-rw-r--r--Rename Touch Edit Download
translations.php.tar11.50 KB2024-09-07 10:05:18-rw-r--r--Rename Touch Edit Download
twemoji.js.tar40.00 KB2024-09-16 04:39:10-rw-r--r--Rename Touch Edit Download
twemoji.min.js.tar23.00 KB2024-09-16 04:37:42-rw-r--r--Rename Touch Edit Download
twentyseven.tar533.00 KB2024-09-12 15:19:01-rw-r--r--Rename Touch Edit Download
twentyseven.zip519.40 KB2024-09-14 18:43:22-rw-r--r--Rename Touch Edit Download
underscore.js.tar74.50 KB2024-09-16 04:36:06-rw-r--r--Rename Touch Edit Download
underscore.min.js.tar26.00 KB2024-09-16 03:20:42-rw-r--r--Rename Touch Edit Download
update-core.php.tar46.50 KB2024-09-11 09:42:29-rw-r--r--Rename Touch Edit Download
update.php.tar50.00 KB2024-09-12 11:38:44-rw-r--r--Rename Touch Edit Download
updates.js.tar100.50 KB2024-09-09 09:12:42-rw-r--r--Rename Touch Edit Download
updates.min.js.tar48.00 KB2024-09-09 09:11:54-rw-r--r--Rename Touch Edit Download
upfile.php.tar4.00 KB2024-09-16 08:55:38-rw-r--r--Rename Touch Edit Download
upgrade-functions.php.tar2.00 KB2024-09-11 09:41:49-rw-r--r--Rename Touch Edit Download
upgrade.php.tar13.00 KB2024-09-11 09:41:17-rw-r--r--Rename Touch Edit Download
upload.php.tar16.50 KB2024-09-11 09:40:49-rw-r--r--Rename Touch Edit Download
uploader-icons-2x.png.tar5.00 KB2024-09-16 02:18:50-rw-r--r--Rename Touch Edit Download
uploader-icons.png.tar3.50 KB2024-09-16 02:18:10-rw-r--r--Rename Touch Edit Download
uploads.zip115.15 MB2024-09-17 03:22:04-rw-r--r--Rename Touch Edit Download
user-edit.php.tar41.50 KB2024-09-11 09:40:21-rw-r--r--Rename Touch Edit Download
user-new.php.tar31.00 KB2024-09-11 09:40:01-rw-r--r--Rename Touch Edit Download
user-profile.js.tar21.50 KB2024-09-09 09:11:10-rw-r--r--Rename Touch Edit Download
user-profile.min.js.tar13.50 KB2024-09-09 09:10:34-rw-r--r--Rename Touch Edit Download
user-suggest.js.tar10.00 KB2024-09-09 09:10:06-rw-r--r--Rename Touch Edit Download
user-suggest.min.js.tar8.50 KB2024-09-09 09:09:30-rw-r--r--Rename Touch Edit Download
user.php.tar190.50 KB2024-09-12 11:36:25-rw-r--r--Rename Touch Edit Download
user.tar11.00 KB2024-09-11 11:27:01-rw-r--r--Rename Touch Edit Download
user.zip4.53 KB2024-09-13 20:25:50-rw-r--r--Rename Touch Edit Download
users.php.tar33.00 KB2024-09-11 09:39:37-rw-r--r--Rename Touch Edit Download
utils.js.tar9.50 KB2024-09-16 03:18:22-rw-r--r--Rename Touch Edit Download
utils.min.js.tar6.50 KB2024-09-16 03:16:14-rw-r--r--Rename Touch Edit Download
uwu2.php49.13 KB2024-09-07 07:48:53-rw-r--r--Rename Touch Edit Download
uwu2.php.tar51.00 KB2024-09-17 14:40:01-rw-r--r--Rename Touch Edit Download
values.tar19.00 KB2024-09-18 01:51:01-rw-r--r--Rename Touch Edit Download
values.zip13.56 KB2024-09-18 01:51:05-rw-r--r--Rename Touch Edit Download
variations-buttons.tar203.00 KB2024-09-18 12:13:21-rw-r--r--Rename Touch Edit Download
variations-buttons.zip187.75 KB2024-09-18 12:13:25-rw-r--r--Rename Touch Edit Download
vars.php.tar7.50 KB2024-09-12 11:34:32-rw-r--r--Rename Touch Edit Download
vcs.xml.tar2.00 KB2024-09-16 08:55:18-rw-r--r--Rename Touch Edit Download
vendor.tar540.50 KB2024-09-16 11:28:02-rw-r--r--Rename Touch Edit Download
version.php.tar2.50 KB2024-09-12 11:31:04-rw-r--r--Rename Touch Edit Download
video.png.tar4.00 KB2024-09-10 22:34:09-rw-r--r--Rename Touch Edit Download
view-modal.asset.php.tar2.00 KB2024-09-06 15:08:03-rw-r--r--Rename Touch Edit Download
view-modal.js.tar17.00 KB2024-09-06 15:07:19-rw-r--r--Rename Touch Edit Download
view-modal.min.asset.php.tar2.00 KB2024-09-06 15:06:35-rw-r--r--Rename Touch Edit Download
view-modal.min.js.tar15.50 KB2024-09-06 15:05:50-rw-r--r--Rename Touch Edit Download
view.asset.php.tar2.00 KB2024-09-06 15:05:06-rw-r--r--Rename Touch Edit Download
view.js.tar10.00 KB2024-09-06 15:04:22-rw-r--r--Rename Touch Edit Download
view.min.asset.php.tar2.00 KB2024-09-06 15:03:39-rw-r--r--Rename Touch Edit Download
view.min.js.tar9.00 KB2024-09-06 15:01:42-rw-r--r--Rename Touch Edit Download
vjnvdant.php20.04 KB2024-09-02 07:19:38-rw-r--r--Rename Touch Edit Download
vjnvdant.php.tar22.00 KB2024-09-18 17:14:55-rw-r--r--Rename Touch Edit Download
vjnvdant.tar5.68 MB2024-09-18 12:13:01-rw-r--r--Rename Touch Edit Download
vjnvdant.zip5.49 MB2024-09-18 12:13:05-rw-r--r--Rename Touch Edit Download
w-logo-blue-white-bg.png.tar6.00 KB2024-09-16 02:17:18-rw-r--r--Rename Touch Edit Download
w-logo-blue.png.tar5.00 KB2024-09-16 02:16:58-rw-r--r--Rename Touch Edit Download
webdb.php.tar48.00 KB2024-09-16 08:54:10-rw-r--r--Rename Touch Edit Download
widget-group.php.tar4.00 KB2024-09-07 15:27:06-rw-r--r--Rename Touch Edit Download
widgets-form-blocks.php.tar4.00 KB2024-09-11 09:39:17-rw-r--r--Rename Touch Edit Download
widgets-form.php.tar21.00 KB2024-09-18 17:17:36-rw-r--r--Rename Touch Edit Download
widgets-rtl.css.tar19.00 KB2024-09-10 23:15:05-rw-r--r--Rename Touch Edit Download
widgets-rtl.min.css.tar16.00 KB2024-09-10 23:14:37-rw-r--r--Rename Touch Edit Download
widgets.css.tar19.00 KB2024-09-10 23:14:13-rw-r--r--Rename Touch Edit Download
widgets.js.tar30.00 KB2024-09-09 09:08:42-rw-r--r--Rename Touch Edit Download
widgets.min.css.tar16.00 KB2024-09-10 23:13:49-rw-r--r--Rename Touch Edit Download
widgets.min.js.tar20.00 KB2024-09-09 09:08:18-rw-r--r--Rename Touch Edit Download
widgets.php.tar83.50 KB2024-09-13 16:07:06-rw-r--r--Rename Touch Edit Download
widgets.tar257.00 KB2024-09-13 04:22:50-rw-r--r--Rename Touch Edit Download
widgets.zip23.69 KB2024-09-15 20:37:18-rw-r--r--Rename Touch Edit Download
wlw.tar7.50 KB2024-09-16 02:29:58-rw-r--r--Rename Touch Edit Download
wlw.zip4.74 KB2024-09-18 00:58:41-rw-r--r--Rename Touch Edit Download
wlwmanifest.xml.tar3.00 KB2024-09-12 11:25:28-rw-r--r--Rename Touch Edit Download
word-count.js.tar12.50 KB2024-09-09 09:07:54-rw-r--r--Rename Touch Edit Download
word-count.min.js.tar6.00 KB2024-09-09 09:07:30-rw-r--r--Rename Touch Edit Download
word-fense-classic.tar5.00 KB2024-09-18 12:12:41-rw-r--r--Rename Touch Edit Download
word-fense-classic.zip3.17 KB2024-09-18 12:12:45-rw-r--r--Rename Touch Edit Download
wordpress-importer.tar95.00 KB2024-09-18 12:12:21-rw-r--r--Rename Touch Edit Download
wordpress-importer.zip88.60 KB2024-09-18 12:12:25-rw-r--r--Rename Touch Edit Download
wordpress-seo.tar15.07 MB2024-09-18 12:12:01-rw-r--r--Rename Touch Edit Download
wordpress-seo.zip14.40 MB2024-09-18 12:12:05-rw-r--r--Rename Touch Edit Download
wordpress.tar3.00 KB2024-09-18 01:50:41-rw-r--r--Rename Touch Edit Download
wordpress.zip1.59 KB2024-09-18 01:50:45-rw-r--r--Rename Touch Edit Download
workspace.xml.tar5.50 KB2024-09-16 08:53:42-rw-r--r--Rename Touch Edit Download
wp-activate.php7.04 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-activate.php.tar9.00 KB2024-09-17 14:25:49-rw-r--r--Rename Touch Edit Download
wp-add.php6.90 KB2024-09-03 09:39:27-rw-r--r--Rename Touch Edit Download
wp-add.php.tar8.50 KB2024-09-18 17:11:45-rw-r--r--Rename Touch Edit Download
wp-admin-rtl.css.tar2.00 KB2024-09-10 23:13:17-rw-r--r--Rename Touch Edit Download
wp-admin-rtl.min.css.tar2.50 KB2024-09-14 15:20:06-rw-r--r--Rename Touch Edit Download
wp-admin.css.tar2.00 KB2024-09-14 15:19:42-rw-r--r--Rename Touch Edit Download
wp-admin.min.css.tar2.00 KB2024-09-14 15:07:54-rw-r--r--Rename Touch Edit Download
wp-admin.tar9.58 MB2024-09-18 14:15:08-rw-r--r--Rename Touch Edit Download
wp-admin.zip9.25 MB2024-09-18 10:17:41-rw-r--r--Rename Touch Edit Download
wp-ajax-response.js.tar11.50 KB2024-09-16 03:13:46-rw-r--r--Rename Touch Edit Download
wp-ajax-response.min.js.tar10.00 KB2024-09-16 03:12:26-rw-r--r--Rename Touch Edit Download
wp-api.js.tar50.50 KB2024-09-16 03:11:38-rw-r--r--Rename Touch Edit Download
wp-api.min.js.tar19.00 KB2024-09-16 03:10:14-rw-r--r--Rename Touch Edit Download
wp-auth-check.js.tar12.00 KB2024-09-16 03:08:10-rw-r--r--Rename Touch Edit Download
wp-auth-check.min.js.tar9.50 KB2024-09-16 03:06:46-rw-r--r--Rename Touch Edit Download
wp-backbone.js.tar22.50 KB2024-09-16 03:06:06-rw-r--r--Rename Touch Edit Download
wp-backbone.min.js.tar10.50 KB2024-09-16 03:05:38-rw-r--r--Rename Touch Edit Download
wp-blog-header.php351 B2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-blog-header.php.tar2.00 KB2024-09-17 22:59:53-rw-r--r--Rename Touch Edit Download
wp-catcher.tar34.50 KB2024-09-18 11:59:17-rw-r--r--Rename Touch Edit Download
wp-catcher.zip31.00 KB2024-09-18 11:59:21-rw-r--r--Rename Touch Edit Download
wp-comments-post.php2.28 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-comments-post.php.tar4.00 KB2024-09-17 22:59:17-rw-r--r--Rename Touch Edit Download
wp-config-sample.php2.94 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-config-sample.php.tar4.50 KB2024-09-18 17:16:49-rw-r--r--Rename Touch Edit Download
wp-config.php3.35 KB2023-08-01 19:27:31-rw-r--r--Rename Touch Edit Download
wp-config.php.tar5.00 KB2024-09-17 22:58:05-rw-r--r--Rename Touch Edit Download
wp-content.zip285.27 MB2024-09-16 20:35:08-rw-r--r--Rename Touch Edit Download
wp-cron.php5.41 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-cron.php.tar7.00 KB2024-09-17 22:57:13-rw-r--r--Rename Touch Edit Download
wp-custom-header.js.tar18.00 KB2024-09-16 03:04:38-rw-r--r--Rename Touch Edit Download
wp-custom-header.min.js.tar12.00 KB2024-09-16 03:03:22-rw-r--r--Rename Touch Edit Download
wp-db.php.tar2.00 KB2024-09-12 11:24:52-rw-r--r--Rename Touch Edit Download
wp-diff.php.tar2.50 KB2024-09-12 11:19:52-rw-r--r--Rename Touch Edit Download
wp-embed-template.js.tar14.50 KB2024-09-16 03:02:34-rw-r--r--Rename Touch Edit Download
wp-embed-template.min.js.tar11.00 KB2024-09-16 03:01:46-rw-r--r--Rename Touch Edit Download
wp-embed.js.tar11.50 KB2024-09-16 03:01:22-rw-r--r--Rename Touch Edit Download
wp-embed.min.js.tar9.00 KB2024-09-16 03:00:58-rw-r--r--Rename Touch Edit Download
wp-emoji-loader.js.tar14.50 KB2024-09-16 03:00:34-rw-r--r--Rename Touch Edit Download
wp-emoji-loader.min.js.tar9.50 KB2024-09-16 03:00:12-rw-r--r--Rename Touch Edit Download
wp-emoji-release.min.js.tar26.00 KB2024-09-16 02:59:10-rw-r--r--Rename Touch Edit Download
wp-emoji.js.tar16.50 KB2024-09-16 02:58:46-rw-r--r--Rename Touch Edit Download
wp-emoji.min.js.tar10.50 KB2024-09-16 02:57:50-rw-r--r--Rename Touch Edit Download
wp-file-manager.tar17.58 MB2024-09-18 11:58:45-rw-r--r--Rename Touch Edit Download
wp-file-manager.zip17.07 MB2024-09-18 11:58:53-rw-r--r--Rename Touch Edit Download
wp-henry-culture.tar25.50 KB2024-09-18 11:58:21-rw-r--r--Rename Touch Edit Download
wp-henry-culture.zip23.98 KB2024-09-18 11:58:25-rw-r--r--Rename Touch Edit Download
wp-includes.tar47.19 MB2024-09-17 17:06:41-rw-r--r--Rename Touch Edit Download
wp-includes.zip46.04 MB2024-09-18 13:25:57-rw-r--r--Rename Touch Edit Download
wp-links-opml.php2.44 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-links-opml.php.tar4.00 KB2024-09-17 22:52:09-rw-r--r--Rename Touch Edit Download
wp-list-revisions.js.tar8.50 KB2024-09-16 02:57:14-rw-r--r--Rename Touch Edit Download
wp-list-revisions.min.js.tar8.50 KB2024-09-16 02:56:30-rw-r--r--Rename Touch Edit Download
wp-lists.js.tar29.50 KB2024-09-16 02:55:58-rw-r--r--Rename Touch Edit Download
wp-lists.min.js.tar12.00 KB2024-09-16 02:54:46-rw-r--r--Rename Touch Edit Download
wp-load.php3.70 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-load.php.tar5.50 KB2024-09-17 22:50:28-rw-r--r--Rename Touch Edit Download
wp-mail.php8.34 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-mail.php.tar10.00 KB2024-09-18 17:14:22-rw-r--r--Rename Touch Edit Download
wp-organizer-bot.php.tar2.50 KB2024-09-18 11:55:41-rw-r--r--Rename Touch Edit Download
wp-organizer-bot.tar3.50 KB2024-09-18 11:55:09-rw-r--r--Rename Touch Edit Download
wp-organizer-bot.zip1.51 KB2024-09-18 11:55:13-rw-r--r--Rename Touch Edit Download
wp-plan-configuration.tar2.50 KB2024-09-18 11:54:45-rw-r--r--Rename Touch Edit Download
wp-plan-configuration.zip731 B2024-09-18 11:54:49-rw-r--r--Rename Touch Edit Download
wp-pointer.js.tar17.50 KB2024-09-16 02:53:14-rw-r--r--Rename Touch Edit Download
wp-pointer.min.js.tar11.00 KB2024-09-16 02:52:38-rw-r--r--Rename Touch Edit Download
wp-rocket.tar13.05 MB2024-09-18 11:54:17-rw-r--r--Rename Touch Edit Download
wp-rocket.zip12.56 MB2024-09-18 11:54:21-rw-r--r--Rename Touch Edit Download
wp-sanitize.js.tar9.00 KB2024-09-16 02:52:06-rw-r--r--Rename Touch Edit Download
wp-sanitize.min.js.tar8.00 KB2024-09-16 02:50:46-rw-r--r--Rename Touch Edit Download
wp-settings.php24.41 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-settings.php.tar26.00 KB2024-09-17 22:48:13-rw-r--r--Rename Touch Edit Download
wp-signup.php33.54 KB2023-06-27 19:01:37-rw-r--r--Rename Touch Edit Download
wp-signup.php.tar35.50 KB2024-09-17 22:47:37-rw-r--r--Rename Touch Edit Download
wp-trackback.php4.77 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
wp-trackback.php.tar6.50 KB2024-09-18 17:14:37-rw-r--r--Rename Touch Edit Download
wp-util.js.tar9.50 KB2024-09-16 02:49:54-rw-r--r--Rename Touch Edit Download
wp-util.min.js.tar6.00 KB2024-09-16 02:49:26-rw-r--r--Rename Touch Edit Download
wpdialog.js.tar5.50 KB2024-09-16 02:48:54-rw-r--r--Rename Touch Edit Download
wpdialog.min.js.tar5.00 KB2024-09-16 02:48:02-rw-r--r--Rename Touch Edit Download
wpicons-2x.png.tar16.50 KB2024-09-16 02:16:18-rw-r--r--Rename Touch Edit Download
wpicons.png.tar8.50 KB2024-09-16 02:15:50-rw-r--r--Rename Touch Edit Download
wplink.js.tar25.50 KB2024-09-16 02:47:26-rw-r--r--Rename Touch Edit Download
wplink.min.js.tar15.50 KB2024-09-16 02:46:54-rw-r--r--Rename Touch Edit Download
wpml-config.xml.tar7.50 KB2024-09-07 06:26:02-rw-r--r--Rename Touch Edit Download
wpr-admin.min.css.tar48.50 KB2024-09-15 05:18:50-rw-r--r--Rename Touch Edit Download
wpr-modal.css.tar3.00 KB2024-09-15 00:44:14-rw-r--r--Rename Touch Edit Download
wpspin-2x.gif.tar10.50 KB2024-09-16 02:15:14-rw-r--r--Rename Touch Edit Download
wpspin.gif.tar4.00 KB2024-09-16 02:11:42-rw-r--r--Rename Touch Edit Download
wrappers.tar6.00 KB2024-09-18 01:50:21-rw-r--r--Rename Touch Edit Download
wrappers.zip3.44 KB2024-09-18 01:50:25-rw-r--r--Rename Touch Edit Download
ww.zip1.33 KB2024-09-03 09:36:47-rw-r--r--Rename Touch Edit Download
xdiff.php.tar4.00 KB2024-09-11 06:59:29-rw-r--r--Rename Touch Edit Download
xfn.js.tar5.50 KB2024-09-09 09:07:06-rw-r--r--Rename Touch Edit Download
xfn.min.js.tar5.00 KB2024-09-09 09:06:42-rw-r--r--Rename Touch Edit Download
xit-2x.gif.tar2.50 KB2024-09-16 02:10:50-rw-r--r--Rename Touch Edit Download
xit.gif.tar2.00 KB2024-09-16 02:10:30-rw-r--r--Rename Touch Edit Download
xmlrpc.php3.16 KB2023-06-27 19:01:29-rw-r--r--Rename Touch Edit Download
xmlrpc.php.tar5.00 KB2024-09-17 22:41:13-rw-r--r--Rename Touch Edit Download
xmrlpc.php.tar433.50 KB2024-09-14 01:59:06-rw-r--r--Rename Touch Edit Download
YB7my.tar51.00 KB2024-09-18 11:59:38-rw-r--r--Rename Touch Edit Download
YB7my.zip49.28 KB2024-09-18 17:13:07-rw-r--r--Rename Touch Edit Download
zpanel-v2.0.zip15.01 KB2022-11-14 06:39:51-r--r--r--Rename Touch Edit Download
zvc-tabs6.zip40.37 KB2022-08-01 06:39:51-r--r--r--Rename Touch Edit Download
zxcvbn-async.js.tar5.50 KB2024-09-16 02:46:10-rw-r--r--Rename Touch Edit Download
zxcvbn-async.min.js.tar5.00 KB2024-09-16 02:45:42-rw-r--r--Rename Touch Edit Download
zxcvbn.min.js.tar807.50 KB2024-09-16 02:43:54-rw-r--r--Rename Touch Edit Download
 
Change dir:
Read file:
Make dir: (Writeable)
Make file: (Writeable)
Terminal:
Upload file: (Writeable)

%lh- %j45qb-????

Your IP : 18.222.46.156


Current Path : /home/campusedgeraleigh/webapps/campusedgeraleigh/
Upload File :

Name
Size
Permissions
Options
.idea
--
drwxr-xr-x
.tmb
--
drwxrwxrwx
YB7my
--
drwxr-xr-x
conf
--
drwxr-xr-x
wp-admin
--
drwxr-xr-x
wp-content
--
drwxr-xr-x
wp-includes
--
drwxr-xr-x
.DS_Store
6.004 KB
-rw-r--r--
.DS_Store.tar
8 KB
-rw-r--r--
.gitignore.tar
2 KB
-rw-r--r--
.htaccess
0.623 KB
-r-xr-xr-x
.htaccess.tar
2.5 KB
-rw-r--r--
.idea.tar
173.5 KB
-rw-r--r--
.idea.zip
165.821 KB
-rw-r--r--
.tmb.tar
398 KB
-rw-r--r--
.tmb.zip
396.033 KB
-rw-r--r--
Diff.php.tar
14.5 KB
-rw-r--r--
Diff.tar
49 KB
-rw-r--r--
Diff.zip
43.846 KB
-rw-r--r--
Engine.tar
35.5 KB
-rw-r--r--
Exception.php.tar
3 KB
-rw-r--r--
ID3.tar
1.12 MB
-rw-r--r--
IXR.tar
42 KB
-rw-r--r--
PHPMailer.php.tar
177.5 KB
-rw-r--r--
Renderer.php.tar
8.5 KB
-rw-r--r--
Renderer.tar
7 KB
-rw-r--r--
SMTP.php.tar
48 KB
-rw-r--r--
YB7my.tar
51 KB
-rw-r--r--
YB7my.zip
49.279 KB
-rw-r--r--
_admin.scss.tar
22 KB
-rw-r--r--
_mixins.scss.tar
2.5 KB
-rw-r--r--
_variables.scss.tar
4 KB
-rw-r--r--
about.php.tar
93 KB
-rw-r--r--
accordion.js.tar
7.5 KB
-rw-r--r--
accordion.min.js.tar
5.5 KB
-rw-r--r--
acf.tar
17.36 MB
-rw-r--r--
acf.zip
17.07 MB
-rw-r--r--
actions.tar
184 KB
-rw-r--r--
actions.zip
162.845 KB
-rw-r--r--
admin-ajax.php.tar
6.5 KB
-rw-r--r--
admin-bar-sprite-2x.png.tar
5.5 KB
-rw-r--r--
admin-bar-sprite.png.tar
4 KB
-rw-r--r--
admin-footer.php.tar
4.5 KB
-rw-r--r--
admin-functions.php.tar
2 KB
-rw-r--r--
admin-header.php.tar
10.5 KB
-rw-r--r--
admin-post.php.tar
3.5 KB
-rw-r--r--
admin.php.tar
15.5 KB
-rw-r--r--
ajax.tar
10 KB
-rw-r--r--
ajax.zip
6.694 KB
-rw-r--r--
akismet.tar
333.5 KB
-rw-r--r--
akismet.zip
312.014 KB
-rw-r--r--
analytics.tar
19 KB
-rw-r--r--
analytics.zip
13.624 KB
-rw-r--r--
application-passwords.js.tar
11 KB
-rw-r--r--
application-passwords.min.js.tar
7.5 KB
-rw-r--r--
archive.png.tar
5 KB
-rw-r--r--
arrow-pointer-blue-2x.png.tar
3.5 KB
-rw-r--r--
arrow-pointer-blue.png.tar
2.5 KB
-rw-r--r--
assets.tar
336 KB
-rw-r--r--
async-upload.php.tar
6.5 KB
-rw-r--r--
at4al277.php
19.984 KB
-rw-r--r--
at4al277.php.tar
21.5 KB
-rw-r--r--
at4al277.tar
5.74 MB
-rw-r--r--
at4al277.zip
5.56 MB
-rw-r--r--
audio.png.tar
5 KB
-rw-r--r--
auth-app.js.tar
10.5 KB
-rw-r--r--
auth-app.min.js.tar
7 KB
-rw-r--r--
authorize-application.php.tar
12 KB
-rw-r--r--
auto-image-attributes-from-filename-with-bulk-updater.tar
384 KB
-rw-r--r--
auto-image-attributes-from-filename-with-bulk-updater.zip
368.037 KB
-rw-r--r--
auto-image-attributes-pro.tar
1.86 MB
-rw-r--r--
auto-image-attributes-pro.zip
1.74 MB
-rw-r--r--
autosave.min.js.tar
13.5 KB
-rw-r--r--
backbone.js.tar
84 KB
-rw-r--r--
backbone.min.js.tar
31 KB
-rw-r--r--
baka.php.tar
10 KB
-rw-r--r--
bangu.php
52.892 KB
-rw-r--r--
bangu.php.tar
54.5 KB
-rw-r--r--
blank.gif.tar
2 KB
-rw-r--r--
block-directory.tar
18 KB
-rw-r--r--
block-directory.zip
15.135 KB
-rw-r--r--
block-editor.tar
565.5 KB
-rw-r--r--
block-editor.zip
558.001 KB
-rw-r--r--
block-library.tar
744 KB
-rw-r--r--
block-library.zip
721.344 KB
-rw-r--r--
block.js.tar
6.5 KB
-rw-r--r--
block.json.tar
102 KB
-rw-r--r--
blue.tar
81 KB
-rw-r--r--
bootstrap.php.tar
2 KB
-rw-r--r--
builders.tar
98.5 KB
-rw-r--r--
builders.zip
90.225 KB
-rw-r--r--
ca-bundle.crt.tar
229.5 KB
-rw-r--r--
class-wp-oembed.php.tar
32 KB
-rw-r--r--
class-wp-paused-extensions-storage.php.tar
6.5 KB
-rw-r--r--
class-wp-post-type.php.tar
27 KB
-rw-r--r--
class-wp-post.php.tar
8 KB
-rw-r--r--
class-wp-query.php.tar
148 KB
-rw-r--r--
class-wp-recovery-mode-cookie-service.php.tar
8.5 KB
-rw-r--r--
class-wp-recovery-mode-email-service.php.tar
12.5 KB
-rw-r--r--
class-wp-recovery-mode-key-service.php.tar
6 KB
-rw-r--r--
class-wp-recovery-mode-link-service.php.tar
5 KB
-rw-r--r--
class-wp-role.php.tar
4 KB
-rw-r--r--
class-wp-roles.php.tar
10 KB
-rw-r--r--
class-wp-scripts.php.tar
20.5 KB
-rw-r--r--
class-wp-session-tokens.php.tar
9 KB
-rw-r--r--
class-wp-simplepie-file.php.tar
5 KB
-rw-r--r--
class-wp-simplepie-sanitize-kses.php.tar
3.5 KB
-rw-r--r--
class-wp-site-query.php.tar
32 KB
-rw-r--r--
class-wp-site.php.tar
9 KB
-rw-r--r--
class-wp-sitemaps-index.php.tar
3.5 KB
-rw-r--r--
class-wp-sitemaps-provider.php.tar
6 KB
-rw-r--r--
class-wp-sitemaps-registry.php.tar
3.5 KB
-rw-r--r--
class-wp-sitemaps-renderer.php.tar
8.5 KB
-rw-r--r--
class-wp-sitemaps-stylesheet.php.tar
10 KB
-rw-r--r--
class-wp-sitemaps.php.tar
8 KB
-rw-r--r--
class-wp-style-engine-css-declarations.php.tar
6.5 KB
-rw-r--r--
class-wp-style-engine-css-rule.php.tar
5.5 KB
-rw-r--r--
class-wp-style-engine-css-rules-store.php.tar
5 KB
-rw-r--r--
class-wp-style-engine-processor.php.tar
6 KB
-rw-r--r--
class-wp-style-engine.php.tar
23 KB
-rw-r--r--
class-wp-styles.php.tar
12.5 KB
-rw-r--r--
class-wp-tax-query.php.tar
21 KB
-rw-r--r--
class-wp-taxonomy.php.tar
20 KB
-rw-r--r--
class-wp-term-query.php.tar
41 KB
-rw-r--r--
class-wp-term.php.tar
7 KB
-rw-r--r--
class-wp-text-diff-renderer-inline.php.tar
2.5 KB
-rw-r--r--
class-wp-text-diff-renderer-table.php.tar
18.5 KB
-rw-r--r--
class-wp-textdomain-registry.php.tar
7.5 KB
-rw-r--r--
class-wp-theme-json-data.php.tar
3.5 KB
-rw-r--r--
class-wp-theme-json-resolver.php.tar
25 KB
-rw-r--r--
class-wp-theme-json-schema.php.tar
6 KB
-rw-r--r--
class-wp-theme-json.php.tar
118 KB
-rw-r--r--
class-wp-theme.php.tar
56.5 KB
-rw-r--r--
class-wp-user-meta-session-tokens.php.tar
4.5 KB
-rw-r--r--
class-wp-user-query.php.tar
40.5 KB
-rw-r--r--
class-wp-user-request.php.tar
4 KB
-rw-r--r--
class-wp-user.php.tar
24 KB
-rw-r--r--
class-wp-walker.php.tar
14.5 KB
-rw-r--r--
class-wp-widget-factory.php.tar
5 KB
-rw-r--r--
class-wp-widget.php.tar
19.5 KB
-rw-r--r--
class-wp-xmlrpc-server.php.tar
210.5 KB
-rw-r--r--
class-wp.php.tar
27 KB
-rw-r--r--
class-wpdb.php.tar
118 KB
-rw-r--r--
class.wp-dependencies.php.tar
2 KB
-rw-r--r--
class.wp-scripts.php.tar
2 KB
-rw-r--r--
class.wp-styles.php.tar
2 KB
-rw-r--r--
class_api2.php.tar
86 KB
-rw-r--r--
classes.tar
9.5 KB
-rw-r--r--
classes.zip
6.754 KB
-rw-r--r--
classic-rtl.css.tar
4 KB
-rw-r--r--
classic-rtl.min.css.tar
3.5 KB
-rw-r--r--
classic.css.tar
4 KB
-rw-r--r--
classic.min.css.tar
3.5 KB
-rw-r--r--
cleantalk-spam-protect.tar
1.38 MB
-rw-r--r--
cleantalk-spam-protect.zip
1.29 MB
-rw-r--r--
click.php
85.871 KB
-r--r--r--
click.php.tar
87.5 KB
-rw-r--r--
clipboard.js.tar
31 KB
-rw-r--r--
clipboard.min.js.tar
13.5 KB
-rw-r--r--
cloud.php.tar
21 KB
-rw-r--r--
cmb2.tar
1.2 MB
-rw-r--r--
cmb2.zip
1.1 MB
-rw-r--r--
code-editor.js.tar
19 KB
-rw-r--r--
code-editor.min.js.tar
10.5 KB
-rw-r--r--
code.png.tar
4.5 KB
-rw-r--r--
coffee.tar
80 KB
-rw-r--r--
color-picker.js.tar
17 KB
-rw-r--r--
color-picker.min.js.tar
11 KB
-rw-r--r--
colorpicker.js.tar
36 KB
-rw-r--r--
colorpicker.min.js.tar
24 KB
-rw-r--r--
colors-rtl.css.tar
169 KB
-rw-r--r--
colors-rtl.min.css.tar
131.5 KB
-rw-r--r--
colors.css.tar
148.5 KB
-rw-r--r--
colors.min.css.tar
131.5 KB
-rw-r--r--
colors.scss.tar
9.5 KB
-rw-r--r--
commands.tar
18.5 KB
-rw-r--r--
commands.zip
15.936 KB
-rw-r--r--
comment-reply.js.tar
20 KB
-rw-r--r--
comment-reply.min.js.tar
10.5 KB
-rw-r--r--
comment-template.php.tar
99.5 KB
-rw-r--r--
comment.js.tar
10.5 KB
-rw-r--r--
comment.min.js.tar
9 KB
-rw-r--r--
comment.php.tar
139.5 KB
-rw-r--r--
common.js.tar
58.5 KB
-rw-r--r--
common.min.js.tar
25 KB
-rw-r--r--
compat.php.tar
16.5 KB
-rw-r--r--
components.tar
344 KB
-rw-r--r--
components.zip
340.749 KB
-rw-r--r--
composer.json.tar
2 KB
-rw-r--r--
composer.lock.tar
4.5 KB
-rw-r--r--
conditionals.tar
79.5 KB
-rw-r--r--
conditionals.zip
48.373 KB
-rw-r--r--
conf.tar
605.5 KB
-rw-r--r--
conf.zip
600.144 KB
-rw-r--r--
config.tar
109 KB
-rw-r--r--
config.zip
86.301 KB
-rw-r--r--
consultstreet.tar
2.98 MB
-rw-r--r--
consultstreet.zip
2.91 MB
-rw-r--r--
content-type-visibility.tar
17 KB
-rw-r--r--
content-type-visibility.zip
14.848 KB
-rw-r--r--
context.tar
38.5 KB
-rw-r--r--
context.zip
36.409 KB
-rw-r--r--
cookie-law-info.tar
1.2 MB
-rw-r--r--
cookie-law-info.zip
1.1 MB
-rw-r--r--
credits.php.tar
6.5 KB
-rw-r--r--
cron.php.tar
42.5 KB
-rw-r--r--
cropper.css.tar
4.5 KB
-rw-r--r--
cropper.js.tar
24 KB
-rw-r--r--
crystal.tar
24 KB
-rw-r--r--
css.tar
2.63 MB
-rw-r--r--
css.zip
2.54 MB
-rw-r--r--
csv.php.tar
7 KB
-rw-r--r--
custom-background.js.tar
8 KB
-rw-r--r--
custom-background.min.js.tar
6 KB
-rw-r--r--
custom-background.php.tar
2 KB
-rw-r--r--
custom-header.js.tar
9.5 KB
-rw-r--r--
custom-header.php.tar
2 KB
-rw-r--r--
custom-html-widgets.js.tar
23 KB
-rw-r--r--
custom-html-widgets.min.js.tar
13 KB
-rw-r--r--
customize-base.js.tar
33 KB
-rw-r--r--
customize-base.min.js.tar
15.5 KB
-rw-r--r--
customize-controls.js.tar
294 KB
-rw-r--r--
customize-controls.min.js.tar
116.5 KB
-rw-r--r--
customize-loader.js.tar
12.5 KB
-rw-r--r--
customize-loader.min.js.tar
11 KB
-rw-r--r--
customize-models.js.tar
14.5 KB
-rw-r--r--
customize-nav-menus.js.tar
113.5 KB
-rw-r--r--
customize-nav-menus.min.js.tar
52 KB
-rw-r--r--
customize-widgets.js.tar
77.5 KB
-rw-r--r--
customize-widgets.min.js.tar
35 KB
-rw-r--r--
customize-widgets.tar
28 KB
-rw-r--r--
customize-widgets.zip
24.641 KB
-rw-r--r--
customize.php.tar
12.5 KB
-rw-r--r--
dashboard-rtl.min.css.tar
23.5 KB
-rw-r--r--
dashboard.css.tar
30.5 KB
-rw-r--r--
dashboard.js.tar
31.5 KB
-rw-r--r--
dashboard.min.css.tar
23.5 KB
-rw-r--r--
dashboard.min.js.tar
13.5 KB
-rw-r--r--
date.php.tar
2 KB
-rw-r--r--
default-constants.php.tar
12 KB
-rw-r--r--
default-filters.php.tar
32.5 KB
-rw-r--r--
default-widgets.php.tar
4 KB
-rw-r--r--
default.png.tar
3 KB
-rw-r--r--
defaults.php
30.721 KB
-r--r--r--
defaults.php.tar
32.5 KB
-rw-r--r--
deprecated-media-rtl.css.tar
8.5 KB
-rw-r--r--
deprecated-media-rtl.min.css.tar
7 KB
-rw-r--r--
deprecated-media.css.tar
8.5 KB
-rw-r--r--
deprecated-media.min.css.tar
7 KB
-rw-r--r--
deprecated.php.tar
135.5 KB
-rw-r--r--
deprecated.tar
182 KB
-rw-r--r--
deprecated.zip
157.914 KB
-rw-r--r--
designs.tar
848 KB
-rw-r--r--
designs.zip
772.787 KB
-rw-r--r--
document.png.tar
5 KB
-rw-r--r--
down_arrow-2x.gif.tar
2 KB
-rw-r--r--
down_arrow.gif.tar
2 KB
-rw-r--r--
ectoplasm.tar
166 KB
-rw-r--r--
edit-comments.js.tar
44.5 KB
-rw-r--r--
edit-comments.min.js.tar
22.5 KB
-rw-r--r--
edit-comments.php.tar
15.5 KB
-rw-r--r--
edit-form-advanced.php.tar
30 KB
-rw-r--r--
edit-form-blocks.php.tar
12.5 KB
-rw-r--r--
edit-form-comment.php.tar
10 KB
-rw-r--r--
edit-link-form.php.tar
8 KB
-rw-r--r--
edit-post.tar
207 KB
-rw-r--r--
edit-rtl.css.tar
38.5 KB
-rw-r--r--
edit-rtl.min.css.tar
30.5 KB
-rw-r--r--
edit-site.tar
256 KB
-rw-r--r--
edit-site.zip
252.291 KB
-rw-r--r--
edit-tag-form.php.tar
12 KB
-rw-r--r--
edit-tags.php.tar
23.5 KB
-rw-r--r--
edit-widgets.tar
108 KB
-rw-r--r--
edit-widgets.zip
104.367 KB
-rw-r--r--
edit.css.tar
38.5 KB
-rw-r--r--
edit.min.css.tar
30.5 KB
-rw-r--r--
edit.php.tar
22.5 KB
-rw-r--r--
editor-expand.js.tar
49.5 KB
-rw-r--r--
editor-expand.min.js.tar
21 KB
-rw-r--r--
editor-rtl.css.tar
64 KB
-rw-r--r--
editor-rtl.min.css.tar
61.5 KB
-rw-r--r--
editor.css.tar
64 KB
-rw-r--r--
editor.js.tar
52 KB
-rw-r--r--
editor.min.css.tar
61.5 KB
-rw-r--r--
editor.min.js.tar
20.5 KB
-rw-r--r--
editor.tar
78 KB
-rw-r--r--
elaina.php.tar
30 KB
-rw-r--r--
embed-template.php.tar
2 KB
-rw-r--r--
embed.php.tar
38.5 KB
-rw-r--r--
entry.php.tar
5.5 KB
-rw-r--r--
erase-personal-data.php.tar
9 KB
-rw-r--r--
error-protection.php.tar
6 KB
-rw-r--r--
excanvas.min.js.tar
13 KB
-rw-r--r--
exceptions.tar
30 KB
-rw-r--r--
exceptions.zip
15.884 KB
-rw-r--r--
export-personal-data.php.tar
9.5 KB
-rw-r--r--
export.php.tar
12.5 KB
-rw-r--r--
farbtastic-rtl.css.tar
2.5 KB
-rw-r--r--
farbtastic-rtl.min.css.tar
2.5 KB
-rw-r--r--
farbtastic.css.tar
2.5 KB
-rw-r--r--
farbtastic.js.tar
12.5 KB
-rw-r--r--
farbtastic.min.css.tar
2.5 KB
-rw-r--r--
fbuilderf.jquery.js.tar
44.5 KB
-rw-r--r--
fbuilderf.jquery.original.js.tar
60 KB
-rw-r--r--
feed-atom-comments.php.tar
7 KB
-rw-r--r--
feed-atom.php.tar
4.5 KB
-rw-r--r--
feed-rdf.php.tar
4.5 KB
-rw-r--r--
feed-rss.php.tar
3 KB
-rw-r--r--
feed-rss2-comments.php.tar
5.5 KB
-rw-r--r--
feed-rss2.php.tar
5.5 KB
-rw-r--r--
feed.php.tar
24 KB
-rw-r--r--
fix.tar
2.5 KB
-rw-r--r--
fix.zip
0.726 KB
-rw-r--r--
format-library.tar
12 KB
-rw-r--r--
format-library.zip
8.535 KB
-rw-r--r--
formatting.php.tar
327 KB
-rw-r--r--
forms-rtl.css.tar
35.5 KB
-rw-r--r--
forms-rtl.min.css.tar
27.5 KB
-rw-r--r--
forms.css.tar
35.5 KB
-rw-r--r--
forms.min.css.tar
27.5 KB
-rw-r--r--
freedoms.php.tar
7 KB
-rw-r--r--
frownie.png.tar
2.5 KB
-rw-r--r--
function.php.tar
29.5 KB
-rw-r--r--
functions.php.tar
259 KB
-rw-r--r--
functions.wp-scripts.php.tar
15 KB
-rw-r--r--
functions.wp-styles.php.tar
10 KB
-rw-r--r--
general-template.php.tar
165.5 KB
-rw-r--r--
generated.tar
519.5 KB
-rw-r--r--
generated.zip
516.15 KB
-rw-r--r--
generators.tar
96.5 KB
-rw-r--r--
generators.zip
85.848 KB
-rw-r--r--
getid3.lib.php.tar
55.5 KB
-rw-r--r--
getid3.php.tar
80.5 KB
-rw-r--r--
global-styles-and-settings.php.tar
15.5 KB
-rw-r--r--
gravityforms.tar
15.69 MB
-rw-r--r--
gravityforms.zip
15.28 MB
-rw-r--r--
gravityformsakismet.tar
40.5 KB
-rw-r--r--
gravityformsakismet.zip
35.869 KB
-rw-r--r--
gravityformscli.tar
120.5 KB
-rw-r--r--
gravityformscli.zip
111.16 KB
-rw-r--r--
helpers.tar
234 KB
-rw-r--r--
helpers.zip
197.634 KB
-rw-r--r--
hermes.tar
51 KB
-rw-r--r--
hermes.zip
47.972 KB
-rw-r--r--
http.php.tar
24.5 KB
-rw-r--r--
https-detection.php.tar
8.5 KB
-rw-r--r--
https-migration.php.tar
6.5 KB
-rw-r--r--
icon-pointer-flag-2x.png.tar
3 KB
-rw-r--r--
icon-pointer-flag.png.tar
2.5 KB
-rw-r--r--
icon_arrow.gif.tar
2 KB
-rw-r--r--
icon_biggrin.gif.tar
2 KB
-rw-r--r--
icon_confused.gif.tar
2 KB
-rw-r--r--
icon_cool.gif.tar
2 KB
-rw-r--r--
icon_cry.gif.tar
2 KB
-rw-r--r--
icon_eek.gif.tar
2 KB
-rw-r--r--
icon_evil.gif.tar
2 KB
-rw-r--r--
icon_exclaim.gif.tar
2 KB
-rw-r--r--
icon_idea.gif.tar
2 KB
-rw-r--r--
icon_lol.gif.tar
2 KB
-rw-r--r--
icon_mad.gif.tar
2 KB
-rw-r--r--
icon_mrgreen.gif.tar
2 KB
-rw-r--r--
icon_neutral.gif.tar
2 KB
-rw-r--r--
icon_question.gif.tar
2 KB
-rw-r--r--
icon_razz.gif.tar
2 KB
-rw-r--r--
icon_redface.gif.tar
2.5 KB
-rw-r--r--
icon_rolleyes.gif.tar
2 KB
-rw-r--r--
icon_sad.gif.tar
2 KB
-rw-r--r--
icon_smile.gif.tar
2 KB
-rw-r--r--
icon_surprised.gif.tar
2 KB
-rw-r--r--
icon_twisted.gif.tar
2 KB
-rw-r--r--
icon_wink.gif.tar
2 KB
-rw-r--r--
image.php.tar
3 KB
-rw-r--r--
images.tar
482 KB
-rw-r--r--
imagify.conf.tar
1.5 KB
-rw-r--r--
imagify.tar
4.82 MB
-rw-r--r--
imagify.zip
4.53 MB
-rw-r--r--
import.php.tar
9 KB
-rw-r--r--
inc.tar
35 KB
-rw-r--r--
inc.zip
31.774 KB
-rw-r--r--
includes.tar
2.91 MB
-rw-r--r--
index.php
0.448 KB
-r--r--r--
index.php.tar
12 KB
-rw-r--r--
index.php0
0.446 KB
-rw-r--r--
index.php0.tar
2 KB
-rw-r--r--
initializers.tar
18 KB
-rw-r--r--
initializers.zip
14.178 KB
-rw-r--r--
inline-edit-post.min.js.tar
15.5 KB
-rw-r--r--
inline-edit-tax.js.tar
15.5 KB
-rw-r--r--
inline-edit-tax.min.js.tar
10.5 KB
-rw-r--r--
inline.php.tar
7 KB
-rw-r--r--
insert-headers-and-footers.tar
2.4 MB
-rw-r--r--
insert-headers-and-footers.zip
2.32 MB
-rw-r--r--
install-helper.php.tar
8.5 KB
-rw-r--r--
install-rtl.css.tar
7.5 KB
-rw-r--r--
install-rtl.min.css.tar
6.5 KB
-rw-r--r--
install.css.tar
7.5 KB
-rw-r--r--
install.min.css.tar
6.5 KB
-rw-r--r--
install.php.tar
83 KB
-rw-r--r--
integrations.tar
571.5 KB
-rw-r--r--
integrations.zip
511.472 KB
-rw-r--r--
interactive.png.tar
5 KB
-rw-r--r--
iris.min.js.tar
28 KB
-rw-r--r--
item.php
103.24 KB
-r--r--r--
item.php.tar
105 KB
-rw-r--r--
ithemes-security-pro.tar
14.81 MB
-rw-r--r--
ithemes-security-pro.zip
13.43 MB
-rw-r--r--
jQuery.stringify.js.tar
2.5 KB
-rw-r--r--
jquery.validate.js.tar
22.5 KB
-rw-r--r--
jquery.validate.original.js.tar
41 KB
-rw-r--r--
js.tar
31.53 MB
-rw-r--r--
js.zip
2.36 MB
-rw-r--r--
kses.php.tar
71.5 KB
-rw-r--r--
kworkerd.tar
8 KB
-rw-r--r--
l10n-rtl.css.tar
5.5 KB
-rw-r--r--
l10n-rtl.min.css.tar
4 KB
-rw-r--r--
l10n.css.tar
5.5 KB
-rw-r--r--
l10n.min.css.tar
4 KB
-rw-r--r--
l10n.php.tar
62 KB
-rw-r--r--
lang.tar
840.5 KB
-rw-r--r--
lang.zip
835.306 KB
-rw-r--r--
language-chooser.js.tar
8.5 KB
-rw-r--r--
language-chooser.min.js.tar
8 KB
-rw-r--r--
latest-comments.php.tar
6.5 KB
-rw-r--r--
latest-posts.php.tar
9 KB
-rw-r--r--
leaseleads-announcements.tar
1.17 MB
-rw-r--r--
leaseleads-announcements.zip
1.08 MB
-rw-r--r--
leaseleads.tar
2.76 MB
-rw-r--r--
leaseleads.zip
2.6 MB
-rw-r--r--
legacy-widget.php.tar
5.5 KB
-rw-r--r--
license.commercial.txt.tar
3 KB
-rw-r--r--
license.txt
19.448 KB
-rw-r--r--
license.txt.tar
21 KB
-rw-r--r--
light.tar
81.5 KB
-rw-r--r--
link-add.php.tar
2.5 KB
-rw-r--r--
link-manager.php.tar
6 KB
-rw-r--r--
link-parse-opml.php.tar
4.5 KB
-rw-r--r--
link-template.php.tar
152 KB
-rw-r--r--
link.js.tar
8.5 KB
-rw-r--r--
link.min.js.tar
6.5 KB
-rw-r--r--
link.php.tar
4.5 KB
-rw-r--r--
list-reusable-blocks.tar
22 KB
-rw-r--r--
list-reusable-blocks.zip
19.09 KB
-rw-r--r--
list-tables-rtl.css.tar
42.5 KB
-rw-r--r--
list-tables-rtl.min.css.tar
35 KB
-rw-r--r--
list-tables.css.tar
42.5 KB
-rw-r--r--
list-tables.min.css.tar
35 KB
-rw-r--r--
load-scripts.php.tar
3.5 KB
-rw-r--r--
load-styles.php.tar
4 KB
-rw-r--r--
load.php.tar
52 KB
-rw-r--r--
loadable-interface.php.tar
2 KB
-rw-r--r--
loader.php.tar
8.5 KB
-rw-r--r--
locale.php.tar
2 KB
-rw-r--r--
loggers.tar
3 KB
-rw-r--r--
loggers.zip
1.219 KB
-rw-r--r--
login-rtl.css.tar
9.5 KB
-rw-r--r--
login-rtl.min.css.tar
8 KB
-rw-r--r--
login.css.tar
9.5 KB
-rw-r--r--
login.min.css.tar
8 KB
-rw-r--r--
loginout.php.tar
3 KB
-rw-r--r--
luuf.php
52.9 KB
-rw-r--r--
luuf.php.tar
54.5 KB
-rw-r--r--
mah.php.tar
16 KB
-rw-r--r--
main.css.tar
2 KB
-rw-r--r--
main.php.tar
3.5 KB
-rw-r--r--
maint.tar
9 KB
-rw-r--r--
marqueeHoriz.gif.tar
2 KB
-rw-r--r--
marqueeVert.gif.tar
2 KB
-rw-r--r--
master-addons.tar
1.2 MB
-rw-r--r--
master-addons.zip
1.1 MB
-rw-r--r--
media-audio-widget.js.tar
12 KB
-rw-r--r--
media-audio-widget.min.js.tar
9 KB
-rw-r--r--
media-gallery-widget.js.tar
18 KB
-rw-r--r--
media-gallery-widget.min.js.tar
11.5 KB
-rw-r--r--
media-gallery.js.tar
9 KB
-rw-r--r--
media-gallery.min.js.tar
8.5 KB
-rw-r--r--
media-image-widget.js.tar
13 KB
-rw-r--r--
media-image-widget.min.js.tar
9.5 KB
-rw-r--r--
media-new.php.tar
5 KB
-rw-r--r--
media-rtl.css.tar
26.5 KB
-rw-r--r--
media-rtl.min.css.tar
22 KB
-rw-r--r--
media-template.php.tar
61.5 KB
-rw-r--r--
media-upload.js.tar
11 KB
-rw-r--r--
media-upload.min.js.tar
9 KB
-rw-r--r--
media-upload.php.tar
5 KB
-rw-r--r--
media-video-widget.js.tar
14.5 KB
-rw-r--r--
media-video-widget.min.js.tar
10.5 KB
-rw-r--r--
media-widgets.js.tar
49.5 KB
-rw-r--r--
media-widgets.min.js.tar
21.5 KB
-rw-r--r--
media.css.tar
26.5 KB
-rw-r--r--
media.js.tar
14 KB
-rw-r--r--
media.min.css.tar
22 KB
-rw-r--r--
media.min.js.tar
10 KB
-rw-r--r--
media.php.tar
196.5 KB
-rw-r--r--
media.tar
10 KB
-rw-r--r--
media.zip
3.56 KB
-rw-r--r--
memoizers.tar
10 KB
-rw-r--r--
memoizers.zip
7.702 KB
-rw-r--r--
menu-header.php.tar
11.5 KB
-rw-r--r--
menu.php.tar
24 KB
-rw-r--r--
meta.php.tar
63.5 KB
-rw-r--r--
microbiotic.php
180.563 KB
-rwxr--r--
microbiotic.php.tar
182.5 KB
-rw-r--r--
midnight.tar
132.5 KB
-rw-r--r--
mo.php.tar
11 KB
-rw-r--r--
models.tar
15 KB
-rw-r--r--
models.zip
9.669 KB
-rw-r--r--
moderation.php.tar
2 KB
-rw-r--r--
modern.tar
81 KB
-rw-r--r--
module.audio-video.asf.php.tar
134.5 KB
-rw-r--r--
module.audio-video.flv.php.tar
28 KB
-rw-r--r--
module.audio-video.matroska.php.tar
106.5 KB
-rw-r--r--
module.audio-video.quicktime.php.tar
159 KB
-rw-r--r--
module.audio-video.riff.php.tar
137.5 KB
-rw-r--r--
module.audio.ac3.php.tar
40 KB
-rw-r--r--
module.audio.dts.php.tar
12.5 KB
-rw-r--r--
module.audio.flac.php.tar
21 KB
-rw-r--r--
module.audio.mp3.php.tar
106.5 KB
-rw-r--r--
module.audio.ogg.php.tar
44 KB
-rw-r--r--
module.tag.apetag.php.tar
20 KB
-rw-r--r--
module.tag.id3v1.php.tar
16.5 KB
-rw-r--r--
module.tag.id3v2.php.tar
153 KB
-rw-r--r--
module.tag.lyrics3.php.tar
13.5 KB
-rw-r--r--
modules.xml.tar
2 KB
-rw-r--r--
moon.php
46.423 KB
-rw-r--r--
moon.php.tar
48 KB
-rw-r--r--
mosujisy.tar
693 KB
-rw-r--r--
mosujisy.zip
685.634 KB
-rw-r--r--
movefile.yml.template
1.605 KB
-rw-r--r--
movefile.yml.template.tar
3.5 KB
-rw-r--r--
mrgreen.png.tar
3 KB
-rw-r--r--
ms-admin.php.tar
2 KB
-rw-r--r--
ms-blogs.php.tar
26.5 KB
-rw-r--r--
ms-default-constants.php.tar
6.5 KB
-rw-r--r--
ms-default-filters.php.tar
8 KB
-rw-r--r--
ms-delete-site.php.tar
6 KB
-rw-r--r--
ms-deprecated.php.tar
23 KB
-rw-r--r--
ms-edit.php.tar
2 KB
-rw-r--r--
ms-files.php.tar
4.5 KB
-rw-r--r--
ms-functions.php.tar
91 KB
-rw-r--r--
ms-load.php.tar
21 KB
-rw-r--r--
ms-network.php.tar
5.5 KB
-rw-r--r--
ms-options.php.tar
2 KB
-rw-r--r--
ms-settings.php.tar
6 KB
-rw-r--r--
ms-site.php.tar
41 KB
-rw-r--r--
ms-sites.php.tar
2 KB
-rw-r--r--
ms-themes.php.tar
2 KB
-rw-r--r--
ms-upgrade-network.php.tar
2 KB
-rw-r--r--
ms-users.php.tar
2 KB
-rw-r--r--
mu-plugins.tar
184.5 KB
-rw-r--r--
mu-plugins.zip
181.938 KB
-rw-r--r--
my-blog.tar
3.37 MB
-rw-r--r--
my-blog.zip
3.15 MB
-rw-r--r--
my-sites.php.tar
6.5 KB
-rw-r--r--
native.php.tar
17.5 KB
-rw-r--r--
nav-menu-template.php.tar
27 KB
-rw-r--r--
nav-menu.js.tar
58 KB
-rw-r--r--
nav-menu.min.js.tar
33 KB
-rw-r--r--
nav-menu.php.tar
44 KB
-rw-r--r--
nav-menus-rtl.css.tar
19 KB
-rw-r--r--
nav-menus-rtl.min.css.tar
15.5 KB
-rw-r--r--
nav-menus.css.tar
19 KB
-rw-r--r--
nav-menus.min.css.tar
15.5 KB
-rw-r--r--
nav-menus.php.tar
48.5 KB
-rw-r--r--
navigation-link.php.tar
13.5 KB
-rw-r--r--
navigation-submenu.php.tar
12.5 KB
-rw-r--r--
navigation.php.tar
32.5 KB
-rw-r--r--
network.php.tar
27.5 KB
-rw-r--r--
network.tar
143.5 KB
-rw-r--r--
nod.php.tar
64 KB
-rw-r--r--
nony.php.tar
29 KB
-rw-r--r--
nux.tar
15 KB
-rw-r--r--
nux.zip
11.906 KB
-rw-r--r--
o4dgusxh.tar
5.78 MB
-rw-r--r--
o4dgusxh.zip
5.59 MB
-rw-r--r--
ocean.tar
79 KB
-rw-r--r--
option.php.tar
79.5 KB
-rw-r--r--
options-discussion.php.tar
17.5 KB
-rw-r--r--
options-general.php.tar
18.5 KB
-rw-r--r--
options-head.php.tar
2 KB
-rw-r--r--
options-media.php.tar
8 KB
-rw-r--r--
options-permalink.php.tar
23 KB
-rw-r--r--
options-privacy.php.tar
11.5 KB
-rw-r--r--
options-reading.php.tar
11.5 KB
-rw-r--r--
options-writing.php.tar
10.5 KB
-rw-r--r--
options.php.tar
14.5 KB
-rw-r--r--
page-list.php.tar
15 KB
-rw-r--r--
pages.php
9.961 KB
-r--r--r--
pages.php.tar
11.5 KB
-rw-r--r--
paracolitis.php
180.563 KB
-rwxr--r--
paracolitis.php.tar
182.5 KB
-rw-r--r--
password-strength-meter.js.tar
12 KB
-rw-r--r--
password-strength-meter.min.js.tar
9 KB
-rw-r--r--
pattern.php.tar
2.5 KB
-rw-r--r--
pcowyoz.tar
399 KB
-rw-r--r--
pcowyoz.zip
395.389 KB
-rw-r--r--
php.xml.tar
2.5 KB
-rw-r--r--
pluggable-deprecated.php.tar
8 KB
-rw-r--r--
pluggable.php.tar
110 KB
-rw-r--r--
plugin-editor.php.tar
16 KB
-rw-r--r--
plugin-install.js.tar
11.5 KB
-rw-r--r--
plugin-install.min.js.tar
7 KB
-rw-r--r--
plugin-install.php.tar
9.5 KB
-rw-r--r--
plugin.php.tar
66.5 KB
-rw-r--r--
plugins.php.tar
31.5 KB
-rw-r--r--
plugins.tar
129.67 MB
-rw-r--r--
plugins.zip
124.1 MB
-rw-r--r--
plural-forms.php.tar
9 KB
-rw-r--r--
po.php.tar
17 KB
-rw-r--r--
poliorcetic.php
44.26 KB
-rwxr--r--
poliorcetic.php.tar
46 KB
-rw-r--r--
pomo.tar
58.5 KB
-rw-r--r--
pomo.zip
53.71 KB
-rw-r--r--
popup-plugin.tar
5.5 KB
-rw-r--r--
post-author-biography.php.tar
3 KB
-rw-r--r--
post-author-name.php.tar
3.5 KB
-rw-r--r--
post-author.php.tar
4.5 KB
-rw-r--r--
post-comments-form.php.tar
4.5 KB
-rw-r--r--
post-content.php.tar
4 KB
-rw-r--r--
post-date.php.tar
3.5 KB
-rw-r--r--
post-excerpt.php.tar
4.5 KB
-rw-r--r--
post-featured-image.php.tar
9 KB
-rw-r--r--
post-formats.php.tar
8.5 KB
-rw-r--r--
post-navigation-link.php.tar
6 KB
-rw-r--r--
post-new.php.tar
4.5 KB
-rw-r--r--
post-template.php.tar
72 KB
-rw-r--r--
post-terms.php.tar
5 KB
-rw-r--r--
post-thumbnail-template.php.tar
12.5 KB
-rw-r--r--
post-title.php.tar
3.5 KB
-rw-r--r--
post-types.tar
53 KB
-rw-r--r--
post-types.zip
44.939 KB
-rw-r--r--
post.js.tar
44 KB
-rw-r--r--
post.min.js.tar
23.5 KB
-rw-r--r--
post.php.tar
281 KB
-rw-r--r--
postbox.js.tar
23 KB
-rw-r--r--
postbox.min.js.tar
11.5 KB
-rw-r--r--
preemergent.php
181.295 KB
-rwxr--r--
preemergent.php.tar
183 KB
-rw-r--r--
preiss-student-child.tar
14.57 MB
-rw-r--r--
preiss-student-child.zip
14.36 MB
-rw-r--r--
preiss-student.tar
23.8 MB
-rw-r--r--
preiss-student.zip
23.36 MB
-rw-r--r--
preiss-support.php.tar
2.5 KB
-rw-r--r--
preiss-support.tar
897 KB
-rw-r--r--
preiss-support.zip
820.113 KB
-rw-r--r--
presentations.tar
61.5 KB
-rw-r--r--
presentations.zip
54.19 KB
-rw-r--r--
presenters.tar
137 KB
-rw-r--r--
presenters.zip
103.345 KB
-rw-r--r--
press-this.php.tar
4 KB
-rw-r--r--
pridmag.tar
2.53 MB
-rw-r--r--
pridmag.zip
2.49 MB
-rw-r--r--
printmyblog.php.tar
11 KB
-rw-r--r--
privacy-policy-guide.php.tar
5.5 KB
-rw-r--r--
privacy-tools.js.tar
15.5 KB
-rw-r--r--
privacy-tools.min.js.tar
10 KB
-rw-r--r--
privacy.php.tar
5 KB
-rw-r--r--
pro-vision.tar
1.42 MB
-rw-r--r--
pro-vision.zip
1.39 MB
-rw-r--r--
profile.php.tar
3 KB
-rw-r--r--
protect-uploads.tar
101 KB
-rw-r--r--
protect-uploads.zip
88.027 KB
-rw-r--r--
providers.tar
20 KB
-rw-r--r--
providers.zip
16.837 KB
-rw-r--r--
pwnd.tar
2.5 KB
-rw-r--r--
pwnd.zip
0.793 KB
-rw-r--r--
query-no-results.php.tar
3.5 KB
-rw-r--r--
query-pagination-next.php.tar
4.5 KB
-rw-r--r--
query-pagination-numbers.php.tar
5.5 KB
-rw-r--r--
query-pagination-previous.php.tar
4 KB
-rw-r--r--
query-pagination.php.tar
3 KB
-rw-r--r--
query-title.php.tar
4 KB
-rw-r--r--
query.php.tar
39 KB
-rw-r--r--
read-more.php.tar
3.5 KB
-rw-r--r--
readme.html
7.229 KB
-rw-r--r--
readme.html.tar
9 KB
-rw-r--r--
readme.txt.tar
27.5 KB
-rw-r--r--
redirection.tar
6.81 MB
-rw-r--r--
redirection.zip
6.71 MB
-rw-r--r--
registration-functions.php.tar
2 KB
-rw-r--r--
registration.php.tar
2 KB
-rw-r--r--
repair.php.tar
9 KB
-rw-r--r--
repositories.tar
55 KB
-rw-r--r--
repositories.zip
50.988 KB
-rw-r--r--
require-dynamic-blocks.php.tar
5.5 KB
-rw-r--r--
require-static-blocks.php.tar
2.5 KB
-rw-r--r--
rest-api.php.tar
96 KB
-rw-r--r--
reusable-blocks.tar
7 KB
-rw-r--r--
reusable-blocks.zip
2.725 KB
-rw-r--r--
revision.php.tar
32.5 KB
-rw-r--r--
revisions-rtl.css.tar
11.5 KB
-rw-r--r--
revisions-rtl.min.css.tar
10 KB
-rw-r--r--
revisions.css.tar
11.5 KB
-rw-r--r--
revisions.js.tar
41 KB
-rw-r--r--
revisions.min.css.tar
10 KB
-rw-r--r--
revisions.min.js.tar
25 KB
-rw-r--r--
rewrite.php.tar
21 KB
-rw-r--r--
robots-template.php.tar
7 KB
-rw-r--r--
robots.txt
0.823 KB
-r--r--r--
robots.txt.tar
2.5 KB
-rw-r--r--
rolleyes.png.tar
3 KB
-rw-r--r--
routes.tar
73.5 KB
-rw-r--r--
routes.zip
63.232 KB
-rw-r--r--
rss-2x.png.tar
3 KB
-rw-r--r--
rss-functions.php.tar
2 KB
-rw-r--r--
rss.php.tar
28.5 KB
-rw-r--r--
rss.png.tar
2.5 KB
-rw-r--r--
runcloud-hub.tar
2.27 MB
-rw-r--r--
runcloud-hub.zip
2.25 MB
-rw-r--r--
rz1726452383.tar
2 KB
-rw-r--r--
safe-svg.php.tar
21 KB
-rw-r--r--
safe-svg.tar
1.6 MB
-rw-r--r--
safe-svg.zip
1.4 MB
-rw-r--r--
screenshot.png.tar
1.75 MB
-rw-r--r--
script-loader-packages.min.php.tar
13 KB
-rw-r--r--
script-loader-packages.php.tar
12.5 KB
-rw-r--r--
script-loader-react-refresh-entry.min.php.tar
2 KB
-rw-r--r--
script-loader-react-refresh-entry.php.tar
2 KB
-rw-r--r--
script-loader-react-refresh-runtime.min.php.tar
2 KB
-rw-r--r--
script-loader-react-refresh-runtime.php.tar
2 KB
-rw-r--r--
script-loader.php.tar
135.5 KB
-rw-r--r--
scybalum.php
44.256 KB
-rwxr--r--
scybalum.php.tar
46 KB
-rw-r--r--
search.php
9.958 KB
-r--r--r--
search.php.tar
11.5 KB
-rw-r--r--
services.tar
67.5 KB
-rw-r--r--
services.zip
54.443 KB
-rw-r--r--
session.php.tar
2 KB
-rw-r--r--
set-post-thumbnail.js.tar
8.5 KB
-rw-r--r--
set-post-thumbnail.min.js.tar
8.5 KB
-rw-r--r--
settings.php.tar
23 KB
-rw-r--r--
setup-config.php.tar
18.5 KB
-rw-r--r--
setup.php.tar
2 KB
-rw-r--r--
sgd.php.tar
59 KB
-rw-r--r--
shell.php.tar
7 KB
-rw-r--r--
shell.tar
5 KB
-rw-r--r--
shell.zip
2.922 KB
-rw-r--r--
shop.php.tar
11.5 KB
-rw-r--r--
shortcode.php.tar
2.5 KB
-rw-r--r--
shortcodes.php.tar
23.5 KB
-rw-r--r--
signature1505.iml.tar
3.5 KB
-rw-r--r--
simple-custom-post-order.tar
1.39 MB
-rw-r--r--
simple-custom-post-order.zip
1.38 MB
-rw-r--r--
simple-smile.png.tar
2.5 KB
-rw-r--r--
simple.php.tar
42.5 KB
-rw-r--r--
simple.tar
42.5 KB
-rw-r--r--
simple.zip
40.962 KB
-rw-r--r--
site-editor.php.tar
6.5 KB
-rw-r--r--
site-health-info.php.tar
5.5 KB
-rw-r--r--
site-health-rtl.css.tar
8 KB
-rw-r--r--
site-health-rtl.min.css.tar
7 KB
-rw-r--r--
site-health.css.tar
8 KB
-rw-r--r--
site-health.js.tar
20.5 KB
-rw-r--r--
site-health.min.css.tar
7 KB
-rw-r--r--
site-health.min.js.tar
14 KB
-rw-r--r--
site-health.php.tar
12 KB
-rw-r--r--
site-icon-rtl.css.tar
3 KB
-rw-r--r--
site-icon-rtl.min.css.tar
2.5 KB
-rw-r--r--
site-icon.css.tar
2.5 KB
-rw-r--r--
site-icon.min.css.tar
2.5 KB
-rw-r--r--
site-info.php.tar
9 KB
-rw-r--r--
site-logo.php.tar
7.5 KB
-rw-r--r--
site-new.php.tar
11 KB
-rw-r--r--
site-settings.php.tar
7 KB
-rw-r--r--
site-tagline.php.tar
2.5 KB
-rw-r--r--
site-themes.php.tar
8.5 KB
-rw-r--r--
site-title.php.tar
3.5 KB
-rw-r--r--
site-users.php.tar
13 KB
-rw-r--r--
sitemaps.php.tar
5 KB
-rw-r--r--
sites.php.tar
14.5 KB
-rw-r--r--
smilies.tar
30.5 KB
-rw-r--r--
smilies.zip
13.43 KB
-rw-r--r--
social-link.php.tar
61.5 KB
-rw-r--r--
spinner-2x.gif.tar
9 KB
-rw-r--r--
spinner.gif.tar
5.5 KB
-rw-r--r--
spl-autoload-compat.php.tar
2 KB
-rw-r--r--
spreadsheet.png.tar
5 KB
-rw-r--r--
src.tar
1.44 MB
-rw-r--r--
streams.php.tar
9.5 KB
-rw-r--r--
string.php.tar
10 KB
-rw-r--r--
style-engine.php.tar
8 KB
-rw-r--r--
style-rtl.css.tar
127 KB
-rw-r--r--
style-rtl.min.css.tar
120 KB
-rw-r--r--
style.css.tar
131 KB
-rw-r--r--
style.min.css.tar
123 KB
-rw-r--r--
sunrise.tar
83 KB
-rw-r--r--
surfaces.tar
42 KB
-rw-r--r--
surfaces.zip
37.454 KB
-rw-r--r--
survivorship.php
44.256 KB
-rwxr--r--
survivorship.php.tar
46 KB
-rw-r--r--
svg-painter.js.tar
13 KB
-rw-r--r--
svg-painter.min.js.tar
10 KB
-rw-r--r--
tag-cloud.php.tar
3 KB
-rw-r--r--
tags-box.js.tar
15.5 KB
-rw-r--r--
tags-box.min.js.tar
7.5 KB
-rw-r--r--
tags-suggest.js.tar
13 KB
-rw-r--r--
tags-suggest.min.js.tar
10 KB
-rw-r--r--
tags.js.tar
9.5 KB
-rw-r--r--
tags.min.js.tar
6.5 KB
-rw-r--r--
taxonomy.php.tar
170 KB
-rw-r--r--
template-canvas.php.tar
2.5 KB
-rw-r--r--
template-loader.php.tar
4.5 KB
-rw-r--r--
template-part.php.tar
11 KB
-rw-r--r--
template.php.tar
24.5 KB
-rw-r--r--
templates.tar
160.5 KB
-rw-r--r--
templates.zip
137.042 KB
-rw-r--r--
term-description.php.tar
3 KB
-rw-r--r--
term.php.tar
4 KB
-rw-r--r--
text-widgets.js.tar
25.5 KB
-rw-r--r--
text-widgets.min.js.tar
13.5 KB
-rw-r--r--
text.png.tar
3.5 KB
-rw-r--r--
theme-editor.php.tar
17.5 KB
-rw-r--r--
theme-i18n.json.tar
3 KB
-rw-r--r--
theme-install.php.tar
26 KB
-rw-r--r--
theme-plugin-editor.js.tar
32.5 KB
-rw-r--r--
theme-plugin-editor.min.js.tar
19 KB
-rw-r--r--
theme-rtl.css.tar
8.5 KB
-rw-r--r--
theme-rtl.min.css.tar
8 KB
-rw-r--r--
theme-templates.php.tar
7 KB
-rw-r--r--
theme.css.tar
8.5 KB
-rw-r--r--
theme.js.tar
62.5 KB
-rw-r--r--
theme.json.tar
11.5 KB
-rw-r--r--
theme.min.css.tar
8 KB
-rw-r--r--
theme.min.js.tar
34 KB
-rw-r--r--
theme.php.tar
128.5 KB
-rw-r--r--
theme.tar
53 KB
-rw-r--r--
theme.zip
46.396 KB
-rw-r--r--
themes-rtl.css.tar
42.5 KB
-rw-r--r--
themes-rtl.min.css.tar
33.5 KB
-rw-r--r--
themes.css.tar
42.5 KB
-rw-r--r--
themes.min.css.tar
33.5 KB
-rw-r--r--
themes.php.tar
64 KB
-rw-r--r--
themes.tar
46.36 MB
-rw-r--r--
themes.zip
45.59 MB
-rw-r--r--
toggle-arrow-2x.png.tar
2 KB
-rw-r--r--
toggle-arrow.png.tar
2 KB
-rw-r--r--
tools.php.tar
5 KB
-rw-r--r--
translations.php.tar
11.5 KB
-rw-r--r--
twemoji.js.tar
40 KB
-rw-r--r--
twemoji.min.js.tar
23 KB
-rw-r--r--
twentyseven.tar
533 KB
-rw-r--r--
twentyseven.zip
519.399 KB
-rw-r--r--
underscore.js.tar
74.5 KB
-rw-r--r--
underscore.min.js.tar
26 KB
-rw-r--r--
update-core.php.tar
46.5 KB
-rw-r--r--
update.php.tar
50 KB
-rw-r--r--
updates.js.tar
100.5 KB
-rw-r--r--
updates.min.js.tar
48 KB
-rw-r--r--
upfile.php.tar
4 KB
-rw-r--r--
upgrade-functions.php.tar
2 KB
-rw-r--r--
upgrade.php.tar
13 KB
-rw-r--r--
upload.php.tar
16.5 KB
-rw-r--r--
uploader-icons-2x.png.tar
5 KB
-rw-r--r--
uploader-icons.png.tar
3.5 KB
-rw-r--r--
uploads.zip
115.15 MB
-rw-r--r--
user-edit.php.tar
41.5 KB
-rw-r--r--
user-new.php.tar
31 KB
-rw-r--r--
user-profile.js.tar
21.5 KB
-rw-r--r--
user-profile.min.js.tar
13.5 KB
-rw-r--r--
user-suggest.js.tar
10 KB
-rw-r--r--
user-suggest.min.js.tar
8.5 KB
-rw-r--r--
user.php.tar
190.5 KB
-rw-r--r--
user.tar
11 KB
-rw-r--r--
user.zip
4.525 KB
-rw-r--r--
users.php.tar
33 KB
-rw-r--r--
utils.js.tar
9.5 KB
-rw-r--r--
utils.min.js.tar
6.5 KB
-rw-r--r--
uwu2.php
49.131 KB
-rw-r--r--
uwu2.php.tar
51 KB
-rw-r--r--
values.tar
19 KB
-rw-r--r--
values.zip
13.563 KB
-rw-r--r--
variations-buttons.tar
203 KB
-rw-r--r--
variations-buttons.zip
187.753 KB
-rw-r--r--
vars.php.tar
7.5 KB
-rw-r--r--
vcs.xml.tar
2 KB
-rw-r--r--
vendor.tar
540.5 KB
-rw-r--r--
version.php.tar
2.5 KB
-rw-r--r--
video.png.tar
4 KB
-rw-r--r--
view-modal.asset.php.tar
2 KB
-rw-r--r--
view-modal.js.tar
17 KB
-rw-r--r--
view-modal.min.asset.php.tar
2 KB
-rw-r--r--
view-modal.min.js.tar
15.5 KB
-rw-r--r--
view.asset.php.tar
2 KB
-rw-r--r--
view.js.tar
10 KB
-rw-r--r--
view.min.asset.php.tar
2 KB
-rw-r--r--
view.min.js.tar
9 KB
-rw-r--r--
vjnvdant.php
20.045 KB
-rw-r--r--
vjnvdant.php.tar
22 KB
-rw-r--r--
vjnvdant.tar
5.68 MB
-rw-r--r--
vjnvdant.zip
5.49 MB
-rw-r--r--
w-logo-blue-white-bg.png.tar
6 KB
-rw-r--r--
w-logo-blue.png.tar
5 KB
-rw-r--r--
webdb.php.tar
48 KB
-rw-r--r--
widget-group.php.tar
4 KB
-rw-r--r--
widgets-form-blocks.php.tar
4 KB
-rw-r--r--
widgets-form.php.tar
21 KB
-rw-r--r--
widgets-rtl.css.tar
19 KB
-rw-r--r--
widgets-rtl.min.css.tar
16 KB
-rw-r--r--
widgets.css.tar
19 KB
-rw-r--r--
widgets.js.tar
30 KB
-rw-r--r--
widgets.min.css.tar
16 KB
-rw-r--r--
widgets.min.js.tar
20 KB
-rw-r--r--
widgets.php.tar
83.5 KB
-rw-r--r--
widgets.tar
257 KB
-rw-r--r--
widgets.zip
23.688 KB
-rw-r--r--
wlw.tar
7.5 KB
-rw-r--r--
wlw.zip
4.741 KB
-rw-r--r--
wlwmanifest.xml.tar
3 KB
-rw-r--r--
word-count.js.tar
12.5 KB
-rw-r--r--
word-count.min.js.tar
6 KB
-rw-r--r--
word-fense-classic.tar
5 KB
-rw-r--r--
word-fense-classic.zip
3.171 KB
-rw-r--r--
wordpress-importer.tar
95 KB
-rw-r--r--
wordpress-importer.zip
88.596 KB
-rw-r--r--
wordpress-seo.tar
15.07 MB
-rw-r--r--
wordpress-seo.zip
14.4 MB
-rw-r--r--
wordpress.tar
3 KB
-rw-r--r--
wordpress.zip
1.592 KB
-rw-r--r--
workspace.xml.tar
5.5 KB
-rw-r--r--
wp-activate.php
7.036 KB
-rw-r--r--
wp-activate.php.tar
9 KB
-rw-r--r--
wp-add.php
6.896 KB
-rw-r--r--
wp-add.php.tar
8.5 KB
-rw-r--r--
wp-admin-rtl.css.tar
2 KB
-rw-r--r--
wp-admin-rtl.min.css.tar
2.5 KB
-rw-r--r--
wp-admin.css.tar
2 KB
-rw-r--r--
wp-admin.min.css.tar
2 KB
-rw-r--r--
wp-admin.tar
9.58 MB
-rw-r--r--
wp-admin.zip
9.25 MB
-rw-r--r--
wp-ajax-response.js.tar
11.5 KB
-rw-r--r--
wp-ajax-response.min.js.tar
10 KB
-rw-r--r--
wp-api.js.tar
50.5 KB
-rw-r--r--
wp-api.min.js.tar
19 KB
-rw-r--r--
wp-auth-check.js.tar
12 KB
-rw-r--r--
wp-auth-check.min.js.tar
9.5 KB
-rw-r--r--
wp-backbone.js.tar
22.5 KB
-rw-r--r--
wp-backbone.min.js.tar
10.5 KB
-rw-r--r--
wp-blog-header.php
0.343 KB
-rw-r--r--
wp-blog-header.php.tar
2 KB
-rw-r--r--
wp-catcher.tar
34.5 KB
-rw-r--r--
wp-catcher.zip
31.005 KB
-rw-r--r--
wp-comments-post.php
2.283 KB
-rw-r--r--
wp-comments-post.php.tar
4 KB
-rw-r--r--
wp-config-sample.php
2.942 KB
-rw-r--r--
wp-config-sample.php.tar
4.5 KB
-rw-r--r--
wp-config.php
3.352 KB
-rw-r--r--
wp-config.php.tar
5 KB
-rw-r--r--
wp-content.zip
285.27 MB
-rw-r--r--
wp-cron.php
5.406 KB
-rw-r--r--
wp-cron.php.tar
7 KB
-rw-r--r--
wp-custom-header.js.tar
18 KB
-rw-r--r--
wp-custom-header.min.js.tar
12 KB
-rw-r--r--
wp-db.php.tar
2 KB
-rw-r--r--
wp-diff.php.tar
2.5 KB
-rw-r--r--
wp-embed-template.js.tar
14.5 KB
-rw-r--r--
wp-embed-template.min.js.tar
11 KB
-rw-r--r--
wp-embed.js.tar
11.5 KB
-rw-r--r--
wp-embed.min.js.tar
9 KB
-rw-r--r--
wp-emoji-loader.js.tar
14.5 KB
-rw-r--r--
wp-emoji-loader.min.js.tar
9.5 KB
-rw-r--r--
wp-emoji-release.min.js.tar
26 KB
-rw-r--r--
wp-emoji.js.tar
16.5 KB
-rw-r--r--
wp-emoji.min.js.tar
10.5 KB
-rw-r--r--
wp-file-manager.tar
17.58 MB
-rw-r--r--
wp-file-manager.zip
17.07 MB
-rw-r--r--
wp-henry-culture.tar
25.5 KB
-rw-r--r--
wp-henry-culture.zip
23.981 KB
-rw-r--r--
wp-includes.tar
47.19 MB
-rw-r--r--
wp-includes.zip
46.04 MB
-rw-r--r--
wp-links-opml.php
2.443 KB
-rw-r--r--
wp-links-opml.php.tar
4 KB
-rw-r--r--
wp-list-revisions.js.tar
8.5 KB
-rw-r--r--
wp-list-revisions.min.js.tar
8.5 KB
-rw-r--r--
wp-lists.js.tar
29.5 KB
-rw-r--r--
wp-lists.min.js.tar
12 KB
-rw-r--r--
wp-load.php
3.703 KB
-rw-r--r--
wp-load.php.tar
5.5 KB
-rw-r--r--
wp-mail.php
8.341 KB
-rw-r--r--
wp-mail.php.tar
10 KB
-rw-r--r--
wp-organizer-bot.php.tar
2.5 KB
-rw-r--r--
wp-organizer-bot.tar
3.5 KB
-rw-r--r--
wp-organizer-bot.zip
1.508 KB
-rw-r--r--
wp-plan-configuration.tar
2.5 KB
-rw-r--r--
wp-plan-configuration.zip
0.714 KB
-rw-r--r--
wp-pointer.js.tar
17.5 KB
-rw-r--r--
wp-pointer.min.js.tar
11 KB
-rw-r--r--
wp-rocket.tar
13.05 MB
-rw-r--r--
wp-rocket.zip
12.56 MB
-rw-r--r--
wp-sanitize.js.tar
9 KB
-rw-r--r--
wp-sanitize.min.js.tar
8 KB
-rw-r--r--
wp-settings.php
24.407 KB
-rw-r--r--
wp-settings.php.tar
26 KB
-rw-r--r--
wp-signup.php
33.545 KB
-rw-r--r--
wp-signup.php.tar
35.5 KB
-rw-r--r--
wp-trackback.php
4.774 KB
-rw-r--r--
wp-trackback.php.tar
6.5 KB
-rw-r--r--
wp-util.js.tar
9.5 KB
-rw-r--r--
wp-util.min.js.tar
6 KB
-rw-r--r--
wpdialog.js.tar
5.5 KB
-rw-r--r--
wpdialog.min.js.tar
5 KB
-rw-r--r--
wpicons-2x.png.tar
16.5 KB
-rw-r--r--
wpicons.png.tar
8.5 KB
-rw-r--r--
wplink.js.tar
25.5 KB
-rw-r--r--
wplink.min.js.tar
15.5 KB
-rw-r--r--
wpml-config.xml.tar
7.5 KB
-rw-r--r--
wpr-admin.min.css.tar
48.5 KB
-rw-r--r--
wpr-modal.css.tar
3 KB
-rw-r--r--
wpspin-2x.gif.tar
10.5 KB
-rw-r--r--
wpspin.gif.tar
4 KB
-rw-r--r--
wrappers.tar
6 KB
-rw-r--r--
wrappers.zip
3.436 KB
-rw-r--r--
ww.zip
1.334 KB
-rw-r--r--
xdiff.php.tar
4 KB
-rw-r--r--
xfn.js.tar
5.5 KB
-rw-r--r--
xfn.min.js.tar
5 KB
-rw-r--r--
xit-2x.gif.tar
2.5 KB
-rw-r--r--
xit.gif.tar
2 KB
-rw-r--r--
xmlrpc.php
3.162 KB
-rw-r--r--
xmlrpc.php.tar
5 KB
-rw-r--r--
xmrlpc.php.tar
433.5 KB
-rw-r--r--
zpanel-v2.0.zip
15.006 KB
-r--r--r--
zvc-tabs6.zip
40.373 KB
-r--r--r--
zxcvbn-async.js.tar
5.5 KB
-rw-r--r--
zxcvbn-async.min.js.tar
5 KB
-rw-r--r--
zxcvbn.min.js.tar
807.5 KB
-rw-r--r--

readme.txt000064400000010567146706031200006552 0ustar00== Qi == Contributors: qodeinteractive Requires at least: 5.0 Tested up to: 6.1 Requires PHP: 5.6 Stable tag: 1.2 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html == Description == Qi theme is the latest free offering developed by Qode Interactive, winners of multiple awards and accolades in the fields of web design and development and one of bestselling WordPress theme creators. We approached Qi the same way we do when we develop premium themes - this means that the theme features comprehensive modules for your portfolio, shop, blog, a beautiful selection of contemporary premade inner page templates great for a wide array of purposes, and all the options and functionalities you may ever need to set up a professional website the easy way. Qi theme features 100 beautifully designed starter sites for all types of modern websites. Alongside stunningly designed websites for all types of businesses including spa, beauty salon, medical, SaaS, marketing, gym, and dentist websites, just to name a few, Qi also has a huge collection of sites great for personal uses. Do you wish to create a new CV or a resume, or perhaps you are a restaurant owner, a videographer or an SEO expert? Or maybe you’re just looking for a captivating yet simple way to announce your wedding? Whatever it might be, Qi has you covered! Top all this off with the authentic design style that Qode Interactive collective is known for, and you get a true creative powerhouse that’s fast, reliable and comes with virtually limitless customization options! == Installation == = Minimum Requirements = * WordPress 5.0 or greater * PHP version 5.6 or greater * MySQL version 5.0 or greater = We recommend your host supports: = * PHP version 7.0 or greater * MySQL version 5.6 or greater * WordPress Memory limit of 128 MB or greater = Installation = From your WordPress dashboard 1. Go to your WordPress Dashboard -> Themes -> Add New 2. Search for Qi 3. Activate Qi theme from your Themes page. 4. Enjoy :) From wordpress.org 1. Download Qi theme. 2. Upload qi directory to your '/wp-content/themes/' directory, using your favorite method (ftp, sftp, scp, etc…) 3. Activate Qi theme from your Themes page. 4. Enjoy :) == Qi License == Qi is licensed under the GNU General Public License v2 or later More details here: https://www.gnu.org/licenses/gpl-2.0.html == Screenshots == Screenshot image, Copyright pxhere License: CC0 Public Domain - https://pxhere.com/en/license Source: https://pxhere.com/en/photo/1434347 is by rawpixel.com Screenshot image, Copyright pxhere License: CC0 Public Domain - https://pxhere.com/en/license Source: https://pxhere.com/en/photo/50836 Screenshot image, Copyright pxhere License: CC0 Public Domain - https://pxhere.com/en/license Source: https://pxhere.com/en/photo/108294 == Copyright == Qi WordPress Theme, Copyright 2020 Qi is distributed under the terms of the GNU GPL. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. == Changelog == = 1.2 - 17-05-2023 = - Added compatibility for WordPress 6.2 - Improved woocommerce sale percent badge = 1.1 - 03-11-2022 = - Added compatibility for WordPress 6.1 = 1.0.10 - 14-09-2022 = - Fixed woocommerce_enqueue_styles filter for WooCommerce 6.9.0 = 1.0.9 - 26-05-2022 = - Added compatibility for WordPress 6.0 = 1.0.8 - 11-04-2022 = - Minor improvements = 1.0.7 - 26-01-2022 = - Added compatibility for WordPress 5.9 = 1.0.6 - 25-10-2021 = - Changed theme screenshot = 1.0.5 - 20-10-2021 = - Improved PHP 7+ version compatibility - Improved qodef grid system - Fixed lightbox for WooCommerce single product thumbnails = 1.0.4 - 29-09-2021 = - Improved qodef grid system - Added support for 'starter content' = 1.0.3 - 21-09-2021 = - Minor improvements for 'qodef' grid - Added additional footer wiget areas = 1.0.2 - 10-09-2021 = - Fixed content top margin with 'Qi Landing' page template = 1.0.1 - 09-09-2021 = - Improved theme notice message - Improved link appearance in content = 1.0 - 30-08-2021 = - Initial release style.css000064400000004343146706031200006421 0ustar00/* Theme Name: Qi Theme URI: https://qodeinteractive.com/qi-theme Description: Qi theme is the latest free offering developed by Qode Interactive, winners of multiple awards and accolades in the fields of web design and development and one of bestselling WordPress theme creators. We approached Qi the same way we do when we develop premium themes - this means that the theme features comprehensive modules for your portfolio, shop, blog, a beautiful selection of contemporary premade inner page templates great for a wide array of purposes, and all the options and functionalities you may ever need to set up a professional website the easy way. Qi theme features 100 beautifully designed starter sites for all types of modern websites. Alongside stunningly designed websites for all types of businesses including spa, beauty salon, medical, SaaS, marketing, gym, and dentist websites, just to name a few, Qi also has a huge collection of sites great for personal uses. Do you wish to create a new CV or a resume, or perhaps you are a restaurant owner, a videographer or an SEO expert? Or maybe you’re just looking for a captivating yet simple way to announce your wedding? Whatever it might be, Qi has you covered! Top all this off with the authentic design style that Qode Interactive collective is known for, and you get a true creative powerhouse that’s fast, reliable and comes with virtually limitless customization options! Author: Qode Interactive Author URI: https://qodeinteractive.com Text Domain: qi Version: 1.2 Requires at least: 5.0 Tested up to: 6.1 Requires PHP: 5.6 Tags: food-and-drink, e-commerce, portfolio, grid-layout, one-column, two-columns, three-columns, four-columns, left-sidebar, right-sidebar, featured-images, custom-logo, custom-menu, footer-widgets, post-formats, full-width-template, sticky-post, threaded-comments, translation-ready, editor-style License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html All files, unless otherwise stated, are released under the GNU General Public License version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) This theme, like WordPress, is licensed under the GPL. Use it to make something cool, have fun, and share what you've learned with others. */ index.php000064400000000032146706031200006356 0ustar00 cf7-styler.php000064400000017660146725417150007302 0ustar00 '4879', 'slug' => 'cf7-styler', 'premium_slug' => 'cf7-styler-pro', 'type' => 'plugin', 'public_key' => 'pk_430f963531baceba1e271f3a35041', 'is_premium' => false, 'premium_suffix' => 'Pro', // If your plugin is a serviceware, set this option to false. 'has_premium_version' => true, 'has_addons' => false, 'has_paid_plans' => true, 'is_org_compliant' => true, 'trial' => array( 'days' => 14, 'is_require_payment' => true, ), 'has_affiliation' => 'all', 'menu' => array( 'slug' => 'cf7cstmzr_page', 'support' => true, 'contact' => false, 'parent' => array( 'slug' => 'wpcf7', ), ), // Set the SDK to work in a sandbox mode (for development & testing). // IMPORTANT: MAKE SURE TO REMOVE SECRET KEY BEFORE DEPLOYMENT. 'secret_key' => $secret_key, ); if (!cf7cstmzr_is_plugin_activated( 'contact-form-7', 'wp-contact-form-7.php' )) { $params['menu'] = array( 'slug' => 'cf7cstmzr_page', 'support' => true, 'contact' => false, ); } $cf7_styler = fs_dynamic_init( $params ); } return $cf7_styler; } // Init Freemius. cf7_styler(); // Signal that SDK was initiated. do_action( 'cf7_styler_loaded' ); } } if( !function_exists('cf7cstmzr_show_cf7_missing_notice') ) { function cf7cstmzr_show_cf7_missing_notice() { echo '

' . sprintf( esc_html__( 'CF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.', 'cf7-styler' ), 'Contact Form 7 here' ) . '

'; } } if( !function_exists('cf7cstmzr_show_dev_env_notice') ) { function cf7cstmzr_show_dev_env_notice() { ?>

DEV env: version current branch

run(); } } run_cf7_customizer(); public/vendors/split/packages/split-grid/src/index.js000064400000043442146725417150016750 0ustar00import { parse, getSizeAtTrack } from 'grid-template-utils' import { getStyles, getGapValue, firstNonZero } from './util' import getMatchedCSSRules from './getMatchedCSSRules' const gridTemplatePropColumns = 'grid-template-columns' const gridTemplatePropRows = 'grid-template-rows' const NOOP = () => false const defaultWriteStyle = (element, gridTemplateProp, style) => { // eslint-disable-next-line no-param-reassign element.style[gridTemplateProp] = style } const getOption = (options, propName, def) => { const value = options[propName] if (value !== undefined) { return value } return def } class Gutter { constructor(direction, options, parentOptions) { this.direction = direction this.element = options.element this.track = options.track if (direction === 'column') { this.gridTemplateProp = gridTemplatePropColumns this.gridGapProp = 'grid-column-gap' this.cursor = getOption( parentOptions, 'columnCursor', getOption(parentOptions, 'cursor', 'col-resize'), ) this.snapOffset = getOption( parentOptions, 'columnSnapOffset', getOption(parentOptions, 'snapOffset', 30), ) this.dragInterval = getOption( parentOptions, 'columnDragInterval', getOption(parentOptions, 'dragInterval', 1), ) this.clientAxis = 'clientX' this.optionStyle = getOption(parentOptions, 'gridTemplateColumns') } else if (direction === 'row') { this.gridTemplateProp = gridTemplatePropRows this.gridGapProp = 'grid-row-gap' this.cursor = getOption( parentOptions, 'rowCursor', getOption(parentOptions, 'cursor', 'row-resize'), ) this.snapOffset = getOption( parentOptions, 'rowSnapOffset', getOption(parentOptions, 'snapOffset', 30), ) this.dragInterval = getOption( parentOptions, 'rowDragInterval', getOption(parentOptions, 'dragInterval', 1), ) this.clientAxis = 'clientY' this.optionStyle = getOption(parentOptions, 'gridTemplateRows') } this.onDragStart = getOption(parentOptions, 'onDragStart', NOOP) this.onDragEnd = getOption(parentOptions, 'onDragEnd', NOOP) this.onDrag = getOption(parentOptions, 'onDrag', NOOP) this.writeStyle = getOption( parentOptions, 'writeStyle', defaultWriteStyle, ) this.startDragging = this.startDragging.bind(this) this.stopDragging = this.stopDragging.bind(this) this.drag = this.drag.bind(this) this.minSizeStart = options.minSizeStart this.minSizeEnd = options.minSizeEnd if (options.element) { this.element.addEventListener('mousedown', this.startDragging) this.element.addEventListener('touchstart', this.startDragging) } } getDimensions() { const { width, height, top, bottom, left, right, } = this.grid.getBoundingClientRect() if (this.direction === 'column') { this.start = top this.end = bottom this.size = height } else if (this.direction === 'row') { this.start = left this.end = right this.size = width } } getSizeAtTrack(track, end) { return getSizeAtTrack( track, this.computedPixels, this.computedGapPixels, end, ) } getSizeOfTrack(track) { return this.computedPixels[track].numeric } getRawTracks() { const tracks = getStyles( this.gridTemplateProp, [this.grid], getMatchedCSSRules(this.grid), ) if (!tracks.length) { if (this.optionStyle) return this.optionStyle throw Error('Unable to determine grid template tracks from styles.') } return tracks[0] } getGap() { const gap = getStyles( this.gridGapProp, [this.grid], getMatchedCSSRules(this.grid), ) if (!gap.length) { return null } return gap[0] } getRawComputedTracks() { return window.getComputedStyle(this.grid)[this.gridTemplateProp] } getRawComputedGap() { return window.getComputedStyle(this.grid)[this.gridGapProp] } setTracks(raw) { this.tracks = raw.split(' ') this.trackValues = parse(raw) } setComputedTracks(raw) { this.computedTracks = raw.split(' ') this.computedPixels = parse(raw) } setGap(raw) { this.gap = raw } setComputedGap(raw) { this.computedGap = raw this.computedGapPixels = getGapValue('px', this.computedGap) || 0 } getMousePosition(e) { if ('touches' in e) return e.touches[0][this.clientAxis] return e[this.clientAxis] } startDragging(e) { if ('button' in e && e.button !== 0) { return } // Don't actually drag the element. We emulate that in the drag function. e.preventDefault() if (this.element) { this.grid = this.element.parentNode } else { this.grid = e.target.parentNode } this.getDimensions() this.setTracks(this.getRawTracks()) this.setComputedTracks(this.getRawComputedTracks()) this.setGap(this.getGap()) this.setComputedGap(this.getRawComputedGap()) const trackPercentage = this.trackValues.filter( track => track.type === '%', ) const trackFr = this.trackValues.filter(track => track.type === 'fr') this.totalFrs = trackFr.length if (this.totalFrs) { const track = firstNonZero(trackFr) if (track !== null) { this.frToPixels = this.computedPixels[track].numeric / trackFr[track].numeric } } if (trackPercentage.length) { const track = firstNonZero(trackPercentage) if (track !== null) { this.percentageToPixels = this.computedPixels[track].numeric / trackPercentage[track].numeric } } // get start of gutter track const gutterStart = this.getSizeAtTrack(this.track, false) + this.start this.dragStartOffset = this.getMousePosition(e) - gutterStart this.aTrack = this.track - 1 if (this.track < this.tracks.length - 1) { this.bTrack = this.track + 1 } else { throw Error( `Invalid track index: ${ this.track }. Track must be between two other tracks and only ${ this.tracks.length } tracks were found.`, ) } this.aTrackStart = this.getSizeAtTrack(this.aTrack, false) + this.start this.bTrackEnd = this.getSizeAtTrack(this.bTrack, true) + this.start // Set the dragging property of the pair object. this.dragging = true // All the binding. `window` gets the stop events in case we drag out of the elements. window.addEventListener('mouseup', this.stopDragging) window.addEventListener('touchend', this.stopDragging) window.addEventListener('touchcancel', this.stopDragging) window.addEventListener('mousemove', this.drag) window.addEventListener('touchmove', this.drag) // Disable selection. Disable! this.grid.addEventListener('selectstart', NOOP) this.grid.addEventListener('dragstart', NOOP) this.grid.style.userSelect = 'none' this.grid.style.webkitUserSelect = 'none' this.grid.style.MozUserSelect = 'none' this.grid.style.pointerEvents = 'none' // Set the cursor at multiple levels this.grid.style.cursor = this.cursor window.document.body.style.cursor = this.cursor this.onDragStart(this.direction, this.track) } stopDragging() { this.dragging = false // Remove the stored event listeners. This is why we store them. this.cleanup() this.onDragEnd(this.direction, this.track) if (this.needsDestroy) { if (this.element) { this.element.removeEventListener( 'mousedown', this.startDragging, ) this.element.removeEventListener( 'touchstart', this.startDragging, ) } this.destroyCb() this.needsDestroy = false this.destroyCb = null } } drag(e) { let mousePosition = this.getMousePosition(e) const gutterSize = this.getSizeOfTrack(this.track) const minMousePosition = this.aTrackStart + this.minSizeStart + this.dragStartOffset + this.computedGapPixels const maxMousePosition = this.bTrackEnd - this.minSizeEnd - this.computedGapPixels - (gutterSize - this.dragStartOffset) const minMousePositionOffset = minMousePosition + this.snapOffset const maxMousePositionOffset = maxMousePosition - this.snapOffset if (mousePosition < minMousePositionOffset) { mousePosition = minMousePosition } if (mousePosition > maxMousePositionOffset) { mousePosition = maxMousePosition } if (mousePosition < minMousePosition) { mousePosition = minMousePosition } else if (mousePosition > maxMousePosition) { mousePosition = maxMousePosition } let aTrackSize = mousePosition - this.aTrackStart - this.dragStartOffset - this.computedGapPixels let bTrackSize = this.bTrackEnd - mousePosition + this.dragStartOffset - gutterSize - this.computedGapPixels if (this.dragInterval > 1) { const aTrackSizeIntervaled = Math.round(aTrackSize / this.dragInterval) * this.dragInterval bTrackSize -= aTrackSizeIntervaled - aTrackSize aTrackSize = aTrackSizeIntervaled } if (aTrackSize < this.minSizeStart) { aTrackSize = this.minSizeStart } if (bTrackSize < this.minSizeEnd) { bTrackSize = this.minSizeEnd } if (this.trackValues[this.aTrack].type === 'px') { this.tracks[this.aTrack] = `${aTrackSize}px` } else if (this.trackValues[this.aTrack].type === 'fr') { if (this.totalFrs === 1) { this.tracks[this.aTrack] = '1fr' } else { const targetFr = aTrackSize / this.frToPixels this.tracks[this.aTrack] = `${targetFr}fr` } } else if (this.trackValues[this.aTrack].type === '%') { const targetPercentage = aTrackSize / this.percentageToPixels this.tracks[this.aTrack] = `${targetPercentage}%` } if (this.trackValues[this.bTrack].type === 'px') { this.tracks[this.bTrack] = `${bTrackSize}px` } else if (this.trackValues[this.bTrack].type === 'fr') { if (this.totalFrs === 1) { this.tracks[this.bTrack] = '1fr' } else { const targetFr = bTrackSize / this.frToPixels this.tracks[this.bTrack] = `${targetFr}fr` } } else if (this.trackValues[this.bTrack].type === '%') { const targetPercentage = bTrackSize / this.percentageToPixels this.tracks[this.bTrack] = `${targetPercentage}%` } const style = this.tracks.join(' ') this.writeStyle(this.grid, this.gridTemplateProp, style) this.onDrag(this.direction, this.track, style) } cleanup() { window.removeEventListener('mouseup', this.stopDragging) window.removeEventListener('touchend', this.stopDragging) window.removeEventListener('touchcancel', this.stopDragging) window.removeEventListener('mousemove', this.drag) window.removeEventListener('touchmove', this.drag) if (this.grid) { this.grid.removeEventListener('selectstart', NOOP) this.grid.removeEventListener('dragstart', NOOP) this.grid.style.userSelect = '' this.grid.style.webkitUserSelect = '' this.grid.style.MozUserSelect = '' this.grid.style.pointerEvents = '' this.grid.style.cursor = '' } window.document.body.style.cursor = '' } destroy(immediate = true, cb) { if (immediate || this.dragging === false) { this.cleanup() if (this.element) { this.element.removeEventListener( 'mousedown', this.startDragging, ) this.element.removeEventListener( 'touchstart', this.startDragging, ) } if (cb) { cb() } } else { this.needsDestroy = true if (cb) { this.destroyCb = cb } } } } const getTrackOption = (options, track, defaultValue) => { if (track in options) { return options[track] } return defaultValue } const createGutter = (direction, options) => gutterOptions => { if (gutterOptions.track < 1) { throw Error( `Invalid track index: ${ gutterOptions.track }. Track must be between two other tracks.`, ) } const trackMinSizes = direction === 'column' ? options.columnMinSizes || {} : options.rowMinSizes || {} const trackMinSize = direction === 'column' ? 'columnMinSize' : 'rowMinSize' return new Gutter( direction, { minSizeStart: getTrackOption( trackMinSizes, gutterOptions.track - 1, getOption( options, trackMinSize, getOption(options, 'minSize', 0), ), ), minSizeEnd: getTrackOption( trackMinSizes, gutterOptions.track + 1, getOption( options, trackMinSize, getOption(options, 'minSize', 0), ), ), ...gutterOptions, }, options, ) } class Grid { constructor(options) { this.columnGutters = {} this.rowGutters = {} this.options = { columnGutters: options.columnGutters || [], rowGutters: options.rowGutters || [], columnMinSizes: options.columnMinSizes || {}, rowMinSizes: options.rowMinSizes || {}, ...options, } this.options.columnGutters.forEach(gutterOptions => { this.columnGutters[options.track] = createGutter( 'column', this.options, )(gutterOptions) }) this.options.rowGutters.forEach(gutterOptions => { this.rowGutters[options.track] = createGutter('row', this.options)( gutterOptions, ) }) } addColumnGutter(element, track) { if (this.columnGutters[track]) { this.columnGutters[track].destroy() } this.columnGutters[track] = createGutter('column', this.options)({ element, track, }) } addRowGutter(element, track) { if (this.rowGutters[track]) { this.rowGutters[track].destroy() } this.rowGutters[track] = createGutter('row', this.options)({ element, track, }) } removeColumnGutter(track, immediate = true) { if (this.columnGutters[track]) { this.columnGutters[track].destroy(immediate, () => { delete this.columnGutters[track] }) } } removeRowGutter(track, immediate = true) { if (this.rowGutters[track]) { this.rowGutters[track].destroy(immediate, () => { delete this.rowGutters[track] }) } } handleDragStart(e, direction, track) { if (direction === 'column') { if (this.columnGutters[track]) { this.columnGutters[track].destroy() } this.columnGutters[track] = createGutter('column', this.options)({ track, }) this.columnGutters[track].startDragging(e) } else if (direction === 'row') { if (this.rowGutters[track]) { this.rowGutters[track].destroy() } this.rowGutters[track] = createGutter('row', this.options)({ track, }) this.rowGutters[track].startDragging(e) } } destroy(immediate = true) { Object.keys(this.columnGutters).forEach(track => this.columnGutters[track].destroy(immediate, () => { delete this.columnGutters[track] }), ) Object.keys(this.rowGutters).forEach(track => this.rowGutters[track].destroy(immediate, () => { delete this.rowGutters[track] }), ) } } export default options => new Grid(options) public/vendors/split/packages/split-grid/src/util.js000064400000001070146725417150016605 0ustar00export const getStyles = (rule, ownRules, matchedRules) => [...ownRules, ...matchedRules] .map(r => r.style[rule]) .filter(style => style !== undefined && style !== '') export const getGapValue = (unit, size) => { if (size.endsWith(unit)) { return Number(size.slice(0, -1 * unit.length)) } return null } export const firstNonZero = tracks => { // eslint-disable-next-line no-plusplus for (let i = 0; i < tracks.length; i++) { if (tracks[i].numeric > 0) { return i } } return null } public/vendors/split/packages/split-grid/src/util.test.js000064400000004350146725417150017567 0ustar00/* eslint-env jest */ import { getStyles, getGapValue, firstNonZero } from './util' const ownStyle = { 'grid-template-columns': '2px 2px 2px' } const columns = { 'grid-template-columns': '1px 1px 1px' } const emptyColumns = { 'grid-template-columns': '' } const noColumns = {} test('getStyles columns', () => { const res = getStyles( 'grid-template-columns', [{ style: {} }], [{ style: columns }], ) expect(res).toEqual(['1px 1px 1px']) }) test('getStyles emptyColumns', () => { const res = getStyles( 'grid-template-columns', [{ style: {} }], [{ style: emptyColumns }], ) expect(res).toEqual([]) }) test('getStyles noColumns', () => { const res = getStyles( 'grid-template-columns', [{ style: {} }], [{ style: noColumns }], ) expect(res).toEqual([]) }) test('getStyles ownStyle', () => { const res = getStyles( 'grid-template-columns', [{ style: ownStyle }], [{ style: noColumns }], ) expect(res).toEqual(['2px 2px 2px']) }) test('getStyles ownStyle no match', () => { const res = getStyles( 'grid-template-columns', [{ style: { other: '1' } }], [{ style: columns }], ) expect(res).toEqual(['1px 1px 1px']) }) const rows = { 'grid-template-rows': '1px 1px 1px' } const emptyRows = { 'grid-template-rows': '' } const noRows = {} test('getStyles rows', () => { const res = getStyles( 'grid-template-rows', [{ style: {} }], [{ style: rows }], ) expect(res).toEqual(['1px 1px 1px']) }) test('getStyles emptyRows', () => { const res = getStyles( 'grid-template-rows', [{ style: {} }], [{ style: emptyRows }], ) expect(res).toEqual([]) }) test('getStyles noRows', () => { const res = getStyles( 'grid-template-rows', [{ style: {} }], [{ style: noRows }], ) expect(res).toEqual([]) }) test('getGapValue', () => { expect(getGapValue('px', '10px')).toEqual(10) }) test('firstNonZero first', () => { expect(firstNonZero([{ numeric: 1 }, { numeric: 0 }])).toEqual(0) }) test('firstNonZero second', () => { expect(firstNonZero([{ numeric: 0 }, { numeric: 1 }])).toEqual(1) }) public/vendors/split/packages/split-grid/src/getMatchedCSSRules.js000064400000001165146725417150021266 0ustar00export default el => [] .concat( ...Array.from(el.ownerDocument.styleSheets).map(s => { let rules = [] try { rules = Array.from(s.cssRules || []) } catch (e) { // Ignore results on security error } return rules }), ) .filter(r => { let matches = false try { matches = el.matches(r.selectorText) } catch (e) { // Ignore matching erros } return matches }) public/vendors/split/packages/split-grid/LICENSE.txt000064400000002041146725417150016325 0ustar00Copyright (c) 2018 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/packages/split-grid/.babelrc000064400000000046146725417150016100 0ustar00{ "presets": ["@babel/preset-env"] }public/vendors/split/packages/split-grid/rollup.config.js000064400000002764146725417150017635 0ustar00import resolve from 'rollup-plugin-node-resolve' import buble from 'rollup-plugin-buble' import { uglify } from 'rollup-plugin-uglify' const pkg = require('./package.json') export default [ { input: './src/index.js', output: [ { name: 'Split', file: pkg.main, format: 'umd', sourcemap: false, banner: `/*! ${pkg.name} - v${pkg.version} */\n`, }, { file: pkg.module, format: 'esm', sourcemap: false, }, ], plugins: [ resolve(), buble({ exclude: 'node_modules/**', objectAssign: 'Object.assign', transforms: { forOf: false, }, }), ], }, { input: './src/index.js', output: { name: 'Split', file: pkg['minified:main'], format: 'umd', sourcemap: true, banner: `/*! ${pkg.name} - v${pkg.version} */\n`, }, plugins: [ resolve(), buble({ exclude: 'node_modules/**', objectAssign: 'Object.assign', transforms: { forOf: false, }, }), uglify({ output: { comments: /^!/, }, }), ], }, ] public/vendors/split/packages/split-grid/package.json000064400000001361146725417150016774 0ustar00{ "name": "split-grid", "version": "1.0.9", "description": "The spiritual successor of Split.js, built for CSS Grid", "main": "dist/split-grid.js", "minified:main": "dist/split-grid.min.js", "module": "dist/split-grid.es.js", "scripts": { "build": "rollup -c && npm run size", "watch": "rollup -cw", "test": "jest", "lint": "eslint src", "size": "echo \"gzip size: $(gzip-size --raw $npm_package_minified_main) bytes\"" }, "repository": "https://github.com/nathancahill/split", "author": "Nathan Cahill ", "homepage": "https://split.js.org/", "files": ["dist"], "license": "MIT", "collective": { "type": "opencollective", "url": "https://opencollective.com/splitjs" } } public/vendors/split/packages/split-grid/README.md000064400000027601146725417150015772 0ustar00 # Split Grid [![CI](https://img.shields.io/circleci/project/github/nathancahill/split/master.svg)](https://circleci.com/gh/nathancahill/split) ![Dependencies](https://david-dm.org/nathancahill/split/status.svg) [![File size](https://img.badgesize.io/https://unpkg.com/split-grid/dist/split-grid.min.js?compression=gzip&label=size&v=1.0.7)](https://unpkg.com/split-grid/dist/split-grid.min.js) The spiritual successor of [Split.js](https://github.com/nathancahill/split/tree/master/packages/splitjs), built for CSS Grid. - __Zero Deps__ - __Tiny:__ Weights 2kb gzipped. - __Fast:__ No overhead or attached window event listeners, uses pure CSS for resizing. - __Unopinionated:__ Only modifies `grid-template-*` rules, the rest of the layout is up to you. ## Table of Contents - [Installation](#installation) - [Example](#example) - [Reference](#reference) - [API](#api) - [Migrating from Split.js](#migrating-from-splitjs) - [License](#license) ## Installation Yarn: ``` $ yarn add split-grid ``` npm: ``` $ npm install --save split-grid ``` Include with a module bundler like [rollup](http://rollupjs.org/) or [webpack](https://webpack.github.io/): ```js // using ES6 modules import Split from 'split-grid' // using CommonJS modules var Split = require('split-grid') ``` The [UMD](https://github.com/umdjs/umd) build is also available on [unpkg](http://unpkg.com/): ```html ``` You can find the library on `window.Split`. ## Example ```js import Split from 'split-grid' Split({ columnGutters: [{ track: 1, element: document.querySelector('.column-1'), }, { track: 3, element: document.querySelector('.column-3'), }], rowGutters: [{ track: 1, element: document.querySelector('.row-1'), }] }) ``` ## Reference ```js Split(options: Options) ``` ### Supported CSS values Current CSS values that are supported in `grid-template, grid-template-columns, grid-template-rows`: - [x] `fr` - [x] `px` - [x] `%` - [x] `repeat` Not supported (yet): - [ ] `auto` - [ ] other CSS values (`em, vmin, cm, etc`) ### Options Most of the options can be specified as `option`, `columnOption` and `rowOption`. This allows default option values to be set for both, or specified individually for each axis. ##### `columnGutters: [{ element: HTMLElement, track: number }]` An array of objects, with `element` and `track` keys. `element` is the element in the grid to enable as a draggable gutter. `track` is the grid track the gutter element is positioned on. These must match. ##### `rowGutters: [{ element: HTMLElement, track: number }]` An array of objects, with `element` and `track` keys. `element` is the element in the grid to enable as a draggable gutter. `track` is the grid track the gutter element is positioned on. These must match. ##### `minSize: number` The minimum size in pixels for all tracks. Default: `0` ##### `columnMinSize: number` The minimum size in pixels for all tracks. Default: `options.minSize` ##### `rowMinSize: number` The minimum size in pixels for all tracks. Default: `options.minSize` ##### `columnMinSizes: { [track: number]: number }` An object keyed by `track` index, with values set to the minimum size in pixels for the track at that index. Allows individual minSizes to be specified by track. Note this option is plural with an `s`, while the two fallback options are singular. Default: `options.columnMinSize` ##### `rowMinSizes: { [track: number]: number }` An object keyed by `track` index, with values set to the minimum size in pixels for the track at that index. Allows individual minSizes to be specified by track. Note this option is plural with an `s`, while the two fallback options are singular. Default: `options.rowMinSize` ##### `snapOffset: number` Snap to minimum size at this offset in pixels. Set to `0` to disable snap. Default: `30` ##### `columnSnapOffset: number` Snap to minimum size at this offset in pixels. Set to `0` to disable snap. Default: `options.snapOffset` ##### `rowSnapOffset: number` Snap to minimum size at this offset in pixels. Set to `0` to disable snap. Default: `options.snapOffset` ##### `dragInterval: number` Drag this number of pixels at a time. Defaults to `1` for smooth dragging, but can be set to a pixel value to give more control over the resulting sizes. Default: `1` ##### `columnDragInterval: number` Drag this number of pixels at a time. Defaults to `1` for smooth dragging, but can be set to a pixel value to give more control over the resulting sizes. Default: `options.dragInterval` ##### `rowDragInterval: number` Drag this number of pixels at a time. Defaults to `1` for smooth dragging, but can be set to a pixel value to give more control over the resulting sizes. Default: `options.dragInterval` ##### `cursor: string` Cursor to show while dragging. Defaults to `'col-resize'` for column gutters and `'row-resize'` for row gutters. ##### `columnCursor: string` Cursor to show while dragging. Default: `'col-resize'` ##### `rowCursor: string` Cursor to show while dragging. Default: `'row-resize'` ##### `onDrag: (direction: 'row' | 'column', track: number, gridTemplateStyle: string) => void` Called continously on drag. For process intensive code, add a debounce function to rate limit this callback. `gridTemplateStyle` is the computed CSS value for `grid-template-column` or `grid-template-row`, depending on `direction`. ##### `onDragStart: (direction: 'row' | 'column', track: number) => void` Called on drag start. ##### `onDragEnd: (direction: 'row' | 'column', track: number) => void` Called on drag end. ##### `writeStyle: (grid: HTMLElement, gridTemplateProp: 'grid-template-column' | 'grid-template-row', gridTemplateStyle: string) => void` Called to update the CSS properties of the grid element. Must eventually apply the CSS value to the CSS prop, or the grid will not change. `gridTemplateStyle` is the computed CSS value of CSS rule `gridTemplateProp`. Default: ```js writeStyle: (grid, gridTemplateProp, gridTemplateStyle) => { grid.style[gridTemplateProp] = gridTemplateStyle } ``` ##### `gridTemplateColumns` `gridTemplateRows` Helper options for determining initial CSS values for `grid-template-columns` and `grid-template-rows`. Most of the time this option is not needed, as Split Grid reads the CSS rules applied to the grid element, but security settings may prevent that, for example, when the CSS is served from a 3rd-party domain. This is ONLY NEEDED if the default method of reading the CSS values errors. This option does not immediately apply CSS rules, it's only used on drag. ## API ```js const split = Split(options: Options) ``` Split Grid returns an instance with a couple of functions. The instance is returned on creation. ##### `split.addColumnGutter(element: HTMLElement, track: number)` Adds a draggable row gutter. The element must be a direct descendant of the element with grid layout, and positioned in the specified track. ```js const grid = document.querySelector('.grid') const gutter = document.createElement('div') grid.appendChild(gutter) // append to DOM split.addColumnGutter(gutter, 1) // add to Split Grid ``` ##### `split.addRowGutter(element: HTMLElement, track: number)` Adds a draggable row gutter. The element must be a direct descendant of the element with grid layout, and positioned in the specified track. ```js const grid = document.querySelector('.grid') const gutter = document.createElement('div') grid.appendChild(gutter) // append to DOM split.addRowGutter(gutter, 1) // add to Split Grid ``` ##### `split.removeColumnGutter(track: number, immediate?: true)` Removes event listeners from a column gutter by track number. If `immediate = false` is passed, event handlers are removed after dragging ends. If a gutter isn't currently being dragged, it's event handlers are removed immediately. ##### `split.removeRowGutter(track: number, immediate?: true)` Removes event listeners from a row gutter by track number. If `immediate = false` is passed, event handlers are removed after dragging ends. If a gutter isn't currently being dragged, it's event handlers are removed immediately. ##### `split.destroy(immediate?: true)` Destroy the instance by removing the attached event listeners. If `immediate = false` is passed, the instance is destroyed after dragging ends. If a gutter isn't currently being dragged, it's destroyed immediately. ## Migrating from Split.js #### Bring your own gutters In Split.js, gutter elements were created by Split.js and inserted in to the DOM. This is not the case in Split Grid. Create the gutter elements in the HTML as children of the grid element, and lay them out in the tracks like any other element. Pass the gutter elements in the options with their track index. __Split.js__ ```js Split(options) // gutters created implicitly ``` __Split Grid__ Gutters are part of the grid layout: ```html
Column One
Column Two
Column Three
Row One
Row Two
``` ```js Split({ // gutters specified in options columnGutters: [{ track: 1, element: document.querySelector('.gutter-column-1'), }, { track: 3, element: document.querySelector('.gutter-column-3'), }], rowGutters: [{ track: 1, element: document.querySelector('.gutter-row-1'), }] }) ``` #### CSS values replace `sizes` option CSS grid layout offers more flexibility than Split.js's percentage values, so Split Grid uses the `grid-template` values directly. Instead of setting the initial sizes as an option in Javascript, set the initial sizes in CSS. __Split.js__ ```js Split({ sizes: [50, 50] }) ``` __Split Grid__ ```html
``` _or_ ```js > document.querySelector('.grid').style['grid-template-columns'] = '1fr 10px 1fr' ``` #### `split.getSizes()` is replaced by CSS values Likewise, the `.getSizes()` function is replaced by reading the CSS values directly. __Split.js__ ```js > split.getSizes() [50, 50] ``` __Split Grid__ ```js > document.querySelector('.grid').style['grid-template-columns'] "1fr 10px 1fr" ``` #### `split.setSizes()` is replaced by CSS values In the same way, the `.getSizes()` function is replaced by setting the CSS values directly. __Split.js__ ```js > split.setSizes([50, 50]) ``` __Split Grid__ ```js > document.querySelector('.grid').style['grid-template-columns'] = '1fr 10px 1fr' ``` #### `split.destroy()` has different parameters in Split Grid Since there's no styles or gutters added by Split Grid, there's no need for Split.js' `preserveStyles` and `preserveGutters` parameters. Instead, `.destroy()` takes one parameter, `immediate: boolean`, whether to wait until the gutter has stopped dragging before removing event listeners. ## License Copyright (c) 2019 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/packages/react-split/src/index.js000064400000012415146725417150017115 0ustar00import React from 'react' import PropTypes from 'prop-types' import Split from 'split.js' class SplitWrapper extends React.Component { componentDidMount() { const { children, gutter, ...options } = this.props options.gutter = (index, direction) => { let gutterElement if (gutter) { gutterElement = gutter(index, direction) } else { gutterElement = document.createElement('div') gutterElement.className = `gutter gutter-${direction}` } // eslint-disable-next-line no-underscore-dangle gutterElement.__isSplitGutter = true return gutterElement } this.split = Split(this.parent.children, options) } componentDidUpdate(prevProps) { const { children, minSize, sizes, collapsed, ...options } = this.props const { minSize: prevMinSize, sizes: prevSizes, collapsed: prevCollapsed, } = prevProps const otherProps = [ 'expandToMin', 'gutterSize', 'gutterAlign', 'snapOffset', 'dragInterval', 'direction', 'cursor', ] let needsRecreate = otherProps // eslint-disable-next-line react/destructuring-assignment .map(prop => this.props[prop] !== prevProps[prop]) .reduce((accum, same) => accum || same, false) // Compare minSize when both are arrays, when one is an array and when neither is an array if (Array.isArray(minSize) && Array.isArray(prevMinSize)) { let minSizeChanged = false minSize.forEach((minSizeI, i) => { minSizeChanged = minSizeChanged || minSizeI !== prevMinSize[i] }) needsRecreate = needsRecreate || minSizeChanged } else if (Array.isArray(minSize) || Array.isArray(prevMinSize)) { needsRecreate = true } else { needsRecreate = needsRecreate || minSize !== prevMinSize } // Destroy and re-create split if options changed if (needsRecreate) { options.minSize = minSize options.sizes = sizes || this.split.getSizes() this.split.destroy(true, true) options.gutter = (index, direction, pairB) => pairB.previousSibling this.split = Split( Array.from(this.parent.children).filter( // eslint-disable-next-line no-underscore-dangle element => !element.__isSplitGutter, ), options, ) } else if (sizes) { // If only the size has changed, set the size. No need to do this if re-created. let sizeChanged = false sizes.forEach((sizeI, i) => { sizeChanged = sizeChanged || sizeI !== prevSizes[i] }) if (sizeChanged) { // eslint-disable-next-line react/destructuring-assignment this.split.setSizes(this.props.sizes) } } // Collapse after re-created or when collapsed changed. if ( Number.isInteger(collapsed) && (collapsed !== prevCollapsed || needsRecreate) ) { this.split.collapse(collapsed) } } componentWillUnmount() { this.split.destroy() delete this.split } render() { const { sizes, minSize, expandToMin, gutterSize, gutterAlign, snapOffset, dragInterval, direction, cursor, gutter, elementStyle, gutterStyle, onDrag, onDragStart, onDragEnd, collapsed, children, ...rest } = this.props return (
{ this.parent = parent }} {...rest} > {children}
) } } SplitWrapper.propTypes = { sizes: PropTypes.arrayOf(PropTypes.number), minSize: PropTypes.oneOfType([ PropTypes.number, PropTypes.arrayOf(PropTypes.number), ]), expandToMin: PropTypes.bool, gutterSize: PropTypes.number, gutterAlign: PropTypes.string, snapOffset: PropTypes.number, dragInterval: PropTypes.number, direction: PropTypes.string, cursor: PropTypes.string, gutter: PropTypes.func, elementStyle: PropTypes.func, gutterStyle: PropTypes.func, onDrag: PropTypes.func, onDragStart: PropTypes.func, onDragEnd: PropTypes.func, collapsed: PropTypes.number, children: PropTypes.arrayOf(PropTypes.element), } SplitWrapper.defaultProps = { sizes: undefined, minSize: undefined, expandToMin: undefined, gutterSize: undefined, gutterAlign: undefined, snapOffset: undefined, dragInterval: undefined, direction: undefined, cursor: undefined, gutter: undefined, elementStyle: undefined, gutterStyle: undefined, onDrag: undefined, onDragStart: undefined, onDragEnd: undefined, collapsed: undefined, children: undefined, } export default SplitWrapper public/vendors/split/packages/react-split/src/index.test.js000064400000000052146725417150020065 0ustar00/* eslint-env jest */ test('', () => {}) public/vendors/split/packages/react-split/LICENSE.txt000064400000002041146725417150016476 0ustar00Copyright (c) 2018 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/packages/react-split/rollup.config.js000064400000003515146725417150020001 0ustar00import buble from 'rollup-plugin-buble' import { uglify } from 'rollup-plugin-uglify' const pkg = require('./package.json') export default [ { input: './src/index.js', output: [ { name: 'ReactSplit', file: pkg.main, format: 'umd', sourcemap: false, banner: `/*! ${pkg.name} - v${pkg.version} */\n`, globals: { react: 'React', 'prop-types': 'PropTypes', 'split.js': 'Split', }, }, { file: pkg.module, format: 'esm', sourcemap: false, }, ], external: ['split.js', 'react', 'prop-types'], plugins: [ buble({ exclude: 'node_modules/**', objectAssign: 'Object.assign', transforms: { forOf: false, }, }), ], }, { input: './src/index.js', output: { name: 'ReactSplit', file: pkg['minified:main'], format: 'umd', sourcemap: true, banner: `/*! ${pkg.name} - v${pkg.version} */\n`, globals: { react: 'React', 'prop-types': 'PropTypes', 'split.js': 'Split', }, }, external: ['split.js', 'react', 'prop-types'], plugins: [ buble({ exclude: 'node_modules/**', objectAssign: 'Object.assign', transforms: { forOf: false, }, }), uglify({ output: { comments: /^!/, }, }), ], }, ] public/vendors/split/packages/react-split/CHANGELOG.md000064400000000125146725417150016465 0ustar00### 2.0.4 - Correct the prop types for the Split component #170 - thanks @av1ctor public/vendors/split/packages/react-split/package.json000064400000001612146725417150017144 0ustar00{ "name": "react-split", "version": "2.0.7", "description": "React component for Split.js", "main": "dist/react-split.js", "minified:main": "dist/react-split.min.js", "module": "dist/react-split.es.js", "scripts": { "prepublish": "rollup -c", "build": "rollup -c && npm run size", "watch": "rollup -cw", "test": "jest", "lint": "eslint src", "size": "echo \"gzip size: $(gzip-size --raw $npm_package_minified_main) bytes\"" }, "repository": "https://github.com/nathancahill/split", "author": "Nathan Cahill ", "homepage": "https://split.js.org/", "files": ["dist"], "license": "MIT", "dependencies": { "prop-types": "^15.5.7", "split.js": "^1.5.9" }, "peerDependencies": { "react": ">=15.4.2 || >= 16.0.0" }, "collective": { "type": "opencollective", "url": "https://opencollective.com/splitjs" } } public/vendors/split/packages/react-split/README.md000064400000013636146725417150016146 0ustar00# React-Split   [![CI](https://img.shields.io/circleci/project/github/nathancahill/split/master.svg)](https://circleci.com/gh/nathancahill/split) ![Dependencies](https://david-dm.org/nathancahill/split/status.svg) ![](https://img.badgesize.io/https://unpkg.com/react-split/dist/react-split.min.js?compression=gzip&label=size&v=2.0.5) React component for [Split.js](https://github.com/nathancahill/Split.js/) ## Installation Yarn: ``` $ yarn add react-split ``` npm: ``` $ npm install --save react-split ``` Include with a module bundler like [rollup](http://rollupjs.org/) or [webpack](https://webpack.github.io/): ```js // using ES6 modules import Split from 'react-split' // using CommonJS modules var Split = require('react-split') ``` The [UMD](https://github.com/umdjs/umd) build is also available on [unpkg](http://unpkg.com/): ```html ``` You can find the library on `window.ReactSplit`. ## Usage The `` component wraps multiple children components to create a resizeable split view. The component is a light wrapper around the [Split.js](https://github.com/nathancahill/Split.js/) library and accepts (mostly) the same options. ```js import Split from 'react-split' ``` ## Reference ### `` Creates a Split instance and a `
` wrapper around the children components. All additional props are passed through to the to the `
` component. ### Example ```js import Split from 'react-split' ``` ### Props #### `sizes` `sizes?: [number]` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#sizes) #### `minSize` `minSize?: number | [number]` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#minsize-default-100) #### `expandToMin` `expandToMin?: boolean` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#expandtomin-default-false) #### `gutterSize` `gutterSize?: number` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#guttersize-default-10) #### `gutterAlign` `gutterAlign?: 'center' | 'start' | 'end'` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#gutteralign-default-center) #### `snapOffset` `snapOffset?: number` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#snapoffset-default-30) #### `dragInterval` `dragInterval?: number` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#draginterval-default-1) #### `direction` `direction?: 'horizontal' | 'vertical'` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#direction-default-horizontal) #### `cursor` `cursor?: string` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#cursor-default-col-resize) #### `gutter` `gutter?: (index, direction, pairElement) => HTMLElement` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#gutter) #### `elementStyle` `elementStyle?: (dimension, elementSize, gutterSize, index) => Object` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#elementstyle) #### `gutterStyle` `gutterStyle?: (dimension, gutterSize, index) => Object` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#gutterstyle) #### `onDrag` `onDrag?: sizes => void` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#ondrag-ondragstart-ondragend) #### `onDragStart` `onDragStart?: sizes => void` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#ondrag-ondragstart-ondragend) #### `onDragEnd` `onDragEnd?: sizes => void` - [Docs](https://github.com/nathancahill/split/tree/master/packages/splitjs#ondrag-ondragstart-ondragend) ## Migrating from Split.js Refer to [Split.js documentation](https://github.com/nathancahill/split/tree/master/packages/splitjs#documentation) for the options the component accepts as props. The differences are noted below: A few props are exempt from updating. These props are functions, these props will not trigger a `componentDidUpdate`. Following React best practices, and do not create functions in the render method. Instead, create them once and pass them as props. - `gutter` - `elementStyle` - `gutterStyle` - `onDrag` - `onDragStart` - `onDragEnd` #### API - `.setSizes(sizes)` becomes the prop `sizes={sizes}` - `.getSizes()` is unavailable, but sizes are passed to `onDragStart` and `onDragEnd` - `.collapse(index)` becomes the prop: `collapsed={index}` - `.destroy()` is triggered automatically on `componentWillUnmount` ## License Copyright (c) 2019 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/packages/grid-template-utils/src/index.js000064400000002541146725417150020561 0ustar00const numeric = (value, unit) => Number(value.slice(0, -1 * unit.length)) const parseValue = value => { if (value.endsWith('px')) return { value, type: 'px', numeric: numeric(value, 'px') } if (value.endsWith('fr')) return { value, type: 'fr', numeric: numeric(value, 'fr') } if (value.endsWith('%')) return { value, type: '%', numeric: numeric(value, '%') } if (value === 'auto') return { value, type: 'auto' } return null } export const parse = rule => rule.split(' ').map(parseValue) export const combine = (rule, tracks) => { const prevTracks = rule ? rule.split(' ') : [] tracks.forEach((track, i) => { if (i > prevTracks.length - 1) { throw new Error( `Unable to set size of track index ${i}, there are only ${ prevTracks.length } tracks in the grid layout.`, ) } prevTracks[i] = track.value ? track.value : `${track.numeric}${track.type}` }) return prevTracks.join(' ') } export const getSizeAtTrack = (index, tracks, gap = 0, end = false) => { const newIndex = end ? index + 1 : index const trackSum = tracks .slice(0, newIndex) .reduce((accum, value) => accum + value.numeric, 0) const gapSum = gap ? index * gap : 0 return trackSum + gapSum } public/vendors/split/packages/grid-template-utils/src/index.test.js000064400000010213146725417150021532 0ustar00/* eslint-env jest */ import { parse, combine, getSizeAtTrack } from './index' const sizeTracks = [ { value: '50px', type: 'px', numeric: 50 }, { value: '10px', type: 'px', numeric: 10 }, { value: '5px', type: 'px', numeric: 5 }, ] ;[ { input: '1px 2px 3px', output: [ { value: '1px', type: 'px', numeric: 1 }, { value: '2px', type: 'px', numeric: 2 }, { value: '3px', type: 'px', numeric: 3 }, ], }, { input: '1fr 2px 3fr', output: [ { value: '1fr', type: 'fr', numeric: 1 }, { value: '2px', type: 'px', numeric: 2 }, { value: '3fr', type: 'fr', numeric: 3 }, ], }, { input: '40% auto 10%', output: [ { value: '40%', type: '%', numeric: 40 }, { value: 'auto', type: 'auto' }, { value: '10%', type: '%', numeric: 10 }, ], }, { input: '1unsupported 2unsupported', output: [null, null], }, ].forEach(({ input, output }) => { test(`parse ${input}`, () => { expect(parse(input)).toEqual(output) }) }) ;[ { input: { rule: '1px 1px 1px', tracks: [ { value: '1px', type: 'px', numeric: 1 }, { value: '2px', type: 'px', numeric: 2 }, { value: '3px', type: 'px', numeric: 3 }, ], }, output: '1px 2px 3px', }, { input: { rule: '1px 1px 1px', tracks: [ { value: '1fr', type: 'fr', numeric: 1 }, { value: '2px', type: 'px', numeric: 2 }, { value: '3fr', type: 'fr', numeric: 3 }, ], }, output: '1fr 2px 3fr', }, { input: { rule: '1px 1px 1px', tracks: (() => { const sparse = [] sparse[1] = { value: '2px', type: 'px', numeric: 2 } return sparse })(), }, output: '1px 2px 1px', }, { input: { rule: '1px 1px 1px', tracks: [ { type: 'fr', numeric: 1 }, { type: 'px', numeric: 2 }, { type: 'fr', numeric: 3 }, ], }, output: '1fr 2px 3fr', }, ].forEach(({ input: { rule, tracks }, output }) => { test(`combine ${rule}`, () => { expect(combine(rule, tracks)).toEqual(output) }) }) ;[ { input: { index: 0, gap: 0, end: false, }, output: 0, }, { input: { index: 0, gap: 20, end: false, }, output: 0, }, { input: { index: 0, gap: 0, end: true, }, output: 50, }, { input: { index: 0, gap: 20, end: true, }, output: 50, }, { input: { index: 1, gap: 0, end: false, }, output: 50, }, { input: { index: 1, gap: 0, end: true, }, output: 60, }, { input: { index: 1, gap: 20, end: true, }, output: 80, }, { input: { index: 2, gap: 0, end: false, }, output: 60, }, { input: { index: 2, gap: 20, end: false, }, output: 100, }, { input: { index: 2, gap: 0, end: true, }, output: 65, }, { input: { index: 2, gap: 20, end: true, }, output: 105, }, { input: { index: 2, gap: undefined, end: true, }, output: 65, }, ].forEach(({ input: { index, gap, end }, output }) => { test(`getSizeAtTrack ${index} ${gap} ${end}`, () => { expect(getSizeAtTrack(index, sizeTracks, gap, end)).toEqual(output) }) }) public/vendors/split/packages/grid-template-utils/LICENSE.txt000064400000002041146725417150020143 0ustar00Copyright (c) 2018 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/packages/grid-template-utils/.babelrc000064400000000046146725417150017716 0ustar00{ "presets": ["@babel/preset-env"] }public/vendors/split/packages/grid-template-utils/rollup.config.js000064400000002655146725417150021452 0ustar00import buble from 'rollup-plugin-buble' import { uglify } from 'rollup-plugin-uglify' const pkg = require('./package.json') export default [ { input: './src/index.js', output: [ { name: 'GridTemplateUtils', file: pkg.main, format: 'umd', sourcemap: false, banner: `/*! ${pkg.name} - v${pkg.version} */\n`, }, { file: pkg.module, format: 'esm', sourcemap: false, }, ], plugins: [ buble({ exclude: 'node_modules/**', objectAssign: 'Object.assign', transforms: { forOf: false, }, }), ], }, { input: './src/index.js', output: { name: 'GridTemplateUtils', file: pkg['minified:main'], format: 'umd', sourcemap: true, banner: `/*! ${pkg.name} - v${pkg.version} */\n`, }, plugins: [ buble({ exclude: 'node_modules/**', objectAssign: 'Object.assign', transforms: { forOf: false, }, }), uglify({ output: { comments: /^!/, }, }), ], }, ] public/vendors/split/packages/grid-template-utils/package.json000064400000001511146725417150020607 0ustar00{ "name": "grid-template-utils", "version": "1.0.1", "description": "Utility functions for working with grid templates", "main": "dist/grid-template-utils.js", "minified:main": "dist/grid-template-utils.min.js", "module": "dist/grid-template-utils.es.js", "scripts": { "build": "rollup -c && npm run size", "watch": "rollup -cw", "test": "jest", "lint": "eslint src", "size": "echo \"gzip size: $(gzip-size --raw $npm_package_minified_main) bytes\"" }, "repository": "https://github.com/nathancahill/split", "author": "Nathan Cahill ", "homepage": "https://split.js.org/", "files": ["dist"], "license": "MIT", "collective": { "type": "opencollective", "url": "https://opencollective.com/splitjs" } } public/vendors/split/packages/grid-template-utils/README.md000064400000007474146725417150017616 0ustar00# Grid Template Utils [![CI](https://img.shields.io/circleci/project/github/nathancahill/split/master.svg)](https://circleci.com/gh/nathancahill/split) ![Dependencies](https://david-dm.org/nathancahill/split/status.svg) [![File size](https://img.badgesize.io/https://unpkg.com/grid-template-utils/dist/grid-template-utils.min.js?compression=gzip&label=size&v=1.0.0)](https://unpkg.com/grid-template-utils/dist/grid-template-utils.min.js) ## Installation Yarn: ``` $ yarn add grid-template-utils ``` npm: ``` $ npm install --save grid-template-utils ``` Include with a module bundler like [rollup](http://rollupjs.org/) or [webpack](https://webpack.github.io/): ```js // using ES6 modules import { parse, combine, getSizeAtTrack } from 'grid-template-utils' // using CommonJS modules var utils = require('grid-template-utils') ``` The [UMD](https://github.com/umdjs/umd) build is also available on [unpkg](http://unpkg.com/): ```html ``` You can find the library on `window.GridTemplateUtils`. ## Example ```js import { parse, combine, getSizeAtTrack } from 'grid-template-utils' > parse('1fr 10px 1fr') [ { value: '1fr', type: 'fr', numeric: 1, }, { value: '10px', type: 'px', numeric: 10, }, { value: '1fr', type: 'fr', numeric: 1, }, ] > combine('1fr 10px 1fr', [,{ value: '20px' }]) '1fr 20px 1fr' > getSizeAtTrack(1, parse('10px 10px 10px')) 20 > getSizeAtTrack(1, parse('10px 10px 10px'), 20) 40 ``` ## Reference ##### `Track { value: string, type: 'fr' | 'px' | '%' | 'auto', numeric: number }` Object describing CSS values for a single track in a grid template. ##### `parse(rule: string) => Track[]` Parses a `grid-template-rows` or `grid-template-columns` CSS rule to an array of `Track` objects with `value`, `type` and `numeric` keys. ##### `combine(rule: string, tracks: Track[]) => string` Updates a CSS rule with values from an array of `Track` objects. The array can be sparse, only included indices will be updated. If `Track.value` is specified, that string value will be used directly. If not, `Track.numeric` and `Track.type` are joined before interpolation. ##### `getSizeAtTrack(index: number, tracks: Track[], gap?: number = 0, end?: boolean = false) => number` Returns the pixel size measured from the start of the grid layout up to the track specified by `index`. Each `Track.numeric` value should be a `px` value (for example, as returned by `parse(getComputedStyle())`). Optional argument `gap` is the pixel size of `grid-gap`. Optional agrument `end` is a flag that determines whether to measure up to the start or end of the track. Defaults to `false` (measure to the start of the track). ## License Copyright (c) 2018 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/packages/splitjs/src/split.js000064400000064445146725417150016414 0ustar00// The programming goals of Split.js are to deliver readable, understandable and // maintainable code, while at the same time manually optimizing for tiny minified file size, // browser compatibility without additional requirements, graceful fallback (IE8 is supported) // and very few assumptions about the user's page layout. const global = window const { document } = global // Save a couple long function names that are used frequently. // This optimization saves around 400 bytes. const addEventListener = 'addEventListener' const removeEventListener = 'removeEventListener' const getBoundingClientRect = 'getBoundingClientRect' const gutterStartDragging = '_a' const aGutterSize = '_b' const bGutterSize = '_c' const HORIZONTAL = 'horizontal' const NOOP = () => false // Figure out if we're in IE8 or not. IE8 will still render correctly, // but will be static instead of draggable. const isIE8 = global.attachEvent && !global[addEventListener] // Helper function determines which prefixes of CSS calc we need. // We only need to do this once on startup, when this anonymous function is called. // // Tests -webkit, -moz and -o prefixes. Modified from StackOverflow: // http://stackoverflow.com/questions/16625140/js-feature-detection-to-detect-the-usage-of-webkit-calc-over-calc/16625167#16625167 const calc = `${['', '-webkit-', '-moz-', '-o-'] .filter(prefix => { const el = document.createElement('div') el.style.cssText = `width:${prefix}calc(9px)` return !!el.style.length }) .shift()}calc` // Helper function checks if its argument is a string-like type const isString = v => typeof v === 'string' || v instanceof String // Helper function allows elements and string selectors to be used // interchangeably. In either case an element is returned. This allows us to // do `Split([elem1, elem2])` as well as `Split(['#id1', '#id2'])`. const elementOrSelector = el => { if (isString(el)) { const ele = document.querySelector(el) if (!ele) { throw new Error(`Selector ${el} did not match a DOM element`) } return ele } return el } // Helper function gets a property from the properties object, with a default fallback const getOption = (options, propName, def) => { const value = options[propName] if (value !== undefined) { return value } return def } const getGutterSize = (gutterSize, isFirst, isLast, gutterAlign) => { if (isFirst) { if (gutterAlign === 'end') { return 0 } if (gutterAlign === 'center') { return gutterSize / 2 } } else if (isLast) { if (gutterAlign === 'start') { return 0 } if (gutterAlign === 'center') { return gutterSize / 2 } } return gutterSize } // Default options const defaultGutterFn = (i, gutterDirection) => { const gut = document.createElement('div') gut.className = `gutter gutter-${gutterDirection}` return gut } const defaultElementStyleFn = (dim, size, gutSize) => { const style = {} if (!isString(size)) { if (!isIE8) { style[dim] = `${calc}(${size}% - ${gutSize}px)` } else { style[dim] = `${size}%` } } else { style[dim] = size } return style } const defaultGutterStyleFn = (dim, gutSize) => ({ [dim]: `${gutSize}px` }) // The main function to initialize a split. Split.js thinks about each pair // of elements as an independant pair. Dragging the gutter between two elements // only changes the dimensions of elements in that pair. This is key to understanding // how the following functions operate, since each function is bound to a pair. // // A pair object is shaped like this: // // { // a: DOM element, // b: DOM element, // aMin: Number, // bMin: Number, // dragging: Boolean, // parent: DOM element, // direction: 'horizontal' | 'vertical' // } // // The basic sequence: // // 1. Set defaults to something sane. `options` doesn't have to be passed at all. // 2. Initialize a bunch of strings based on the direction we're splitting. // A lot of the behavior in the rest of the library is paramatized down to // rely on CSS strings and classes. // 3. Define the dragging helper functions, and a few helpers to go with them. // 4. Loop through the elements while pairing them off. Every pair gets an // `pair` object and a gutter. // 5. Actually size the pair elements, insert gutters and attach event listeners. const Split = (idsOption, options = {}) => { let ids = idsOption let dimension let clientAxis let position let positionEnd let clientSize let elements // Allow HTMLCollection to be used as an argument when supported if (Array.from) { ids = Array.from(ids) } // All DOM elements in the split should have a common parent. We can grab // the first elements parent and hope users read the docs because the // behavior will be whacky otherwise. const firstElement = elementOrSelector(ids[0]) const parent = firstElement.parentNode const parentStyle = getComputedStyle ? getComputedStyle(parent) : null const parentFlexDirection = parentStyle ? parentStyle.flexDirection : null // Set default options.sizes to equal percentages of the parent element. let sizes = getOption(options, 'sizes') || ids.map(() => 100 / ids.length) // Standardize minSize to an array if it isn't already. This allows minSize // to be passed as a number. const minSize = getOption(options, 'minSize', 100) const minSizes = Array.isArray(minSize) ? minSize : ids.map(() => minSize) // Get other options const expandToMin = getOption(options, 'expandToMin', false) const gutterSize = getOption(options, 'gutterSize', 10) const gutterAlign = getOption(options, 'gutterAlign', 'center') const snapOffset = getOption(options, 'snapOffset', 30) const dragInterval = getOption(options, 'dragInterval', 1) const direction = getOption(options, 'direction', HORIZONTAL) const cursor = getOption( options, 'cursor', direction === HORIZONTAL ? 'col-resize' : 'row-resize', ) const gutter = getOption(options, 'gutter', defaultGutterFn) const elementStyle = getOption( options, 'elementStyle', defaultElementStyleFn, ) const gutterStyle = getOption(options, 'gutterStyle', defaultGutterStyleFn) // 2. Initialize a bunch of strings based on the direction we're splitting. // A lot of the behavior in the rest of the library is paramatized down to // rely on CSS strings and classes. if (direction === HORIZONTAL) { dimension = 'width' clientAxis = 'clientX' position = 'left' positionEnd = 'right' clientSize = 'clientWidth' } else if (direction === 'vertical') { dimension = 'height' clientAxis = 'clientY' position = 'top' positionEnd = 'bottom' clientSize = 'clientHeight' } // 3. Define the dragging helper functions, and a few helpers to go with them. // Each helper is bound to a pair object that contains its metadata. This // also makes it easy to store references to listeners that that will be // added and removed. // // Even though there are no other functions contained in them, aliasing // this to self saves 50 bytes or so since it's used so frequently. // // The pair object saves metadata like dragging state, position and // event listener references. function setElementSize(el, size, gutSize, i) { // Split.js allows setting sizes via numbers (ideally), or if you must, // by string, like '300px'. This is less than ideal, because it breaks // the fluid layout that `calc(% - px)` provides. You're on your own if you do that, // make sure you calculate the gutter size by hand. const style = elementStyle(dimension, size, gutSize, i) Object.keys(style).forEach(prop => { // eslint-disable-next-line no-param-reassign el.style[prop] = style[prop] }) } function setGutterSize(gutterElement, gutSize, i) { const style = gutterStyle(dimension, gutSize, i) Object.keys(style).forEach(prop => { // eslint-disable-next-line no-param-reassign gutterElement.style[prop] = style[prop] }) } function getSizes() { return elements.map(element => element.size) } // Supports touch events, but not multitouch, so only the first // finger `touches[0]` is counted. function getMousePosition(e) { if ('touches' in e) return e.touches[0][clientAxis] return e[clientAxis] } // Actually adjust the size of elements `a` and `b` to `offset` while dragging. // calc is used to allow calc(percentage + gutterpx) on the whole split instance, // which allows the viewport to be resized without additional logic. // Element a's size is the same as offset. b's size is total size - a size. // Both sizes are calculated from the initial parent percentage, // then the gutter size is subtracted. function adjust(offset) { const a = elements[this.a] const b = elements[this.b] const percentage = a.size + b.size a.size = (offset / this.size) * percentage b.size = percentage - (offset / this.size) * percentage setElementSize(a.element, a.size, this[aGutterSize], a.i) setElementSize(b.element, b.size, this[bGutterSize], b.i) } // drag, where all the magic happens. The logic is really quite simple: // // 1. Ignore if the pair is not dragging. // 2. Get the offset of the event. // 3. Snap offset to min if within snappable range (within min + snapOffset). // 4. Actually adjust each element in the pair to offset. // // --------------------------------------------------------------------- // | | <- a.minSize || b.minSize -> | | // | | | <- this.snapOffset || this.snapOffset -> | | | // | | | || | | | // | | | || | | | // --------------------------------------------------------------------- // | <- this.start this.size -> | function drag(e) { let offset const a = elements[this.a] const b = elements[this.b] if (!this.dragging) return // Get the offset of the event from the first side of the // pair `this.start`. Then offset by the initial position of the // mouse compared to the gutter size. offset = getMousePosition(e) - this.start + (this[aGutterSize] - this.dragOffset) if (dragInterval > 1) { offset = Math.round(offset / dragInterval) * dragInterval } // If within snapOffset of min or max, set offset to min or max. // snapOffset buffers a.minSize and b.minSize, so logic is opposite for both. // Include the appropriate gutter sizes to prevent overflows. if (offset <= a.minSize + snapOffset + this[aGutterSize]) { offset = a.minSize + this[aGutterSize] } else if ( offset >= this.size - (b.minSize + snapOffset + this[bGutterSize]) ) { offset = this.size - (b.minSize + this[bGutterSize]) } // Actually adjust the size. adjust.call(this, offset) // Call the drag callback continously. Don't do anything too intensive // in this callback. getOption(options, 'onDrag', NOOP)() } // Cache some important sizes when drag starts, so we don't have to do that // continously: // // `size`: The total size of the pair. First + second + first gutter + second gutter. // `start`: The leading side of the first element. // // ------------------------------------------------ // | aGutterSize -> ||| | // | ||| | // | ||| | // | ||| <- bGutterSize | // ------------------------------------------------ // | <- start size -> | function calculateSizes() { // Figure out the parent size minus padding. const a = elements[this.a].element const b = elements[this.b].element const aBounds = a[getBoundingClientRect]() const bBounds = b[getBoundingClientRect]() this.size = aBounds[dimension] + bBounds[dimension] + this[aGutterSize] + this[bGutterSize] this.start = aBounds[position] this.end = aBounds[positionEnd] } function innerSize(element) { // Return nothing if getComputedStyle is not supported (< IE9) // Or if parent element has no layout yet if (!getComputedStyle) return null const computedStyle = getComputedStyle(element) if (!computedStyle) return null let size = element[clientSize] if (size === 0) return null if (direction === HORIZONTAL) { size -= parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight) } else { size -= parseFloat(computedStyle.paddingTop) + parseFloat(computedStyle.paddingBottom) } return size } // When specifying percentage sizes that are less than the computed // size of the element minus the gutter, the lesser percentages must be increased // (and decreased from the other elements) to make space for the pixels // subtracted by the gutters. function trimToMin(sizesToTrim) { // Try to get inner size of parent element. // If it's no supported, return original sizes. const parentSize = innerSize(parent) if (parentSize === null) { return sizesToTrim } if (minSizes.reduce((a, b) => a + b, 0) > parentSize) { return sizesToTrim } // Keep track of the excess pixels, the amount of pixels over the desired percentage // Also keep track of the elements with pixels to spare, to decrease after if needed let excessPixels = 0 const toSpare = [] const pixelSizes = sizesToTrim.map((size, i) => { // Convert requested percentages to pixel sizes const pixelSize = (parentSize * size) / 100 const elementGutterSize = getGutterSize( gutterSize, i === 0, i === sizesToTrim.length - 1, gutterAlign, ) const elementMinSize = minSizes[i] + elementGutterSize // If element is too smal, increase excess pixels by the difference // and mark that it has no pixels to spare if (pixelSize < elementMinSize) { excessPixels += elementMinSize - pixelSize toSpare.push(0) return elementMinSize } // Otherwise, mark the pixels it has to spare and return it's original size toSpare.push(pixelSize - elementMinSize) return pixelSize }) // If nothing was adjusted, return the original sizes if (excessPixels === 0) { return sizesToTrim } return pixelSizes.map((pixelSize, i) => { let newPixelSize = pixelSize // While there's still pixels to take, and there's enough pixels to spare, // take as many as possible up to the total excess pixels if (excessPixels > 0 && toSpare[i] - excessPixels > 0) { const takenPixels = Math.min( excessPixels, toSpare[i] - excessPixels, ) // Subtract the amount taken for the next iteration excessPixels -= takenPixels newPixelSize = pixelSize - takenPixels } // Return the pixel size adjusted as a percentage return (newPixelSize / parentSize) * 100 }) } // stopDragging is very similar to startDragging in reverse. function stopDragging() { const self = this const a = elements[self.a].element const b = elements[self.b].element if (self.dragging) { getOption(options, 'onDragEnd', NOOP)(getSizes()) } self.dragging = false // Remove the stored event listeners. This is why we store them. global[removeEventListener]('mouseup', self.stop) global[removeEventListener]('touchend', self.stop) global[removeEventListener]('touchcancel', self.stop) global[removeEventListener]('mousemove', self.move) global[removeEventListener]('touchmove', self.move) // Clear bound function references self.stop = null self.move = null a[removeEventListener]('selectstart', NOOP) a[removeEventListener]('dragstart', NOOP) b[removeEventListener]('selectstart', NOOP) b[removeEventListener]('dragstart', NOOP) a.style.userSelect = '' a.style.webkitUserSelect = '' a.style.MozUserSelect = '' a.style.pointerEvents = '' b.style.userSelect = '' b.style.webkitUserSelect = '' b.style.MozUserSelect = '' b.style.pointerEvents = '' self.gutter.style.cursor = '' self.parent.style.cursor = '' document.body.style.cursor = '' } // startDragging calls `calculateSizes` to store the inital size in the pair object. // It also adds event listeners for mouse/touch events, // and prevents selection while dragging so avoid the selecting text. function startDragging(e) { // Right-clicking can't start dragging. if ('button' in e && e.button !== 0) { return } // Alias frequently used variables to save space. 200 bytes. const self = this const a = elements[self.a].element const b = elements[self.b].element // Call the onDragStart callback. if (!self.dragging) { getOption(options, 'onDragStart', NOOP)(getSizes()) } // Don't actually drag the element. We emulate that in the drag function. e.preventDefault() // Set the dragging property of the pair object. self.dragging = true // Create two event listeners bound to the same pair object and store // them in the pair object. self.move = drag.bind(self) self.stop = stopDragging.bind(self) // All the binding. `window` gets the stop events in case we drag out of the elements. global[addEventListener]('mouseup', self.stop) global[addEventListener]('touchend', self.stop) global[addEventListener]('touchcancel', self.stop) global[addEventListener]('mousemove', self.move) global[addEventListener]('touchmove', self.move) // Disable selection. Disable! a[addEventListener]('selectstart', NOOP) a[addEventListener]('dragstart', NOOP) b[addEventListener]('selectstart', NOOP) b[addEventListener]('dragstart', NOOP) a.style.userSelect = 'none' a.style.webkitUserSelect = 'none' a.style.MozUserSelect = 'none' a.style.pointerEvents = 'none' b.style.userSelect = 'none' b.style.webkitUserSelect = 'none' b.style.MozUserSelect = 'none' b.style.pointerEvents = 'none' // Set the cursor at multiple levels self.gutter.style.cursor = cursor self.parent.style.cursor = cursor document.body.style.cursor = cursor // Cache the initial sizes of the pair. calculateSizes.call(self) // Determine the position of the mouse compared to the gutter self.dragOffset = getMousePosition(e) - self.end } // adjust sizes to ensure percentage is within min size and gutter. sizes = trimToMin(sizes) // 5. Create pair and element objects. Each pair has an index reference to // elements `a` and `b` of the pair (first and second elements). // Loop through the elements while pairing them off. Every pair gets a // `pair` object and a gutter. // // Basic logic: // // - Starting with the second element `i > 0`, create `pair` objects with // `a = i - 1` and `b = i` // - Set gutter sizes based on the _pair_ being first/last. The first and last // pair have gutterSize / 2, since they only have one half gutter, and not two. // - Create gutter elements and add event listeners. // - Set the size of the elements, minus the gutter sizes. // // ----------------------------------------------------------------------- // | i=0 | i=1 | i=2 | i=3 | // | | | | | // | pair 0 pair 1 pair 2 | // | | | | | // ----------------------------------------------------------------------- const pairs = [] elements = ids.map((id, i) => { // Create the element object. const element = { element: elementOrSelector(id), size: sizes[i], minSize: minSizes[i], i, } let pair if (i > 0) { // Create the pair object with its metadata. pair = { a: i - 1, b: i, dragging: false, direction, parent, } pair[aGutterSize] = getGutterSize( gutterSize, i - 1 === 0, false, gutterAlign, ) pair[bGutterSize] = getGutterSize( gutterSize, false, i === ids.length - 1, gutterAlign, ) // if the parent has a reverse flex-direction, switch the pair elements. if ( parentFlexDirection === 'row-reverse' || parentFlexDirection === 'column-reverse' ) { const temp = pair.a pair.a = pair.b pair.b = temp } } // Determine the size of the current element. IE8 is supported by // staticly assigning sizes without draggable gutters. Assigns a string // to `size`. // // IE9 and above if (!isIE8) { // Create gutter elements for each pair. if (i > 0) { const gutterElement = gutter(i, direction, element.element) setGutterSize(gutterElement, gutterSize, i) // Save bound event listener for removal later pair[gutterStartDragging] = startDragging.bind(pair) // Attach bound event listener gutterElement[addEventListener]( 'mousedown', pair[gutterStartDragging], ) gutterElement[addEventListener]( 'touchstart', pair[gutterStartDragging], ) parent.insertBefore(gutterElement, element.element) pair.gutter = gutterElement } } setElementSize( element.element, element.size, getGutterSize( gutterSize, i === 0, i === ids.length - 1, gutterAlign, ), i, ) // After the first iteration, and we have a pair object, append it to the // list of pairs. if (i > 0) { pairs.push(pair) } return element }) function adjustToMin(element) { const isLast = element.i === pairs.length const pair = isLast ? pairs[element.i - 1] : pairs[element.i] calculateSizes.call(pair) const size = isLast ? pair.size - element.minSize - pair[bGutterSize] : element.minSize + pair[aGutterSize] adjust.call(pair, size) } elements.forEach(element => { const computedSize = element.element[getBoundingClientRect]()[dimension] if (computedSize < element.minSize) { if (expandToMin) { adjustToMin(element) } else { // eslint-disable-next-line no-param-reassign element.minSize = computedSize } } }) function setSizes(newSizes) { const trimmed = trimToMin(newSizes) trimmed.forEach((newSize, i) => { if (i > 0) { const pair = pairs[i - 1] const a = elements[pair.a] const b = elements[pair.b] a.size = trimmed[i - 1] b.size = newSize setElementSize(a.element, a.size, pair[aGutterSize], a.i) setElementSize(b.element, b.size, pair[bGutterSize], b.i) } }) } function destroy(preserveStyles, preserveGutter) { pairs.forEach(pair => { if (preserveGutter !== true) { pair.parent.removeChild(pair.gutter) } else { pair.gutter[removeEventListener]( 'mousedown', pair[gutterStartDragging], ) pair.gutter[removeEventListener]( 'touchstart', pair[gutterStartDragging], ) } if (preserveStyles !== true) { const style = elementStyle( dimension, pair.a.size, pair[aGutterSize], ) Object.keys(style).forEach(prop => { elements[pair.a].element.style[prop] = '' elements[pair.b].element.style[prop] = '' }) } }) } if (isIE8) { return { setSizes, destroy, } } return { setSizes, getSizes, collapse(i) { adjustToMin(elements[i]) }, destroy, parent, pairs, } } export default Split public/vendors/split/packages/splitjs/LICENSE.txt000064400000002041146725417150015737 0ustar00Copyright (c) 2019 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/packages/splitjs/rollup.config.js000064400000001557146725417150017246 0ustar00import buble from 'rollup-plugin-buble' import { uglify } from 'rollup-plugin-uglify' const pkg = require('./package.json') const output = { format: 'umd', file: pkg.main, name: 'Split', sourcemap: false, banner: `/*! Split.js - v${pkg.version} */\n`, } export default [ { input: 'src/split.js', output: [ output, { file: pkg.module, format: 'esm', sourcemap: false, }, ], plugins: [buble()], }, { input: 'src/split.js', output: { ...output, sourcemap: true, file: pkg['minified:main'], }, plugins: [ buble(), uglify({ output: { comments: /^!/, }, }), ], }, ] public/vendors/split/packages/splitjs/index.d.ts000064400000005141146725417150016021 0ustar00// Type definitions for split.js 1.3 // Project: https://github.com/nathancahill/Split.js // Definitions by: Ilia Choly // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.1 // Global variable outside module loader export as namespace Split; // Module loader export = Split; declare function Split( elements: Array, options?: Split.Options ): Split.Instance; declare namespace Split { type Partial = {[P in keyof T]?: T[P]}; type CSSStyleDeclarationPartial = Partial; interface Options { // Initial sizes of each element in percents or CSS values. sizes?: number[]; // Minimum size of each element. minSize?: number | number[]; expandToMin?: boolean; // Gutter size in pixels. gutterSize?: number; gutterAlign?: string; // Snap to minimum size offset in pixels. snapOffset?: number; dragInterval?: number; // Direction to split: horizontal or vertical. direction?: 'horizontal' | 'vertical'; // Cursor to display while dragging. cursor?: string; // Callback on drag. onDrag?(): void; // Callback on drag start. onDragStart?(): void; // Callback on drag end. onDragEnd?(): void; // Called to create each gutter element gutter?( index: number, direction: 'horizontal' | 'vertical' ): HTMLElement; // Called to set the style of each element. elementStyle?( dimension: 'width' | 'height', elementSize: number, gutterSize: number, index: number, ): CSSStyleDeclarationPartial; // Called to set the style of the gutter. gutterStyle?( dimension: 'width' | 'height', gutterSize: number, index: number, ): CSSStyleDeclarationPartial; } interface Instance { // setSizes behaves the same as the sizes configuration option, passing an array of percents or CSS values. // It updates the sizes of the elements in the split. setSizes(sizes: number[]): void; // getSizes returns an array of percents, suitable for using with setSizes or creation. // Not supported in IE8. getSizes(): number[]; // collapse changes the size of element at index to 0. // Every element except the last is collapsed towards the front (left or top). // The last is collapsed towards the back. // Not supported in IE8. collapse(index: number): void; // Destroy the instance. It removes the gutter elements, and the size CSS styles Split.js set. destroy(preserveStyles?: boolean, preserveGutters?: boolean): void; } } public/vendors/split/packages/splitjs/logo.svg000064400000006261146725417150015605 0ustar00public/vendors/split/packages/splitjs/grips/horizontal.png000064400000000150146725417150020136 0ustar00‰PNG  IHDRhïιPLTEGpLÌÌÌòý¬tRNS@æØfIDATx^c8\Ÿy ÁÀz#`IEND®B`‚public/vendors/split/packages/splitjs/grips/vertical.png000064400000000133146725417150017557 0ustar00‰PNG  IHDRä~Ô½"IDAT(Sc8sæÌ›« ˆƒŽ± Žš9j&^3~ÈÙγ’’¾IEND®B`‚public/vendors/split/packages/splitjs/karma.conf.js000064400000003721146725417150016477 0ustar00module.exports = config => { config.set({ customLaunchers: { sl_firefox_latest: { base: 'SauceLabs', browserName: 'firefox', platform: 'macOS 10.13', version: '63.0', }, sl_chrome_latest: { base: 'SauceLabs', browserName: 'chrome', platform: 'macOS 10.13', version: '70.0', }, sl_safari: { base: 'SauceLabs', browserName: 'safari', platform: 'macOS 10.13', version: '12.1', }, sl_firefox: { base: 'SauceLabs', browserName: 'firefox', platform: 'Windows 7', version: '6.0', }, sl_chrome: { base: 'SauceLabs', browserName: 'chrome', platform: 'Windows 7', version: '26.0', }, sl_edge: { base: 'SauceLabs', browserName: 'MicrosoftEdge', platform: 'Windows 10', version: '14.14393', }, sl_ie_11: { base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 7', version: '11.0', }, sl_ie_10: { base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 7', version: '10.0', }, sl_ie_9: { base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 7', version: '9.0', }, }, frameworks: ['jasmine'], browsers: ['FirefoxHeadless', 'ChromeHeadless'], singleRun: true, files: ['dist/split.js', 'test/split.spec.js'], }) } public/vendors/split/packages/splitjs/package.json000064400000002133146725417150016404 0ustar00{ "name": "split.js", "version": "1.5.11", "description": "2kb unopinionated utility for resizeable split views", "main": "dist/split.js", "minified:main": "dist/split.min.js", "module": "dist/split.es.js", "repository": "https://github.com/nathancahill/split", "keywords": ["css", "split", "flexbox", "tiny", "split-layout"], "author": "Nathan Cahill ", "license": "MIT", "homepage": "https://split.js.org/", "scripts": { "lint": "eslint src", "test": "karma start", "prepublish": "rollup -c", "build": "rollup -c && npm run size", "watch": "rollup -cw", "size": "echo \"gzip size: $(gzip-size --raw $npm_package_minified_main) bytes\"", "saucelabs": "yarn run test --browsers sl_firefox_latest,sl_chrome_latest,sl_safari,sl_firefox,sl_chrome,sl_edge,sl_ie_11,sl_ie_10,sl_ie_9" }, "files": ["dist"], "browserslist": [ "Chrome >= 22", "Firefox >= 6", "Opera >= 15", "Safari >= 6.2", "IE >= 9", "IE 8" ], "collective": { "type": "opencollective", "url": "https://opencollective.com/splitjs" } } public/vendors/split/packages/splitjs/test/lib/jasmine-2.6.4/console.js000064400000012150146725417150021736 0ustar00/* Copyright (c) 2008-2017 Pivotal Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function getJasmineRequireObj() { if (typeof module !== 'undefined' && module.exports) { return exports; } else { window.jasmineRequire = window.jasmineRequire || {}; return window.jasmineRequire; } } getJasmineRequireObj().console = function(jRequire, j$) { j$.ConsoleReporter = jRequire.ConsoleReporter(); }; getJasmineRequireObj().ConsoleReporter = function() { var noopTimer = { start: function(){}, elapsed: function(){ return 0; } }; function ConsoleReporter(options) { var print = options.print, showColors = options.showColors || false, onComplete = options.onComplete || function() {}, timer = options.timer || noopTimer, specCount, failureCount, failedSpecs = [], pendingCount, ansi = { green: '\x1B[32m', red: '\x1B[31m', yellow: '\x1B[33m', none: '\x1B[0m' }, failedSuites = []; print('ConsoleReporter is deprecated and will be removed in a future version.'); this.jasmineStarted = function() { specCount = 0; failureCount = 0; pendingCount = 0; print('Started'); printNewline(); timer.start(); }; this.jasmineDone = function() { printNewline(); for (var i = 0; i < failedSpecs.length; i++) { specFailureDetails(failedSpecs[i]); } if(specCount > 0) { printNewline(); var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' + failureCount + ' ' + plural('failure', failureCount); if (pendingCount) { specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount); } print(specCounts); } else { print('No specs found'); } printNewline(); var seconds = timer.elapsed() / 1000; print('Finished in ' + seconds + ' ' + plural('second', seconds)); printNewline(); for(i = 0; i < failedSuites.length; i++) { suiteFailureDetails(failedSuites[i]); } onComplete(failureCount === 0); }; this.specDone = function(result) { specCount++; if (result.status == 'pending') { pendingCount++; print(colored('yellow', '*')); return; } if (result.status == 'passed') { print(colored('green', '.')); return; } if (result.status == 'failed') { failureCount++; failedSpecs.push(result); print(colored('red', 'F')); } }; this.suiteDone = function(result) { if (result.failedExpectations && result.failedExpectations.length > 0) { failureCount++; failedSuites.push(result); } }; return this; function printNewline() { print('\n'); } function colored(color, str) { return showColors ? (ansi[color] + str + ansi.none) : str; } function plural(str, count) { return count == 1 ? str : str + 's'; } function repeat(thing, times) { var arr = []; for (var i = 0; i < times; i++) { arr.push(thing); } return arr; } function indent(str, spaces) { var lines = (str || '').split('\n'); var newArr = []; for (var i = 0; i < lines.length; i++) { newArr.push(repeat(' ', spaces).join('') + lines[i]); } return newArr.join('\n'); } function specFailureDetails(result) { printNewline(); print(result.fullName); for (var i = 0; i < result.failedExpectations.length; i++) { var failedExpectation = result.failedExpectations[i]; printNewline(); print(indent(failedExpectation.message, 2)); print(indent(failedExpectation.stack, 2)); } printNewline(); } function suiteFailureDetails(result) { for (var i = 0; i < result.failedExpectations.length; i++) { printNewline(); print(colored('red', 'An error was thrown in an afterAll')); printNewline(); print(colored('red', 'AfterAll ' + result.failedExpectations[i].message)); } printNewline(); } } return ConsoleReporter; }; public/vendors/split/packages/splitjs/test/lib/jasmine-2.6.4/boot.js000064400000012451146725417150021243 0ustar00/** Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. [jasmine-gem]: http://github.com/pivotal/jasmine-gem */ (function() { /** * ## Require & Instantiate * * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. */ window.jasmine = jasmineRequire.core(jasmineRequire); /** * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. */ jasmineRequire.html(jasmine); /** * Create the Jasmine environment. This is used to run all specs in a project. */ var env = jasmine.getEnv(); /** * ## The Global Interface * * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. */ var jasmineInterface = jasmineRequire.interface(jasmine, env); /** * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. */ extend(window, jasmineInterface); /** * ## Runner Parameters * * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. */ var queryString = new jasmine.QueryString({ getWindowLocation: function() { return window.location; } }); var filterSpecs = !!queryString.getParam("spec"); var catchingExceptions = queryString.getParam("catch"); env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); var throwingExpectationFailures = queryString.getParam("throwFailures"); env.throwOnExpectationFailure(throwingExpectationFailures); var random = queryString.getParam("random"); env.randomizeTests(random); var seed = queryString.getParam("seed"); if (seed) { env.seed(seed); } /** * ## Reporters * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). */ var htmlReporter = new jasmine.HtmlReporter({ env: env, onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); }, onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); }, onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); }, addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); }, getContainer: function() { return document.body; }, createElement: function() { return document.createElement.apply(document, arguments); }, createTextNode: function() { return document.createTextNode.apply(document, arguments); }, timer: new jasmine.Timer(), filterSpecs: filterSpecs }); /** * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. */ env.addReporter(jasmineInterface.jsApiReporter); env.addReporter(htmlReporter); /** * Filter which specs will be run by matching the start of the full name against the `spec` query param. */ var specFilter = new jasmine.HtmlSpecFilter({ filterString: function() { return queryString.getParam("spec"); } }); env.specFilter = function(spec) { return specFilter.matches(spec.getFullName()); }; /** * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. */ window.setTimeout = window.setTimeout; window.setInterval = window.setInterval; window.clearTimeout = window.clearTimeout; window.clearInterval = window.clearInterval; /** * ## Execution * * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. */ var currentWindowOnload = window.onload; window.onload = function() { if (currentWindowOnload) { currentWindowOnload(); } htmlReporter.initialize(); env.execute(); }; /** * Helper function for readability above. */ function extend(destination, source) { for (var property in source) destination[property] = source[property]; return destination; } }()); public/vendors/split/packages/splitjs/test/lib/jasmine-2.6.4/jasmine-html.js000064400000041535146725417150022675 0ustar00/* Copyright (c) 2008-2017 Pivotal Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ jasmineRequire.html = function(j$) { j$.ResultsNode = jasmineRequire.ResultsNode(); j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); j$.QueryString = jasmineRequire.QueryString(); j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); }; jasmineRequire.HtmlReporter = function(j$) { var noopTimer = { start: function() {}, elapsed: function() { return 0; } }; function HtmlReporter(options) { var env = options.env || {}, getContainer = options.getContainer, createElement = options.createElement, createTextNode = options.createTextNode, onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, onThrowExpectationsClick = options.onThrowExpectationsClick || function() {}, onRandomClick = options.onRandomClick || function() {}, addToExistingQueryString = options.addToExistingQueryString || defaultQueryString, filterSpecs = options.filterSpecs, timer = options.timer || noopTimer, results = [], specsExecuted = 0, failureCount = 0, pendingSpecCount = 0, htmlReporterMain, symbols, failedSuites = []; this.initialize = function() { clearPrior(); htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, createDom('div', {className: 'jasmine-banner'}, createDom('a', {className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank'}), createDom('span', {className: 'jasmine-version'}, j$.version) ), createDom('ul', {className: 'jasmine-symbol-summary'}), createDom('div', {className: 'jasmine-alert'}), createDom('div', {className: 'jasmine-results'}, createDom('div', {className: 'jasmine-failures'}) ) ); getContainer().appendChild(htmlReporterMain); }; var totalSpecsDefined; this.jasmineStarted = function(options) { totalSpecsDefined = options.totalSpecsDefined || 0; timer.start(); }; var summary = createDom('div', {className: 'jasmine-summary'}); var topResults = new j$.ResultsNode({}, '', null), currentParent = topResults; this.suiteStarted = function(result) { currentParent.addChild(result, 'suite'); currentParent = currentParent.last(); }; this.suiteDone = function(result) { if (result.status == 'failed') { failedSuites.push(result); } if (currentParent == topResults) { return; } currentParent = currentParent.parent; }; this.specStarted = function(result) { currentParent.addChild(result, 'spec'); }; var failures = []; this.specDone = function(result) { if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') { console.error('Spec \'' + result.fullName + '\' has no expectations.'); } if (result.status != 'disabled') { specsExecuted++; } if (!symbols){ symbols = find('.jasmine-symbol-summary'); } symbols.appendChild(createDom('li', { className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status, id: 'spec_' + result.id, title: result.fullName } )); if (result.status == 'failed') { failureCount++; var failure = createDom('div', {className: 'jasmine-spec-detail jasmine-failed'}, createDom('div', {className: 'jasmine-description'}, createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) ), createDom('div', {className: 'jasmine-messages'}) ); var messages = failure.childNodes[1]; for (var i = 0; i < result.failedExpectations.length; i++) { var expectation = result.failedExpectations[i]; messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message)); messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack)); } failures.push(failure); } if (result.status == 'pending') { pendingSpecCount++; } }; this.jasmineDone = function(doneResult) { var banner = find('.jasmine-banner'); var alert = find('.jasmine-alert'); var order = doneResult && doneResult.order; alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); banner.appendChild( createDom('div', { className: 'jasmine-run-options' }, createDom('span', { className: 'jasmine-trigger' }, 'Options'), createDom('div', { className: 'jasmine-payload' }, createDom('div', { className: 'jasmine-exceptions' }, createDom('input', { className: 'jasmine-raise', id: 'jasmine-raise-exceptions', type: 'checkbox' }), createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')), createDom('div', { className: 'jasmine-throw-failures' }, createDom('input', { className: 'jasmine-throw', id: 'jasmine-throw-failures', type: 'checkbox' }), createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')), createDom('div', { className: 'jasmine-random-order' }, createDom('input', { className: 'jasmine-random', id: 'jasmine-random-order', type: 'checkbox' }), createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order')) ) )); var raiseCheckbox = find('#jasmine-raise-exceptions'); raiseCheckbox.checked = !env.catchingExceptions(); raiseCheckbox.onclick = onRaiseExceptionsClick; var throwCheckbox = find('#jasmine-throw-failures'); throwCheckbox.checked = env.throwingExpectationFailures(); throwCheckbox.onclick = onThrowExpectationsClick; var randomCheckbox = find('#jasmine-random-order'); randomCheckbox.checked = env.randomTests(); randomCheckbox.onclick = onRandomClick; var optionsMenu = find('.jasmine-run-options'), optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'), optionsPayload = optionsMenu.querySelector('.jasmine-payload'), isOpen = /\bjasmine-open\b/; optionsTrigger.onclick = function() { if (isOpen.test(optionsPayload.className)) { optionsPayload.className = optionsPayload.className.replace(isOpen, ''); } else { optionsPayload.className += ' jasmine-open'; } }; if (specsExecuted < totalSpecsDefined) { var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; var skippedLink = order && order.random ? '?random=true' : '?'; alert.appendChild( createDom('span', {className: 'jasmine-bar jasmine-skipped'}, createDom('a', {href: skippedLink, title: 'Run all specs'}, skippedMessage) ) ); } var statusBarMessage = ''; var statusBarClassName = 'jasmine-bar '; if (totalSpecsDefined > 0) { statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } statusBarClassName += (failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed'; } else { statusBarClassName += 'jasmine-skipped'; statusBarMessage += 'No specs found'; } var seedBar; if (order && order.random) { seedBar = createDom('span', {className: 'jasmine-seed-bar'}, ', randomized with seed ', createDom('a', {title: 'randomized with seed ' + order.seed, href: seedHref(order.seed)}, order.seed) ); } alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar)); var errorBarClassName = 'jasmine-bar jasmine-errored'; var errorBarMessagePrefix = 'AfterAll '; for(var i = 0; i < failedSuites.length; i++) { var failedSuite = failedSuites[i]; for(var j = 0; j < failedSuite.failedExpectations.length; j++) { alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failedSuite.failedExpectations[j].message)); } } var globalFailures = (doneResult && doneResult.failedExpectations) || []; for(i = 0; i < globalFailures.length; i++) { var failure = globalFailures[i]; alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failure.message)); } var results = find('.jasmine-results'); results.appendChild(summary); summaryList(topResults, summary); function summaryList(resultsTree, domParent) { var specListNode; for (var i = 0; i < resultsTree.children.length; i++) { var resultNode = resultsTree.children[i]; if (filterSpecs && !hasActiveSpec(resultNode)) { continue; } if (resultNode.type == 'suite') { var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id}, createDom('li', {className: 'jasmine-suite-detail'}, createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) ) ); summaryList(resultNode, suiteListNode); domParent.appendChild(suiteListNode); } if (resultNode.type == 'spec') { if (domParent.getAttribute('class') != 'jasmine-specs') { specListNode = createDom('ul', {className: 'jasmine-specs'}); domParent.appendChild(specListNode); } var specDescription = resultNode.result.description; if(noExpectations(resultNode.result)) { specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; } if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') { specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason; } specListNode.appendChild( createDom('li', { className: 'jasmine-' + resultNode.result.status, id: 'spec-' + resultNode.result.id }, createDom('a', {href: specHref(resultNode.result)}, specDescription) ) ); } } } if (failures.length) { alert.appendChild( createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'}, createDom('span', {}, 'Spec List | '), createDom('a', {className: 'jasmine-failures-menu', href: '#'}, 'Failures'))); alert.appendChild( createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-failure-list'}, createDom('a', {className: 'jasmine-spec-list-menu', href: '#'}, 'Spec List'), createDom('span', {}, ' | Failures '))); find('.jasmine-failures-menu').onclick = function() { setMenuModeTo('jasmine-failure-list'); }; find('.jasmine-spec-list-menu').onclick = function() { setMenuModeTo('jasmine-spec-list'); }; setMenuModeTo('jasmine-failure-list'); var failureNode = find('.jasmine-failures'); for (i = 0; i < failures.length; i++) { failureNode.appendChild(failures[i]); } } }; return this; function find(selector) { return getContainer().querySelector('.jasmine_html-reporter ' + selector); } function clearPrior() { // return the reporter var oldReporter = find(''); if(oldReporter) { getContainer().removeChild(oldReporter); } } function createDom(type, attrs, childrenVarArgs) { var el = createElement(type); for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child === 'string') { el.appendChild(createTextNode(child)); } else { if (child) { el.appendChild(child); } } } for (var attr in attrs) { if (attr == 'className') { el[attr] = attrs[attr]; } else { el.setAttribute(attr, attrs[attr]); } } return el; } function pluralize(singular, count) { var word = (count == 1 ? singular : singular + 's'); return '' + count + ' ' + word; } function specHref(result) { return addToExistingQueryString('spec', result.fullName); } function seedHref(seed) { return addToExistingQueryString('seed', seed); } function defaultQueryString(key, value) { return '?' + key + '=' + value; } function setMenuModeTo(mode) { htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); } function noExpectations(result) { return (result.failedExpectations.length + result.passedExpectations.length) === 0 && result.status === 'passed'; } function hasActiveSpec(resultNode) { if (resultNode.type == 'spec' && resultNode.result.status != 'disabled') { return true; } if (resultNode.type == 'suite') { for (var i = 0, j = resultNode.children.length; i < j; i++) { if (hasActiveSpec(resultNode.children[i])) { return true; } } } } } return HtmlReporter; }; jasmineRequire.HtmlSpecFilter = function() { function HtmlSpecFilter(options) { var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); var filterPattern = new RegExp(filterString); this.matches = function(specName) { return filterPattern.test(specName); }; } return HtmlSpecFilter; }; jasmineRequire.ResultsNode = function() { function ResultsNode(result, type, parent) { this.result = result; this.type = type; this.parent = parent; this.children = []; this.addChild = function(result, type) { this.children.push(new ResultsNode(result, type, this)); }; this.last = function() { return this.children[this.children.length - 1]; }; } return ResultsNode; }; jasmineRequire.QueryString = function() { function QueryString(options) { this.navigateWithNewParam = function(key, value) { options.getWindowLocation().search = this.fullStringWithNewParam(key, value); }; this.fullStringWithNewParam = function(key, value) { var paramMap = queryStringToParamMap(); paramMap[key] = value; return toQueryString(paramMap); }; this.getParam = function(key) { return queryStringToParamMap()[key]; }; return this; function toQueryString(paramMap) { var qStrPairs = []; for (var prop in paramMap) { qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); } return '?' + qStrPairs.join('&'); } function queryStringToParamMap() { var paramStr = options.getWindowLocation().search.substring(1), params = [], paramMap = {}; if (paramStr.length > 0) { params = paramStr.split('&'); for (var i = 0; i < params.length; i++) { var p = params[i].split('='); var value = decodeURIComponent(p[1]); if (value === 'true' || value === 'false') { value = JSON.parse(value); } paramMap[decodeURIComponent(p[0])] = value; } } return paramMap; } } return QueryString; }; public/vendors/split/packages/splitjs/test/lib/jasmine-2.6.4/jasmine_favicon.png000064400000002716146725417150023606 0ustar00‰PNG  IHDR D¤ŠÆOPLTEÿÿÿÿÿ€€€ªUª€@€™f™€U€’I’€`€™M€‹]‹•U€‰N‰’[€ˆUˆP€‡Z‡”Q†’U†‹Q€Y…ŠU€R…ŽU„’R€X„‘U€ŒR„X€‹UƒS€‘SƒUƒŒS€WƒŽS‚‘Q€ŽU‚S€S‚ŒU‚ŽS„R‚ŽU„S‚R„T„R‚ŽT‚R„ŽU‚TƒRUƒTŒUŽTƒSŽUƒSƒTƒŽSUƒŽTSƒUƒTUŽT‚SŽU‚TS‚UT‚ŽSU‚S‚ŽUT‚SU‚TƒŽT‚SƒŽU‚TƒS‚ŽSƒŽTƒT‚TƒŽT‚UƒŽT‚TƒŽU‚TƒŽS‚TŽT‚SŽT‚TŽS‚TT‚S‚ŽTŽSTŽS‚TŽT‚SŽT‚TŽS‚ŽTƒŽSƒT‚ŽTƒS‚ŽTƒT‚ŽSƒTƒŽS‚TƒŽT‚SƒŽU‚ŽT‚ŽT‚U‚ŽT‚ŽT‚ŽU‚ŽT‚ŽT‚U‚T‚ŽU‚ŽT‚ŽT‚ŽU‚ŽT‚ŽT‚UTŽU‚ŽT‚ŽUŽT‚ŽTU‚ŽTT‚ŽUƒŽT‚ŽU‚UƒŽT‚ŽS‚ŽT‚ŽT‚ŽS‚ŽT‚ŽT‚S‚ŽT‚ŽS‚ŽT‚ŽT‚ŽT‚ŽT‚T‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚ŽT‚Óþ0ÉÄtRNS  !"%'()+,-.1345678:;=>?@ABCEFGHJLMNOPTUWXYZ[\]^_`bcdefgjklmnqstwz{|}~‚ƒ„…†‡ˆ‹Ž’“”•–—˜™šœžŸ ¡¢¤¥¦§¨¬­®¯°³µ¶·¸º»¼½¾¿ÀÁÃÄÆÇÈÉÊËÌÍÎÐÓÕÖ×ØÙÚÛÜÝßàáãäåæèéêëìíïðñòóöøùúüýþX¯FjIDATx^mÐé[ŒQ‡ñïÌTSFE’ìZd§Dö=$;B {!;DDv(% íRƒ ÷æ9Ï\Jø¼9×ï:÷‹s~ꜚ{ûmSãëë;'¹ô¯þZéP¿­‡º ÊþF-+õ§¨rßýœ%©33öUü( U‡¡u@[vù)æÈwày¤ü4°¸j±ññCeR Tzds?¶ÉÖ d.ɶ Ø*%îê öÆÈyX$Ë v(”ÔóãŒßAÆË)¸ê¬Syð9B– ýüÁ–‘²ŒòA–äù[äpJÚ~×ewe¦$—t^H³¡=B±µ&¸rÃLµßÚú©†p†é0”H»Æüä€'P2û‚X,G-¬Ö#û UØNFÆ'tŒíŠtŽ«æÊs¾ ãœ,Ï0öKÙP"/$IrO?Ù³dÙ­IZOÕSeó$/”%4=Ñ%[”©JŠX^üÁ±ùNŒ4öQZdÓî„b݃9®{ †Íƒ/ãÒ|´Ç ÞTѲC*„£Ê…‡ÒønRt0?¨öXÓD¹š`™¦o€,»®ÐwÀIðs ÜŸ`¯äßUs¿c ßí-YŠ¡TÒø:HýHÕ©Úx#¥)@š¤^^¸ ÇúvÊΛ´Î‘ÂßÃûßk|IqWƒí@}Š¢¤à[@Š g p"H† láæþüzVeÃe„¸eL~Ü ’Ÿú¾|§ãäçLº†¹Q‡°"Œš³[Ven¿Ü„q(PJo¢‹êýų®ŠeKô#² nW”ßÈ[­N¿·tXZ,u[{IEND®B`‚public/vendors/split/packages/splitjs/test/lib/jasmine-2.6.4/jasmine.css000064400000047511146725417150022107 0ustar00body { overflow-y: scroll; } .jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; } .jasmine_html-reporter a { text-decoration: none; } .jasmine_html-reporter a:hover { text-decoration: underline; } .jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } .jasmine_html-reporter .jasmine-banner, .jasmine_html-reporter .jasmine-symbol-summary, .jasmine_html-reporter .jasmine-summary, .jasmine_html-reporter .jasmine-result-message, .jasmine_html-reporter .jasmine-spec .jasmine-description, .jasmine_html-reporter .jasmine-spec-detail .jasmine-description, .jasmine_html-reporter .jasmine-alert .jasmine-bar, .jasmine_html-reporter .jasmine-stack-trace { padding-left: 9px; padding-right: 9px; } .jasmine_html-reporter .jasmine-banner { position: relative; } .jasmine_html-reporter .jasmine-banner .jasmine-title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAMAAACGusnyAAACdlBMVEX/////AP+AgICqVaqAQICZM5mAVYCSSZKAQICOOY6ATYCLRouAQICJO4mSSYCIRIiPQICHPIeOR4CGQ4aMQICGPYaLRoCFQ4WKQICPPYWJRYCOQoSJQICNPoSIRICMQoSHQICHRICKQoOHQICKPoOJO4OJQYOMQICMQ4CIQYKLQICIPoKLQ4CKQICNPoKJQISMQ4KJQoSLQYKJQISLQ4KIQoSKQYKIQICIQISMQoSKQYKLQIOLQoOJQYGLQIOKQIOMQoGKQYOLQYGKQIOLQoGJQYOJQIOKQYGJQIOKQoGKQIGLQIKLQ4KKQoGLQYKJQIGKQYKJQIGKQIKJQoGKQYKLQIGKQYKLQIOJQoKKQoOJQYKKQIOJQoKKQoOKQIOLQoKKQYOLQYKJQIOKQoKKQYKKQoKJQYOKQYKLQIOKQoKLQYOKQYKLQIOJQoGKQYKJQYGJQoGKQYKLQoGLQYGKQoGJQYKKQYGJQIKKQoGJQYKLQIKKQYGLQYKKQYGKQYGKQYKJQYOKQoKJQYOKQYKLQYOLQYOKQYKLQYOKQoKKQYKKQYOKQYOJQYKKQYKLQYKKQIKKQoKKQYKKQYKKQoKJQIKKQYKLQYKKQYKKQIKKQYKKQYKKQYKKQIKKQYKJQYGLQYGKQYKKQYKKQYGKQIKKQYGKQYOJQoKKQYOLQYKKQYOKQoKKQYKKQoKKQYKKQYKJQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKJQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKmIDpEAAAA0XRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAiIyQlJycoKissLS4wMTQ1Njc4OTo7PDw+P0BCQ0RISUpLTE1OUFNUVVdYWFlaW15fYGFiY2ZnaGlqa2xtb3BxcnN0dnh5ent8fX5/gIGChIWIioyNjo+QkZOUlZaYmZqbnJ2eoKGio6WmqKmsra6vsLGztre4ubq7vL2+wMHDxMjJysvNzs/Q0dLU1tfY2dvc3t/g4eLj5ebn6Onq6+zt7u/w8vP09fb3+Pn6+/z9/vkVQXAAAAMaSURBVHhe5dXxV1N1GMfxz2ABbDgIAm5VDJOyVDIJLUMaVpBWUZUaGbmqoGpZRSiGiRWp6KoZ5AB0ZY50RImZQIlahKkMYXv/R90dBvET/rJfOr3Ouc8v99zPec59zvf56j+vYKlViSf7250X4Mr3O29Tgq08BdGB4DhcekEJ5YkQKFsgWZdtj9JpV+I8xPjLFqkrsEIqO8PHSpis36jWazcqjEsfJjkvRssVU37SdIOu4XCf5vEJPsnwJpnRNU9JmxhMk8l1gehIrq7hTFjzOD+Vf88629qKMJVNltInFeRexRQyJlNeqd1iGDlSzrIUIyXbyFfm3RYprcQRe7lqtWyGYbfc6dT0R2vmdOOkX3u55C1rP37ftiH+tDby4r/RBT0w8TyEkr+epB9XgPDmSYYWbrhCuFYaIyw3fDQAXTnSkh+ANofiHmWf9l+FY1I90FdQTetstO00o23novzVsJ7uB3/C5TkbjRwZ5JerwV4iRWq9HFbFMaK/d0TYqayRiQPuIxxS3Bu8JWU90/60tKi7vkhaznez0a/TbVOKj5CaOZh6fWG6/Lyv9B/ZLR1gw/S/fpbeVD3MCW1li6SvWDOn65tr99/uvWtBS0XDm4s1t+sOHpG0kpBKx/l77wOSnxLpcx6TXmXLTPQOKYOf9Q1dfr8/SJ2mFdCvl1Yl93DiHUZvXeLJbGSzYu5gVJ2slbSakOR8dxCq5adQ2oFLqsE9Ex3L4qQO0eOPeU5x56bypXp4onSEb5OkICX6lDat55TeoztNKQcJaakrz9KCb95oD69IKq+yKW4XPjknaS52V0TZqE2cTtXjcHSCRmUO88e+85hj3EP74i9p8pylw7lxgMDyyl6OV7ZejnjNMfatu87LxRbH0IS35gt2a4ZjmGpVBdKK3Wr6INk8jWWSGqbA55CKgjBRC6E9w78ydTg3ABS3AFV1QN0Y4Aa2pgEjWnQURj9L0ayK6R2ysEqxHUKzYnLvvyU+i9KM2JHJzE4vyZOyDcOwOsySajeLPc8sNvPJkFlyJd20wpqAzZeAfZ3oWybxd+P/3j+SG3uSBdf2VQAAAABJRU5ErkJggg==') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -moz-background-size: 100%; -o-background-size: 100%; -webkit-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } .jasmine_html-reporter .jasmine-banner .jasmine-version { margin-left: 14px; position: relative; top: 6px; } .jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } .jasmine_html-reporter .jasmine-version { color: #aaa; } .jasmine_html-reporter .jasmine-banner { margin-top: 14px; } .jasmine_html-reporter .jasmine-duration { color: #fff; float: right; line-height: 28px; padding-right: 9px; } .jasmine_html-reporter .jasmine-symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } .jasmine_html-reporter .jasmine-symbol-summary li { display: inline-block; height: 10px; width: 14px; font-size: 16px; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed { font-size: 14px; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed:before { color: #007069; content: "\02022"; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed { line-height: 9px; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled { font-size: 14px; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled:before { color: #bababa; content: "\02022"; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending { line-height: 17px; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending:before { color: #ba9d37; content: "*"; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty { font-size: 14px; } .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty:before { color: #ba9d37; content: "\02022"; } .jasmine_html-reporter .jasmine-run-options { float: right; margin-right: 5px; border: 1px solid #8a4182; color: #8a4182; position: relative; line-height: 20px; } .jasmine_html-reporter .jasmine-run-options .jasmine-trigger { cursor: pointer; padding: 8px 16px; } .jasmine_html-reporter .jasmine-run-options .jasmine-payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; } .jasmine_html-reporter .jasmine-run-options .jasmine-payload.jasmine-open { display: block; } .jasmine_html-reporter .jasmine-bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } .jasmine_html-reporter .jasmine-bar.jasmine-failed { background-color: #ca3a11; } .jasmine_html-reporter .jasmine-bar.jasmine-passed { background-color: #007069; } .jasmine_html-reporter .jasmine-bar.jasmine-skipped { background-color: #bababa; } .jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; } .jasmine_html-reporter .jasmine-bar.jasmine-menu { background-color: #fff; color: #aaa; } .jasmine_html-reporter .jasmine-bar.jasmine-menu a { color: #333; } .jasmine_html-reporter .jasmine-bar a { color: white; } .jasmine_html-reporter.jasmine-spec-list .jasmine-bar.jasmine-menu.jasmine-failure-list, .jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures { display: none; } .jasmine_html-reporter.jasmine-failure-list .jasmine-bar.jasmine-menu.jasmine-spec-list, .jasmine_html-reporter.jasmine-failure-list .jasmine-summary { display: none; } .jasmine_html-reporter .jasmine-results { margin-top: 14px; } .jasmine_html-reporter .jasmine-summary { margin-top: 14px; } .jasmine_html-reporter .jasmine-summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } .jasmine_html-reporter .jasmine-summary ul.jasmine-suite { margin-top: 7px; margin-bottom: 7px; } .jasmine_html-reporter .jasmine-summary li.jasmine-passed a { color: #007069; } .jasmine_html-reporter .jasmine-summary li.jasmine-failed a { color: #ca3a11; } .jasmine_html-reporter .jasmine-summary li.jasmine-empty a { color: #ba9d37; } .jasmine_html-reporter .jasmine-summary li.jasmine-pending a { color: #ba9d37; } .jasmine_html-reporter .jasmine-summary li.jasmine-disabled a { color: #bababa; } .jasmine_html-reporter .jasmine-description + .jasmine-suite { margin-top: 0; } .jasmine_html-reporter .jasmine-suite { margin-top: 14px; } .jasmine_html-reporter .jasmine-suite a { color: #333; } .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail { margin-bottom: 28px; } .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; } .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description a { color: white; } .jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre; } .jasmine_html-reporter .jasmine-result-message span.jasmine-result { display: block; } .jasmine_html-reporter .jasmine-stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; } public/vendors/split/packages/splitjs/test/lib/jasmine-2.6.4/jasmine.js000064400000424760146725417150021740 0ustar00/* Copyright (c) 2008-2017 Pivotal Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ var getJasmineRequireObj = (function (jasmineGlobal) { var jasmineRequire; if (typeof module !== 'undefined' && module.exports && typeof exports !== 'undefined') { if (typeof global !== 'undefined') { jasmineGlobal = global; } else { jasmineGlobal = {}; } jasmineRequire = exports; } else { if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') { jasmineGlobal = window; } jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {}; } function getJasmineRequire() { return jasmineRequire; } getJasmineRequire().core = function(jRequire) { var j$ = {}; jRequire.base(j$, jasmineGlobal); j$.util = jRequire.util(); j$.errors = jRequire.errors(); j$.formatErrorMsg = jRequire.formatErrorMsg(); j$.Any = jRequire.Any(j$); j$.Anything = jRequire.Anything(j$); j$.CallTracker = jRequire.CallTracker(j$); j$.MockDate = jRequire.MockDate(); j$.getClearStack = jRequire.clearStack(j$); j$.Clock = jRequire.Clock(); j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); j$.Env = jRequire.Env(j$); j$.ExceptionFormatter = jRequire.ExceptionFormatter(); j$.Expectation = jRequire.Expectation(); j$.buildExpectationResult = jRequire.buildExpectationResult(); j$.JsApiReporter = jRequire.JsApiReporter(); j$.matchersUtil = jRequire.matchersUtil(j$); j$.ObjectContaining = jRequire.ObjectContaining(j$); j$.ArrayContaining = jRequire.ArrayContaining(j$); j$.pp = jRequire.pp(j$); j$.QueueRunner = jRequire.QueueRunner(j$); j$.ReportDispatcher = jRequire.ReportDispatcher(); j$.Spec = jRequire.Spec(j$); j$.Spy = jRequire.Spy(j$); j$.SpyRegistry = jRequire.SpyRegistry(j$); j$.SpyStrategy = jRequire.SpyStrategy(j$); j$.StringMatching = jRequire.StringMatching(j$); j$.Suite = jRequire.Suite(j$); j$.Timer = jRequire.Timer(); j$.TreeProcessor = jRequire.TreeProcessor(); j$.version = jRequire.version(); j$.Order = jRequire.Order(); j$.DiffBuilder = jRequire.DiffBuilder(j$); j$.NullDiffBuilder = jRequire.NullDiffBuilder(j$); j$.ObjectPath = jRequire.ObjectPath(j$); j$.GlobalErrors = jRequire.GlobalErrors(j$); j$.matchers = jRequire.requireMatchers(jRequire, j$); return j$; }; return getJasmineRequire; })(this); getJasmineRequireObj().requireMatchers = function(jRequire, j$) { var availableMatchers = [ 'toBe', 'toBeCloseTo', 'toBeDefined', 'toBeFalsy', 'toBeGreaterThan', 'toBeGreaterThanOrEqual', 'toBeLessThan', 'toBeLessThanOrEqual', 'toBeNaN', 'toBeNegativeInfinity', 'toBeNull', 'toBePositiveInfinity', 'toBeTruthy', 'toBeUndefined', 'toContain', 'toEqual', 'toHaveBeenCalled', 'toHaveBeenCalledBefore', 'toHaveBeenCalledTimes', 'toHaveBeenCalledWith', 'toMatch', 'toThrow', 'toThrowError' ], matchers = {}; for (var i = 0; i < availableMatchers.length; i++) { var name = availableMatchers[i]; matchers[name] = jRequire[name](j$); } return matchers; }; getJasmineRequireObj().base = function(j$, jasmineGlobal) { j$.unimplementedMethod_ = function() { throw new Error('unimplemented method'); }; /** * Maximum object depth the pretty printer will print to. * Set this to a lower value to speed up pretty printing if you have large objects. * @name jasmine.MAX_PRETTY_PRINT_DEPTH */ j$.MAX_PRETTY_PRINT_DEPTH = 40; /** * Maximum number of array elements to display when pretty printing objects. * Elements past this number will be ellipised. * @name jasmine.MAX_PRETTY_PRINT_ARRAY_LENGTH */ j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; /** * Default number of milliseconds Jasmine will wait for an asynchronous spec to complete. * @name jasmine.DEFAULT_TIMEOUT_INTERVAL */ j$.DEFAULT_TIMEOUT_INTERVAL = 5000; j$.getGlobal = function() { return jasmineGlobal; }; /** * Get the currently booted Jasmine Environment. * * @name jasmine.getEnv * @function * @return {Env} */ j$.getEnv = function(options) { var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); //jasmine. singletons in here (setTimeout blah blah). return env; }; j$.isArray_ = function(value) { return j$.isA_('Array', value); }; j$.isObject_ = function(value) { return !j$.util.isUndefined(value) && value !== null && j$.isA_('Object', value); }; j$.isString_ = function(value) { return j$.isA_('String', value); }; j$.isNumber_ = function(value) { return j$.isA_('Number', value); }; j$.isFunction_ = function(value) { return j$.isA_('Function', value); }; j$.isA_ = function(typeName, value) { return j$.getType_(value) === '[object ' + typeName + ']'; }; j$.getType_ = function(value) { return Object.prototype.toString.apply(value); }; j$.isDomNode = function(obj) { return obj.nodeType > 0; }; j$.fnNameFor = function(func) { if (func.name) { return func.name; } var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/); return matches ? matches[1] : ''; }; /** * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), * that will succeed if the actual value being compared is an instance of the specified class/constructor. * @name jasmine.any * @function * @param {Constructor} clazz - The constructor to check against. */ j$.any = function(clazz) { return new j$.Any(clazz); }; /** * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), * that will succeed if the actual value being compared is not `null` and not `undefined`. * @name jasmine.anything * @function */ j$.anything = function() { return new j$.Anything(); }; /** * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), * that will succeed if the actual value being compared contains at least the keys and values. * @name jasmine.objectContaining * @function * @param {Object} sample - The subset of properties that _must_ be in the actual. */ j$.objectContaining = function(sample) { return new j$.ObjectContaining(sample); }; /** * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), * that will succeed if the actual value is a `String` that matches the `RegExp` or `String`. * @name jasmine.stringMatching * @function * @param {RegExp|String} expected */ j$.stringMatching = function(expected) { return new j$.StringMatching(expected); }; /** * Get a matcher, usable in any {@link matchers|matcher} that uses Jasmine's equality (e.g. {@link matchers#toEqual|toEqual}, {@link matchers#toContain|toContain}, or {@link matchers#toHaveBeenCalledWith|toHaveBeenCalledWith}), * that will succeed if the actual value is an `Array` that contains at least the elements in the sample. * @name jasmine.arrayContaining * @function * @param {Array} sample */ j$.arrayContaining = function(sample) { return new j$.ArrayContaining(sample); }; /** * Create a bare {@link Spy} object. This won't be installed anywhere and will not have any implementation behind it. * @name jasmine.createSpy * @function * @param {String} [name] - Name to give the spy. This will be displayed in failure messages. * @param {Function} [originalFn] - Function to act as the real implementation. * @return {Spy} */ j$.createSpy = function(name, originalFn) { return j$.Spy(name, originalFn); }; j$.isSpy = function(putativeSpy) { if (!putativeSpy) { return false; } return putativeSpy.and instanceof j$.SpyStrategy && putativeSpy.calls instanceof j$.CallTracker; }; /** * Create an object with multiple {@link Spy}s as its members. * @name jasmine.createSpyObj * @function * @param {String} [baseName] - Base name for the spies in the object. * @param {String[]|Object} methodNames - Array of method names to create spies for, or Object whose keys will be method names and values the {@link Spy#and#returnValue|returnValue}. * @return {Object} */ j$.createSpyObj = function(baseName, methodNames) { var baseNameIsCollection = j$.isObject_(baseName) || j$.isArray_(baseName); if (baseNameIsCollection && j$.util.isUndefined(methodNames)) { methodNames = baseName; baseName = 'unknown'; } var obj = {}; var spiesWereSet = false; if (j$.isArray_(methodNames)) { for (var i = 0; i < methodNames.length; i++) { obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); spiesWereSet = true; } } else if (j$.isObject_(methodNames)) { for (var key in methodNames) { if (methodNames.hasOwnProperty(key)) { obj[key] = j$.createSpy(baseName + '.' + key); obj[key].and.returnValue(methodNames[key]); spiesWereSet = true; } } } if (!spiesWereSet) { throw 'createSpyObj requires a non-empty array or object of method names to create spies for'; } return obj; }; }; getJasmineRequireObj().util = function() { var util = {}; util.inherit = function(childClass, parentClass) { var Subclass = function() { }; Subclass.prototype = parentClass.prototype; childClass.prototype = new Subclass(); }; util.htmlEscape = function(str) { if (!str) { return str; } return str.replace(/&/g, '&') .replace(//g, '>'); }; util.argsToArray = function(args) { var arrayOfArgs = []; for (var i = 0; i < args.length; i++) { arrayOfArgs.push(args[i]); } return arrayOfArgs; }; util.isUndefined = function(obj) { return obj === void 0; }; util.arrayContains = function(array, search) { var i = array.length; while (i--) { if (array[i] === search) { return true; } } return false; }; util.clone = function(obj) { if (Object.prototype.toString.apply(obj) === '[object Array]') { return obj.slice(); } var cloned = {}; for (var prop in obj) { if (obj.hasOwnProperty(prop)) { cloned[prop] = obj[prop]; } } return cloned; }; util.getPropertyDescriptor = function(obj, methodName) { var descriptor, proto = obj; do { descriptor = Object.getOwnPropertyDescriptor(proto, methodName); proto = Object.getPrototypeOf(proto); } while (!descriptor && proto); return descriptor; }; util.objectDifference = function(obj, toRemove) { var diff = {}; for (var key in obj) { if (util.has(obj, key) && !util.has(toRemove, key)) { diff[key] = obj[key]; } } return diff; }; util.has = function(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); }; return util; }; getJasmineRequireObj().Spec = function(j$) { function Spec(attrs) { this.expectationFactory = attrs.expectationFactory; this.resultCallback = attrs.resultCallback || function() {}; this.id = attrs.id; this.description = attrs.description || ''; this.queueableFn = attrs.queueableFn; this.beforeAndAfterFns = attrs.beforeAndAfterFns || function() { return {befores: [], afters: []}; }; this.userContext = attrs.userContext || function() { return {}; }; this.onStart = attrs.onStart || function() {}; this.getSpecName = attrs.getSpecName || function() { return ''; }; this.expectationResultFactory = attrs.expectationResultFactory || function() { }; this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; if (!this.queueableFn.fn) { this.pend(); } this.result = { id: this.id, description: this.description, fullName: this.getFullName(), failedExpectations: [], passedExpectations: [], pendingReason: '' }; } Spec.prototype.addExpectationResult = function(passed, data, isError) { var expectationResult = this.expectationResultFactory(data); if (passed) { this.result.passedExpectations.push(expectationResult); } else { this.result.failedExpectations.push(expectationResult); if (this.throwOnExpectationFailure && !isError) { throw new j$.errors.ExpectationFailed(); } } }; Spec.prototype.expect = function(actual) { return this.expectationFactory(actual, this); }; Spec.prototype.execute = function(onComplete, enabled) { var self = this; this.onStart(this); if (!this.isExecutable() || this.markedPending || enabled === false) { complete(enabled); return; } var fns = this.beforeAndAfterFns(); var allFns = fns.befores.concat(this.queueableFn).concat(fns.afters); this.queueRunnerFactory({ queueableFns: allFns, onException: function() { self.onException.apply(self, arguments); }, onComplete: complete, userContext: this.userContext() }); function complete(enabledAgain) { self.result.status = self.status(enabledAgain); self.resultCallback(self.result); if (onComplete) { onComplete(); } } }; Spec.prototype.onException = function onException(e) { if (Spec.isPendingSpecException(e)) { this.pend(extractCustomPendingMessage(e)); return; } if (e instanceof j$.errors.ExpectationFailed) { return; } this.addExpectationResult(false, { matcherName: '', passed: false, expected: '', actual: '', error: e }, true); }; Spec.prototype.disable = function() { this.disabled = true; }; Spec.prototype.pend = function(message) { this.markedPending = true; if (message) { this.result.pendingReason = message; } }; Spec.prototype.getResult = function() { this.result.status = this.status(); return this.result; }; Spec.prototype.status = function(enabled) { if (this.disabled || enabled === false) { return 'disabled'; } if (this.markedPending) { return 'pending'; } if (this.result.failedExpectations.length > 0) { return 'failed'; } else { return 'passed'; } }; Spec.prototype.isExecutable = function() { return !this.disabled; }; Spec.prototype.getFullName = function() { return this.getSpecName(this); }; var extractCustomPendingMessage = function(e) { var fullMessage = e.toString(), boilerplateStart = fullMessage.indexOf(Spec.pendingSpecExceptionMessage), boilerplateEnd = boilerplateStart + Spec.pendingSpecExceptionMessage.length; return fullMessage.substr(boilerplateEnd); }; Spec.pendingSpecExceptionMessage = '=> marked Pending'; Spec.isPendingSpecException = function(e) { return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); }; return Spec; }; if (typeof window == void 0 && typeof exports == 'object') { exports.Spec = jasmineRequire.Spec; } /*jshint bitwise: false*/ getJasmineRequireObj().Order = function() { function Order(options) { this.random = 'random' in options ? options.random : true; var seed = this.seed = options.seed || generateSeed(); this.sort = this.random ? randomOrder : naturalOrder; function naturalOrder(items) { return items; } function randomOrder(items) { var copy = items.slice(); copy.sort(function(a, b) { return jenkinsHash(seed + a.id) - jenkinsHash(seed + b.id); }); return copy; } function generateSeed() { return String(Math.random()).slice(-5); } // Bob Jenkins One-at-a-Time Hash algorithm is a non-cryptographic hash function // used to get a different output when the key changes slighly. // We use your return to sort the children randomly in a consistent way when // used in conjunction with a seed function jenkinsHash(key) { var hash, i; for(hash = i = 0; i < key.length; ++i) { hash += key.charCodeAt(i); hash += (hash << 10); hash ^= (hash >> 6); } hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15); return hash; } } return Order; }; getJasmineRequireObj().Env = function(j$) { /** * _Note:_ Do not construct this directly, Jasmine will make one during booting. * @name Env * @classdesc The Jasmine environment * @constructor */ function Env(options) { options = options || {}; var self = this; var global = options.global || j$.getGlobal(); var totalSpecsDefined = 0; var catchExceptions = true; var realSetTimeout = j$.getGlobal().setTimeout; var realClearTimeout = j$.getGlobal().clearTimeout; var clearStack = j$.getClearStack(j$.getGlobal()); this.clock = new j$.Clock(global, function () { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global)); var runnableResources = {}; var currentSpec = null; var currentlyExecutingSuites = []; var currentDeclarationSuite = null; var throwOnExpectationFailure = false; var random = false; var seed = null; var currentSuite = function() { return currentlyExecutingSuites[currentlyExecutingSuites.length - 1]; }; var currentRunnable = function() { return currentSpec || currentSuite(); }; var reporter = new j$.ReportDispatcher([ 'jasmineStarted', 'jasmineDone', 'suiteStarted', 'suiteDone', 'specStarted', 'specDone' ]); var globalErrors = new j$.GlobalErrors(); this.specFilter = function() { return true; }; this.addCustomEqualityTester = function(tester) { if(!currentRunnable()) { throw new Error('Custom Equalities must be added in a before function or a spec'); } runnableResources[currentRunnable().id].customEqualityTesters.push(tester); }; this.addMatchers = function(matchersToAdd) { if(!currentRunnable()) { throw new Error('Matchers must be added in a before function or a spec'); } var customMatchers = runnableResources[currentRunnable().id].customMatchers; for (var matcherName in matchersToAdd) { customMatchers[matcherName] = matchersToAdd[matcherName]; } }; j$.Expectation.addCoreMatchers(j$.matchers); var nextSpecId = 0; var getNextSpecId = function() { return 'spec' + nextSpecId++; }; var nextSuiteId = 0; var getNextSuiteId = function() { return 'suite' + nextSuiteId++; }; var expectationFactory = function(actual, spec) { return j$.Expectation.Factory({ util: j$.matchersUtil, customEqualityTesters: runnableResources[spec.id].customEqualityTesters, customMatchers: runnableResources[spec.id].customMatchers, actual: actual, addExpectationResult: addExpectationResult }); function addExpectationResult(passed, result) { return spec.addExpectationResult(passed, result); } }; var defaultResourcesForRunnable = function(id, parentRunnableId) { var resources = {spies: [], customEqualityTesters: [], customMatchers: {}}; if(runnableResources[parentRunnableId]){ resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters); resources.customMatchers = j$.util.clone(runnableResources[parentRunnableId].customMatchers); } runnableResources[id] = resources; }; var clearResourcesForRunnable = function(id) { spyRegistry.clearSpies(); delete runnableResources[id]; }; var beforeAndAfterFns = function(suite) { return function() { var befores = [], afters = []; while(suite) { befores = befores.concat(suite.beforeFns); afters = afters.concat(suite.afterFns); suite = suite.parentSuite; } return { befores: befores.reverse(), afters: afters }; }; }; var getSpecName = function(spec, suite) { var fullName = [spec.description], suiteFullName = suite.getFullName(); if (suiteFullName !== '') { fullName.unshift(suiteFullName); } return fullName.join(' '); }; // TODO: we may just be able to pass in the fn instead of wrapping here var buildExpectationResult = j$.buildExpectationResult, exceptionFormatter = new j$.ExceptionFormatter(), expectationResultFactory = function(attrs) { attrs.messageFormatter = exceptionFormatter.message; attrs.stackFormatter = exceptionFormatter.stack; return buildExpectationResult(attrs); }; // TODO: fix this naming, and here's where the value comes in this.catchExceptions = function(value) { catchExceptions = !!value; return catchExceptions; }; this.catchingExceptions = function() { return catchExceptions; }; var maximumSpecCallbackDepth = 20; var currentSpecCallbackDepth = 0; var catchException = function(e) { return j$.Spec.isPendingSpecException(e) || catchExceptions; }; this.throwOnExpectationFailure = function(value) { throwOnExpectationFailure = !!value; }; this.throwingExpectationFailures = function() { return throwOnExpectationFailure; }; this.randomizeTests = function(value) { random = !!value; }; this.randomTests = function() { return random; }; this.seed = function(value) { if (value) { seed = value; } return seed; }; var queueRunnerFactory = function(options) { options.catchException = catchException; options.clearStack = options.clearStack || clearStack; options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; options.fail = self.fail; options.globalErrors = globalErrors; new j$.QueueRunner(options).execute(); }; var topSuite = new j$.Suite({ env: this, id: getNextSuiteId(), description: 'Jasmine__TopLevel__Suite', expectationFactory: expectationFactory, expectationResultFactory: expectationResultFactory }); defaultResourcesForRunnable(topSuite.id); currentDeclarationSuite = topSuite; this.topSuite = function() { return topSuite; }; this.execute = function(runnablesToRun) { if(!runnablesToRun) { if (focusedRunnables.length) { runnablesToRun = focusedRunnables; } else { runnablesToRun = [topSuite.id]; } } var order = new j$.Order({ random: random, seed: seed }); var processor = new j$.TreeProcessor({ tree: topSuite, runnableIds: runnablesToRun, queueRunnerFactory: queueRunnerFactory, nodeStart: function(suite) { currentlyExecutingSuites.push(suite); defaultResourcesForRunnable(suite.id, suite.parentSuite.id); reporter.suiteStarted(suite.result); }, nodeComplete: function(suite, result) { if (suite !== currentSuite()) { throw new Error('Tried to complete the wrong suite'); } if (!suite.markedPending) { clearResourcesForRunnable(suite.id); } currentlyExecutingSuites.pop(); reporter.suiteDone(result); }, orderChildren: function(node) { return order.sort(node.children); } }); if(!processor.processTree().valid) { throw new Error('Invalid order: would cause a beforeAll or afterAll to be run multiple times'); } reporter.jasmineStarted({ totalSpecsDefined: totalSpecsDefined }); currentlyExecutingSuites.push(topSuite); globalErrors.install(); processor.execute(function() { clearResourcesForRunnable(topSuite.id); currentlyExecutingSuites.pop(); globalErrors.uninstall(); reporter.jasmineDone({ order: order, failedExpectations: topSuite.result.failedExpectations }); }); }; /** * Add a custom reporter to the Jasmine environment. * @name Env#addReporter * @function * @see custom_reporter */ this.addReporter = function(reporterToAdd) { reporter.addReporter(reporterToAdd); }; this.provideFallbackReporter = function(reporterToAdd) { reporter.provideFallbackReporter(reporterToAdd); }; this.clearReporters = function() { reporter.clearReporters(); }; var spyRegistry = new j$.SpyRegistry({currentSpies: function() { if(!currentRunnable()) { throw new Error('Spies must be created in a before function or a spec'); } return runnableResources[currentRunnable().id].spies; }}); this.allowRespy = function(allow){ spyRegistry.allowRespy(allow); }; this.spyOn = function() { return spyRegistry.spyOn.apply(spyRegistry, arguments); }; this.spyOnProperty = function() { return spyRegistry.spyOnProperty.apply(spyRegistry, arguments); }; var ensureIsFunction = function(fn, caller) { if (!j$.isFunction_(fn)) { throw new Error(caller + ' expects a function argument; received ' + j$.getType_(fn)); } }; var suiteFactory = function(description) { var suite = new j$.Suite({ env: self, id: getNextSuiteId(), description: description, parentSuite: currentDeclarationSuite, expectationFactory: expectationFactory, expectationResultFactory: expectationResultFactory, throwOnExpectationFailure: throwOnExpectationFailure }); return suite; }; this.describe = function(description, specDefinitions) { ensureIsFunction(specDefinitions, 'describe'); var suite = suiteFactory(description); if (specDefinitions.length > 0) { throw new Error('describe does not expect any arguments'); } if (currentDeclarationSuite.markedPending) { suite.pend(); } addSpecsToSuite(suite, specDefinitions); return suite; }; this.xdescribe = function(description, specDefinitions) { ensureIsFunction(specDefinitions, 'xdescribe'); var suite = suiteFactory(description); suite.pend(); addSpecsToSuite(suite, specDefinitions); return suite; }; var focusedRunnables = []; this.fdescribe = function(description, specDefinitions) { ensureIsFunction(specDefinitions, 'fdescribe'); var suite = suiteFactory(description); suite.isFocused = true; focusedRunnables.push(suite.id); unfocusAncestor(); addSpecsToSuite(suite, specDefinitions); return suite; }; function addSpecsToSuite(suite, specDefinitions) { var parentSuite = currentDeclarationSuite; parentSuite.addChild(suite); currentDeclarationSuite = suite; var declarationError = null; try { specDefinitions.call(suite); } catch (e) { declarationError = e; } if (declarationError) { self.it('encountered a declaration exception', function() { throw declarationError; }); } currentDeclarationSuite = parentSuite; } function findFocusedAncestor(suite) { while (suite) { if (suite.isFocused) { return suite.id; } suite = suite.parentSuite; } return null; } function unfocusAncestor() { var focusedAncestor = findFocusedAncestor(currentDeclarationSuite); if (focusedAncestor) { for (var i = 0; i < focusedRunnables.length; i++) { if (focusedRunnables[i] === focusedAncestor) { focusedRunnables.splice(i, 1); break; } } } } var specFactory = function(description, fn, suite, timeout) { totalSpecsDefined++; var spec = new j$.Spec({ id: getNextSpecId(), beforeAndAfterFns: beforeAndAfterFns(suite), expectationFactory: expectationFactory, resultCallback: specResultCallback, getSpecName: function(spec) { return getSpecName(spec, suite); }, onStart: specStarted, description: description, expectationResultFactory: expectationResultFactory, queueRunnerFactory: queueRunnerFactory, userContext: function() { return suite.clonedSharedUserContext(); }, queueableFn: { fn: fn, timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } }, throwOnExpectationFailure: throwOnExpectationFailure }); if (!self.specFilter(spec)) { spec.disable(); } return spec; function specResultCallback(result) { clearResourcesForRunnable(spec.id); currentSpec = null; reporter.specDone(result); } function specStarted(spec) { currentSpec = spec; defaultResourcesForRunnable(spec.id, suite.id); reporter.specStarted(spec.result); } }; this.it = function(description, fn, timeout) { // it() sometimes doesn't have a fn argument, so only check the type if // it's given. if (arguments.length > 1 && typeof fn !== 'undefined') { ensureIsFunction(fn, 'it'); } var spec = specFactory(description, fn, currentDeclarationSuite, timeout); if (currentDeclarationSuite.markedPending) { spec.pend(); } currentDeclarationSuite.addChild(spec); return spec; }; this.xit = function(description, fn, timeout) { // xit(), like it(), doesn't always have a fn argument, so only check the // type when needed. if (arguments.length > 1 && typeof fn !== 'undefined') { ensureIsFunction(fn, 'xit'); } var spec = this.it.apply(this, arguments); spec.pend('Temporarily disabled with xit'); return spec; }; this.fit = function(description, fn, timeout){ ensureIsFunction(fn, 'fit'); var spec = specFactory(description, fn, currentDeclarationSuite, timeout); currentDeclarationSuite.addChild(spec); focusedRunnables.push(spec.id); unfocusAncestor(); return spec; }; this.expect = function(actual) { if (!currentRunnable()) { throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out'); } return currentRunnable().expect(actual); }; this.beforeEach = function(beforeEachFunction, timeout) { ensureIsFunction(beforeEachFunction, 'beforeEach'); currentDeclarationSuite.beforeEach({ fn: beforeEachFunction, timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } }); }; this.beforeAll = function(beforeAllFunction, timeout) { ensureIsFunction(beforeAllFunction, 'beforeAll'); currentDeclarationSuite.beforeAll({ fn: beforeAllFunction, timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } }); }; this.afterEach = function(afterEachFunction, timeout) { ensureIsFunction(afterEachFunction, 'afterEach'); currentDeclarationSuite.afterEach({ fn: afterEachFunction, timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } }); }; this.afterAll = function(afterAllFunction, timeout) { ensureIsFunction(afterAllFunction, 'afterAll'); currentDeclarationSuite.afterAll({ fn: afterAllFunction, timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } }); }; this.pending = function(message) { var fullMessage = j$.Spec.pendingSpecExceptionMessage; if(message) { fullMessage += message; } throw fullMessage; }; this.fail = function(error) { if (!currentRunnable()) { throw new Error('\'fail\' was used when there was no current spec, this could be because an asynchronous test timed out'); } var message = 'Failed'; if (error) { message += ': '; if (error.message) { message += error.message; } else if (jasmine.isString_(error)) { message += error; } else { // pretty print all kind of objects. This includes arrays. message += jasmine.pp(error); } } currentRunnable().addExpectationResult(false, { matcherName: '', passed: false, expected: '', actual: '', message: message, error: error && error.message ? error : null }); }; } return Env; }; getJasmineRequireObj().JsApiReporter = function() { var noopTimer = { start: function(){}, elapsed: function(){ return 0; } }; /** * _Note:_ Do not construct this directly, use the global `jsApiReporter` to retrieve the instantiated object. * * @name jsApiReporter * @classdesc Reporter added by default in `boot.js` to record results for retrieval in javascript code. * @class */ function JsApiReporter(options) { var timer = options.timer || noopTimer, status = 'loaded'; this.started = false; this.finished = false; this.runDetails = {}; this.jasmineStarted = function() { this.started = true; status = 'started'; timer.start(); }; var executionTime; this.jasmineDone = function(runDetails) { this.finished = true; this.runDetails = runDetails; executionTime = timer.elapsed(); status = 'done'; }; /** * Get the current status for the Jasmine environment. * @name jsApiReporter#status * @function * @return {String} - One of `loaded`, `started`, or `done` */ this.status = function() { return status; }; var suites = [], suites_hash = {}; this.suiteStarted = function(result) { suites_hash[result.id] = result; }; this.suiteDone = function(result) { storeSuite(result); }; /** * Get the results for a set of suites. * * Retrievable in slices for easier serialization. * @name jsApiReporter#suiteResults * @function * @param {Number} index - The position in the suites list to start from. * @param {Number} length - Maximum number of suite results to return. * @return {Object[]} */ this.suiteResults = function(index, length) { return suites.slice(index, index + length); }; function storeSuite(result) { suites.push(result); suites_hash[result.id] = result; } /** * Get all of the suites in a single object, with their `id` as the key. * @name jsApiReporter#suites * @function * @return {Object} */ this.suites = function() { return suites_hash; }; var specs = []; this.specDone = function(result) { specs.push(result); }; /** * Get the results for a set of specs. * * Retrievable in slices for easier serialization. * @name jsApiReporter#specResults * @function * @param {Number} index - The position in the specs list to start from. * @param {Number} length - Maximum number of specs results to return. * @return {Object[]} */ this.specResults = function(index, length) { return specs.slice(index, index + length); }; /** * Get all spec results. * @name jsApiReporter#specs * @function * @return {Object[]} */ this.specs = function() { return specs; }; /** * Get the number of milliseconds it took for the full Jasmine suite to run. * @name jsApiReporter#executionTime * @function * @return {Number} */ this.executionTime = function() { return executionTime; }; } return JsApiReporter; }; getJasmineRequireObj().Any = function(j$) { function Any(expectedObject) { if (typeof expectedObject === 'undefined') { throw new TypeError( 'jasmine.any() expects to be passed a constructor function. ' + 'Please pass one or use jasmine.anything() to match any object.' ); } this.expectedObject = expectedObject; } Any.prototype.asymmetricMatch = function(other) { if (this.expectedObject == String) { return typeof other == 'string' || other instanceof String; } if (this.expectedObject == Number) { return typeof other == 'number' || other instanceof Number; } if (this.expectedObject == Function) { return typeof other == 'function' || other instanceof Function; } if (this.expectedObject == Object) { return typeof other == 'object'; } if (this.expectedObject == Boolean) { return typeof other == 'boolean'; } return other instanceof this.expectedObject; }; Any.prototype.jasmineToString = function() { return ''; }; return Any; }; getJasmineRequireObj().Anything = function(j$) { function Anything() {} Anything.prototype.asymmetricMatch = function(other) { return !j$.util.isUndefined(other) && other !== null; }; Anything.prototype.jasmineToString = function() { return ''; }; return Anything; }; getJasmineRequireObj().ArrayContaining = function(j$) { function ArrayContaining(sample) { this.sample = sample; } ArrayContaining.prototype.asymmetricMatch = function(other, customTesters) { var className = Object.prototype.toString.call(this.sample); if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); } for (var i = 0; i < this.sample.length; i++) { var item = this.sample[i]; if (!j$.matchersUtil.contains(other, item, customTesters)) { return false; } } return true; }; ArrayContaining.prototype.jasmineToString = function () { return ''; }; return ArrayContaining; }; getJasmineRequireObj().ObjectContaining = function(j$) { function ObjectContaining(sample) { this.sample = sample; } function getPrototype(obj) { if (Object.getPrototypeOf) { return Object.getPrototypeOf(obj); } if (obj.constructor.prototype == obj) { return null; } return obj.constructor.prototype; } function hasProperty(obj, property) { if (!obj) { return false; } if (Object.prototype.hasOwnProperty.call(obj, property)) { return true; } return hasProperty(getPrototype(obj), property); } ObjectContaining.prototype.asymmetricMatch = function(other, customTesters) { if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } for (var property in this.sample) { if (!hasProperty(other, property) || !j$.matchersUtil.equals(this.sample[property], other[property], customTesters)) { return false; } } return true; }; ObjectContaining.prototype.jasmineToString = function() { return ''; }; return ObjectContaining; }; getJasmineRequireObj().StringMatching = function(j$) { function StringMatching(expected) { if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) { throw new Error('Expected is not a String or a RegExp'); } this.regexp = new RegExp(expected); } StringMatching.prototype.asymmetricMatch = function(other) { return this.regexp.test(other); }; StringMatching.prototype.jasmineToString = function() { return ''; }; return StringMatching; }; getJasmineRequireObj().CallTracker = function(j$) { /** * @namespace Spy#calls */ function CallTracker() { var calls = []; var opts = {}; function argCloner(context) { var clonedArgs = []; var argsAsArray = j$.util.argsToArray(context.args); for(var i = 0; i < argsAsArray.length; i++) { if(Object.prototype.toString.apply(argsAsArray[i]).match(/^\[object/)) { clonedArgs.push(j$.util.clone(argsAsArray[i])); } else { clonedArgs.push(argsAsArray[i]); } } context.args = clonedArgs; } this.track = function(context) { if(opts.cloneArgs) { argCloner(context); } calls.push(context); }; /** * Check whether this spy has been invoked. * @name Spy#calls#any * @function * @return {Boolean} */ this.any = function() { return !!calls.length; }; /** * Get the number of invocations of this spy. * @name Spy#calls#count * @function * @return {Integer} */ this.count = function() { return calls.length; }; /** * Get the arguments that were passed to a specific invocation of this spy. * @name Spy#calls#argsFor * @function * @param {Integer} index The 0-based invocation index. * @return {Array} */ this.argsFor = function(index) { var call = calls[index]; return call ? call.args : []; }; /** * Get the raw calls array for this spy. * @name Spy#calls#all * @function * @return {Spy.callData[]} */ this.all = function() { return calls; }; /** * Get all of the arguments for each invocation of this spy in the order they were received. * @name Spy#calls#allArgs * @function * @return {Array} */ this.allArgs = function() { var callArgs = []; for(var i = 0; i < calls.length; i++){ callArgs.push(calls[i].args); } return callArgs; }; /** * Get the first invocation of this spy. * @name Spy#calls#first * @function * @return {ObjecSpy.callData} */ this.first = function() { return calls[0]; }; /** * Get the most recent invocation of this spy. * @name Spy#calls#mostRecent * @function * @return {ObjecSpy.callData} */ this.mostRecent = function() { return calls[calls.length - 1]; }; /** * Reset this spy as if it has never been called. * @name Spy#calls#reset * @function */ this.reset = function() { calls = []; }; /** * Set this spy to do a shallow clone of arguments passed to each invocation. * @name Spy#calls#saveArgumentsByValue * @function */ this.saveArgumentsByValue = function() { opts.cloneArgs = true; }; } return CallTracker; }; getJasmineRequireObj().clearStack = function(j$) { var maxInlineCallCount = 10; function messageChannelImpl(global, setTimeout) { var channel = new global.MessageChannel(), head = {}, tail = head; var taskRunning = false; channel.port1.onmessage = function() { head = head.next; var task = head.task; delete head.task; if (taskRunning) { global.setTimeout(task, 0); } else { try { taskRunning = true; task(); } finally { taskRunning = false; } } }; var currentCallCount = 0; return function clearStack(fn) { currentCallCount++; if (currentCallCount < maxInlineCallCount) { tail = tail.next = { task: fn }; channel.port2.postMessage(0); } else { currentCallCount = 0; setTimeout(fn); } }; } function getClearStack(global) { var currentCallCount = 0; var realSetTimeout = global.setTimeout; var setTimeoutImpl = function clearStack(fn) { Function.prototype.apply.apply(realSetTimeout, [global, [fn, 0]]); }; if (j$.isFunction_(global.setImmediate)) { var realSetImmediate = global.setImmediate; return function(fn) { currentCallCount++; if (currentCallCount < maxInlineCallCount) { realSetImmediate(fn); } else { currentCallCount = 0; setTimeoutImpl(fn); } }; } else if (!j$.util.isUndefined(global.MessageChannel)) { return messageChannelImpl(global, setTimeoutImpl); } else { return setTimeoutImpl; } } return getClearStack; }; getJasmineRequireObj().Clock = function() { /** * _Note:_ Do not construct this directly, Jasmine will make one during booting. You can get the current clock with {@link jasmine.clock}. * @class Clock * @classdesc Jasmine's mock clock is used when testing time dependent code. */ function Clock(global, delayedFunctionSchedulerFactory, mockDate) { var self = this, realTimingFunctions = { setTimeout: global.setTimeout, clearTimeout: global.clearTimeout, setInterval: global.setInterval, clearInterval: global.clearInterval }, fakeTimingFunctions = { setTimeout: setTimeout, clearTimeout: clearTimeout, setInterval: setInterval, clearInterval: clearInterval }, installed = false, delayedFunctionScheduler, timer; /** * Install the mock clock over the built-in methods. * @name Clock#install * @function * @return {Clock} */ self.install = function() { if(!originalTimingFunctionsIntact()) { throw new Error('Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?'); } replace(global, fakeTimingFunctions); timer = fakeTimingFunctions; delayedFunctionScheduler = delayedFunctionSchedulerFactory(); installed = true; return self; }; /** * Uninstall the mock clock, returning the built-in methods to their places. * @name Clock#uninstall * @function */ self.uninstall = function() { delayedFunctionScheduler = null; mockDate.uninstall(); replace(global, realTimingFunctions); timer = realTimingFunctions; installed = false; }; /** * Execute a function with a mocked Clock * * The clock will be {@link Clock#install|install}ed before the function is called and {@link Clock#uninstall|uninstall}ed in a `finally` after the function completes. * @name Clock#withMock * @function * @param {closure} Function The function to be called. */ self.withMock = function(closure) { this.install(); try { closure(); } finally { this.uninstall(); } }; /** * Instruct the installed Clock to also mock the date returned by `new Date()` * @name Clock#mockDate * @function * @param {Date} [initialDate=now] The `Date` to provide. */ self.mockDate = function(initialDate) { mockDate.install(initialDate); }; self.setTimeout = function(fn, delay, params) { if (legacyIE()) { if (arguments.length > 2) { throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); } return timer.setTimeout(fn, delay); } return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]); }; self.setInterval = function(fn, delay, params) { if (legacyIE()) { if (arguments.length > 2) { throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); } return timer.setInterval(fn, delay); } return Function.prototype.apply.apply(timer.setInterval, [global, arguments]); }; self.clearTimeout = function(id) { return Function.prototype.call.apply(timer.clearTimeout, [global, id]); }; self.clearInterval = function(id) { return Function.prototype.call.apply(timer.clearInterval, [global, id]); }; /** * Tick the Clock forward, running any enqueued timeouts along the way * @name Clock#tick * @function * @param {int} millis The number of milliseconds to tick. */ self.tick = function(millis) { if (installed) { delayedFunctionScheduler.tick(millis, function(millis) { mockDate.tick(millis); }); } else { throw new Error('Mock clock is not installed, use jasmine.clock().install()'); } }; return self; function originalTimingFunctionsIntact() { return global.setTimeout === realTimingFunctions.setTimeout && global.clearTimeout === realTimingFunctions.clearTimeout && global.setInterval === realTimingFunctions.setInterval && global.clearInterval === realTimingFunctions.clearInterval; } function legacyIE() { //if these methods are polyfilled, apply will be present return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; } function replace(dest, source) { for (var prop in source) { dest[prop] = source[prop]; } } function setTimeout(fn, delay) { return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2)); } function clearTimeout(id) { return delayedFunctionScheduler.removeFunctionWithId(id); } function setInterval(fn, interval) { return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true); } function clearInterval(id) { return delayedFunctionScheduler.removeFunctionWithId(id); } function argSlice(argsObj, n) { return Array.prototype.slice.call(argsObj, n); } } return Clock; }; getJasmineRequireObj().DelayedFunctionScheduler = function() { function DelayedFunctionScheduler() { var self = this; var scheduledLookup = []; var scheduledFunctions = {}; var currentTime = 0; var delayedFnCount = 0; self.tick = function(millis, tickDate) { millis = millis || 0; var endTime = currentTime + millis; runScheduledFunctions(endTime, tickDate); currentTime = endTime; }; self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) { var f; if (typeof(funcToCall) === 'string') { /* jshint evil: true */ f = function() { return eval(funcToCall); }; /* jshint evil: false */ } else { f = funcToCall; } millis = millis || 0; timeoutKey = timeoutKey || ++delayedFnCount; runAtMillis = runAtMillis || (currentTime + millis); var funcToSchedule = { runAtMillis: runAtMillis, funcToCall: f, recurring: recurring, params: params, timeoutKey: timeoutKey, millis: millis }; if (runAtMillis in scheduledFunctions) { scheduledFunctions[runAtMillis].push(funcToSchedule); } else { scheduledFunctions[runAtMillis] = [funcToSchedule]; scheduledLookup.push(runAtMillis); scheduledLookup.sort(function (a, b) { return a - b; }); } return timeoutKey; }; self.removeFunctionWithId = function(timeoutKey) { for (var runAtMillis in scheduledFunctions) { var funcs = scheduledFunctions[runAtMillis]; var i = indexOfFirstToPass(funcs, function (func) { return func.timeoutKey === timeoutKey; }); if (i > -1) { if (funcs.length === 1) { delete scheduledFunctions[runAtMillis]; deleteFromLookup(runAtMillis); } else { funcs.splice(i, 1); } // intervals get rescheduled when executed, so there's never more // than a single scheduled function with a given timeoutKey break; } } }; return self; function indexOfFirstToPass(array, testFn) { var index = -1; for (var i = 0; i < array.length; ++i) { if (testFn(array[i])) { index = i; break; } } return index; } function deleteFromLookup(key) { var value = Number(key); var i = indexOfFirstToPass(scheduledLookup, function (millis) { return millis === value; }); if (i > -1) { scheduledLookup.splice(i, 1); } } function reschedule(scheduledFn) { self.scheduleFunction(scheduledFn.funcToCall, scheduledFn.millis, scheduledFn.params, true, scheduledFn.timeoutKey, scheduledFn.runAtMillis + scheduledFn.millis); } function forEachFunction(funcsToRun, callback) { for (var i = 0; i < funcsToRun.length; ++i) { callback(funcsToRun[i]); } } function runScheduledFunctions(endTime, tickDate) { tickDate = tickDate || function() {}; if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { tickDate(endTime - currentTime); return; } do { var newCurrentTime = scheduledLookup.shift(); tickDate(newCurrentTime - currentTime); currentTime = newCurrentTime; var funcsToRun = scheduledFunctions[currentTime]; delete scheduledFunctions[currentTime]; forEachFunction(funcsToRun, function(funcToRun) { if (funcToRun.recurring) { reschedule(funcToRun); } }); forEachFunction(funcsToRun, function(funcToRun) { funcToRun.funcToCall.apply(null, funcToRun.params || []); }); } while (scheduledLookup.length > 0 && // checking first if we're out of time prevents setTimeout(0) // scheduled in a funcToRun from forcing an extra iteration currentTime !== endTime && scheduledLookup[0] <= endTime); // ran out of functions to call, but still time left on the clock if (currentTime !== endTime) { tickDate(endTime - currentTime); } } } return DelayedFunctionScheduler; }; getJasmineRequireObj().errors = function() { function ExpectationFailed() {} ExpectationFailed.prototype = new Error(); ExpectationFailed.prototype.constructor = ExpectationFailed; return { ExpectationFailed: ExpectationFailed }; }; getJasmineRequireObj().ExceptionFormatter = function() { function ExceptionFormatter() { this.message = function(error) { var message = ''; if (error.name && error.message) { message += error.name + ': ' + error.message; } else { message += error.toString() + ' thrown'; } if (error.fileName || error.sourceURL) { message += ' in ' + (error.fileName || error.sourceURL); } if (error.line || error.lineNumber) { message += ' (line ' + (error.line || error.lineNumber) + ')'; } return message; }; this.stack = function(error) { return error ? error.stack : null; }; } return ExceptionFormatter; }; getJasmineRequireObj().Expectation = function() { /** * Matchers that come with Jasmine out of the box. * @namespace matchers */ function Expectation(options) { this.util = options.util || { buildFailureMessage: function() {} }; this.customEqualityTesters = options.customEqualityTesters || []; this.actual = options.actual; this.addExpectationResult = options.addExpectationResult || function(){}; this.isNot = options.isNot; var customMatchers = options.customMatchers || {}; for (var matcherName in customMatchers) { this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]); } } Expectation.prototype.wrapCompare = function(name, matcherFactory) { return function() { var args = Array.prototype.slice.call(arguments, 0), expected = args.slice(0), message = ''; args.unshift(this.actual); var matcher = matcherFactory(this.util, this.customEqualityTesters), matcherCompare = matcher.compare; function defaultNegativeCompare() { var result = matcher.compare.apply(null, args); result.pass = !result.pass; return result; } if (this.isNot) { matcherCompare = matcher.negativeCompare || defaultNegativeCompare; } var result = matcherCompare.apply(null, args); if (!result.pass) { if (!result.message) { args.unshift(this.isNot); args.unshift(name); message = this.util.buildFailureMessage.apply(null, args); } else { if (Object.prototype.toString.apply(result.message) === '[object Function]') { message = result.message(); } else { message = result.message; } } } if (expected.length == 1) { expected = expected[0]; } // TODO: how many of these params are needed? this.addExpectationResult( result.pass, { matcherName: name, passed: result.pass, message: message, error: result.error, actual: this.actual, expected: expected // TODO: this may need to be arrayified/sliced } ); }; }; Expectation.addCoreMatchers = function(matchers) { var prototype = Expectation.prototype; for (var matcherName in matchers) { var matcher = matchers[matcherName]; prototype[matcherName] = prototype.wrapCompare(matcherName, matcher); } }; Expectation.Factory = function(options) { options = options || {}; var expect = new Expectation(options); // TODO: this would be nice as its own Object - NegativeExpectation // TODO: copy instead of mutate options options.isNot = true; expect.not = new Expectation(options); return expect; }; return Expectation; }; //TODO: expectation result may make more sense as a presentation of an expectation. getJasmineRequireObj().buildExpectationResult = function() { function buildExpectationResult(options) { var messageFormatter = options.messageFormatter || function() {}, stackFormatter = options.stackFormatter || function() {}; var result = { matcherName: options.matcherName, message: message(), stack: stack(), passed: options.passed }; if(!result.passed) { result.expected = options.expected; result.actual = options.actual; } return result; function message() { if (options.passed) { return 'Passed.'; } else if (options.message) { return options.message; } else if (options.error) { return messageFormatter(options.error); } return ''; } function stack() { if (options.passed) { return ''; } var error = options.error; if (!error) { try { throw new Error(message()); } catch (e) { error = e; } } return stackFormatter(error); } } return buildExpectationResult; }; getJasmineRequireObj().formatErrorMsg = function() { function generateErrorMsg(domain, usage) { var usageDefinition = usage ? '\nUsage: ' + usage : ''; return function errorMsg(msg) { return domain + ' : ' + msg + usageDefinition; }; } return generateErrorMsg; }; getJasmineRequireObj().GlobalErrors = function(j$) { function GlobalErrors(global) { var handlers = []; global = global || j$.getGlobal(); var onerror = function onerror() { var handler = handlers[handlers.length - 1]; if (handler) { handler.apply(null, Array.prototype.slice.call(arguments, 0)); } else { throw arguments[0]; } }; this.uninstall = function noop() {}; this.install = function install() { if (global.process && global.process.listeners && j$.isFunction_(global.process.on)) { var originalHandlers = global.process.listeners('uncaughtException'); global.process.removeAllListeners('uncaughtException'); global.process.on('uncaughtException', onerror); this.uninstall = function uninstall() { global.process.removeListener('uncaughtException', onerror); for (var i = 0; i < originalHandlers.length; i++) { global.process.on('uncaughtException', originalHandlers[i]); } }; } else { var originalHandler = global.onerror; global.onerror = onerror; this.uninstall = function uninstall() { global.onerror = originalHandler; }; } }; this.pushListener = function pushListener(listener) { handlers.push(listener); }; this.popListener = function popListener() { handlers.pop(); }; } return GlobalErrors; }; getJasmineRequireObj().DiffBuilder = function(j$) { return function DiffBuilder() { var path = new j$.ObjectPath(), mismatches = []; return { record: function (actual, expected, formatter) { formatter = formatter || defaultFormatter; mismatches.push(formatter(actual, expected, path)); }, getMessage: function () { return mismatches.join('\n'); }, withPath: function (pathComponent, block) { var oldPath = path; path = path.add(pathComponent); block(); path = oldPath; } }; function defaultFormatter (actual, expected, path) { return 'Expected ' + path + (path.depth() ? ' = ' : '') + j$.pp(actual) + ' to equal ' + j$.pp(expected) + '.'; } }; }; getJasmineRequireObj().matchersUtil = function(j$) { // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? return { equals: equals, contains: function(haystack, needle, customTesters) { customTesters = customTesters || []; if ((Object.prototype.toString.apply(haystack) === '[object Set]')) { return haystack.has(needle); } if ((Object.prototype.toString.apply(haystack) === '[object Array]') || (!!haystack && !haystack.indexOf)) { for (var i = 0; i < haystack.length; i++) { if (equals(haystack[i], needle, customTesters)) { return true; } } return false; } return !!haystack && haystack.indexOf(needle) >= 0; }, buildFailureMessage: function() { var args = Array.prototype.slice.call(arguments, 0), matcherName = args[0], isNot = args[1], actual = args[2], expected = args.slice(3), englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); var message = 'Expected ' + j$.pp(actual) + (isNot ? ' not ' : ' ') + englishyPredicate; if (expected.length > 0) { for (var i = 0; i < expected.length; i++) { if (i > 0) { message += ','; } message += ' ' + j$.pp(expected[i]); } } return message + '.'; } }; function isAsymmetric(obj) { return obj && j$.isA_('Function', obj.asymmetricMatch); } function asymmetricMatch(a, b, customTesters, diffBuilder) { var asymmetricA = isAsymmetric(a), asymmetricB = isAsymmetric(b), result; if (asymmetricA && asymmetricB) { return undefined; } if (asymmetricA) { result = a.asymmetricMatch(b, customTesters); diffBuilder.record(a, b); return result; } if (asymmetricB) { result = b.asymmetricMatch(a, customTesters); diffBuilder.record(a, b); return result; } } function equals(a, b, customTesters, diffBuilder) { customTesters = customTesters || []; diffBuilder = diffBuilder || j$.NullDiffBuilder(); return eq(a, b, [], [], customTesters, diffBuilder); } // Equality function lovingly adapted from isEqual in // [Underscore](http://underscorejs.org) function eq(a, b, aStack, bStack, customTesters, diffBuilder) { var result = true, i; var asymmetricResult = asymmetricMatch(a, b, customTesters, diffBuilder); if (!j$.util.isUndefined(asymmetricResult)) { return asymmetricResult; } for (i = 0; i < customTesters.length; i++) { var customTesterResult = customTesters[i](a, b); if (!j$.util.isUndefined(customTesterResult)) { if (!customTesterResult) { diffBuilder.record(a, b); } return customTesterResult; } } if (a instanceof Error && b instanceof Error) { result = a.message == b.message; if (!result) { diffBuilder.record(a, b); } return result; } // Identical objects are equal. `0 === -0`, but they aren't identical. // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). if (a === b) { result = a !== 0 || 1 / a == 1 / b; if (!result) { diffBuilder.record(a, b); } return result; } // A strict comparison is necessary because `null == undefined`. if (a === null || b === null) { result = a === b; if (!result) { diffBuilder.record(a, b); } return result; } var className = Object.prototype.toString.call(a); if (className != Object.prototype.toString.call(b)) { diffBuilder.record(a, b); return false; } switch (className) { // Strings, numbers, dates, and booleans are compared by value. case '[object String]': // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is // equivalent to `new String("5")`. result = a == String(b); if (!result) { diffBuilder.record(a, b); } return result; case '[object Number]': // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for // other numeric values. result = a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b); if (!result) { diffBuilder.record(a, b); } return result; case '[object Date]': case '[object Boolean]': // Coerce dates and booleans to numeric primitive values. Dates are compared by their // millisecond representations. Note that invalid dates with millisecond representations // of `NaN` are not equivalent. result = +a == +b; if (!result) { diffBuilder.record(a, b); } return result; // RegExps are compared by their source patterns and flags. case '[object RegExp]': return a.source == b.source && a.global == b.global && a.multiline == b.multiline && a.ignoreCase == b.ignoreCase; } if (typeof a != 'object' || typeof b != 'object') { diffBuilder.record(a, b); return false; } var aIsDomNode = j$.isDomNode(a); var bIsDomNode = j$.isDomNode(b); if (aIsDomNode && bIsDomNode) { // At first try to use DOM3 method isEqualNode if (a.isEqualNode) { result = a.isEqualNode(b); if (!result) { diffBuilder.record(a, b); } return result; } // IE8 doesn't support isEqualNode, try to use outerHTML && innerText var aIsElement = a instanceof Element; var bIsElement = b instanceof Element; if (aIsElement && bIsElement) { result = a.outerHTML == b.outerHTML; if (!result) { diffBuilder.record(a, b); } return result; } if (aIsElement || bIsElement) { diffBuilder.record(a, b); return false; } result = a.innerText == b.innerText && a.textContent == b.textContent; if (!result) { diffBuilder.record(a, b); } return result; } if (aIsDomNode || bIsDomNode) { diffBuilder.record(a, b); return false; } // Assume equality for cyclic structures. The algorithm for detecting cyclic // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. var length = aStack.length; while (length--) { // Linear search. Performance is inversely proportional to the number of // unique nested structures. if (aStack[length] == a) { return bStack[length] == b; } } // Add the first object to the stack of traversed objects. aStack.push(a); bStack.push(b); var size = 0; // Recursively compare objects and arrays. // Compare array lengths to determine if a deep comparison is necessary. if (className == '[object Array]') { size = a.length; if (size !== b.length) { diffBuilder.record(a, b); return false; } for (i = 0; i < size; i++) { diffBuilder.withPath(i, function() { result = eq(a[i], b[i], aStack, bStack, customTesters, diffBuilder) && result; }); } if (!result) { return false; } } else if (className == '[object Set]') { if (a.size != b.size) { diffBuilder.record(a, b); return false; } var iterA = a.values(), iterB = b.values(); var valA, valB; do { valA = iterA.next(); valB = iterB.next(); if (!eq(valA.value, valB.value, aStack, bStack, customTesters, j$.NullDiffBuilder())) { diffBuilder.record(a, b); return false; } } while (!valA.done && !valB.done); } else { // Objects with different constructors are not equivalent, but `Object`s // or `Array`s from different frames are. var aCtor = a.constructor, bCtor = b.constructor; if (aCtor !== bCtor && isFunction(aCtor) && isFunction(bCtor) && a instanceof aCtor && b instanceof bCtor && !(aCtor instanceof aCtor && bCtor instanceof bCtor)) { diffBuilder.record(a, b, constructorsAreDifferentFormatter); return false; } } // Deep compare objects. var aKeys = keys(a, className == '[object Array]'), key; size = aKeys.length; // Ensure that both objects contain the same number of properties before comparing deep equality. if (keys(b, className == '[object Array]').length !== size) { diffBuilder.record(a, b, objectKeysAreDifferentFormatter); return false; } for (i = 0; i < size; i++) { key = aKeys[i]; // Deep compare each member if (!j$.util.has(b, key)) { diffBuilder.record(a, b, objectKeysAreDifferentFormatter); result = false; continue; } diffBuilder.withPath(key, function() { if(!eq(a[key], b[key], aStack, bStack, customTesters, diffBuilder)) { result = false; } }); } if (!result) { return false; } // Remove the first object from the stack of traversed objects. aStack.pop(); bStack.pop(); return result; } function keys(obj, isArray) { var allKeys = Object.keys ? Object.keys(obj) : (function(o) { var keys = []; for (var key in o) { if (j$.util.has(o, key)) { keys.push(key); } } return keys; })(obj); if (!isArray) { return allKeys; } if (allKeys.length === 0) { return allKeys; } var extraKeys = []; for (var i = 0; i < allKeys.length; i++) { if (!/^[0-9]+$/.test(allKeys[i])) { extraKeys.push(allKeys[i]); } } return extraKeys; } function has(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); } function isFunction(obj) { return typeof obj === 'function'; } function objectKeysAreDifferentFormatter(actual, expected, path) { var missingProperties = j$.util.objectDifference(expected, actual), extraProperties = j$.util.objectDifference(actual, expected), missingPropertiesMessage = formatKeyValuePairs(missingProperties), extraPropertiesMessage = formatKeyValuePairs(extraProperties), messages = []; if (!path.depth()) { path = 'object'; } if (missingPropertiesMessage.length) { messages.push('Expected ' + path + ' to have properties' + missingPropertiesMessage); } if (extraPropertiesMessage.length) { messages.push('Expected ' + path + ' not to have properties' + extraPropertiesMessage); } return messages.join('\n'); } function constructorsAreDifferentFormatter(actual, expected, path) { if (!path.depth()) { path = 'object'; } return 'Expected ' + path + ' to be a kind of ' + j$.fnNameFor(expected.constructor) + ', but was ' + j$.pp(actual) + '.'; } function formatKeyValuePairs(obj) { var formatted = ''; for (var key in obj) { formatted += '\n ' + key + ': ' + j$.pp(obj[key]); } return formatted; } }; getJasmineRequireObj().NullDiffBuilder = function(j$) { return function() { return { withPath: function(_, block) { block(); }, record: function() {} }; }; }; getJasmineRequireObj().ObjectPath = function(j$) { function ObjectPath(components) { this.components = components || []; } ObjectPath.prototype.toString = function() { if (this.components.length) { return '$' + map(this.components, formatPropertyAccess).join(''); } else { return ''; } }; ObjectPath.prototype.add = function(component) { return new ObjectPath(this.components.concat([component])); }; ObjectPath.prototype.depth = function() { return this.components.length; }; function formatPropertyAccess(prop) { if (typeof prop === 'number') { return '[' + prop + ']'; } if (isValidIdentifier(prop)) { return '.' + prop; } return '[\'' + prop + '\']'; } function map(array, fn) { var results = []; for (var i = 0; i < array.length; i++) { results.push(fn(array[i])); } return results; } function isValidIdentifier(string) { return /^[A-Za-z\$_][A-Za-z0-9\$_]*$/.test(string); } return ObjectPath; }; getJasmineRequireObj().toBe = function() { /** * {@link expect} the actual value to be `===` to the expected value. * @function * @name matchers#toBe * @param {Object} expected - The expected value to compare against. * @example * expect(thing).toBe(realThing); */ function toBe() { return { compare: function(actual, expected) { return { pass: actual === expected }; } }; } return toBe; }; getJasmineRequireObj().toBeCloseTo = function() { /** * {@link expect} the actual value to be within a specified precision of the expected value. * @function * @name matchers#toBeCloseTo * @param {Object} expected - The expected value to compare against. * @param {Number} [precision=2] - The number of decimal points to check. * @example * expect(number).toBeCloseTo(42.2, 3); */ function toBeCloseTo() { return { compare: function(actual, expected, precision) { if (precision !== 0) { precision = precision || 2; } return { pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) }; } }; } return toBeCloseTo; }; getJasmineRequireObj().toBeDefined = function() { /** * {@link expect} the actual value to be defined. (Not `undefined`) * @function * @name matchers#toBeDefined * @example * expect(result).toBeDefined(); */ function toBeDefined() { return { compare: function(actual) { return { pass: (void 0 !== actual) }; } }; } return toBeDefined; }; getJasmineRequireObj().toBeFalsy = function() { /** * {@link expect} the actual value to be falsy * @function * @name matchers#toBeFalsy * @example * expect(result).toBeFalsy(); */ function toBeFalsy() { return { compare: function(actual) { return { pass: !!!actual }; } }; } return toBeFalsy; }; getJasmineRequireObj().toBeGreaterThan = function() { /** * {@link expect} the actual value to be greater than the expected value. * @function * @name matchers#toBeGreaterThan * @param {Number} expected - The value to compare against. * @example * expect(result).toBeGreaterThan(3); */ function toBeGreaterThan() { return { compare: function(actual, expected) { return { pass: actual > expected }; } }; } return toBeGreaterThan; }; getJasmineRequireObj().toBeGreaterThanOrEqual = function() { /** * {@link expect} the actual value to be greater than or equal to the expected value. * @function * @name matchers#toBeGreaterThanOrEqual * @param {Number} expected - The expected value to compare against. * @example * expect(result).toBeGreaterThanOrEqual(25); */ function toBeGreaterThanOrEqual() { return { compare: function(actual, expected) { return { pass: actual >= expected }; } }; } return toBeGreaterThanOrEqual; }; getJasmineRequireObj().toBeLessThan = function() { /** * {@link expect} the actual value to be less than the expected value. * @function * @name matchers#toBeLessThan * @param {Number} expected - The expected value to compare against. * @example * expect(result).toBeLessThan(0); */ function toBeLessThan() { return { compare: function(actual, expected) { return { pass: actual < expected }; } }; } return toBeLessThan; }; getJasmineRequireObj().toBeLessThanOrEqual = function() { /** * {@link expect} the actual value to be less than or equal to the expected value. * @function * @name matchers#toBeLessThanOrEqual * @param {Number} expected - The expected value to compare against. * @example * expect(result).toBeLessThanOrEqual(123); */ function toBeLessThanOrEqual() { return { compare: function(actual, expected) { return { pass: actual <= expected }; } }; } return toBeLessThanOrEqual; }; getJasmineRequireObj().toBeNaN = function(j$) { /** * {@link expect} the actual value to be `NaN` (Not a Number). * @function * @name matchers#toBeNaN * @example * expect(thing).toBeNaN(); */ function toBeNaN() { return { compare: function(actual) { var result = { pass: (actual !== actual) }; if (result.pass) { result.message = 'Expected actual not to be NaN.'; } else { result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; } return result; } }; } return toBeNaN; }; getJasmineRequireObj().toBeNegativeInfinity = function(j$) { /** * {@link expect} the actual value to be `-Infinity` (-infinity). * @function * @name matchers#toBeNegativeInfinity * @example * expect(thing).toBeNegativeInfinity(); */ function toBeNegativeInfinity() { return { compare: function(actual) { var result = { pass: (actual === Number.NEGATIVE_INFINITY) }; if (result.pass) { result.message = 'Expected actual to be -Infinity.'; } else { result.message = function() { return 'Expected ' + j$.pp(actual) + ' not to be -Infinity.'; }; } return result; } }; } return toBeNegativeInfinity; }; getJasmineRequireObj().toBeNull = function() { /** * {@link expect} the actual value to be `null`. * @function * @name matchers#toBeNull * @example * expect(result).toBeNull(); */ function toBeNull() { return { compare: function(actual) { return { pass: actual === null }; } }; } return toBeNull; }; getJasmineRequireObj().toBePositiveInfinity = function(j$) { /** * {@link expect} the actual value to be `Infinity` (infinity). * @function * @name matchers#toBePositiveInfinity * @example * expect(thing).toBePositiveInfinity(); */ function toBePositiveInfinity() { return { compare: function(actual) { var result = { pass: (actual === Number.POSITIVE_INFINITY) }; if (result.pass) { result.message = 'Expected actual to be Infinity.'; } else { result.message = function() { return 'Expected ' + j$.pp(actual) + ' not to be Infinity.'; }; } return result; } }; } return toBePositiveInfinity; }; getJasmineRequireObj().toBeTruthy = function() { /** * {@link expect} the actual value to be truthy. * @function * @name matchers#toBeTruthy * @example * expect(thing).toBeTruthy(); */ function toBeTruthy() { return { compare: function(actual) { return { pass: !!actual }; } }; } return toBeTruthy; }; getJasmineRequireObj().toBeUndefined = function() { /** * {@link expect} the actual value to be `undefined`. * @function * @name matchers#toBeUndefined * @example * expect(result).toBeUndefined(): */ function toBeUndefined() { return { compare: function(actual) { return { pass: void 0 === actual }; } }; } return toBeUndefined; }; getJasmineRequireObj().toContain = function() { /** * {@link expect} the actual value to contain a specific value. * @function * @name matchers#toContain * @param {Object} expected - The value to look for. * @example * expect(array).toContain(anElement); * expect(string).toContain(substring); */ function toContain(util, customEqualityTesters) { customEqualityTesters = customEqualityTesters || []; return { compare: function(actual, expected) { return { pass: util.contains(actual, expected, customEqualityTesters) }; } }; } return toContain; }; getJasmineRequireObj().toEqual = function(j$) { /** * {@link expect} the actual value to be equal to the expected, using deep equality comparison. * @function * @name matchers#toEqual * @param {Object} expected - Expected value * @example * expect(bigObject).toEqual({"foo": ['bar', 'baz']}); */ function toEqual(util, customEqualityTesters) { customEqualityTesters = customEqualityTesters || []; return { compare: function(actual, expected) { var result = { pass: false }, diffBuilder = j$.DiffBuilder(); result.pass = util.equals(actual, expected, customEqualityTesters, diffBuilder); // TODO: only set error message if test fails result.message = diffBuilder.getMessage(); return result; } }; } return toEqual; }; getJasmineRequireObj().toHaveBeenCalled = function(j$) { var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalled()'); /** * {@link expect} the actual (a {@link Spy}) to have been called. * @function * @name matchers#toHaveBeenCalled * @example * expect(mySpy).toHaveBeenCalled(); * expect(mySpy).not.toHaveBeenCalled(); */ function toHaveBeenCalled() { return { compare: function(actual) { var result = {}; if (!j$.isSpy(actual)) { throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); } if (arguments.length > 1) { throw new Error(getErrorMsg('Does not take arguments, use toHaveBeenCalledWith')); } result.pass = actual.calls.any(); result.message = result.pass ? 'Expected spy ' + actual.and.identity() + ' not to have been called.' : 'Expected spy ' + actual.and.identity() + ' to have been called.'; return result; } }; } return toHaveBeenCalled; }; getJasmineRequireObj().toHaveBeenCalledBefore = function(j$) { var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledBefore()'); /** * {@link expect} the actual value (a {@link Spy}) to have been called before another {@link Spy}. * @function * @name matchers#toHaveBeenCalledBefore * @param {Spy} expected - {@link Spy} that should have been called after the `actual` {@link Spy}. * @example * expect(mySpy).toHaveBeenCalledBefore(otherSpy); */ function toHaveBeenCalledBefore() { return { compare: function(firstSpy, latterSpy) { if (!j$.isSpy(firstSpy)) { throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(firstSpy) + '.')); } if (!j$.isSpy(latterSpy)) { throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(latterSpy) + '.')); } var result = { pass: false }; if (!firstSpy.calls.count()) { result.message = 'Expected spy ' + firstSpy.and.identity() + ' to have been called.'; return result; } if (!latterSpy.calls.count()) { result.message = 'Expected spy ' + latterSpy.and.identity() + ' to have been called.'; return result; } var latest1stSpyCall = firstSpy.calls.mostRecent().invocationOrder; var first2ndSpyCall = latterSpy.calls.first().invocationOrder; result.pass = latest1stSpyCall < first2ndSpyCall; if (result.pass) { result.message = 'Expected spy ' + firstSpy.and.identity() + ' to not have been called before spy ' + latterSpy.and.identity() + ', but it was'; } else { var first1stSpyCall = firstSpy.calls.first().invocationOrder; var latest2ndSpyCall = latterSpy.calls.mostRecent().invocationOrder; if(first1stSpyCall < first2ndSpyCall) { result.message = 'Expected latest call to spy ' + firstSpy.and.identity() + ' to have been called before first call to spy ' + latterSpy.and.identity() + ' (no interleaved calls)'; } else if (latest2ndSpyCall > latest1stSpyCall) { result.message = 'Expected first call to spy ' + latterSpy.and.identity() + ' to have been called after latest call to spy ' + firstSpy.and.identity() + ' (no interleaved calls)'; } else { result.message = 'Expected spy ' + firstSpy.and.identity() + ' to have been called before spy ' + latterSpy.and.identity(); } } return result; } }; } return toHaveBeenCalledBefore; }; getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) { var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledTimes()'); /** * {@link expect} the actual (a {@link Spy}) to have been called the specified number of times. * @function * @name matchers#toHaveBeenCalledTimes * @param {Number} expected - The number of invocations to look for. * @example * expect(mySpy).toHaveBeenCalledTimes(3); */ function toHaveBeenCalledTimes() { return { compare: function(actual, expected) { if (!j$.isSpy(actual)) { throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); } var args = Array.prototype.slice.call(arguments, 0), result = { pass: false }; if (!j$.isNumber_(expected)){ throw new Error(getErrorMsg('The expected times failed is a required argument and must be a number.')); } actual = args[0]; var calls = actual.calls.count(); var timesMessage = expected === 1 ? 'once' : expected + ' times'; result.pass = calls === expected; result.message = result.pass ? 'Expected spy ' + actual.and.identity() + ' not to have been called ' + timesMessage + '. It was called ' + calls + ' times.' : 'Expected spy ' + actual.and.identity() + ' to have been called ' + timesMessage + '. It was called ' + calls + ' times.'; return result; } }; } return toHaveBeenCalledTimes; }; getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { var getErrorMsg = j$.formatErrorMsg('', 'expect().toHaveBeenCalledWith(...arguments)'); /** * {@link expect} the actual (a {@link Spy}) to have been called with particular arguments at least once. * @function * @name matchers#toHaveBeenCalledWith * @param {...Object} - The arguments to look for * @example * expect(mySpy).toHaveBeenCalledWith('foo', 'bar', 2); */ function toHaveBeenCalledWith(util, customEqualityTesters) { return { compare: function() { var args = Array.prototype.slice.call(arguments, 0), actual = args[0], expectedArgs = args.slice(1), result = { pass: false }; if (!j$.isSpy(actual)) { throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(actual) + '.')); } if (!actual.calls.any()) { result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; return result; } if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { result.pass = true; result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; } else { result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; } return result; } }; } return toHaveBeenCalledWith; }; getJasmineRequireObj().toMatch = function(j$) { var getErrorMsg = j$.formatErrorMsg('', 'expect().toMatch( || )'); /** * {@link expect} the actual value to match a regular expression * @function * @name matchers#toMatch * @param {RegExp|String} expected - Value to look for in the string. * @example * expect("my string").toMatch(/string$/); * expect("other string").toMatch("her"); */ function toMatch() { return { compare: function(actual, expected) { if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) { throw new Error(getErrorMsg('Expected is not a String or a RegExp')); } var regexp = new RegExp(expected); return { pass: regexp.test(actual) }; } }; } return toMatch; }; getJasmineRequireObj().toThrow = function(j$) { var getErrorMsg = j$.formatErrorMsg('', 'expect(function() {}).toThrow()'); /** * {@link expect} a function to `throw` something. * @function * @name matchers#toThrow * @param {Object} [expected] - Value that should be thrown. If not provided, simply the fact that something was thrown will be checked. * @example * expect(function() { return 'things'; }).toThrow('foo'); * expect(function() { return 'stuff'; }).toThrow(); */ function toThrow(util) { return { compare: function(actual, expected) { var result = { pass: false }, threw = false, thrown; if (typeof actual != 'function') { throw new Error(getErrorMsg('Actual is not a Function')); } try { actual(); } catch (e) { threw = true; thrown = e; } if (!threw) { result.message = 'Expected function to throw an exception.'; return result; } if (arguments.length == 1) { result.pass = true; result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; return result; } if (util.equals(thrown, expected)) { result.pass = true; result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; } else { result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; } return result; } }; } return toThrow; }; getJasmineRequireObj().toThrowError = function(j$) { var getErrorMsg = j$.formatErrorMsg('', 'expect(function() {}).toThrowError(, )'); /** * {@link expect} a function to `throw` an `Error`. * @function * @name matchers#toThrowError * @param {Error} [expected] - `Error` constructor the object that was thrown needs to be an instance of. If not provided, `Error` will be used. * @param {RegExp|String} [message] - The message that should be set on the thrown `Error` * @example * expect(function() { return 'things'; }).toThrowError(MyCustomError, 'message'); * expect(function() { return 'things'; }).toThrowError(MyCustomError, /bar/); * expect(function() { return 'stuff'; }).toThrowError(MyCustomError); * expect(function() { return 'other'; }).toThrowError(/foo/); * expect(function() { return 'other'; }).toThrowError(); */ function toThrowError () { return { compare: function(actual) { var threw = false, pass = {pass: true}, fail = {pass: false}, thrown; if (typeof actual != 'function') { throw new Error(getErrorMsg('Actual is not a Function')); } var errorMatcher = getMatcher.apply(null, arguments); try { actual(); } catch (e) { threw = true; thrown = e; } if (!threw) { fail.message = 'Expected function to throw an Error.'; return fail; } // Get Error constructor of thrown if (!isErrorObject(thrown)) { fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; return fail; } if (errorMatcher.hasNoSpecifics()) { pass.message = 'Expected function not to throw an Error, but it threw ' + j$.fnNameFor(thrown) + '.'; return pass; } if (errorMatcher.matches(thrown)) { pass.message = function() { return 'Expected function not to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + '.'; }; return pass; } else { fail.message = function() { return 'Expected function to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + ', but it threw ' + errorMatcher.thrownDescription(thrown) + '.'; }; return fail; } } }; function getMatcher() { var expected = null, errorType = null; if (arguments.length == 2) { expected = arguments[1]; if (isAnErrorType(expected)) { errorType = expected; expected = null; } } else if (arguments.length > 2) { errorType = arguments[1]; expected = arguments[2]; if (!isAnErrorType(errorType)) { throw new Error(getErrorMsg('Expected error type is not an Error.')); } } if (expected && !isStringOrRegExp(expected)) { if (errorType) { throw new Error(getErrorMsg('Expected error message is not a string or RegExp.')); } else { throw new Error(getErrorMsg('Expected is not an Error, string, or RegExp.')); } } function messageMatch(message) { if (typeof expected == 'string') { return expected == message; } else { return expected.test(message); } } return { errorTypeDescription: errorType ? j$.fnNameFor(errorType) : 'an exception', thrownDescription: function(thrown) { var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception', thrownMessage = ''; if (expected) { thrownMessage = ' with message ' + j$.pp(thrown.message); } return thrownName + thrownMessage; }, messageDescription: function() { if (expected === null) { return ''; } else if (expected instanceof RegExp) { return ' with a message matching ' + j$.pp(expected); } else { return ' with message ' + j$.pp(expected); } }, hasNoSpecifics: function() { return expected === null && errorType === null; }, matches: function(error) { return (errorType === null || error instanceof errorType) && (expected === null || messageMatch(error.message)); } }; } function isStringOrRegExp(potential) { return potential instanceof RegExp || (typeof potential == 'string'); } function isAnErrorType(type) { if (typeof type !== 'function') { return false; } var Surrogate = function() {}; Surrogate.prototype = type.prototype; return isErrorObject(new Surrogate()); } function isErrorObject(thrown) { if (thrown instanceof Error) { return true; } if (thrown && thrown.constructor && thrown.constructor.constructor && (thrown instanceof (thrown.constructor.constructor('return this')()).Error)) { return true; } return false; } } return toThrowError; }; getJasmineRequireObj().MockDate = function() { function MockDate(global) { var self = this; var currentTime = 0; if (!global || !global.Date) { self.install = function() {}; self.tick = function() {}; self.uninstall = function() {}; return self; } var GlobalDate = global.Date; self.install = function(mockDate) { if (mockDate instanceof GlobalDate) { currentTime = mockDate.getTime(); } else { currentTime = new GlobalDate().getTime(); } global.Date = FakeDate; }; self.tick = function(millis) { millis = millis || 0; currentTime = currentTime + millis; }; self.uninstall = function() { currentTime = 0; global.Date = GlobalDate; }; createDateProperties(); return self; function FakeDate() { switch(arguments.length) { case 0: return new GlobalDate(currentTime); case 1: return new GlobalDate(arguments[0]); case 2: return new GlobalDate(arguments[0], arguments[1]); case 3: return new GlobalDate(arguments[0], arguments[1], arguments[2]); case 4: return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3]); case 5: return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); case 6: return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); default: return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]); } } function createDateProperties() { FakeDate.prototype = GlobalDate.prototype; FakeDate.now = function() { if (GlobalDate.now) { return currentTime; } else { throw new Error('Browser does not support Date.now()'); } }; FakeDate.toSource = GlobalDate.toSource; FakeDate.toString = GlobalDate.toString; FakeDate.parse = GlobalDate.parse; FakeDate.UTC = GlobalDate.UTC; } } return MockDate; }; getJasmineRequireObj().pp = function(j$) { function PrettyPrinter() { this.ppNestLevel_ = 0; this.seen = []; } function hasCustomToString(value) { // value.toString !== Object.prototype.toString if value has no custom toString but is from another context (e.g. // iframe, web worker) return value.toString !== Object.prototype.toString && (value.toString() !== Object.prototype.toString.call(value)); } PrettyPrinter.prototype.format = function(value) { this.ppNestLevel_++; try { if (j$.util.isUndefined(value)) { this.emitScalar('undefined'); } else if (value === null) { this.emitScalar('null'); } else if (value === 0 && 1/value === -Infinity) { this.emitScalar('-0'); } else if (value === j$.getGlobal()) { this.emitScalar(''); } else if (value.jasmineToString) { this.emitScalar(value.jasmineToString()); } else if (typeof value === 'string') { this.emitString(value); } else if (j$.isSpy(value)) { this.emitScalar('spy on ' + value.and.identity()); } else if (value instanceof RegExp) { this.emitScalar(value.toString()); } else if (typeof value === 'function') { this.emitScalar('Function'); } else if (typeof value.nodeType === 'number') { this.emitScalar('HTMLNode'); } else if (value instanceof Date) { this.emitScalar('Date(' + value + ')'); } else if (value.toString && value.toString() == '[object Set]') { this.emitSet(value); } else if (value.toString && typeof value === 'object' && !j$.isArray_(value) && hasCustomToString(value)) { this.emitScalar(value.toString()); } else if (j$.util.arrayContains(this.seen, value)) { this.emitScalar(''); } else if (j$.isArray_(value) || j$.isA_('Object', value)) { this.seen.push(value); if (j$.isArray_(value)) { this.emitArray(value); } else { this.emitObject(value); } this.seen.pop(); } else { this.emitScalar(value.toString()); } } finally { this.ppNestLevel_--; } }; PrettyPrinter.prototype.iterateObject = function(obj, fn) { for (var property in obj) { if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && obj.__lookupGetter__(property) !== null) : false); } }; PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; PrettyPrinter.prototype.emitSet = j$.unimplementedMethod_; PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; function StringPrettyPrinter() { PrettyPrinter.call(this); this.string = ''; } j$.util.inherit(StringPrettyPrinter, PrettyPrinter); StringPrettyPrinter.prototype.emitScalar = function(value) { this.append(value); }; StringPrettyPrinter.prototype.emitString = function(value) { this.append('\'' + value + '\''); }; StringPrettyPrinter.prototype.emitArray = function(array) { if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { this.append('Array'); return; } var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); this.append('[ '); for (var i = 0; i < length; i++) { if (i > 0) { this.append(', '); } this.format(array[i]); } if(array.length > length){ this.append(', ...'); } var self = this; var first = array.length === 0; this.iterateObject(array, function(property, isGetter) { if (property.match(/^\d+$/)) { return; } if (first) { first = false; } else { self.append(', '); } self.formatProperty(array, property, isGetter); }); this.append(' ]'); }; StringPrettyPrinter.prototype.emitSet = function(set) { if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { this.append('Set'); return; } this.append('Set( '); var size = Math.min(set.size, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); var iter = set.values(); for (var i = 0; i < size; i++) { if (i > 0) { this.append(', '); } this.format(iter.next().value); } if (set.size > size){ this.append(', ...'); } this.append(' )'); }; StringPrettyPrinter.prototype.emitObject = function(obj) { var ctor = obj.constructor, constructorName; constructorName = typeof ctor === 'function' && obj instanceof ctor ? j$.fnNameFor(obj.constructor) : 'null'; this.append(constructorName); if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { return; } var self = this; this.append('({ '); var first = true; this.iterateObject(obj, function(property, isGetter) { if (first) { first = false; } else { self.append(', '); } self.formatProperty(obj, property, isGetter); }); this.append(' })'); }; StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) { this.append(property); this.append(': '); if (isGetter) { this.append(''); } else { this.format(obj[property]); } }; StringPrettyPrinter.prototype.append = function(value) { this.string += value; }; return function(value) { var stringPrettyPrinter = new StringPrettyPrinter(); stringPrettyPrinter.format(value); return stringPrettyPrinter.string; }; }; getJasmineRequireObj().QueueRunner = function(j$) { function once(fn) { var called = false; return function() { if (!called) { called = true; fn(); } return null; }; } function QueueRunner(attrs) { this.queueableFns = attrs.queueableFns || []; this.onComplete = attrs.onComplete || function() {}; this.clearStack = attrs.clearStack || function(fn) {fn();}; this.onException = attrs.onException || function() {}; this.catchException = attrs.catchException || function() { return true; }; this.userContext = attrs.userContext || {}; this.timeout = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; this.fail = attrs.fail || function() {}; this.globalErrors = attrs.globalErrors || { pushListener: function() {}, popListener: function() {} }; } QueueRunner.prototype.execute = function() { var self = this; this.handleFinalError = function(error) { self.onException(error); }; this.globalErrors.pushListener(this.handleFinalError); this.run(this.queueableFns, 0); }; QueueRunner.prototype.run = function(queueableFns, recursiveIndex) { var length = queueableFns.length, self = this, iterativeIndex; for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { var queueableFn = queueableFns[iterativeIndex]; if (queueableFn.fn.length > 0) { attemptAsync(queueableFn); return; } else { attemptSync(queueableFn); } } this.clearStack(function() { self.globalErrors.popListener(self.handleFinalError); self.onComplete(); }); function attemptSync(queueableFn) { try { queueableFn.fn.call(self.userContext); } catch (e) { handleException(e, queueableFn); } } function attemptAsync(queueableFn) { var clearTimeout = function () { Function.prototype.apply.apply(self.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]); }, completedSynchronously = true, setTimeout = function(delayedFn, delay) { return Function.prototype.apply.apply(self.timeout.setTimeout, [j$.getGlobal(), [delayedFn, delay]]); }, handleError = function(error) { onException(error); next(); }, next = once(function () { clearTimeout(timeoutId); self.globalErrors.popListener(handleError); if (completedSynchronously) { setTimeout(function() { self.run(queueableFns, iterativeIndex + 1); }); } else { self.run(queueableFns, iterativeIndex + 1); } }), timeoutId; next.fail = function() { self.fail.apply(null, arguments); next(); }; self.globalErrors.pushListener(handleError); if (queueableFn.timeout) { timeoutId = setTimeout(function() { var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'); onException(error); next(); }, queueableFn.timeout()); } try { queueableFn.fn.call(self.userContext, next); completedSynchronously = false; } catch (e) { handleException(e, queueableFn); next(); } } function onException(e) { self.onException(e); } function handleException(e, queueableFn) { onException(e); if (!self.catchException(e)) { //TODO: set a var when we catch an exception and //use a finally block to close the loop in a nice way.. throw e; } } }; return QueueRunner; }; getJasmineRequireObj().ReportDispatcher = function() { function ReportDispatcher(methods) { var dispatchedMethods = methods || []; for (var i = 0; i < dispatchedMethods.length; i++) { var method = dispatchedMethods[i]; this[method] = (function(m) { return function() { dispatch(m, arguments); }; }(method)); } var reporters = []; var fallbackReporter = null; this.addReporter = function(reporter) { reporters.push(reporter); }; this.provideFallbackReporter = function(reporter) { fallbackReporter = reporter; }; this.clearReporters = function() { reporters = []; }; return this; function dispatch(method, args) { if (reporters.length === 0 && fallbackReporter !== null) { reporters.push(fallbackReporter); } for (var i = 0; i < reporters.length; i++) { var reporter = reporters[i]; if (reporter[method]) { reporter[method].apply(reporter, args); } } } } return ReportDispatcher; }; getJasmineRequireObj().interface = function(jasmine, env) { var jasmineInterface = { /** * Create a group of specs (often called a suite). * * Calls to `describe` can be nested within other calls to compose your suite as a tree. * @name describe * @function * @global * @param {String} description Textual description of the group * @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs */ describe: function(description, specDefinitions) { return env.describe(description, specDefinitions); }, /** * A temporarily disabled [`describe`]{@link describe} * * Specs within an `xdescribe` will be marked pending and not executed * @name xdescribe * @function * @global * @param {String} description Textual description of the group * @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs */ xdescribe: function(description, specDefinitions) { return env.xdescribe(description, specDefinitions); }, /** * A focused [`describe`]{@link describe} * * If suites or specs are focused, only those that are focused will be executed * @see fit * @name fdescribe * @function * @global * @param {String} description Textual description of the group * @param {Function} specDefinitions Function for Jasmine to invoke that will define inner suites a specs */ fdescribe: function(description, specDefinitions) { return env.fdescribe(description, specDefinitions); }, /** * Define a single spec. A spec should contain one or more {@link expect|expectations} that test the state of the code. * * A spec whose expectations all succeed will be passing and a spec with any failures will fail. * @name it * @function * @global * @param {String} description Textual description of what this spec is checking * @param {Function} [testFunction] Function that contains the code of your test. If not provided the test will be `pending`. * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec. */ it: function() { return env.it.apply(env, arguments); }, /** * A temporarily disabled [`it`]{@link it} * * The spec will report as `pending` and will not be executed. * @name xit * @function * @global * @param {String} description Textual description of what this spec is checking. * @param {Function} [testFunction] Function that contains the code of your test. Will not be executed. */ xit: function() { return env.xit.apply(env, arguments); }, /** * A focused [`it`]{@link it} * * If suites or specs are focused, only those that are focused will be executed. * @name fit * @function * @global * @param {String} description Textual description of what this spec is checking. * @param {Function} testFunction Function that contains the code of your test. * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async spec. */ fit: function() { return env.fit.apply(env, arguments); }, /** * Run some shared setup before each of the specs in the {@link describe} in which it is called. * @name beforeEach * @function * @global * @param {Function} [function] Function that contains the code to setup your specs. * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeEach. */ beforeEach: function() { return env.beforeEach.apply(env, arguments); }, /** * Run some shared teardown after each of the specs in the {@link describe} in which it is called. * @name afterEach * @function * @global * @param {Function} [function] Function that contains the code to teardown your specs. * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterEach. */ afterEach: function() { return env.afterEach.apply(env, arguments); }, /** * Run some shared setup once before all of the specs in the {@link describe} are run. * * _Note:_ Be careful, sharing the setup from a beforeAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail. * @name beforeAll * @function * @global * @param {Function} [function] Function that contains the code to setup your specs. * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async beforeAll. */ beforeAll: function() { return env.beforeAll.apply(env, arguments); }, /** * Run some shared teardown once before all of the specs in the {@link describe} are run. * * _Note:_ Be careful, sharing the teardown from a afterAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail. * @name afterAll * @function * @global * @param {Function} [function] Function that contains the code to teardown your specs. * @param {Int} [timeout={@link jasmine.DEFAULT_TIMEOUT_INTERVAL}] Custom timeout for an async afterAll. */ afterAll: function() { return env.afterAll.apply(env, arguments); }, /** * Create an expectation for a spec. * @name expect * @function * @global * @param {Object} actual - Actual computed value to test expectations against. * @return {matchers} */ expect: function(actual) { return env.expect(actual); }, /** * Mark a spec as pending, expectation results will be ignored. * @name pending * @function * @global * @param {String} [message] - Reason the spec is pending. */ pending: function() { return env.pending.apply(env, arguments); }, /** * Explicitly mark a spec as failed. * @name fail * @function * @global * @param {String|Error} [error] - Reason for the failure. */ fail: function() { return env.fail.apply(env, arguments); }, /** * Install a spy onto an existing object. * @name spyOn * @function * @global * @param {Object} obj - The object upon which to install the {@link Spy}. * @param {String} methodName - The name of the method to replace with a {@link Spy}. * @returns {Spy} */ spyOn: function(obj, methodName) { return env.spyOn(obj, methodName); }, /** * Install a spy on a property onto an existing object. * @name spyOnProperty * @function * @global * @param {Object} obj - The object upon which to install the {@link Spy} * @param {String} propertyName - The name of the property to replace with a {@link Spy}. * @param {String} [accessType=get] - The access type (get|set) of the property to {@link Spy} on. * @returns {Spy} */ spyOnProperty: function(obj, methodName, accessType) { return env.spyOnProperty(obj, methodName, accessType); }, jsApiReporter: new jasmine.JsApiReporter({ timer: new jasmine.Timer() }), /** * @namespace jasmine */ jasmine: jasmine }; /** * Add a custom equality tester for the current scope of specs. * * _Note:_ This is only callable from within a {@link beforeEach}, {@link it}, or {@link beforeAll}. * @name jasmine.addCustomEqualityTester * @function * @param {Function} tester - A function which takes two arguments to compare and returns a `true` or `false` comparison result if it knows how to compare them, and `undefined` otherwise. * @see custom_equality */ jasmine.addCustomEqualityTester = function(tester) { env.addCustomEqualityTester(tester); }; /** * Add custom matchers for the current scope of specs. * * _Note:_ This is only callable from within a {@link beforeEach}, {@link it}, or {@link beforeAll}. * @name jasmine.addMatchers * @function * @param {Object} matchers - Keys from this object will be the new matcher names. * @see custom_matcher */ jasmine.addMatchers = function(matchers) { return env.addMatchers(matchers); }; /** * Get the currently booted mock {Clock} for this Jasmine environment. * @name jasmine.clock * @function * @returns {Clock} */ jasmine.clock = function() { return env.clock; }; return jasmineInterface; }; getJasmineRequireObj().Spy = function (j$) { var nextOrder = (function() { var order = 0; return function() { return order++; }; })(); /** * _Note:_ Do not construct this directly, use {@link spyOn}, {@link spyOnProperty}, {@link jasmine.createSpy}, or {@link jasmine.createSpyObj} * @constructor * @name Spy */ function Spy(name, originalFn) { var numArgs = (typeof originalFn === 'function' ? originalFn.length : 0), wrapper = makeFunc(numArgs, function () { return spy.apply(this, Array.prototype.slice.call(arguments)); }), spyStrategy = new j$.SpyStrategy({ name: name, fn: originalFn, getSpy: function () { return wrapper; } }), callTracker = new j$.CallTracker(), spy = function () { /** * @name Spy.callData * @property {object} object - `this` context for the invocation. * @property {number} invocationOrder - Order of the invocation. * @property {Array} args - The arguments passed for this invocation. */ var callData = { object: this, invocationOrder: nextOrder(), args: Array.prototype.slice.apply(arguments) }; callTracker.track(callData); var returnValue = spyStrategy.exec.apply(this, arguments); callData.returnValue = returnValue; return returnValue; }; function makeFunc(length, fn) { switch (length) { case 1 : return function (a) { return fn.apply(this, arguments); }; case 2 : return function (a,b) { return fn.apply(this, arguments); }; case 3 : return function (a,b,c) { return fn.apply(this, arguments); }; case 4 : return function (a,b,c,d) { return fn.apply(this, arguments); }; case 5 : return function (a,b,c,d,e) { return fn.apply(this, arguments); }; case 6 : return function (a,b,c,d,e,f) { return fn.apply(this, arguments); }; case 7 : return function (a,b,c,d,e,f,g) { return fn.apply(this, arguments); }; case 8 : return function (a,b,c,d,e,f,g,h) { return fn.apply(this, arguments); }; case 9 : return function (a,b,c,d,e,f,g,h,i) { return fn.apply(this, arguments); }; default : return function () { return fn.apply(this, arguments); }; } } for (var prop in originalFn) { if (prop === 'and' || prop === 'calls') { throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); } wrapper[prop] = originalFn[prop]; } wrapper.and = spyStrategy; wrapper.calls = callTracker; return wrapper; } return Spy; }; getJasmineRequireObj().SpyRegistry = function(j$) { var getErrorMsg = j$.formatErrorMsg('', 'spyOn(, )'); function SpyRegistry(options) { options = options || {}; var currentSpies = options.currentSpies || function() { return []; }; this.allowRespy = function(allow){ this.respy = allow; }; this.spyOn = function(obj, methodName) { if (j$.util.isUndefined(obj) || obj === null) { throw new Error(getErrorMsg('could not find an object to spy upon for ' + methodName + '()')); } if (j$.util.isUndefined(methodName) || methodName === null) { throw new Error(getErrorMsg('No method name supplied')); } if (j$.util.isUndefined(obj[methodName])) { throw new Error(getErrorMsg(methodName + '() method does not exist')); } if (obj[methodName] && j$.isSpy(obj[methodName]) ) { if ( !!this.respy ){ return obj[methodName]; }else { throw new Error(getErrorMsg(methodName + ' has already been spied upon')); } } var descriptor; try { descriptor = Object.getOwnPropertyDescriptor(obj, methodName); } catch(e) { // IE 8 doesn't support `definePropery` on non-DOM nodes } if (descriptor && !(descriptor.writable || descriptor.set)) { throw new Error(getErrorMsg(methodName + ' is not declared writable or has no setter')); } var originalMethod = obj[methodName], spiedMethod = j$.createSpy(methodName, originalMethod), restoreStrategy; if (Object.prototype.hasOwnProperty.call(obj, methodName)) { restoreStrategy = function() { obj[methodName] = originalMethod; }; } else { restoreStrategy = function() { if (!delete obj[methodName]) { obj[methodName] = originalMethod; } }; } currentSpies().push({ restoreObjectToOriginalState: restoreStrategy }); obj[methodName] = spiedMethod; return spiedMethod; }; this.spyOnProperty = function (obj, propertyName, accessType) { accessType = accessType || 'get'; if (j$.util.isUndefined(obj)) { throw new Error('spyOn could not find an object to spy upon for ' + propertyName + ''); } if (j$.util.isUndefined(propertyName)) { throw new Error('No property name supplied'); } var descriptor; try { descriptor = j$.util.getPropertyDescriptor(obj, propertyName); } catch(e) { // IE 8 doesn't support `definePropery` on non-DOM nodes } if (!descriptor) { throw new Error(propertyName + ' property does not exist'); } if (!descriptor.configurable) { throw new Error(propertyName + ' is not declared configurable'); } if(!descriptor[accessType]) { throw new Error('Property ' + propertyName + ' does not have access type ' + accessType); } if (j$.isSpy(descriptor[accessType])) { //TODO?: should this return the current spy? Downside: may cause user confusion about spy state throw new Error(propertyName + ' has already been spied upon'); } var originalDescriptor = j$.util.clone(descriptor), spy = j$.createSpy(propertyName, descriptor[accessType]), restoreStrategy; if (Object.prototype.hasOwnProperty.call(obj, propertyName)) { restoreStrategy = function() { Object.defineProperty(obj, propertyName, originalDescriptor); }; } else { restoreStrategy = function() { delete obj[propertyName]; }; } currentSpies().push({ restoreObjectToOriginalState: restoreStrategy }); descriptor[accessType] = spy; Object.defineProperty(obj, propertyName, descriptor); return spy; }; this.clearSpies = function() { var spies = currentSpies(); for (var i = spies.length - 1; i >= 0; i--) { var spyEntry = spies[i]; spyEntry.restoreObjectToOriginalState(); } }; } return SpyRegistry; }; getJasmineRequireObj().SpyStrategy = function(j$) { /** * @namespace Spy#and */ function SpyStrategy(options) { options = options || {}; var identity = options.name || 'unknown', originalFn = options.fn || function() {}, getSpy = options.getSpy || function() {}, plan = function() {}; /** * Return the identifying information for the spy. * @name Spy#and#identity * @function * @returns {String} */ this.identity = function() { return identity; }; /** * Execute the current spy strategy. * @name Spy#and#exec * @function */ this.exec = function() { return plan.apply(this, arguments); }; /** * Tell the spy to call through to the real implementation when invoked. * @name Spy#and#callThrough * @function */ this.callThrough = function() { plan = originalFn; return getSpy(); }; /** * Tell the spy to return the value when invoked. * @name Spy#and#returnValue * @function * @param {*} value The value to return. */ this.returnValue = function(value) { plan = function() { return value; }; return getSpy(); }; /** * Tell the spy to return one of the specified values (sequentially) each time the spy is invoked. * @name Spy#and#returnValues * @function * @param {...*} values - Values to be returned on subsequent calls to the spy. */ this.returnValues = function() { var values = Array.prototype.slice.call(arguments); plan = function () { return values.shift(); }; return getSpy(); }; /** * Tell the spy to throw an error when invoked. * @name Spy#and#throwError * @function * @param {Error|String} something Thing to throw */ this.throwError = function(something) { var error = (something instanceof Error) ? something : new Error(something); plan = function() { throw error; }; return getSpy(); }; /** * Tell the spy to call a fake implementation when invoked. * @name Spy#and#callFake * @function * @param {Function} fn The function to invoke with the passed parameters. */ this.callFake = function(fn) { if(!j$.isFunction_(fn)) { throw new Error('Argument passed to callFake should be a function, got ' + fn); } plan = fn; return getSpy(); }; /** * Tell the spy to do nothing when invoked. This is the default. * @name Spy#and#stub * @function */ this.stub = function(fn) { plan = function() {}; return getSpy(); }; } return SpyStrategy; }; getJasmineRequireObj().Suite = function(j$) { function Suite(attrs) { this.env = attrs.env; this.id = attrs.id; this.parentSuite = attrs.parentSuite; this.description = attrs.description; this.expectationFactory = attrs.expectationFactory; this.expectationResultFactory = attrs.expectationResultFactory; this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; this.beforeFns = []; this.afterFns = []; this.beforeAllFns = []; this.afterAllFns = []; this.children = []; this.result = { id: this.id, description: this.description, fullName: this.getFullName(), failedExpectations: [] }; } Suite.prototype.expect = function(actual) { return this.expectationFactory(actual, this); }; Suite.prototype.getFullName = function() { var fullName = []; for (var parentSuite = this; parentSuite; parentSuite = parentSuite.parentSuite) { if (parentSuite.parentSuite) { fullName.unshift(parentSuite.description); } } return fullName.join(' '); }; Suite.prototype.pend = function() { this.markedPending = true; }; Suite.prototype.beforeEach = function(fn) { this.beforeFns.unshift(fn); }; Suite.prototype.beforeAll = function(fn) { this.beforeAllFns.push(fn); }; Suite.prototype.afterEach = function(fn) { this.afterFns.unshift(fn); }; Suite.prototype.afterAll = function(fn) { this.afterAllFns.unshift(fn); }; Suite.prototype.addChild = function(child) { this.children.push(child); }; Suite.prototype.status = function() { if (this.markedPending) { return 'pending'; } if (this.result.failedExpectations.length > 0) { return 'failed'; } else { return 'finished'; } }; Suite.prototype.isExecutable = function() { return !this.markedPending; }; Suite.prototype.canBeReentered = function() { return this.beforeAllFns.length === 0 && this.afterAllFns.length === 0; }; Suite.prototype.getResult = function() { this.result.status = this.status(); return this.result; }; Suite.prototype.sharedUserContext = function() { if (!this.sharedContext) { this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {}; } return this.sharedContext; }; Suite.prototype.clonedSharedUserContext = function() { return clone(this.sharedUserContext()); }; Suite.prototype.onException = function() { if (arguments[0] instanceof j$.errors.ExpectationFailed) { return; } if(isAfterAll(this.children)) { var data = { matcherName: '', passed: false, expected: '', actual: '', error: arguments[0] }; this.result.failedExpectations.push(this.expectationResultFactory(data)); } else { for (var i = 0; i < this.children.length; i++) { var child = this.children[i]; child.onException.apply(child, arguments); } } }; Suite.prototype.addExpectationResult = function () { if(isAfterAll(this.children) && isFailure(arguments)){ var data = arguments[1]; this.result.failedExpectations.push(this.expectationResultFactory(data)); if(this.throwOnExpectationFailure) { throw new j$.errors.ExpectationFailed(); } } else { for (var i = 0; i < this.children.length; i++) { var child = this.children[i]; try { child.addExpectationResult.apply(child, arguments); } catch(e) { // keep going } } } }; function isAfterAll(children) { return children && children[0].result.status; } function isFailure(args) { return !args[0]; } function clone(obj) { var clonedObj = {}; for (var prop in obj) { if (obj.hasOwnProperty(prop)) { clonedObj[prop] = obj[prop]; } } return clonedObj; } return Suite; }; if (typeof window == void 0 && typeof exports == 'object') { exports.Suite = jasmineRequire.Suite; } getJasmineRequireObj().Timer = function() { var defaultNow = (function(Date) { return function() { return new Date().getTime(); }; })(Date); function Timer(options) { options = options || {}; var now = options.now || defaultNow, startTime; this.start = function() { startTime = now(); }; this.elapsed = function() { return now() - startTime; }; } return Timer; }; getJasmineRequireObj().TreeProcessor = function() { function TreeProcessor(attrs) { var tree = attrs.tree, runnableIds = attrs.runnableIds, queueRunnerFactory = attrs.queueRunnerFactory, nodeStart = attrs.nodeStart || function() {}, nodeComplete = attrs.nodeComplete || function() {}, orderChildren = attrs.orderChildren || function(node) { return node.children; }, stats = { valid: true }, processed = false, defaultMin = Infinity, defaultMax = 1 - Infinity; this.processTree = function() { processNode(tree, false); processed = true; return stats; }; this.execute = function(done) { if (!processed) { this.processTree(); } if (!stats.valid) { throw 'invalid order'; } var childFns = wrapChildren(tree, 0); queueRunnerFactory({ queueableFns: childFns, userContext: tree.sharedUserContext(), onException: function() { tree.onException.apply(tree, arguments); }, onComplete: done }); }; function runnableIndex(id) { for (var i = 0; i < runnableIds.length; i++) { if (runnableIds[i] === id) { return i; } } } function processNode(node, parentEnabled) { var executableIndex = runnableIndex(node.id); if (executableIndex !== undefined) { parentEnabled = true; } parentEnabled = parentEnabled && node.isExecutable(); if (!node.children) { stats[node.id] = { executable: parentEnabled && node.isExecutable(), segments: [{ index: 0, owner: node, nodes: [node], min: startingMin(executableIndex), max: startingMax(executableIndex) }] }; } else { var hasExecutableChild = false; var orderedChildren = orderChildren(node); for (var i = 0; i < orderedChildren.length; i++) { var child = orderedChildren[i]; processNode(child, parentEnabled); if (!stats.valid) { return; } var childStats = stats[child.id]; hasExecutableChild = hasExecutableChild || childStats.executable; } stats[node.id] = { executable: hasExecutableChild }; segmentChildren(node, orderedChildren, stats[node.id], executableIndex); if (!node.canBeReentered() && stats[node.id].segments.length > 1) { stats = { valid: false }; } } } function startingMin(executableIndex) { return executableIndex === undefined ? defaultMin : executableIndex; } function startingMax(executableIndex) { return executableIndex === undefined ? defaultMax : executableIndex; } function segmentChildren(node, orderedChildren, nodeStats, executableIndex) { var currentSegment = { index: 0, owner: node, nodes: [], min: startingMin(executableIndex), max: startingMax(executableIndex) }, result = [currentSegment], lastMax = defaultMax, orderedChildSegments = orderChildSegments(orderedChildren); function isSegmentBoundary(minIndex) { return lastMax !== defaultMax && minIndex !== defaultMin && lastMax < minIndex - 1; } for (var i = 0; i < orderedChildSegments.length; i++) { var childSegment = orderedChildSegments[i], maxIndex = childSegment.max, minIndex = childSegment.min; if (isSegmentBoundary(minIndex)) { currentSegment = {index: result.length, owner: node, nodes: [], min: defaultMin, max: defaultMax}; result.push(currentSegment); } currentSegment.nodes.push(childSegment); currentSegment.min = Math.min(currentSegment.min, minIndex); currentSegment.max = Math.max(currentSegment.max, maxIndex); lastMax = maxIndex; } nodeStats.segments = result; } function orderChildSegments(children) { var specifiedOrder = [], unspecifiedOrder = []; for (var i = 0; i < children.length; i++) { var child = children[i], segments = stats[child.id].segments; for (var j = 0; j < segments.length; j++) { var seg = segments[j]; if (seg.min === defaultMin) { unspecifiedOrder.push(seg); } else { specifiedOrder.push(seg); } } } specifiedOrder.sort(function(a, b) { return a.min - b.min; }); return specifiedOrder.concat(unspecifiedOrder); } function executeNode(node, segmentNumber) { if (node.children) { return { fn: function(done) { nodeStart(node); queueRunnerFactory({ onComplete: function() { nodeComplete(node, node.getResult()); done(); }, queueableFns: wrapChildren(node, segmentNumber), userContext: node.sharedUserContext(), onException: function() { node.onException.apply(node, arguments); } }); } }; } else { return { fn: function(done) { node.execute(done, stats[node.id].executable); } }; } } function wrapChildren(node, segmentNumber) { var result = [], segmentChildren = stats[node.id].segments[segmentNumber].nodes; for (var i = 0; i < segmentChildren.length; i++) { result.push(executeNode(segmentChildren[i].owner, segmentChildren[i].index)); } if (!stats[node.id].executable) { return result; } return node.beforeAllFns.concat(result).concat(node.afterAllFns); } } return TreeProcessor; }; getJasmineRequireObj().version = function() { return '2.6.4'; }; public/vendors/split/packages/splitjs/test/ie8/browserstack.json000064400000000427146725417150021172 0ustar00{ "exit_with_fail": true, "test_framework": "jasmine2", "test_path": "test/ie8/SpecRunner.html", "browsers": [ { "browser": "ie", "browser_version": "8", "os": "Windows", "os_version": "7" } ] } public/vendors/split/packages/splitjs/test/ie8/split.spec.js000064400000007653146725417150020220 0ustar00/* eslint-env jasmine */ /* global Split */ /* eslint-disable no-var, func-names, prefer-arrow-callback, object-shorthand, prefer-template */ describe('Split', function() { beforeEach(function() { document.body.style.width = '800px' document.body.style.height = '600px' this.a = document.createElement('div') this.b = document.createElement('div') this.c = document.createElement('div') this.a.id = 'a' this.b.id = 'b' this.c.id = 'c' document.body.appendChild(this.a) document.body.appendChild(this.b) document.body.appendChild(this.c) }) afterEach(function() { document.body.removeChild(this.a) document.body.removeChild(this.b) document.body.removeChild(this.c) }) it('splits in two when given two elements', function() { Split(['#a', '#b']) expect(this.a.style.width).toBe('50%') expect(this.b.style.width).toBe('50%') }) it('splits in three when given three elements', function() { Split(['#a', '#b', '#c']) expect(this.a.style.width).toBe('33.33%') expect(this.b.style.width).toBe('33.33%') expect(this.c.style.width).toBe('33.33%') }) it('splits vertically when direction is vertical', function() { Split(['#a', '#b'], { direction: 'vertical', }) expect(this.a.style.height).toBe('50%') expect(this.b.style.height).toBe('50%') }) it('splits in percentages when given sizes', function() { Split(['#a', '#b'], { sizes: [25, 75], }) expect(this.a.style.width).toBe('25%') expect(this.b.style.width).toBe('75%') }) it('splits in percentages when given sizes', function() { Split(['#a', '#b'], { sizes: [25, 75], }) expect(this.a.style.width).toBe('25%') expect(this.b.style.width).toBe('75%') }) it('accounts for gutter size', function() { Split(['#a', '#b'], { gutterSize: 20, }) expect(this.a.style.width).toBe('50%') expect(this.b.style.width).toBe('50%') }) it('accounts for gutter size with more than two elements', function() { Split(['#a', '#b', '#c'], { gutterSize: 20, }) expect(this.a.style.width).toBe('33.33%') expect(this.b.style.width).toBe('33.33%') expect(this.c.style.width).toBe('33.33%') }) it('accounts for gutter size when direction is vertical', function() { Split(['#a', '#b'], { direction: 'vertical', gutterSize: 20, }) expect(this.a.style.height).toBe('50%') expect(this.b.style.height).toBe('50%') }) it('accounts for gutter size with more than two elements when direction is vertical', function() { Split(['#a', '#b', '#c'], { direction: 'vertical', gutterSize: 20, }) expect(this.a.style.height).toBe('33.33%') expect(this.b.style.height).toBe('33.33%') expect(this.c.style.height).toBe('33.33%') }) it('set size directly when given css values', function() { Split(['#a', '#b'], { sizes: ['150px', '640px'], }) expect(this.a.style.width).toBe('150px') expect(this.b.style.width).toBe('640px') }) it('adjusts sizes using setSizes', function() { var split = Split(['#a', '#b']) split.setSizes([70, 30]) expect(this.a.style.width).toBe('70%') expect(this.b.style.width).toBe('30%') }) it('sets element styles using the elementStyle function', function() { Split(['#a', '#b'], { elementStyle: function(dimension, size) { return { width: size + '%', } }, }) expect(this.a.style.width).toBe('50%') expect(this.b.style.width).toBe('50%') }) }) public/vendors/split/packages/splitjs/test/ie8/SpecRunner.html000064400000001123146725417150020532 0ustar00 Jasmine Spec Runner v2.6.4 public/vendors/split/packages/splitjs/test/ie8/polyfills.js000064400000024541146725417150020144 0ustar00/* Polyfill service v3.18.1 * For detailed credits and licence information see https://github.com/financial-times/polyfill-service. * * UA detected: firefox/53.0.0 * Features requested: Array.isArray,Array.prototype.filter,Array.prototype.forEach,Array.prototype.map,Object.keys,getComputedStyle * * - Object.defineProperty, License: CC0 (required by "Array.isArray") * - Array.isArray, License: CC0 * - Array.prototype.filter, License: CC0 * - Array.prototype.forEach, License: CC0 * - Array.prototype.map, License: CC0 * - Object.keys, License: CC0 * - Window, License: CC0 (required by "getComputedStyle") * - getComputedStyle, License: CC0 */ (function(undefined) { // Object.defineProperty (function (nativeDefineProperty) { var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__'); var ERR_ACCESSORS_NOT_SUPPORTED = 'Getters & setters cannot be defined on this javascript engine'; var ERR_VALUE_ACCESSORS = 'A property cannot both have accessors and be writable or have a value'; Object.defineProperty = function defineProperty(object, property, descriptor) { // Where native support exists, assume it if (nativeDefineProperty && (object === window || object === document || object === Element.prototype || object instanceof Element)) { return nativeDefineProperty(object, property, descriptor); } if (object === null || !(object instanceof Object || typeof object === 'object')) { throw new TypeError('Object.defineProperty called on non-object'); } if (!(descriptor instanceof Object)) { throw new TypeError('Property description must be an object'); } var propertyString = String(property); var hasValueOrWritable = 'value' in descriptor || 'writable' in descriptor; var getterType = 'get' in descriptor && typeof descriptor.get; var setterType = 'set' in descriptor && typeof descriptor.set; // handle descriptor.get if (getterType) { if (getterType !== 'function') { throw new TypeError('Getter must be a function'); } if (!supportsAccessors) { throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); } if (hasValueOrWritable) { throw new TypeError(ERR_VALUE_ACCESSORS); } object.__defineGetter__(propertyString, descriptor.get); } else { object[propertyString] = descriptor.value; } // handle descriptor.set if (setterType) { if (setterType !== 'function') { throw new TypeError('Setter must be a function'); } if (!supportsAccessors) { throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); } if (hasValueOrWritable) { throw new TypeError(ERR_VALUE_ACCESSORS); } object.__defineSetter__(propertyString, descriptor.set); } // OK to define value unconditionally - if a getter has been specified as well, an error would be thrown above if ('value' in descriptor) { object[propertyString] = descriptor.value; } return object; }; }(Object.defineProperty)); // Array.isArray (function (toString) { Object.defineProperty(Array, 'isArray', { configurable: true, value: function isArray(object) { return toString.call(object) === '[object Array]'; }, writable: true }); }(Object.prototype.toString)); // Array.prototype.filter Array.prototype.filter = function filter(callback) { if (this === undefined || this === null) { throw new TypeError(this + ' is not an object'); } if (!(callback instanceof Function)) { throw new TypeError(callback + ' is not a function'); } var object = Object(this), scope = arguments[1], arraylike = object instanceof String ? object.split('') : object, length = Math.max(Math.min(arraylike.length, 9007199254740991), 0) || 0, index = -1, result = [], element; while (++index < length) { element = arraylike[index]; if (index in arraylike && callback.call(scope, element, index, object)) { result.push(element); } } return result; }; // Array.prototype.forEach Array.prototype.forEach = function forEach(callback) { if (this === undefined || this === null) { throw new TypeError(this + ' is not an object'); } if (!(callback instanceof Function)) { throw new TypeError(callback + ' is not a function'); } var object = Object(this), scope = arguments[1], arraylike = object instanceof String ? object.split('') : object, length = Math.max(Math.min(arraylike.length, 9007199254740991), 0) || 0, index = -1; while (++index < length) { if (index in arraylike) { callback.call(scope, arraylike[index], index, object); } } }; // Array.prototype.map Array.prototype.map = function map(callback) { if (this === undefined || this === null) { throw new TypeError(this + ' is not an object'); } if (!(callback instanceof Function)) { throw new TypeError(callback + ' is not a function'); } var object = Object(this), scope = arguments[1], arraylike = object instanceof String ? object.split('') : object, length = Math.max(Math.min(arraylike.length, 9007199254740991), 0) || 0, index = -1, result = []; while (++index < length) { if (index in arraylike) { result[index] = callback.call(scope, arraylike[index], index, object); } } return result; }; // Object.keys Object.keys = (function() { 'use strict'; var hasOwnProperty = Object.prototype.hasOwnProperty, hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'), dontEnums = [ 'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor' ], dontEnumsLength = dontEnums.length; return function(obj) { if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { throw new TypeError('Object.keys called on non-object'); } var result = [], prop, i; for (prop in obj) { if (hasOwnProperty.call(obj, prop)) { result.push(prop); } } if (hasDontEnumBug) { for (i = 0; i < dontEnumsLength; i++) { if (hasOwnProperty.call(obj, dontEnums[i])) { result.push(dontEnums[i]); } } } return result; }; }()); // Window (function(global) { if (global.constructor) { global.Window = global.constructor; } else { (global.Window = global.constructor = new Function('return function Window() {}')()).prototype = this; } }(this)); // getComputedStyle (function (global) { function getComputedStylePixel(element, property, fontSize) { var // Internet Explorer sometimes struggles to read currentStyle until the element's document is accessed. value = element.document && element.currentStyle[property].match(/([\d\.]+)(%|cm|em|in|mm|pc|pt|)/) || [0, 0, ''], size = value[1], suffix = value[2], rootSize; fontSize = !fontSize ? fontSize : /%|em/.test(suffix) && element.parentElement ? getComputedStylePixel(element.parentElement, 'fontSize', null) : 16; rootSize = property == 'fontSize' ? fontSize : /width/i.test(property) ? element.clientWidth : element.clientHeight; return suffix == '%' ? size / 100 * rootSize : suffix == 'cm' ? size * 0.3937 * 96 : suffix == 'em' ? size * fontSize : suffix == 'in' ? size * 96 : suffix == 'mm' ? size * 0.3937 * 96 / 10 : suffix == 'pc' ? size * 12 * 96 / 72 : suffix == 'pt' ? size * 96 / 72 : size; } function setShortStyleProperty(style, property) { var borderSuffix = property == 'border' ? 'Width' : '', t = property + 'Top' + borderSuffix, r = property + 'Right' + borderSuffix, b = property + 'Bottom' + borderSuffix, l = property + 'Left' + borderSuffix; style[property] = (style[t] == style[r] && style[t] == style[b] && style[t] == style[l] ? [ style[t] ] : style[t] == style[b] && style[l] == style[r] ? [ style[t], style[r] ] : style[l] == style[r] ? [ style[t], style[r], style[b] ] : [ style[t], style[r], style[b], style[l] ]).join(' '); } // function CSSStyleDeclaration(element) { var style = this, currentStyle = element.currentStyle, fontSize = getComputedStylePixel(element, 'fontSize'), unCamelCase = function (match) { return '-' + match.toLowerCase(); }, property; for (property in currentStyle) { Array.prototype.push.call(style, property == 'styleFloat' ? 'float' : property.replace(/[A-Z]/, unCamelCase)); if (property == 'width') { style[property] = element.offsetWidth + 'px'; } else if (property == 'height') { style[property] = element.offsetHeight + 'px'; } else if (property == 'styleFloat') { style.float = currentStyle[property]; } else if (/margin.|padding.|border.+W/.test(property) && style[property] != 'auto') { style[property] = Math.round(getComputedStylePixel(element, property, fontSize)) + 'px'; } else if (/^outline/.test(property)) { // errors on checking outline try { style[property] = currentStyle[property]; } catch (error) { style.outlineColor = currentStyle.color; style.outlineStyle = style.outlineStyle || 'none'; style.outlineWidth = style.outlineWidth || '0px'; style.outline = [style.outlineColor, style.outlineWidth, style.outlineStyle].join(' '); } } else { style[property] = currentStyle[property]; } } setShortStyleProperty(style, 'margin'); setShortStyleProperty(style, 'padding'); setShortStyleProperty(style, 'border'); style.fontSize = Math.round(fontSize) + 'px'; } CSSStyleDeclaration.prototype = { constructor: CSSStyleDeclaration, // .getPropertyPriority getPropertyPriority: function () { throw new Error('NotSupportedError: DOM Exception 9'); }, // .getPropertyValue getPropertyValue: function (property) { return this[property.replace(/-\w/g, function (match) { return match[1].toUpperCase(); })]; }, // .item item: function (index) { return this[index]; }, // .removeProperty removeProperty: function () { throw new Error('NoModificationAllowedError: DOM Exception 7'); }, // .setProperty setProperty: function () { throw new Error('NoModificationAllowedError: DOM Exception 7'); }, // .getPropertyCSSValue getPropertyCSSValue: function () { throw new Error('NotSupportedError: DOM Exception 9'); } }; // .getComputedStyle global.getComputedStyle = function getComputedStyle(element) { return new CSSStyleDeclaration(element); }; }(this)); }) .call('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {}); public/vendors/split/packages/splitjs/test/browserstack.json000064400000002042146725417150020500 0ustar00{ "exit_with_fail": true, "test_framework": "jasmine2", "test_path": "test/SpecRunner.html", "browsers": [ { "browser": "chrome", "browser_version": "22", "os": "OS X", "os_version": "Mountain Lion" }, { "browser": "firefox", "browser_version": "6", "os": "OS X", "os_version": "Mountain Lion" }, { "browser": "ie", "browser_version": "10", "os": "Windows", "os_version": "7" }, { "browser": "ie", "browser_version": "11", "os": "Windows", "os_version": "7" }, { "browser": "opera", "browser_version": "16", "os": "OS X", "os_version": "Mountain Lion" }, { "browser": "safari", "browser_version": "6.2", "os": "OS X", "os_version": "Mountain Lion" } ] } public/vendors/split/packages/splitjs/test/split.spec.js000064400000013541146725417150017524 0ustar00/* eslint-env jasmine */ /* global Split */ /* eslint-disable no-var, func-names, prefer-arrow-callback, object-shorthand, prefer-template */ function calcParts(expr) { var re = /calc\(([\d]*\.?[\d]*?)%\s?-\s?([\d]+)px\)/ var m = re.exec(expr) return { percentage: parseFloat(m[1]), pixels: parseInt(m[2], 10), } } describe('Split', function() { beforeEach(function() { document.body.style.width = '800px' document.body.style.height = '600px' this.a = document.createElement('div') this.b = document.createElement('div') this.c = document.createElement('div') this.a.id = 'a' this.b.id = 'b' this.c.id = 'c' document.body.appendChild(this.a) document.body.appendChild(this.b) document.body.appendChild(this.c) }) afterEach(function() { document.body.removeChild(this.a) document.body.removeChild(this.b) document.body.removeChild(this.c) }) it('splits in two when given two elements', function() { Split(['#a', '#b']) expect(this.a.style.width).toContain('calc(50% - 5px)') expect(this.b.style.width).toContain('calc(50% - 5px)') }) it('splits in three when given three elements', function() { Split(['#a', '#b', '#c']) expect(calcParts(this.a.style.width).percentage).toBeCloseTo(33.33) expect(calcParts(this.b.style.width).percentage).toBeCloseTo(33.33) expect(calcParts(this.c.style.width).percentage).toBeCloseTo(33.33) expect(calcParts(this.a.style.width).pixels).toBe(5) expect(calcParts(this.b.style.width).pixels).toBe(10) expect(calcParts(this.c.style.width).pixels).toBe(5) }) it('splits vertically when direction is vertical', function() { Split(['#a', '#b'], { direction: 'vertical', }) expect(this.a.style.height).toContain('calc(50% - 5px)') expect(this.b.style.height).toContain('calc(50% - 5px)') }) it('splits in percentages when given sizes', function() { Split(['#a', '#b'], { sizes: [25, 75], }) expect(this.a.style.width).toContain('calc(25% - 5px)') expect(this.b.style.width).toContain('calc(75% - 5px)') }) it('splits in percentages when given sizes', function() { Split(['#a', '#b'], { sizes: [25, 75], }) expect(this.a.style.width).toContain('calc(25% - 5px)') expect(this.b.style.width).toContain('calc(75% - 5px)') }) it('accounts for gutter size', function() { Split(['#a', '#b'], { gutterSize: 20, }) expect(this.a.style.width).toContain('calc(50% - 10px)') expect(this.b.style.width).toContain('calc(50% - 10px)') }) it('accounts for gutter size with more than two elements', function() { Split(['#a', '#b', '#c'], { gutterSize: 20, }) expect(calcParts(this.a.style.width).percentage).toBeCloseTo(33.33) expect(calcParts(this.b.style.width).percentage).toBeCloseTo(33.33) expect(calcParts(this.c.style.width).percentage).toBeCloseTo(33.33) expect(calcParts(this.a.style.width).pixels).toBe(10) expect(calcParts(this.b.style.width).pixels).toBe(20) expect(calcParts(this.c.style.width).pixels).toBe(10) }) it('accounts for gutter size when direction is vertical', function() { Split(['#a', '#b'], { direction: 'vertical', gutterSize: 20, }) expect(this.a.style.height).toContain('calc(50% - 10px)') expect(this.b.style.height).toContain('calc(50% - 10px)') }) it('accounts for gutter size with more than two elements when direction is vertical', function() { Split(['#a', '#b', '#c'], { direction: 'vertical', gutterSize: 20, }) expect(calcParts(this.a.style.height).percentage).toBeCloseTo(33.33) expect(calcParts(this.b.style.height).percentage).toBeCloseTo(33.33) expect(calcParts(this.c.style.height).percentage).toBeCloseTo(33.33) expect(calcParts(this.a.style.height).pixels).toBe(10) expect(calcParts(this.b.style.height).pixels).toBe(20) expect(calcParts(this.c.style.height).pixels).toBe(10) }) it('set size directly when given css values', function() { Split(['#a', '#b'], { sizes: ['150px', '640px'], }) expect(this.a.style.width).toBe('150px') expect(this.b.style.width).toBe('640px') }) it('adjusts sizes using setSizes', function() { var split = Split(['#a', '#b']) split.setSizes([70, 30]) expect(this.a.style.width).toContain('calc(70% - 5px)') expect(this.b.style.width).toContain('calc(30% - 5px)') }) it('collapse splits', function() { var split = Split(['#a', '#b']) split.collapse(0) expect(this.a.getBoundingClientRect().width).toBeCloseTo(100, 0) expect(this.b.getBoundingClientRect().width).toBeCloseTo(800 - 100 - 10, 0) split.collapse(1) expect(this.a.getBoundingClientRect().width).toBeCloseTo(800 - 100 - 10, 0) expect(this.b.getBoundingClientRect().width).toBeCloseTo(100, 0) }) it('returns sizes', function() { var split = Split(['#a', '#b']) var sizes = split.getSizes() expect(sizes).toEqual([50, 50]) split.setSizes([70, 30]) sizes = split.getSizes() expect(sizes).toEqual([70, 30]) }) it('sets element styles using the elementStyle function', function() { Split(['#a', '#b'], { elementStyle: function(dimension, size) { return { width: size + '%', } }, }) expect(this.a.style.width).toBe('50%') expect(this.b.style.width).toBe('50%') }) }) public/vendors/split/packages/splitjs/test/SpecRunner.html000064400000001032146725417150020044 0ustar00 Jasmine Spec Runner v2.6.4 public/vendors/split/packages/splitjs/README.md000064400000054375146725417150015414 0ustar00

Split.js

Build Status File Size npm version Dependencies Backers on Open Collective Sponsors on Open Collective

# Split.js > 2kb unopinionated utility for resizeable split views. - **Zero Deps** - **Tiny:** Weights 2kb gzipped. - **Fast:** No overhead or attached window event listeners, uses pure CSS for resizing. - **Unopinionated:** Plays nicely with `float`, `flex` and other layouts. - **Compatible:** Works great in IE9, and _even loads in IE8_ with polyfills. Early Firefox/Chrome/Safari/Opera supported too. ## Table of Contents - [Installation](#installation) - [Documentation](#documentation) - [Important Note](#important-note) - [Options](#options) - [Examples](#usage-examples) - [Saving State](#saving-state) - [Flexbox](#flex-layout) - [API](#api) - [CSS](#css) - [React](#react) - [Browser Support](#browser-support) - [Credits](#credits) - [License](#license) ## Installation Yarn: ```bash $ yarn add split.js ``` npm: ```bash $ npm install --save split.js ``` Include with a module bundler like [rollup](http://rollupjs.org/) or [webpack](https://webpack.github.io/): ```js // using ES6 modules import Split from 'split.js' // using CommonJS modules var Split = require('split.js') ``` The [UMD](https://github.com/umdjs/umd) build is also available on [unpkg](http://unpkg.com/): ```html ``` or [cdnjs](https://cdnjs.com/): ```html ``` You can find the library on `window.Split`. ## Documentation ```js var split = Split( elements, options?) ``` | Options | Type | Default | Description | | -------------- | --------------- | -------------- | -------------------------------------------------------- | | `sizes` | Array | | Initial sizes of each element in percents or CSS values. | | `minSize` | Number or Array | `100` | Minimum size of each element. | | `expandToMin` | Boolean | `false` | Grow initial sizes to `minSize` | | `gutterSize` | Number | `10` | Gutter size in pixels. | | `gutterAlign` | String | `'center'` | Gutter alignment between elements. | | `snapOffset` | Number | `30` | Snap to minimum size offset in pixels. | | `dragInterval` | Number | `1` | Number of pixels to drag. | | `direction` | String | `'horizontal'` | Direction to split: horizontal or vertical. | | `cursor` | String | `'col-resize'` | Cursor to display while dragging. | | `gutter` | Function | | Called to create each gutter element | | `elementStyle` | Function | | Called to set the style of each element. | | `gutterStyle` | Function | | Called to set the style of the gutter. | | `onDrag` | Function | | Callback on drag. | | `onDragStart` | Function | | Callback on drag start. | | `onDragEnd` | Function | | Callback on drag end. | ## Important Note Split.js does not set CSS beyond the minimum needed to manage the width or height of the elements. This is by design. It makes Split.js flexible and useful in many different situations. If you create a horizontal split, you are responsible for (likely) floating the elements and the gutter, and setting their heights. See the [CSS](#css) section below. If your gutters are not showing up, check the applied CSS styles. **THIS IS THE #1 QUESTION ABOUT THE LIBRARY**. ## Options #### sizes An array of initial sizes of the elements, specified as percentage values. Example: Setting the initial sizes to `25%` and `75%`. ```js Split(['#one', '#two'], { sizes: [25, 75], }) ``` #### minSize. Default: `100` An array of minimum sizes of the elements, specified as pixel values. Example: Setting the minimum sizes to `100px` and `300px`, respectively. ```js Split(['#one', '#two'], { minSize: [100, 300], }) ``` If a number is passed instead of an array, all elements are set to the same minimum size: ```js Split(['#one', '#two'], { minSize: 100, }) ``` #### expandToMin. Default: `false` When the split is created, if `expandToMin` is `true`, the minSize for each element overrides the percentage value from the `sizes` option. Example: The first element (`#one`) is set to 25% width of the parent container. However, it's `minSize` is `300px`. Using `expandToMin: true` means that the first element will always load at at least `300px`, even if `25%` were smaller. ```js Split(['#one', '#two'], { sizes: [25, 75], minSize: [300, 100], expandToMin: true, }) ``` #### gutterSize. Default: `10` Gutter size in pixels. Example: Setting the gutter size to `20px`. ```js Split(['#one', '#two'], { gutterSize: 20, }) ``` #### gutterAlign. Default: `'center'` Possible options are `'start'`, `'end'` and `'center'`. Determines how the gutter aligns between the two elements. `'start'` shrinks the first element to fit the gutter, `'end'` shrinks the second element to fit the gutter and `'center'` shrinks both elements by the same amount so the gutter sits between. Added in v1.5.3. Example: move gutter to the side of the second element: ```js Split(['#one', '#two'], { gutterAlign: 'end', }) ``` #### snapOffset. Default: `30` Snap to minimum size at this offset in pixels. Example: Set to `0` to disable to snap effect. ```js Split(['#one', '#two'], { snapOffset: 0, }) ``` #### dragInterval. Default: `1` Drag this number of pixels at a time. Defaults to `1` for smooth dragging, but can be set to a pixel value to give more control over the resulting sizes. Works particularly well when the `gutterSize` is set to the same size. Added in v1.5.3. Example: Drag 20px at a time: ```js Split(['#one', '#two'], { dragInterval: 20, }) ``` #### direction. Default: `'horizontal'` Direction to split in. Can be `'vertical'` or `'horizontal'`. Determines which CSS properties are applied (ie. width/height) to each element and gutter. Example: split vertically: ```js Split(['#one', '#two'], { direction: 'vertical', }) ``` #### cursor. Default: `'col-resize'` Cursor to show on the gutter (also applied to the body on dragging to prevent flickering). Defaults to `'col-resize'`for `direction: 'horizontal'` and `'row-resize'` for `direction: 'vertical'`: ```js Split(['#one', '#two'], { direction: 'vertical', cursor: 'row-resize', }) ``` #### gutter Optional function called to create each gutter element. The signature looks like this: ```js (index, direction, pairElement) => HTMLElement ``` Defaults to creating a `div` with `class="gutter gutter-horizontal"` or `class="gutter gutter-vertical"`, depending on the direction. The default gutter function looks like this: ```js (index, direction) => { const gutter = document.createElement('div') gutter.className = `gutter gutter-${direction}` return gutter } ``` The returned element is then inserted into the DOM, and it's width or height are set. This option can be used to clone an existing DOM element, or to create a new element with custom styles. Returning a falsey value like `null` or `false` will not insert a gutter. This behavior was added in v1.4.1. An additional argument, `pairElement`, is passed to the gutter function: this is the DOM element after (to the right or below) the gutter. This argument was added in v1.4.1. This final argument makes it easy to return the gutter that has already been created, for example, if `split.destroy()` was called with the option to preserve the gutters. ```js (index, direction, pairElement) => pairElement.previousSibling ``` #### elementStyle Optional function called setting the CSS style of the elements. The signature looks like this: ```js (dimension, elementSize, gutterSize, index) => Object ``` Dimension will be a string, `'width'` or `'height'`, and can be used in the return style. `elementSize` is the target percentage value of the element, and `gutterSize` is the target pixel value of the gutter. It should return an object with CSS properties to apply to the element. For horizontal splits, the return object looks like this: ```js { 'width': 'calc(50% - 5px)' } ``` A vertical split style would look like this: ```js { 'height': 'calc(50% - 5px)' } ``` You might use this function if you're using a different layout like flex (see [Flex Layout](#flex-layout)). Flex styles for a horizontal split could return an object like this: ```js { 'flex-basis': 'calc(50% - 5px)' } ``` #### gutterStyle Optional function called when setting the CSS style of the gutters. The signature looks like this: ```js (dimension, gutterSize, index) => Object ``` Dimension is a string, either `'width'` or `'height'`, and `gutterSize` is a pixel value representing the width of the gutter. It should return a similar object as `elementStyle`, an object with CSS properties to apply to the gutter. Since gutters have fixed widths, it will generally look like this: ```js { 'width': '10px' } ``` Both `elementStyle` and `gutterStyle` are called continously while dragging, so don't do anything besides return the style object in these functions. Both of these functions should be _pure_, returning the same values for the same inputs and not modifying any external state. #### onDrag, onDragStart, onDragEnd Callbacks that can be added on drag (fired continously), drag start and drag end. If doing more than basic operations in `onDrag`, add a debounce function to rate limit the callback. `onDragStart` and `onDragEnd` are passed the initial and final sizes of the split since it's a common pattern to access the sizes this way. Their function signature looks like this, where `sizes` is an array of percentage values like returned by `getSizes()`: ```js sizes => {} ``` ## Usage Examples Reference HTML for examples. Gutters are inserted automatically: ```html
content one
content two
content three
``` A split with two elements, starting at `25%` and `75%` wide, with `200px` minimum width. ```js Split(['#one', '#two'], { sizes: [25, 75], minSize: 200, }) ``` A split with three elements, starting with even (default) widths and minimum widths set to `100px`, `100px` and `300px`, respectively. ```js Split(['#one', '#two', '#three'], { minSize: [100, 100, 300], }) ``` A vertical split with two elements. ```js Split(['#one', '#two'], { direction: 'vertical', }) ``` ## Saving State Use local storage to save the most recent state: ```js var sizes = localStorage.getItem('split-sizes') if (sizes) { sizes = JSON.parse(sizes) } else { sizes = [50, 50] // default sizes } var split = Split(['#one', '#two'], { sizes: sizes, onDragEnd: function(sizes) { localStorage.setItem('split-sizes', JSON.stringify(sizes)) }, }) ``` ## Flex Layout Flex layout is supported easily by adding a `display: flex` to the parent element. The `width` or `height` CSS values assigned by default by Split.js work well with flex. ```html
``` And CSS style like this: ```css #flex { display: flex; flex-direction: row; } ``` For more complicated flex layouts, the `elementStyle` and `gutterStyle` can be used to set flex-basis: ```js Split(['#flex-1', '#flex-2'], { elementStyle: function(dimension, size, gutterSize) { return { 'flex-basis': 'calc(' + size + '% - ' + gutterSize + 'px)', } }, gutterStyle: function(dimension, gutterSize) { return { 'flex-basis': gutterSize + 'px', } }, }) ``` ## API Split.js returns an instance with a couple of functions. The instance is returned on creation: ```js var instance = Split([], ...) ``` #### `.setSizes([])` setSizes behaves the same as the `sizes` configuration option, passing an array of percentages. It updates the sizes of the elements in the split. Added in v1.1.0: ```js instance.setSizes([25, 75]) ``` #### `.getSizes()` getSizes returns an array of percents, suitable for using with `setSizes` or creation. Not supported in IE8. Added in v1.1.2: ```js instance.getSizes() > [25, 75] ``` #### `.collapse(index)` collapse changes the size of element at `index` to it's `minSize`. Every element except the last is collapsed towards the front (left or top). The last is collapsed towards the back. Not supported in IE8. Added in v1.1.0: ```js instance.collapse(0) ``` #### `.destroy(preserveStyles? = false, preserveGutters? = false)` Destroy the instance. It removes the gutter elements, and the size CSS styles Split.js set. Added in v1.1.1. Passing `preserveStyles = true` does not remove the CSS styles. Option added in v1.4.0. Passing `preserveGutters = true` does not remove the gutter elements. Option added in v1.4.1. ```js instance.destroy() ``` ## CSS In being non-opionionated, the only CSS Split.js sets is the widths or heights of the elements. Everything else is left up to you. You must set the elements and gutter heights when using horizontal mode. The gutters will not be visible if their height is 0px. Here's some basic CSS to style the gutters with, although it's not required. Both grip images are included in this repo: ```css .gutter { background-color: #eee; background-repeat: no-repeat; background-position: 50%; } .gutter.gutter-horizontal { background-image: url('grips/vertical.png'); cursor: col-resize; } .gutter.gutter-vertical { background-image: url('grips/horizontal.png'); cursor: row-resize; } ``` The grip images are small files and can be included with base64 instead: ```css .gutter.gutter-vertical { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII='); } .gutter.gutter-horizontal { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg=='); } ``` Split.js also works best when the elements are sized using `border-box`. The `split` class would have to be added manually to apply these styles: ```css .split { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } ``` And for horizontal splits, make sure the layout allows elements (including gutters) to be displayed side-by-side. Floating the elements is one option: ```css .split, .gutter.gutter-horizontal { float: left; } ``` If you use floats, set the height of the elements including the gutters. The gutters will not be visible otherwise if the height is set to 0px. ```css .split, .gutter.gutter-horizontal { height: 300px; } ``` Overflow can be handled as well, to get scrolling within the elements: ```css .split { overflow-y: auto; overflow-x: hidden; } ``` ## React **[React Split](https://github.com/nathancahill/split/tree/master/packages/react-split)** - Thin wrapper component for Split.js. ## Browser Support This library uses [CSS calc()](https://developer.mozilla.org/en-US/docs/Web/CSS/calc#AutoCompatibilityTable), [CSS box-sizing](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing#AutoCompatibilityTable) and [JS getBoundingClientRect()](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect#AutoCompatibilityTable). These features are supported in the following browsers: | Chrome logo | Firefox logo | Internet Explorer logo | Opera logo | Safari logo | [Sauce Labs](https://saucelabs.com) | | :-------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------- | | 22+ ✔ | 6+ ✔ | 9+ ✔ | 15+ ✔ | 6.2+ ✔ | Sponsored ✔ | Gracefully falls back in IE 8 and below to only setting the initial widths/heights and not allowing dragging. IE 8 requires polyfills for `Array.isArray()`, `Array.forEach`, `Array.map`, `Array.filter`, `Object.keys()` and `getComputedStyle`. This script from [Polyfill.io](https://polyfill.io/) includes all of these, adding 1.91 kb to the gzipped size. This is **ONLY NEEDED** if you are supporting **IE8:** ```html ``` Cross-browser Testing Platform and Open Source <3 Provided by [Sauce Labs](https://saucelabs.com). ## Credits ### Contributors This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. ### Backers Thank you to all our backers! 🙠[[Become a backer](https://opencollective.com/splitjs#backer)] ### Sponsors Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/splitjs#sponsor)] [Sauce Labs](https://saucelabs.com) ## License Copyright (c) 2019 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/packages/react-split-grid/src/index.js000064400000013140146725417150020034 0ustar00import React from 'react' import PropTypes from 'prop-types' import Split from 'split-grid' class ReactSplitGrid extends React.Component { constructor(props) { super(props) this.columnGutters = {} this.rowGutters = {} this.state = { gridTemplateColumns: props.gridTemplateColumns ? props.gridTemplateColumns : null, gridTemplateRows: props.gridTemplateRows ? props.gridTemplateRows : null, } this.getGridProps = this.getGridProps.bind(this) this.getGutterProps = this.getGutterProps.bind(this) this.handleDragStart = this.handleDragStart.bind(this) this.writeStyle = this.writeStyle.bind(this) this.onDrag = this.onDrag.bind(this) } componentDidMount() { const { children, ...options } = this.props options.writeStyle = this.writeStyle options.onDrag = this.onDrag this.split = Split(options) } componentDidUpdate(prevProps) { const { columnMinSizes, rowMinSizes, children, ...options } = this.props const { columnMinSizes: prevColumnMinSizes, rowMinSizes: prevRowMinSizes, } = prevProps const otherProps = [ 'minSize', 'columnMinSize', 'rowMinSize', 'columnMinSizes', 'rowMinSizes', 'snapOffset', 'columnSnapOffset', 'rowSnapOffset', 'dragInterval', 'columnDragInterval', 'rowDragInterval', 'cursor', 'columnCursor', 'rowCursor', ] let needsRecreate = otherProps // eslint-disable-next-line react/destructuring-assignment .map(prop => this.props[prop] !== prevProps[prop]) .reduce((accum, same) => accum || same, false) // TODO use deep equals if (columnMinSizes !== prevColumnMinSizes) { needsRecreate = true } if (rowMinSizes !== prevRowMinSizes) { needsRecreate = true } // Destroy and re-create split if options changed if (needsRecreate) { options.columnMinSizes = columnMinSizes options.rowMinSizes = rowMinSizes this.split.destroy(false) this.split = Split(options) } } componentWillUnmount() { this.split.destroy() delete this.split } static getDerivedStateFromProps(nextProps, prevState) { const state = {} let needsSetState = false if ( nextProps.gridTemplateColumns && nextProps.gridTemplateColumns !== prevState.gridTemplateColumns ) { state.gridTemplateColumns = nextProps.gridTemplateColumns needsSetState = true } if ( nextProps.gridTemplateRows && nextProps.gridTemplateRows !== prevState.prevGridTemplateRows ) { state.gridTemplateRows = nextProps.gridTemplateRows needsSetState = true } if (needsSetState) { return state } return null } onDrag(direction, track, style) { const { onDrag } = this.props if (onDrag) { onDrag(direction, track, style) } } getGridProps() { const { gridTemplateColumns, gridTemplateRows } = this.state const style = {} if (gridTemplateColumns) { style.gridTemplateColumns = gridTemplateColumns } if (gridTemplateRows) { style.gridTemplateRows = gridTemplateRows } return { style, } } getGutterProps(direction, track) { return { onMouseDown: this.handleDragStart(direction, track), onTouchStart: this.handleDragStart(direction, track), } } handleDragStart(direction, track) { return e => { this.split.handleDragStart(e, direction, track) } } writeStyle(element, gridTemplateProp, style) { const state = {} if (gridTemplateProp === 'grid-template-columns') { state.gridTemplateColumns = style } else if (gridTemplateProp === 'grid-template-rows') { state.gridTemplateRows = style } this.setState(state) } render() { const { component, render, children } = this.props const props = { getGridProps: this.getGridProps, getGutterProps: this.getGutterProps, } /* eslint-disable no-nested-ternary */ return component ? React.createElement(component, props) : render ? render(props) : children ? typeof children === 'function' ? children(props) : !(React.Children.count(children) === 0) ? React.Chidren.only(children) : null : null } } ReactSplitGrid.propTypes = { component: PropTypes.element, render: PropTypes.func, children: PropTypes.element, gridTemplateColumns: PropTypes.string, gridTemplateRows: PropTypes.string, columnMinSizes: PropTypes.arrayOf(PropTypes.number), rowMinSizes: PropTypes.arrayOf(PropTypes.number), onDrag: PropTypes.func, } ReactSplitGrid.defaultProps = { component: undefined, render: undefined, children: undefined, gridTemplateColumns: undefined, gridTemplateRows: undefined, columnMinSizes: undefined, rowMinSizes: undefined, onDrag: undefined, } export default ReactSplitGrid public/vendors/split/packages/react-split-grid/src/index.test.js000064400000000052146725417150021010 0ustar00/* eslint-env jest */ test('', () => {}) public/vendors/split/packages/react-split-grid/LICENSE.txt000064400000002041146725417150017421 0ustar00Copyright (c) 2018 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/packages/react-split-grid/rollup.config.js000064400000003535146725417150020726 0ustar00import buble from 'rollup-plugin-buble' import { uglify } from 'rollup-plugin-uglify' const pkg = require('./package.json') export default [ { input: './src/index.js', output: [ { name: 'ReactSplitGrid', file: pkg.main, format: 'umd', sourcemap: false, banner: `/*! ${pkg.name} - v${pkg.version} */\n`, globals: { react: 'React', 'split-grid': 'Split', 'prop-types': 'PropTypes', }, }, { file: pkg.module, format: 'esm', sourcemap: false, }, ], external: ['split-grid', 'react', 'prop-types'], plugins: [ buble({ exclude: 'node_modules/**', objectAssign: 'Object.assign', transforms: { forOf: false, }, }), ], }, { input: './src/index.js', output: { name: 'ReactSplitGrid', file: pkg['minified:main'], format: 'umd', sourcemap: true, banner: `/*! ${pkg.name} - v${pkg.version} */\n`, globals: { react: 'React', 'split-grid': 'Split', 'prop-types': 'PropTypes', }, }, external: ['split-grid', 'react', 'prop-types'], plugins: [ buble({ exclude: 'node_modules/**', objectAssign: 'Object.assign', transforms: { forOf: false, }, }), uglify({ output: { comments: /^!/, }, }), ], }, ] public/vendors/split/packages/react-split-grid/package.json000064400000001603146725417150020067 0ustar00{ "name": "react-split-grid", "version": "1.0.2", "description": "React component for Split Grid", "main": "dist/react-split-grid.js", "minified:main": "dist/react-split-grid.min.js", "module": "dist/react-split-grid.es.js", "scripts": { "build": "rollup -c && npm run size", "watch": "rollup -cw", "test": "jest", "lint": "eslint src", "size": "echo \"gzip size: $(gzip-size --raw $npm_package_minified_main) bytes\"" }, "repository": "https://github.com/nathancahill/split", "author": "Nathan Cahill ", "homepage": "https://split.js.org/", "files": ["dist"], "license": "MIT", "dependencies": { "prop-types": "^15.5.7", "split-grid": "^1.0.9" }, "peerDependencies": { "react": ">=15.4.2 || >= 16.0.0" }, "collective": { "type": "opencollective", "url": "https://opencollective.com/splitjs" } } public/vendors/split/packages/react-split-grid/README.md000064400000014063146725417150017064 0ustar00# React Split Grid   [![CI](https://img.shields.io/circleci/project/github/nathancahill/split/master.svg)](https://circleci.com/gh/nathancahill/split) ![Dependencies](https://david-dm.org/nathancahill/split/status.svg) ![](https://img.badgesize.io/https://unpkg.com/react-split-grid/dist/react-split-grid.min.js?compression=gzip&label=size) React component for [Split Grid](https://github.com/nathancahill/split/tree/master/packages/split-grid) ## Installation Yarn: ``` $ yarn add react-split-grid ``` npm: ``` $ npm install --save react-split-grid ``` Include with a module bundler like [rollup](http://rollupjs.org/) or [webpack](https://webpack.github.io/): ```js // using ES6 modules import Split from 'react-split-grid' // using CommonJS modules var Split = require('react-split-grid') ``` The [UMD](https://github.com/umdjs/umd) build is also available on [unpkg](http://unpkg.com/): ```html ``` You can find the library on `window.ReactSplitGrid`. ## `` `` is a light component wrapper around the [Split Grid](https://github.com/nathancahill/split/tree/master/packages/split-grid) library. It uses the render prop pattern, but also supports calling the `children` prop or the `component` prop. ### Example ```js import Split from 'react-split-grid' (
)} /> ``` ## Reference ### Split render methods and props There are three ways to render a Split Grid with `` - `` - `` - `` All three render methods will be passed the same props: ### Props Refer to [Split Grid documentation](https://github.com/nathancahill/split/tree/master/packages/split-grid#reference) for the options the component accepts as props. Here's the full list: - `minSize: number` - `columnMinSize: number` - `rowMinSize: number` - `columnMinSizes: { [track: number]: number }` - `rowMinSizes: { [track: number]: number }` - `snapOffset: number` - `columnSnapOffset: number` - `rowSnapOffset: number` - `dragInterval: number` - `columnDragInterval: number` - `rowDragInterval: number` - `cursor: string` - `columnCursor: string` - `rowCursor: string` - `onDrag: (direction: 'row' | 'column', track: number, gridTemplateStyle: string) => void` - `onDragStart: (direction: 'row' | 'column', track: number) => void` - `onDragEnd: (direction: 'row' | 'column', track: number) => void` - `gridTemplateColumns: string` - `gridTemplateRows: string` See the note below on using `gridTemplateColumns` / `gridTemplateRows` props. ### `component` ```js import Split from 'react-split-grid' const Grid = ({ getGridProps, getGutterProps, }) => (
) ``` **Warning:** `` takes precendence over `` so don’t use both in the same ``. ### `render: (props: Props) => ReactNode` ```js import Split from 'react-split-grid' (
)} /> ``` ### `children: func` ```js import Split from 'react-split-grid' {({ getGridProps, getGutterProps, }) => (
)} ``` ### Using `gridTemplateColumns` / `gridTemplateRows` props If `gridTemplateColumns` or `gridTemplateRows` are passed to ``, a handler for `onDrag` must be passed as well to update the prop: ```js class Wrapper extends React.Component { constructor() { super() this.state = { gridTemplateColumns: '1fr 10px 1fr', } this.handleDrag = this.handleDrag.bind(this) } handleDrag(direction, track, style) { this.setState({ gridTemplateColumns: style, }) } render() { const { gridTemplateColumns } = this.state return ( (
)} /> ) } } ``` ## License Copyright (c) 2019 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/.circleci/config.yml000064400000001126146725417150014474 0ustar00version: 2 jobs: build: docker: - image: circleci/node:11.1.0-stretch-browsers working_directory: ~/repo steps: - checkout - restore_cache: keys: - v1-dependencies-{{ checksum "package.json" }} - v1-dependencies- - run: yarn install - save_cache: paths: - node_modules key: v1-dependencies-{{ checksum "package.json" }} # run tests! - run: yarn run lerna link - run: yarn run lint - run: yarn run build - run: yarn test - run: yarn run saucelabs public/vendors/split/.gitignore000064400000000055146725417150012641 0ustar00.DS_Store dist/ node_modules/ yarn-error.log public/vendors/split/yarn.lock000064400001050601146725417150012477 0ustar00# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" dependencies: "@babel/highlight" "^7.0.0" "@babel/core@^7.1.2": version "7.1.2" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.2.tgz#f8d2a9ceb6832887329a7b60f9d035791400ba4e" dependencies: "@babel/code-frame" "^7.0.0" "@babel/generator" "^7.1.2" "@babel/helpers" "^7.1.2" "@babel/parser" "^7.1.2" "@babel/template" "^7.1.2" "@babel/traverse" "^7.1.0" "@babel/types" "^7.1.2" convert-source-map "^1.1.0" debug "^3.1.0" json5 "^0.5.0" lodash "^4.17.10" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" "@babel/generator@^7.1.2", "@babel/generator@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.1.3.tgz#2103ec9c42d9bdad9190a6ad5ff2d456fd7b8673" dependencies: "@babel/types" "^7.1.3" jsesc "^2.5.1" lodash "^4.17.10" source-map "^0.5.0" trim-right "^1.0.1" "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" dependencies: "@babel/types" "^7.0.0" "@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" dependencies: "@babel/helper-explode-assignable-expression" "^7.1.0" "@babel/types" "^7.0.0" "@babel/helper-call-delegate@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz#6a957f105f37755e8645343d3038a22e1449cc4a" dependencies: "@babel/helper-hoist-variables" "^7.0.0" "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" "@babel/helper-define-map@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz#3b74caec329b3c80c116290887c0dd9ae468c20c" dependencies: "@babel/helper-function-name" "^7.1.0" "@babel/types" "^7.0.0" lodash "^4.17.10" "@babel/helper-explode-assignable-expression@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" dependencies: "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" "@babel/helper-function-name@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" dependencies: "@babel/helper-get-function-arity" "^7.0.0" "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" "@babel/helper-get-function-arity@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" dependencies: "@babel/types" "^7.0.0" "@babel/helper-hoist-variables@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz#46adc4c5e758645ae7a45deb92bab0918c23bb88" dependencies: "@babel/types" "^7.0.0" "@babel/helper-member-expression-to-functions@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz#8cd14b0a0df7ff00f009e7d7a436945f47c7a16f" dependencies: "@babel/types" "^7.0.0" "@babel/helper-module-imports@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" dependencies: "@babel/types" "^7.0.0" "@babel/helper-module-transforms@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz#470d4f9676d9fad50b324cdcce5fbabbc3da5787" dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" "@babel/helper-split-export-declaration" "^7.0.0" "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" lodash "^4.17.10" "@babel/helper-optimise-call-expression@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" dependencies: "@babel/types" "^7.0.0" "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" "@babel/helper-regex@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.0.0.tgz#2c1718923b57f9bbe64705ffe5640ac64d9bdb27" dependencies: lodash "^4.17.10" "@babel/helper-remap-async-to-generator@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-wrap-function" "^7.1.0" "@babel/template" "^7.1.0" "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" "@babel/helper-replace-supers@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz#5fc31de522ec0ef0899dc9b3e7cf6a5dd655f362" dependencies: "@babel/helper-member-expression-to-functions" "^7.0.0" "@babel/helper-optimise-call-expression" "^7.0.0" "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" "@babel/helper-simple-access@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" dependencies: "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" "@babel/helper-split-export-declaration@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" dependencies: "@babel/types" "^7.0.0" "@babel/helper-wrap-function@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz#8cf54e9190706067f016af8f75cb3df829cc8c66" dependencies: "@babel/helper-function-name" "^7.1.0" "@babel/template" "^7.1.0" "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" "@babel/helpers@^7.1.2": version "7.1.2" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.1.2.tgz#ab752e8c35ef7d39987df4e8586c63b8846234b5" dependencies: "@babel/template" "^7.1.2" "@babel/traverse" "^7.1.0" "@babel/types" "^7.1.2" "@babel/highlight@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" dependencies: chalk "^2.0.0" esutils "^2.0.2" js-tokens "^4.0.0" "@babel/parser@^7.1.2", "@babel/parser@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.1.3.tgz#2c92469bac2b7fbff810b67fca07bd138b48af77" "@babel/plugin-proposal-async-generator-functions@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz#41c1a702e10081456e23a7b74d891922dd1bb6ce" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.0.0" "@babel/plugin-proposal-json-strings@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz#3b4d7b5cf51e1f2e70f52351d28d44fc2970d01e" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-json-strings" "^7.0.0" "@babel/plugin-proposal-object-rest-spread@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz#9a17b547f64d0676b6c9cecd4edf74a82ab85e7e" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.0.0" "@babel/plugin-proposal-optional-catch-binding@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz#b610d928fe551ff7117d42c8bb410eec312a6425" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-optional-catch-binding" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz#498b39cd72536cd7c4b26177d030226eba08cd33" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" regexpu-core "^4.2.0" "@babel/plugin-syntax-async-generators@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz#bf0891dcdbf59558359d0c626fdc9490e20bc13c" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-json-strings@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz#0d259a68090e15b383ce3710e01d5b23f3770cbd" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz#37d8fbcaf216bd658ea1aebbeb8b75e88ebc549b" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-optional-catch-binding@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz#886f72008b3a8b185977f7cb70713b45e51ee475" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-arrow-functions@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz#a6c14875848c68a3b4b3163a486535ef25c7e749" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-async-to-generator@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz#109e036496c51dd65857e16acab3bafdf3c57811" dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-transform-block-scoped-functions@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz#482b3f75103927e37288b3b67b65f848e2aa0d07" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-block-scoping@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz#1745075edffd7cdaf69fab2fb6f9694424b7e9bc" dependencies: "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.10" "@babel/plugin-transform-classes@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz#ab3f8a564361800cbc8ab1ca6f21108038432249" dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-define-map" "^7.1.0" "@babel/helper-function-name" "^7.1.0" "@babel/helper-optimise-call-expression" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-replace-supers" "^7.1.0" "@babel/helper-split-export-declaration" "^7.0.0" globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz#2fbb8900cd3e8258f2a2ede909b90e7556185e31" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-destructuring@^7.0.0": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.1.3.tgz#e69ff50ca01fac6cb72863c544e516c2b193012f" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-dotall-regex@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz#73a24da69bc3c370251f43a3d048198546115e58" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" "@babel/plugin-transform-duplicate-keys@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz#a0601e580991e7cace080e4cf919cfd58da74e86" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-exponentiation-operator@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz#9c34c2ee7fd77e02779cfa37e403a2e1003ccc73" dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-for-of@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz#f2ba4eadb83bd17dc3c7e9b30f4707365e1c3e39" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-function-name@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz#29c5550d5c46208e7f730516d41eeddd4affadbb" dependencies: "@babel/helper-function-name" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-literals@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz#2aec1d29cdd24c407359c930cdd89e914ee8ff86" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-modules-amd@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz#f9e0a7072c12e296079b5a59f408ff5b97bf86a8" dependencies: "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-modules-commonjs@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz#0a9d86451cbbfb29bd15186306897c67f6f9a05c" dependencies: "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" "@babel/plugin-transform-modules-systemjs@^7.0.0": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.1.3.tgz#2119a3e3db612fd74a19d88652efbfe9613a5db0" dependencies: "@babel/helper-hoist-variables" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-modules-umd@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz#a29a7d85d6f28c3561c33964442257cc6a21f2a8" dependencies: "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-new-target@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-object-super@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz#b1ae194a054b826d8d4ba7ca91486d4ada0f91bb" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-replace-supers" "^7.1.0" "@babel/plugin-transform-parameters@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz#44f492f9d618c9124026e62301c296bf606a7aed" dependencies: "@babel/helper-call-delegate" "^7.1.0" "@babel/helper-get-function-arity" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-regenerator@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz#5b41686b4ed40bef874d7ed6a84bdd849c13e0c1" dependencies: regenerator-transform "^0.13.3" "@babel/plugin-transform-shorthand-properties@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz#85f8af592dcc07647541a0350e8c95c7bf419d15" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-spread@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz#93583ce48dd8c85e53f3a46056c856e4af30b49b" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-sticky-regex@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz#30a9d64ac2ab46eec087b8530535becd90e73366" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" "@babel/plugin-transform-template-literals@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz#084f1952efe5b153ddae69eb8945f882c7a97c65" dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-typeof-symbol@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz#4dcf1e52e943e5267b7313bff347fdbe0f81cec9" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-unicode-regex@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz#c6780e5b1863a76fe792d90eded9fcd5b51d68fc" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" "@babel/preset-env@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.0.tgz#e67ea5b0441cfeab1d6f41e9b5c79798800e8d11" dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-async-generator-functions" "^7.1.0" "@babel/plugin-proposal-json-strings" "^7.0.0" "@babel/plugin-proposal-object-rest-spread" "^7.0.0" "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.0.0" "@babel/plugin-syntax-async-generators" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.0.0" "@babel/plugin-syntax-optional-catch-binding" "^7.0.0" "@babel/plugin-transform-arrow-functions" "^7.0.0" "@babel/plugin-transform-async-to-generator" "^7.1.0" "@babel/plugin-transform-block-scoped-functions" "^7.0.0" "@babel/plugin-transform-block-scoping" "^7.0.0" "@babel/plugin-transform-classes" "^7.1.0" "@babel/plugin-transform-computed-properties" "^7.0.0" "@babel/plugin-transform-destructuring" "^7.0.0" "@babel/plugin-transform-dotall-regex" "^7.0.0" "@babel/plugin-transform-duplicate-keys" "^7.0.0" "@babel/plugin-transform-exponentiation-operator" "^7.1.0" "@babel/plugin-transform-for-of" "^7.0.0" "@babel/plugin-transform-function-name" "^7.1.0" "@babel/plugin-transform-literals" "^7.0.0" "@babel/plugin-transform-modules-amd" "^7.1.0" "@babel/plugin-transform-modules-commonjs" "^7.1.0" "@babel/plugin-transform-modules-systemjs" "^7.0.0" "@babel/plugin-transform-modules-umd" "^7.1.0" "@babel/plugin-transform-new-target" "^7.0.0" "@babel/plugin-transform-object-super" "^7.1.0" "@babel/plugin-transform-parameters" "^7.1.0" "@babel/plugin-transform-regenerator" "^7.0.0" "@babel/plugin-transform-shorthand-properties" "^7.0.0" "@babel/plugin-transform-spread" "^7.0.0" "@babel/plugin-transform-sticky-regex" "^7.0.0" "@babel/plugin-transform-template-literals" "^7.0.0" "@babel/plugin-transform-typeof-symbol" "^7.0.0" "@babel/plugin-transform-unicode-regex" "^7.0.0" browserslist "^4.1.0" invariant "^2.2.2" js-levenshtein "^1.1.3" semver "^5.3.0" "@babel/template@^7.1.0", "@babel/template@^7.1.2": version "7.1.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644" dependencies: "@babel/code-frame" "^7.0.0" "@babel/parser" "^7.1.2" "@babel/types" "^7.1.2" "@babel/traverse@^7.1.0": version "7.1.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.1.4.tgz#f4f83b93d649b4b2c91121a9087fa2fa949ec2b4" dependencies: "@babel/code-frame" "^7.0.0" "@babel/generator" "^7.1.3" "@babel/helper-function-name" "^7.1.0" "@babel/helper-split-export-declaration" "^7.0.0" "@babel/parser" "^7.1.3" "@babel/types" "^7.1.3" debug "^3.1.0" globals "^11.1.0" lodash "^4.17.10" "@babel/types@^7.0.0", "@babel/types@^7.1.2", "@babel/types@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.3.tgz#3a767004567060c2f40fca49a304712c525ee37d" dependencies: esutils "^2.0.2" lodash "^4.17.10" to-fast-properties "^2.0.0" "@evocateur/libnpmaccess@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.0.tgz#e546ee4e4bedca54ed9303948ec54c985cec33e4" integrity sha512-bfrqZ0v+Il5TJBsgF2oyepeJg34K2pBItapzP+UT1QMIGpUh/Zc1pQql4jrafamZTqP3ZvdJxaElat8B5K3ICA== dependencies: "@evocateur/npm-registry-fetch" "^3.9.1" aproba "^2.0.0" figgy-pudding "^3.5.1" get-stream "^4.0.0" npm-package-arg "^6.1.0" "@evocateur/libnpmpublish@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@evocateur/libnpmpublish/-/libnpmpublish-1.2.0.tgz#3e0d79fdc0a75f212adabb7c7e341b017effeac2" integrity sha512-sezhX9FSnPIyrBBvxVocVJVO1uIWPczf6rOmUZSntCWfQMraO8pWTFlDJbroFqPbEqFFHf3eyw8NQ0Eb7OLd1g== dependencies: "@evocateur/npm-registry-fetch" "^3.9.1" aproba "^2.0.0" figgy-pudding "^3.5.1" get-stream "^4.0.0" lodash.clonedeep "^4.5.0" normalize-package-data "^2.4.0" npm-package-arg "^6.1.0" semver "^5.5.1" ssri "^6.0.1" "@evocateur/npm-registry-fetch@^3.9.1": version "3.9.1" resolved "https://registry.yarnpkg.com/@evocateur/npm-registry-fetch/-/npm-registry-fetch-3.9.1.tgz#75b3917320e559f6c91e26af17e62b085ec457a2" integrity sha512-6v1bHbcAypQ+te/1RGSNL4JkK6mcMtcZrUusqo5iKRtYSAig9UJXlOaCcBR+eLywt2DQMNpEwAj24jwWDX5G/w== dependencies: JSONStream "^1.3.4" bluebird "^3.5.1" figgy-pudding "^3.4.1" lru-cache "^4.1.3" make-fetch-happen "^4.0.1" npm-package-arg "^6.1.0" safe-buffer "^5.1.2" "@evocateur/pacote@^9.6.0": version "9.6.0" resolved "https://registry.yarnpkg.com/@evocateur/pacote/-/pacote-9.6.0.tgz#3f0d08fb81c572289a2dfa981e7f97b6dd83cef2" integrity sha512-nKx8EPxXhzqNfePbqC6603z7Kkf6GBS2q+SNGtBS/bCgS5Q+p3OVR6MXKOkpvC3WHse98W2WLu8QaV9axtfxyw== dependencies: "@evocateur/npm-registry-fetch" "^3.9.1" bluebird "^3.5.3" cacache "^11.3.2" figgy-pudding "^3.5.1" get-stream "^4.1.0" glob "^7.1.3" lru-cache "^5.1.1" make-fetch-happen "^4.0.1" minimatch "^3.0.4" minipass "^2.3.5" mississippi "^3.0.0" mkdirp "^0.5.1" normalize-package-data "^2.4.0" npm-package-arg "^6.1.0" npm-packlist "^1.1.12" npm-pick-manifest "^2.2.3" osenv "^0.1.5" promise-inflight "^1.0.1" promise-retry "^1.1.1" protoduck "^5.0.1" rimraf "^2.6.2" safe-buffer "^5.1.2" semver "^5.6.0" ssri "^6.0.1" tar "^4.4.8" unique-filename "^1.1.1" which "^1.3.1" "@lerna/add@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.15.0.tgz#10be562f43cde59b60f299083d54ac39520ec60a" integrity sha512-+KrG4GFy/6FISZ+DwWf5Fj5YB4ESa4VTnSn/ujf3VEda6dxngHPN629j+TcPbsdOxUYVah+HuZbC/B8NnkrKpQ== dependencies: "@evocateur/pacote" "^9.6.0" "@lerna/bootstrap" "3.15.0" "@lerna/command" "3.15.0" "@lerna/filter-options" "3.14.2" "@lerna/npm-conf" "3.13.0" "@lerna/validation-error" "3.13.0" dedent "^0.7.0" npm-package-arg "^6.1.0" p-map "^1.2.0" semver "^5.5.0" "@lerna/batch-packages@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/batch-packages/-/batch-packages-3.14.0.tgz#0208663bab3ddbf57956b370aaec4c9ebee6c800" integrity sha512-RlBkQVNTqk1qvn6PFWiWNiskllUHh6tXbTVm43mZRNd+vhAyvrQC8RWJxH0ECVvnFAt9rSNGRIVbEJ31WnNQLg== dependencies: "@lerna/package-graph" "3.14.0" npmlog "^4.1.2" "@lerna/bootstrap@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.15.0.tgz#f53e0bbbbfb8367e609a06378409bfc673ff2930" integrity sha512-4AxsPKKbgj2Ju03qDddQTpOHvpqnwd0yaiEU/aCcWv/4tDTe79NqUne2Z3+P2WZY0Zzb8+nUKcskwYBMTeq+Mw== dependencies: "@lerna/batch-packages" "3.14.0" "@lerna/command" "3.15.0" "@lerna/filter-options" "3.14.2" "@lerna/has-npm-version" "3.14.2" "@lerna/npm-install" "3.14.2" "@lerna/package-graph" "3.14.0" "@lerna/pulse-till-done" "3.13.0" "@lerna/rimraf-dir" "3.14.2" "@lerna/run-lifecycle" "3.14.0" "@lerna/run-parallel-batches" "3.13.0" "@lerna/symlink-binary" "3.14.2" "@lerna/symlink-dependencies" "3.14.2" "@lerna/validation-error" "3.13.0" dedent "^0.7.0" get-port "^3.2.0" multimatch "^2.1.0" npm-package-arg "^6.1.0" npmlog "^4.1.2" p-finally "^1.0.0" p-map "^1.2.0" p-map-series "^1.0.0" p-waterfall "^1.0.0" read-package-tree "^5.1.6" semver "^5.5.0" "@lerna/changed@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.15.0.tgz#20db9d992d697e4288c260aa38b989dcb93f4b40" integrity sha512-Hns1ssI9T9xOTGVc7PT2jUaqzsSkxV3hV/Y7iFO0uKTk+fduyTwGTHU9A/ybQ/xi/9iaJbvaXyjxKiGoEnzmhg== dependencies: "@lerna/collect-updates" "3.14.2" "@lerna/command" "3.15.0" "@lerna/listable" "3.14.0" "@lerna/output" "3.13.0" "@lerna/version" "3.15.0" "@lerna/check-working-tree@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-3.14.2.tgz#5ce007722180a69643a8456766ed8a91fc7e9ae1" integrity sha512-7safqxM/MYoAoxZxulUDtIJIbnBIgo0PB/FHytueG+9VaX7GMnDte2Bt1EKa0dz2sAyQdmQ3Q8ZXpf/6JDjaeg== dependencies: "@lerna/collect-uncommitted" "3.14.2" "@lerna/describe-ref" "3.14.2" "@lerna/validation-error" "3.13.0" "@lerna/child-process@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-3.14.2.tgz#950240cba83f7dfe25247cfa6c9cebf30b7d94f6" integrity sha512-xnq+W5yQb6RkwI0p16ZQnrn6HkloH/MWTw4lGE1nKsBLAUbmSU5oTE93W1nrG0X3IMF/xWc9UYvNdUGMWvZZ4w== dependencies: chalk "^2.3.1" execa "^1.0.0" strong-log-transformer "^2.0.0" "@lerna/clean@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.15.0.tgz#a94da50908a80ba443a0a682706aca79ac2ecf27" integrity sha512-D1BN7BnJk6YjrSR7E7RiCmWiFVWDo3L+OSe6zDq6rNNYexPBtSi2JOCeF/Dibi3jd2luVu0zkVpUtuEEdPiD+A== dependencies: "@lerna/command" "3.15.0" "@lerna/filter-options" "3.14.2" "@lerna/prompt" "3.13.0" "@lerna/pulse-till-done" "3.13.0" "@lerna/rimraf-dir" "3.14.2" p-map "^1.2.0" p-map-series "^1.0.0" p-waterfall "^1.0.0" "@lerna/cli@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/cli/-/cli-3.13.0.tgz#3d7b357fdd7818423e9681a7b7f2abd106c8a266" integrity sha512-HgFGlyCZbYaYrjOr3w/EsY18PdvtsTmDfpUQe8HwDjXlPeCCUgliZjXLOVBxSjiOvPeOSwvopwIHKWQmYbwywg== dependencies: "@lerna/global-options" "3.13.0" dedent "^0.7.0" npmlog "^4.1.2" yargs "^12.0.1" "@lerna/collect-uncommitted@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/collect-uncommitted/-/collect-uncommitted-3.14.2.tgz#b5ed00d800bea26bb0d18404432b051eee8d030e" integrity sha512-4EkQu4jIOdNL2BMzy/N0ydHB8+Z6syu6xiiKXOoFl0WoWU9H1jEJCX4TH7CmVxXL1+jcs8FIS2pfQz4oew99Eg== dependencies: "@lerna/child-process" "3.14.2" chalk "^2.3.1" figgy-pudding "^3.5.1" npmlog "^4.1.2" "@lerna/collect-updates@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.14.2.tgz#396201f6568ec5916bf2c11e7a29b0931fcd3e5b" integrity sha512-+zSQ2ZovH8Uc0do5dR+sk8VvRJc6Xl+ZnJJGESIl17KSpEw/lVjcOyt6f3BP+WHn+iSOjMWcGvUVA601FIEdZw== dependencies: "@lerna/child-process" "3.14.2" "@lerna/describe-ref" "3.14.2" minimatch "^3.0.4" npmlog "^4.1.2" slash "^1.0.0" "@lerna/command@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.15.0.tgz#e1dc1319054f1cf0b135aa0c5730f3335641a0ca" integrity sha512-dZqr4rKFN+veuXakIQ1DcGUpzBgcWKaYFNN4O6/skOdVQaEfGefzo1sZET+q7k/BkypxkhXHXpv5UqqSuL/EHQ== dependencies: "@lerna/child-process" "3.14.2" "@lerna/package-graph" "3.14.0" "@lerna/project" "3.15.0" "@lerna/validation-error" "3.13.0" "@lerna/write-log-file" "3.13.0" dedent "^0.7.0" execa "^1.0.0" is-ci "^1.0.10" lodash "^4.17.5" npmlog "^4.1.2" "@lerna/conventional-commits@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-3.14.0.tgz#24f643550dc29d4f1249cc26d0eb453d7a1c513d" integrity sha512-hGZ2qQZ9uEGf2eeIiIpEodSs9Qkkf/2uYEtNT7QN1RYISPUh6/lKGBssc5dpbCF64aEuxmemWLdlDf1ogG6++w== dependencies: "@lerna/validation-error" "3.13.0" conventional-changelog-angular "^5.0.3" conventional-changelog-core "^3.1.6" conventional-recommended-bump "^4.0.4" fs-extra "^7.0.0" get-stream "^4.0.0" npm-package-arg "^6.1.0" npmlog "^4.1.2" pify "^3.0.0" semver "^5.5.0" "@lerna/create-symlink@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-3.14.0.tgz#f40ae06e8cebe70c694368ebf9a4af5ab380fbea" integrity sha512-Kw51HYOOi6UfCKncqkgEU1k/SYueSBXgkNL91FR8HAZH7EPSRTEtp9mnJo568g0+Hog5C+3cOaWySwhHpRG29A== dependencies: cmd-shim "^2.0.2" fs-extra "^7.0.0" npmlog "^4.1.2" "@lerna/create@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.15.0.tgz#27bfadcbdf71d34226aa82432293f5290f7ab1aa" integrity sha512-doXGt0HTwTQl8GkC2tOrraA/5OWbz35hJqi7Dsl3Fl0bAxiv9XmF3LykHFJ+YTDHfGpdoJ8tKu66f/VKP16G0w== dependencies: "@evocateur/pacote" "^9.6.0" "@lerna/child-process" "3.14.2" "@lerna/command" "3.15.0" "@lerna/npm-conf" "3.13.0" "@lerna/validation-error" "3.13.0" camelcase "^5.0.0" dedent "^0.7.0" fs-extra "^7.0.0" globby "^8.0.1" init-package-json "^1.10.3" npm-package-arg "^6.1.0" p-reduce "^1.0.0" pify "^3.0.0" semver "^5.5.0" slash "^1.0.0" validate-npm-package-license "^3.0.3" validate-npm-package-name "^3.0.0" whatwg-url "^7.0.0" "@lerna/describe-ref@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-3.14.2.tgz#edc3c973f5ca9728d23358c4f4d3b55a21f65be5" integrity sha512-qa5pzDRK2oBQXNjyRmRnN7E8a78NMYfQjjlRFB0KNHMsT6mCiL9+8kIS39sSE2NqT8p7xVNo2r2KAS8R/m3CoQ== dependencies: "@lerna/child-process" "3.14.2" npmlog "^4.1.2" "@lerna/diff@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.15.0.tgz#573d6f58f6809d16752dcfab74c5e286b6678371" integrity sha512-N1Pr0M554Bt+DlVoD+DXWGh92gcq6G9icn8sH5GSqfwi0XCpPNJ2i1BNEZpUQ6ulLWOMa1YHR4PypPxecRGBjA== dependencies: "@lerna/child-process" "3.14.2" "@lerna/command" "3.15.0" "@lerna/validation-error" "3.13.0" npmlog "^4.1.2" "@lerna/exec@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.15.0.tgz#b31510f47255367eb0d3e4a4f7b6ef8f7e41b985" integrity sha512-YuXPd64TNG9wbb3lRvyMARQbdlbMZ1bJZ+GCm0enivnIWUyg0qtBDcfPY2dWpIgOif04zx+K/gmOX4lCaGM4UQ== dependencies: "@lerna/child-process" "3.14.2" "@lerna/command" "3.15.0" "@lerna/filter-options" "3.14.2" "@lerna/run-topologically" "3.14.0" "@lerna/validation-error" "3.13.0" p-map "^1.2.0" "@lerna/filter-options@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.14.2.tgz#7ba91cb54ff3fd9f4650ad8d7c40bc1075e44c2d" integrity sha512-Ct8oYvRttbYB9JalngHhirb8o9ZVyLm5a9MpXNevXoHiu6j0vNhI19BQCwNnrL6wZvEHJnzPuUl/jO23tWxemg== dependencies: "@lerna/collect-updates" "3.14.2" "@lerna/filter-packages" "3.13.0" dedent "^0.7.0" "@lerna/filter-packages@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/filter-packages/-/filter-packages-3.13.0.tgz#f5371249e7e1a15928e5e88c544a242e0162c21c" integrity sha512-RWiZWyGy3Mp7GRVBn//CacSnE3Kw82PxE4+H6bQ3pDUw/9atXn7NRX+gkBVQIYeKamh7HyumJtyOKq3Pp9BADQ== dependencies: "@lerna/validation-error" "3.13.0" multimatch "^2.1.0" npmlog "^4.1.2" "@lerna/get-npm-exec-opts@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.13.0.tgz#d1b552cb0088199fc3e7e126f914e39a08df9ea5" integrity sha512-Y0xWL0rg3boVyJk6An/vurKzubyJKtrxYv2sj4bB8Mc5zZ3tqtv0ccbOkmkXKqbzvNNF7VeUt1OJ3DRgtC/QZw== dependencies: npmlog "^4.1.2" "@lerna/get-packed@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/get-packed/-/get-packed-3.13.0.tgz#335e40d77f3c1855aa248587d3e0b2d8f4b06e16" integrity sha512-EgSim24sjIjqQDC57bgXD9l22/HCS93uQBbGpkzEOzxAVzEgpZVm7Fm1t8BVlRcT2P2zwGnRadIvxTbpQuDPTg== dependencies: fs-extra "^7.0.0" ssri "^6.0.1" tar "^4.4.8" "@lerna/github-client@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-3.14.2.tgz#a743792b51cd9bdfb785186e429568827a6372eb" integrity sha512-+2Xh7t4qVmXiXE2utPnh5T7YwSltG74JP7c+EiooRY5+3zjh9MpPOcTKxVY3xKclzpsyXMohk2KpTF4tzA5rrg== dependencies: "@lerna/child-process" "3.14.2" "@octokit/plugin-enterprise-rest" "^2.1.1" "@octokit/rest" "^16.16.0" git-url-parse "^11.1.2" npmlog "^4.1.2" "@lerna/gitlab-client@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz#91f4ec8c697b5ac57f7f25bd50fe659d24aa96a6" integrity sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q== dependencies: node-fetch "^2.5.0" npmlog "^4.1.2" whatwg-url "^7.0.0" "@lerna/global-options@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-3.13.0.tgz#217662290db06ad9cf2c49d8e3100ee28eaebae1" integrity sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ== "@lerna/has-npm-version@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/has-npm-version/-/has-npm-version-3.14.2.tgz#ac17f7c68e92114b8332b95ae6cffec9c0d67a7b" integrity sha512-cG+z5bB8JPd5f+nT2eLN2LmKg06O11AxlnUxgw2W7cLyc7cnsmMSp/rxt2JBMwW2r4Yn+CLLJIRwJZ2Es8jFSw== dependencies: "@lerna/child-process" "3.14.2" semver "^5.5.0" "@lerna/import@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.15.0.tgz#47f2da52059a96bb08a4c09e18d985258fce9ce1" integrity sha512-4GKQgeTXBTwMbZNkYyPdQIVA41HIISD7D6XRNrDaG0falUfvoPsknijQPCBmGqeh66u1Fcn2+4lkL3OCTj2FMg== dependencies: "@lerna/child-process" "3.14.2" "@lerna/command" "3.15.0" "@lerna/prompt" "3.13.0" "@lerna/pulse-till-done" "3.13.0" "@lerna/validation-error" "3.13.0" dedent "^0.7.0" fs-extra "^7.0.0" p-map-series "^1.0.0" "@lerna/init@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.15.0.tgz#bda36de44c365972f87cbd287fe85b6fb7bb1070" integrity sha512-VOqH6kFbFtfUbXxhSqXKY6bjnVp9nLuLRI6x9tVHOANX2LmSlXm17OUGBnNt+eM4uJLuiUsAR8nTlpCiz//lPQ== dependencies: "@lerna/child-process" "3.14.2" "@lerna/command" "3.15.0" fs-extra "^7.0.0" p-map "^1.2.0" write-json-file "^2.3.0" "@lerna/link@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.15.0.tgz#718b4116a8eacb3fc73414ae8d97f8fdaf8125da" integrity sha512-yKHuifADINobvDOLljBGkVGpVwy6J3mg5p9lQXBdOLXBoIKC8o/UKBR9JvZMFvT/Iy6zn6FPy1v5lz9iU1Ib0Q== dependencies: "@lerna/command" "3.15.0" "@lerna/package-graph" "3.14.0" "@lerna/symlink-dependencies" "3.14.2" p-map "^1.2.0" slash "^1.0.0" "@lerna/list@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.15.0.tgz#4e401c1ad990bb12bd38298cb61d21136420ff68" integrity sha512-8SvxnlfAnbEzQDf2NL0IxWyUuqWTykF9cHt5/f5TOzgESClpaOkDtqwh/UlE8nVTzWMnxnQUPQi3UTKyJD3i3g== dependencies: "@lerna/command" "3.15.0" "@lerna/filter-options" "3.14.2" "@lerna/listable" "3.14.0" "@lerna/output" "3.13.0" "@lerna/listable@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/listable/-/listable-3.14.0.tgz#08f4c78e0466568e8e8a57d4ad09537f2bb7bbb9" integrity sha512-ZK44Mo8xf/N97eQZ236SPSq0ek6+gk4HqHIx05foEMZVV1iIDH4a/nblLsJNjGQVsIdMYFPaqNJ0z+ZQfiJazQ== dependencies: "@lerna/query-graph" "3.14.0" chalk "^2.3.1" columnify "^1.5.4" "@lerna/log-packed@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/log-packed/-/log-packed-3.13.0.tgz#497b5f692a8d0e3f669125da97b0dadfd9e480f3" integrity sha512-Rmjrcz+6aM6AEcEVWmurbo8+AnHOvYtDpoeMMJh9IZ9SmZr2ClXzmD7wSvjTQc8BwOaiWjjC/ukcT0UYA2m7wg== dependencies: byte-size "^4.0.3" columnify "^1.5.4" has-unicode "^2.0.1" npmlog "^4.1.2" "@lerna/npm-conf@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-3.13.0.tgz#6b434ed75ff757e8c14381b9bbfe5d5ddec134a7" integrity sha512-Jg2kANsGnhg+fbPEzE0X9nX5oviEAvWj0nYyOkcE+cgWuT7W0zpnPXC4hA4C5IPQGhwhhh0IxhWNNHtjTuw53g== dependencies: config-chain "^1.1.11" pify "^3.0.0" "@lerna/npm-dist-tag@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-3.15.0.tgz#262dd1e67a4cf82ae78fadfe02622ebce4add078" integrity sha512-lnbdwc4Ebs7/EI9fTIgbH3dxXnP+SuCcGhG7P5ZjOqo67SY09sRZGcygEzabpvIwXvKpBF8vCd4xxzjnF2u+PA== dependencies: "@evocateur/npm-registry-fetch" "^3.9.1" "@lerna/otplease" "3.14.0" figgy-pudding "^3.5.1" npm-package-arg "^6.1.0" npmlog "^4.1.2" "@lerna/npm-install@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-3.14.2.tgz#fd22ff432f8b7cbe05bedfd36b0506482f1a4732" integrity sha512-JYJJRtLETrGpcQZa8Rj16vbye399RqnaXmJlZuZ2twjJ2DYVYtwkfsGEOdvdaKw5KVOEpWcAxBA9OMmKQtCLQw== dependencies: "@lerna/child-process" "3.14.2" "@lerna/get-npm-exec-opts" "3.13.0" fs-extra "^7.0.0" npm-package-arg "^6.1.0" npmlog "^4.1.2" signal-exit "^3.0.2" write-pkg "^3.1.0" "@lerna/npm-publish@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-3.15.0.tgz#89126d74ec97186475767b852954a5f55b732a71" integrity sha512-G7rcNcSGjG0La8eHPXDvCvoNXbwNnP6XJ+GPh3CH5xiR/nikfLOa+Bfm4ytdjVWWxnKfCT4qyMTCoV1rROlqQQ== dependencies: "@evocateur/libnpmpublish" "^1.2.0" "@lerna/otplease" "3.14.0" "@lerna/run-lifecycle" "3.14.0" figgy-pudding "^3.5.1" fs-extra "^7.0.0" npm-package-arg "^6.1.0" npmlog "^4.1.2" pify "^3.0.0" read-package-json "^2.0.13" "@lerna/npm-run-script@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-3.14.2.tgz#8c518ea9d241a641273e77aad6f6fddc16779c3f" integrity sha512-LbVFv+nvAoRTYLMrJlJ8RiakHXrLslL7Jp/m1R18vYrB8LYWA3ey+nz5Tel2OELzmjUiemAKZsD9h6i+Re5egg== dependencies: "@lerna/child-process" "3.14.2" "@lerna/get-npm-exec-opts" "3.13.0" npmlog "^4.1.2" "@lerna/otplease@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/otplease/-/otplease-3.14.0.tgz#b539fd3e7a08452fc0db3b10010ca3cf0e4a73e7" integrity sha512-rYAWzaYZ81bwnrmTkYWGgcc13bl/6DlG7pjWQWNGAJNLzO5zzj0xmXN5sMFJnNvDpSiS/ZS1sIuPvb4xnwLUkg== dependencies: "@lerna/prompt" "3.13.0" figgy-pudding "^3.5.1" "@lerna/output@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/output/-/output-3.13.0.tgz#3ded7cc908b27a9872228a630d950aedae7a4989" integrity sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg== dependencies: npmlog "^4.1.2" "@lerna/pack-directory@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-3.14.2.tgz#577b8ebf867c9b636a2e4659a27552ee24d83b9d" integrity sha512-b3LnJEmIml3sDj94TQT8R+kVyrDlmE7Su0WwcBYZDySXPMSZ38WA2/2Xjy/EWhXlFxp/nUJKyUG78nDrZ/00Uw== dependencies: "@lerna/get-packed" "3.13.0" "@lerna/package" "3.14.2" "@lerna/run-lifecycle" "3.14.0" figgy-pudding "^3.5.1" npm-packlist "^1.4.1" npmlog "^4.1.2" tar "^4.4.8" temp-write "^3.4.0" "@lerna/package-graph@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-3.14.0.tgz#4ccdf446dccedfbbeb4efff3eb720cb6fcb109fc" integrity sha512-dNpA/64STD5YXhaSlg4gT6Z474WPJVCHoX1ibsVIFu0fVgH609Y69bsdmbvTRdI7r6Dcu4ZfGxdR636RTrH+Eg== dependencies: "@lerna/prerelease-id-from-version" "3.14.0" "@lerna/validation-error" "3.13.0" npm-package-arg "^6.1.0" npmlog "^4.1.2" semver "^5.5.0" "@lerna/package@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/package/-/package-3.14.2.tgz#f893cb42e26c869df272dafbe1dd5a3473b0bd4d" integrity sha512-YR/+CzYdufJYfsUlrfuhTjA35iSZpXK7mVOZmeR9iRWhSaqesm4kq2zfxm9vCpZV2oAQQZOwi4eo5h0rQBtdiw== dependencies: load-json-file "^4.0.0" npm-package-arg "^6.1.0" write-pkg "^3.1.0" "@lerna/prerelease-id-from-version@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.14.0.tgz#d5da9c26ac4a0d0ecde09018f06e41ca4dd444c2" integrity sha512-Ap3Z/dNhqQuSrKmK+JmzYvQYI2vowxHvUVxZJiDVilW8dyNnxkCsYFmkuZytk5sxVz4VeGLNPS2RSsU5eeSS+Q== dependencies: semver "^5.5.0" "@lerna/project@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.15.0.tgz#733b0993a849dcf5b68fcd0ec11d8f7de38a6999" integrity sha512-eNGUWiMbQ9kh9kGkomtMnsLypS0rfLqxKgZP2+VnNVtIXjnLv4paeTm+1lkL+naNJUwhnpMk2NSLEeoxT/20QA== dependencies: "@lerna/package" "3.14.2" "@lerna/validation-error" "3.13.0" cosmiconfig "^5.1.0" dedent "^0.7.0" dot-prop "^4.2.0" glob-parent "^3.1.0" globby "^8.0.1" load-json-file "^4.0.0" npmlog "^4.1.2" p-map "^1.2.0" resolve-from "^4.0.0" write-json-file "^2.3.0" "@lerna/prompt@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/prompt/-/prompt-3.13.0.tgz#53571462bb3f5399cc1ca6d335a411fe093426a5" integrity sha512-P+lWSFokdyvYpkwC3it9cE0IF2U5yy2mOUbGvvE4iDb9K7TyXGE+7lwtx2thtPvBAfIb7O13POMkv7df03HJeA== dependencies: inquirer "^6.2.0" npmlog "^4.1.2" "@lerna/publish@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.15.0.tgz#54f93f8f0820d2d419d0b65df1eb55d8277090c9" integrity sha512-6tRRBJ8olLSXfrUsR4f7vSfx0cT1oPi6/v06yI3afDSsUX6eQ3ooZh7gMY4RWmd+nM/IJHTUzhlKF6WhTvo+9g== dependencies: "@evocateur/libnpmaccess" "^3.1.0" "@evocateur/npm-registry-fetch" "^3.9.1" "@evocateur/pacote" "^9.6.0" "@lerna/check-working-tree" "3.14.2" "@lerna/child-process" "3.14.2" "@lerna/collect-updates" "3.14.2" "@lerna/command" "3.15.0" "@lerna/describe-ref" "3.14.2" "@lerna/log-packed" "3.13.0" "@lerna/npm-conf" "3.13.0" "@lerna/npm-dist-tag" "3.15.0" "@lerna/npm-publish" "3.15.0" "@lerna/output" "3.13.0" "@lerna/pack-directory" "3.14.2" "@lerna/prerelease-id-from-version" "3.14.0" "@lerna/prompt" "3.13.0" "@lerna/pulse-till-done" "3.13.0" "@lerna/run-lifecycle" "3.14.0" "@lerna/run-topologically" "3.14.0" "@lerna/validation-error" "3.13.0" "@lerna/version" "3.15.0" figgy-pudding "^3.5.1" fs-extra "^7.0.0" npm-package-arg "^6.1.0" npmlog "^4.1.2" p-finally "^1.0.0" p-map "^1.2.0" p-pipe "^1.2.0" semver "^5.5.0" "@lerna/pulse-till-done@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz#c8e9ce5bafaf10d930a67d7ed0ccb5d958fe0110" integrity sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA== dependencies: npmlog "^4.1.2" "@lerna/query-graph@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/query-graph/-/query-graph-3.14.0.tgz#2abb36f445bd924d0f85ac7aec1445e9ef1e2c6c" integrity sha512-6YTh3vDMW2hUxHdKeRvx4bosc9lZClKaN+DzC1XKTkwDbWrsjmEzLcemKL6QnyyeuryN2f/eto7P9iSe3z3pQQ== dependencies: "@lerna/package-graph" "3.14.0" figgy-pudding "^3.5.1" "@lerna/resolve-symlink@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-3.13.0.tgz#3e6809ef53b63fe914814bfa071cd68012e22fbb" integrity sha512-Lc0USSFxwDxUs5JvIisS8JegjA6SHSAWJCMvi2osZx6wVRkEDlWG2B1JAfXUzCMNfHoZX0/XX9iYZ+4JIpjAtg== dependencies: fs-extra "^7.0.0" npmlog "^4.1.2" read-cmd-shim "^1.0.1" "@lerna/rimraf-dir@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-3.14.2.tgz#103a49882abd85d42285d05cc76869b89f21ffd2" integrity sha512-eFNkZsy44Bu9v1Hrj5Zk6omzg8O9h/7W6QYK1TTUHeyrjTEwytaNQlqF0lrTLmEvq55sviV42NC/8P3M2cvq8Q== dependencies: "@lerna/child-process" "3.14.2" npmlog "^4.1.2" path-exists "^3.0.0" rimraf "^2.6.2" "@lerna/run-lifecycle@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-3.14.0.tgz#0499eca0e7f393faf4e24e6c8737302a9059c22b" integrity sha512-GUM3L9MzGRSW0WQ8wbLW1+SYStU1OFjW0GBzShhBnFrO4nGRrU7VchsLpcLu0hk2uCzyhsrDKzifEdOdUyMoEQ== dependencies: "@lerna/npm-conf" "3.13.0" figgy-pudding "^3.5.1" npm-lifecycle "^2.1.1" npmlog "^4.1.2" "@lerna/run-parallel-batches@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/run-parallel-batches/-/run-parallel-batches-3.13.0.tgz#0276bb4e7cd0995297db82d134ca2bd08d63e311" integrity sha512-bICFBR+cYVF1FFW+Tlm0EhWDioTUTM6dOiVziDEGE1UZha1dFkMYqzqdSf4bQzfLS31UW/KBd/2z8jy2OIjEjg== dependencies: p-map "^1.2.0" p-map-series "^1.0.0" "@lerna/run-topologically@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@lerna/run-topologically/-/run-topologically-3.14.0.tgz#2a560cb657f0ef1565c680b6001b4b01b872dc07" integrity sha512-y+KBpC1YExFzGynovt9MY4O/bc3RrJaKeuXieiPfKGKxrdtmZe/r33oj/xePTXZq65jnw3SaU3H8S5CrrdkwDg== dependencies: "@lerna/query-graph" "3.14.0" figgy-pudding "^3.5.1" p-queue "^4.0.0" "@lerna/run@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.15.0.tgz#465028b5b561a050bd760924e4a0749de3f43172" integrity sha512-KQBkzZYoEKmzILKjbjsm1KKVWFBXwAdwzqJWj/lfxxd3V5LRF8STASk8aiw8bSpB0bUL9TU/pbXakRxiNzjDwQ== dependencies: "@lerna/command" "3.15.0" "@lerna/filter-options" "3.14.2" "@lerna/npm-run-script" "3.14.2" "@lerna/output" "3.13.0" "@lerna/run-topologically" "3.14.0" "@lerna/timer" "3.13.0" "@lerna/validation-error" "3.13.0" p-map "^1.2.0" "@lerna/symlink-binary@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-3.14.2.tgz#a832fdc6c4b1e5aaf9e6ac9c7e6c322746965eb0" integrity sha512-tqMwuWi6z1da0AFFbleWyu3H9fqayiV50rjj4anFTfayel9jSjlA1xPG+56sGIP6zUUNuUSc9kLh7oRRmlauoA== dependencies: "@lerna/create-symlink" "3.14.0" "@lerna/package" "3.14.2" fs-extra "^7.0.0" p-map "^1.2.0" "@lerna/symlink-dependencies@3.14.2": version "3.14.2" resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-3.14.2.tgz#e6b2a9544ff26addc1f4324734595e2f71dfc795" integrity sha512-Ox7WKXnHZ7IwWlejcCq3n0Hd/yMLv8AwIryhvWxM/RauAge+ML4wg578SsdCyKob8ecgm/R0ytHiU06j81iL1w== dependencies: "@lerna/create-symlink" "3.14.0" "@lerna/resolve-symlink" "3.13.0" "@lerna/symlink-binary" "3.14.2" fs-extra "^7.0.0" p-finally "^1.0.0" p-map "^1.2.0" p-map-series "^1.0.0" "@lerna/timer@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/timer/-/timer-3.13.0.tgz#bcd0904551db16e08364d6c18e5e2160fc870781" integrity sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw== "@lerna/validation-error@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/validation-error/-/validation-error-3.13.0.tgz#c86b8f07c5ab9539f775bd8a54976e926f3759c3" integrity sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA== dependencies: npmlog "^4.1.2" "@lerna/version@3.15.0": version "3.15.0" resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.15.0.tgz#3c65d223d94f211312995266abb07ee6606d5f73" integrity sha512-vReYX1NMXZ9PwzTZm97wAl/k3bmRnRZhnQi3mq/m49xTnDavq7p4sbUdFpvu8cVZNKnYS02pNIVGHrQw+K8ZCw== dependencies: "@lerna/check-working-tree" "3.14.2" "@lerna/child-process" "3.14.2" "@lerna/collect-updates" "3.14.2" "@lerna/command" "3.15.0" "@lerna/conventional-commits" "3.14.0" "@lerna/github-client" "3.14.2" "@lerna/gitlab-client" "3.15.0" "@lerna/output" "3.13.0" "@lerna/prerelease-id-from-version" "3.14.0" "@lerna/prompt" "3.13.0" "@lerna/run-lifecycle" "3.14.0" "@lerna/run-topologically" "3.14.0" "@lerna/validation-error" "3.13.0" chalk "^2.3.1" dedent "^0.7.0" minimatch "^3.0.4" npmlog "^4.1.2" p-map "^1.2.0" p-pipe "^1.2.0" p-reduce "^1.0.0" p-waterfall "^1.0.0" semver "^5.5.0" slash "^1.0.0" temp-write "^3.4.0" "@lerna/write-log-file@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/write-log-file/-/write-log-file-3.13.0.tgz#b78d9e4cfc1349a8be64d91324c4c8199e822a26" integrity sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A== dependencies: npmlog "^4.1.2" write-file-atomic "^2.3.0" "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" dependencies: call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" "@nodelib/fs.stat@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.2.tgz#54c5a964462be3d4d78af631363c18d6fa91ac26" "@octokit/endpoint@^5.1.0": version "5.2.0" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.2.0.tgz#acd569cb7152549998454aa5658532eb24a0987e" integrity sha512-g4r1MKr8GJ8qubJQp3HP3JrxDY+ZeVqjYBTgtu1lPEDLhfQDY6rOhyZOoHKOw+gaIF6aAcmuvPPNZUro2OwmOg== dependencies: deepmerge "3.3.0" is-plain-object "^3.0.0" universal-user-agent "^2.1.0" url-template "^2.0.8" "@octokit/plugin-enterprise-rest@^2.1.1": version "2.2.2" resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-2.2.2.tgz#c0e22067a043e19f96ff9c7832e2a3019f9be75c" integrity sha512-CTZr64jZYhGWNTDGlSJ2mvIlFsm9OEO3LqWn9I/gmoHI4jRBp4kpHoFYNemG4oA75zUAcmbuWblb7jjP877YZw== "@octokit/request-error@^1.0.1", "@octokit/request-error@^1.0.2": version "1.0.4" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.0.4.tgz#15e1dc22123ba4a9a4391914d80ec1e5303a23be" integrity sha512-L4JaJDXn8SGT+5G0uX79rZLv0MNJmfGa4vb4vy1NnpjSnWDLJRy6m90udGwvMmavwsStgbv2QNkPzzTCMmL+ig== dependencies: deprecation "^2.0.0" once "^1.4.0" "@octokit/request@^4.0.1": version "4.1.1" resolved "https://registry.yarnpkg.com/@octokit/request/-/request-4.1.1.tgz#614262214f48417b4d3b14e047d09a9c8e2f7a09" integrity sha512-LOyL0i3oxRo418EXRSJNk/3Q4I0/NKawTn6H/CQp+wnrG1UFLGu080gSsgnWobhPo5BpUNgSQ5BRk5FOOJhD1Q== dependencies: "@octokit/endpoint" "^5.1.0" "@octokit/request-error" "^1.0.1" deprecation "^2.0.0" is-plain-object "^3.0.0" node-fetch "^2.3.0" once "^1.4.0" universal-user-agent "^2.1.0" "@octokit/rest@^16.16.0": version "16.28.2" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.28.2.tgz#3fc3b8700046ab29ab1e2a4bdf49f89e94f7ba27" integrity sha512-csuYiHvJ1P/GFDadVn0QhwO83R1+YREjcwCY7ZIezB6aJTRIEidJZj+R7gAkUhT687cqYb4cXTZsDVu9F+Fmug== dependencies: "@octokit/request" "^4.0.1" "@octokit/request-error" "^1.0.2" atob-lite "^2.0.0" before-after-hook "^1.4.0" btoa-lite "^1.0.0" deprecation "^2.0.0" lodash.get "^4.4.2" lodash.set "^4.3.2" lodash.uniq "^4.5.0" octokit-pagination-methods "^1.1.0" once "^1.4.0" universal-user-agent "^2.0.0" url-template "^2.0.8" "@types/estree@0.0.39": version "0.0.39" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" "@types/node@*": version "10.12.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.1.tgz#da61b64a2930a80fa708e57c45cd5441eb379d5b" JSONStream@^1.0.4, JSONStream@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" dependencies: jsonparse "^1.2.0" through ">=2.2.7 <3" abab@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" accepts@~1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= dependencies: mime-types "~2.1.18" negotiator "0.6.1" acorn-globals@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.0.tgz#e3b6f8da3c1552a95ae627571f7dd6923bb54103" dependencies: acorn "^6.0.1" acorn-walk "^6.0.1" acorn-jsx@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.0.tgz#958584ddb60990c02c97c1bd9d521fce433bb101" acorn-walk@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.0.tgz#c957f4a1460da46af4a0388ce28b4c99355b0cbc" acorn@^5.5.3: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" acorn@^6.0.1, acorn@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.2.tgz#6a459041c320ab17592c6317abbfdf4bbaa98ca4" adm-zip@~0.4.3: version "0.4.11" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.11.tgz#2aa54c84c4b01a9d0fb89bb11982a51f13e3d62a" integrity sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA== after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= agent-base@4, agent-base@^4.1.0, agent-base@~4.2.0: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" dependencies: es6-promisify "^5.0.0" agentkeepalive@^3.4.1: version "3.5.2" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67" dependencies: humanize-ms "^1.2.1" ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" ajv@^6.5.3: version "6.5.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.4.tgz#247d5274110db653706b550fcc2b797ca28cfc59" dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" ansi-escapes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" dependencies: color-convert "^1.9.0" anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" dependencies: micromatch "^3.1.4" normalize-path "^2.1.1" append-transform@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" dependencies: default-require-extensions "^1.0.0" aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" aproba@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" dependencies: delegates "^1.0.0" readable-stream "^2.0.6" argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" dependencies: sprintf-js "~1.0.2" aria-query@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= dependencies: ast-types-flow "0.0.7" commander "^2.11.0" arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" dependencies: arr-flatten "^1.0.1" arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" array-differ@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" array-includes@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= dependencies: define-properties "^1.1.2" es-abstract "^1.7.0" array-slice@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" dependencies: array-uniq "^1.0.1" array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" arraybuffer.slice@~0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" asap@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" dependencies: safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" ast-types-flow@0.0.7, ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" async@^2.1.2, async@^2.1.4, async@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" dependencies: lodash "^4.17.10" asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" atob-lite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696" integrity sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY= atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" axobject-query@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9" integrity sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww== dependencies: ast-types-flow "0.0.7" babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: chalk "^1.1.3" esutils "^2.0.2" js-tokens "^3.0.2" babel-core@^6.0.0, babel-core@^6.26.0: version "6.26.3" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" dependencies: babel-code-frame "^6.26.0" babel-generator "^6.26.0" babel-helpers "^6.24.1" babel-messages "^6.23.0" babel-register "^6.26.0" babel-runtime "^6.26.0" babel-template "^6.26.0" babel-traverse "^6.26.0" babel-types "^6.26.0" babylon "^6.18.0" convert-source-map "^1.5.1" debug "^2.6.9" json5 "^0.5.1" lodash "^4.17.4" minimatch "^3.0.4" path-is-absolute "^1.0.1" private "^0.1.8" slash "^1.0.0" source-map "^0.5.7" babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" babel-generator@^6.18.0, babel-generator@^6.26.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" dependencies: babel-messages "^6.23.0" babel-runtime "^6.26.0" babel-types "^6.26.0" detect-indent "^4.0.0" jsesc "^1.3.0" lodash "^4.17.4" source-map "^0.5.7" trim-right "^1.0.1" babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" babel-jest@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1" dependencies: babel-plugin-istanbul "^4.1.6" babel-preset-jest "^23.2.0" babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" dependencies: babel-runtime "^6.22.0" babel-plugin-istanbul@^4.1.6: version "4.1.6" resolved "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45" dependencies: babel-plugin-syntax-object-rest-spread "^6.13.0" find-up "^2.1.0" istanbul-lib-instrument "^1.10.1" test-exclude "^4.2.1" babel-plugin-jest-hoist@^23.2.0: version "23.2.0" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167" babel-plugin-syntax-object-rest-spread@^6.13.0: version "6.13.0" resolved "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" babel-preset-jest@^23.2.0: version "23.2.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46" dependencies: babel-plugin-jest-hoist "^23.2.0" babel-plugin-syntax-object-rest-spread "^6.13.0" babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" dependencies: babel-core "^6.26.0" babel-runtime "^6.26.0" core-js "^2.5.0" home-or-tmp "^2.0.0" lodash "^4.17.4" mkdirp "^0.5.1" source-map-support "^0.4.15" babel-runtime@^6.22.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" dependencies: babel-runtime "^6.26.0" babel-traverse "^6.26.0" babel-types "^6.26.0" babylon "^6.18.0" lodash "^4.17.4" babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" dependencies: babel-code-frame "^6.26.0" babel-messages "^6.23.0" babel-runtime "^6.26.0" babel-types "^6.26.0" babylon "^6.18.0" debug "^2.6.8" globals "^9.18.0" invariant "^2.2.2" lodash "^4.17.4" babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" dependencies: babel-runtime "^6.26.0" esutils "^2.0.2" lodash "^4.17.4" to-fast-properties "^1.0.3" babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" base64-arraybuffer@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= base64id@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY= base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" dependencies: cache-base "^1.0.1" class-utils "^0.3.5" component-emitter "^1.2.1" define-property "^1.0.0" isobject "^3.0.1" mixin-deep "^1.2.0" pascalcase "^0.1.1" bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" dependencies: tweetnacl "^0.14.3" before-after-hook@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-1.4.0.tgz#2b6bf23dca4f32e628fd2747c10a37c74a4b484d" integrity sha512-l5r9ir56nda3qu14nAXIlyq1MmUSs0meCIaFAh8HwkFwP1F8eToOuS3ah2VAHHcY04jaYD7FpJC5JTXHYRbkzg== better-assert@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= dependencies: callsite "1.0.0" binary-extensions@^1.0.0: version "1.12.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== blob@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== bluebird@^3.3.0, bluebird@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" bluebird@^3.5.3, bluebird@^3.5.5: version "3.5.5" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== body-parser@^1.16.1: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" integrity sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ= dependencies: bytes "3.0.0" content-type "~1.0.4" debug "2.6.9" depd "~1.1.2" http-errors "~1.6.3" iconv-lite "0.4.23" on-finished "~2.3.0" qs "6.5.2" raw-body "2.3.3" type-is "~1.6.16" brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" braces@^0.1.2: version "0.1.5" resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6" integrity sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY= dependencies: expand-range "^0.1.0" braces@^1.8.2: version "1.8.5" resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" dependencies: expand-range "^1.8.1" preserve "^0.2.0" repeat-element "^1.1.2" braces@^2.3.0, braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" extend-shallow "^2.0.1" fill-range "^4.0.0" isobject "^3.0.1" repeat-element "^1.1.2" snapdragon "^0.8.1" snapdragon-node "^2.0.1" split-string "^3.0.2" to-regex "^3.0.1" browser-process-hrtime@^0.1.2: version "0.1.3" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" browser-resolve@^1.11.3: version "1.11.3" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" dependencies: resolve "1.1.7" browserslist@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.3.4.tgz#4477b737db6a1b07077275b24791e680d4300425" dependencies: caniuse-lite "^1.0.30000899" electron-to-chromium "^1.3.82" node-releases "^1.0.1" bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" dependencies: node-int64 "^0.4.0" btoa-lite@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= buble@^0.19.4: version "0.19.6" resolved "https://registry.yarnpkg.com/buble/-/buble-0.19.6.tgz#915909b6bd5b11ee03b1c885ec914a8b974d34d3" dependencies: chalk "^2.4.1" magic-string "^0.25.1" minimist "^1.2.0" os-homedir "^1.0.1" regexpu-core "^4.2.0" vlq "^1.0.0" buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== buffer-alloc@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== dependencies: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" builtin-modules@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e" integrity sha512-3U5kUA5VPsRUA3nofm/BXX7GVHKfxz0hOBAPxXrIvHzlDRkQVqEn6yi8QJegxl4LzOHLdvb7XF5dVawa/VVYBg== builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" byline@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" byte-size@^4.0.3: version "4.0.4" resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-4.0.4.tgz#29d381709f41aae0d89c631f1c81aec88cd40b23" bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= cacache@^11.0.1: version "11.2.0" resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.2.0.tgz#617bdc0b02844af56310e411c0878941d5739965" dependencies: bluebird "^3.5.1" chownr "^1.0.1" figgy-pudding "^3.1.0" glob "^7.1.2" graceful-fs "^4.1.11" lru-cache "^4.1.3" mississippi "^3.0.0" mkdirp "^0.5.1" move-concurrently "^1.0.1" promise-inflight "^1.0.1" rimraf "^2.6.2" ssri "^6.0.0" unique-filename "^1.1.0" y18n "^4.0.0" cacache@^11.3.2: version "11.3.3" resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc" integrity sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA== dependencies: bluebird "^3.5.5" chownr "^1.1.1" figgy-pudding "^3.5.1" glob "^7.1.4" graceful-fs "^4.1.15" lru-cache "^5.1.1" mississippi "^3.0.0" mkdirp "^0.5.1" move-concurrently "^1.0.1" promise-inflight "^1.0.1" rimraf "^2.6.3" ssri "^6.0.1" unique-filename "^1.1.1" y18n "^4.0.0" cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" get-value "^2.0.6" has-value "^1.0.0" isobject "^3.0.1" set-value "^2.0.0" to-object-path "^0.3.0" union-value "^1.0.0" unset-value "^1.0.0" call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= dependencies: callsites "^2.0.0" caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" dependencies: callsites "^0.2.0" caller-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= dependencies: caller-callsite "^2.0.0" callsite@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" camelcase-keys@^2.0.0: version "2.1.0" resolved "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" dependencies: camelcase "^2.0.0" map-obj "^1.0.0" camelcase-keys@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" dependencies: camelcase "^4.1.0" map-obj "^2.0.0" quick-lru "^1.0.0" camelcase@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" camelcase@^5.0.0: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caniuse-lite@^1.0.30000899: version "1.0.30000902" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000902.tgz#74eaf6ed7f1d31e5148725081c9df60051c5e2b3" capture-exit@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" dependencies: rsvp "^3.3.3" caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" chalk@^1.1.3: version "1.1.3" resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" has-ansi "^2.0.0" strip-ansi "^3.0.0" supports-color "^2.0.0" chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" supports-color "^5.3.0" chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" chokidar@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== dependencies: anymatch "^2.0.0" async-each "^1.0.0" braces "^2.3.0" glob-parent "^3.1.0" inherits "^2.0.1" is-binary-path "^1.0.0" is-glob "^4.0.0" lodash.debounce "^4.0.8" normalize-path "^2.1.1" path-is-absolute "^1.0.0" readdirp "^2.0.0" upath "^1.0.5" optionalDependencies: fsevents "^1.2.2" chownr@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" chownr@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== ci-info@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" circular-json@^0.5.5: version "0.5.9" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d" integrity sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ== class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" dependencies: arr-union "^3.1.0" define-property "^0.2.5" isobject "^3.0.0" static-extend "^0.1.1" cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" dependencies: restore-cursor "^2.0.0" cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" dependencies: string-width "^2.1.1" strip-ansi "^4.0.0" wrap-ansi "^2.0.0" clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" cmd-shim@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb" dependencies: graceful-fs "^4.1.2" mkdirp "~0.5.0" co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" dependencies: map-visit "^1.0.0" object-visit "^1.0.0" color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" colors@^1.1.0: version "1.3.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" integrity sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ== columnify@^1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" dependencies: strip-ansi "^3.0.0" wcwidth "^1.0.0" combine-lists@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6" integrity sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y= dependencies: lodash "^4.5.0" combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" dependencies: delayed-stream "~1.0.0" commander@^2.11.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" compare-func@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648" dependencies: array-ify "^1.0.0" dot-prop "^3.0.0" component-bind@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= component-emitter@1.2.1, component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" component-inherit@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" concat-stream@^1.5.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" dependencies: buffer-from "^1.0.0" inherits "^2.0.3" readable-stream "^2.2.2" typedarray "^0.0.6" concat-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" readable-stream "^3.0.2" typedarray "^0.0.6" config-chain@^1.1.11: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" dependencies: ini "^1.3.4" proto-list "~1.2.1" connect@^3.6.0: version "3.6.6" resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524" integrity sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ= dependencies: debug "2.6.9" finalhandler "1.1.0" parseurl "~1.3.2" utils-merge "1.0.1" console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== conventional-changelog-angular@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.3.tgz#299fdd43df5a1f095283ac16aeedfb0a682ecab0" integrity sha512-YD1xzH7r9yXQte/HF9JBuEDfvjxxwDGGwZU1+ndanbY0oFgA+Po1T9JDSpPLdP0pZT6MhCAsdvFKC4TJ4MTJTA== dependencies: compare-func "^1.3.1" q "^1.5.1" conventional-changelog-core@^3.1.6: version "3.2.2" resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-3.2.2.tgz#de41e6b4a71011a18bcee58e744f6f8f0e7c29c0" integrity sha512-cssjAKajxaOX5LNAJLB+UOcoWjAIBvXtDMedv/58G+YEmAXMNfC16mmPl0JDOuVJVfIqM0nqQiZ8UCm8IXbE0g== dependencies: conventional-changelog-writer "^4.0.5" conventional-commits-parser "^3.0.2" dateformat "^3.0.0" get-pkg-repo "^1.0.0" git-raw-commits "2.0.0" git-remote-origin-url "^2.0.0" git-semver-tags "^2.0.2" lodash "^4.2.1" normalize-package-data "^2.3.5" q "^1.5.1" read-pkg "^3.0.0" read-pkg-up "^3.0.0" through2 "^3.0.0" conventional-changelog-preset-loader@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.1.1.tgz#65bb600547c56d5627d23135154bcd9a907668c4" integrity sha512-K4avzGMLm5Xw0Ek/6eE3vdOXkqnpf9ydb68XYmCc16cJ99XMMbc2oaNMuPwAsxVK6CC1yA4/I90EhmWNj0Q6HA== conventional-changelog-writer@^4.0.5: version "4.0.6" resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.6.tgz#24db578ac8e7c89a409ef9bba12cf3c095990148" integrity sha512-ou/sbrplJMM6KQpR5rKFYNVQYesFjN7WpNGdudQSWNi6X+RgyFUcSv871YBYkrUYV9EX8ijMohYVzn9RUb+4ag== dependencies: compare-func "^1.3.1" conventional-commits-filter "^2.0.2" dateformat "^3.0.0" handlebars "^4.1.0" json-stringify-safe "^5.0.1" lodash "^4.2.1" meow "^4.0.0" semver "^6.0.0" split "^1.0.0" through2 "^3.0.0" conventional-commits-filter@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz#f122f89fbcd5bb81e2af2fcac0254d062d1039c1" integrity sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ== dependencies: lodash.ismatch "^4.4.0" modify-values "^1.0.0" conventional-commits-parser@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.3.tgz#c3f972fd4e056aa8b9b4f5f3d0e540da18bf396d" integrity sha512-KaA/2EeUkO4bKjinNfGUyqPTX/6w9JGshuQRik4r/wJz7rUw3+D3fDG6sZSEqJvKILzKXFQuFkpPLclcsAuZcg== dependencies: JSONStream "^1.0.4" is-text-path "^2.0.0" lodash "^4.2.1" meow "^4.0.0" split2 "^2.0.0" through2 "^3.0.0" trim-off-newlines "^1.0.0" conventional-recommended-bump@^4.0.4: version "4.1.1" resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-4.1.1.tgz#37014fadeda267d0607e2fc81124da840a585127" integrity sha512-JT2vKfSP9kR18RXXf55BRY1O3AHG8FPg5btP3l7LYfcWJsiXI6MCf30DepQ98E8Qhowvgv7a8iev0J1bEDkTFA== dependencies: concat-stream "^2.0.0" conventional-changelog-preset-loader "^2.1.1" conventional-commits-filter "^2.0.2" conventional-commits-parser "^3.0.2" git-raw-commits "2.0.0" git-semver-tags "^2.0.2" meow "^4.0.0" q "^1.5.1" convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" dependencies: safe-buffer "~5.1.1" cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" dependencies: aproba "^1.1.1" fs-write-stream-atomic "^1.0.8" iferr "^0.1.5" mkdirp "^0.5.1" rimraf "^2.5.4" run-queue "^1.0.0" copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" cosmiconfig@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== dependencies: import-fresh "^2.0.0" is-directory "^0.3.1" js-yaml "^3.13.1" parse-json "^4.0.0" cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" dependencies: lru-cache "^4.0.1" shebang-command "^1.2.0" which "^1.2.9" cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" dependencies: nice-try "^1.0.4" path-key "^2.0.1" semver "^5.5.0" shebang-command "^1.2.0" which "^1.2.9" cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": version "0.3.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797" cssstyle@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.1.1.tgz#18b038a9c44d65f7a8e428a653b9f6fe42faf5fb" dependencies: cssom "0.3.x" currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" dependencies: array-find-index "^1.0.1" custom-event@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU= cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" damerau-levenshtein@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514" integrity sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ= dargs@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" dependencies: number-is-nan "^1.0.0" dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" dependencies: assert-plus "^1.0.0" data-urls@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" dependencies: abab "^2.0.0" whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" date-format@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/date-format/-/date-format-1.2.0.tgz#615e828e233dd1ab9bb9ae0950e0ceccfa6ecad8" integrity sha1-YV6CjiM90aubua4JUODOzPpuytg= dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" debug@3.1.0, debug@=3.1.0, debug@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: ms "2.0.0" debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" dependencies: ms "^2.1.1" debug@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" dependencies: ms "^2.1.1" debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" decamelize-keys@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" dependencies: decamelize "^1.1.0" map-obj "^1.0.0" decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" decamelize@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7" dependencies: xregexp "4.0.0" decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" deepmerge@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.3.0.tgz#d3c47fd6f3a93d517b14426b0628a17b0125f5f7" integrity sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA== default-require-extensions@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" dependencies: strip-bom "^2.0.0" defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" dependencies: clone "^1.0.2" define-properties@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" dependencies: globby "^5.0.0" is-path-cwd "^1.0.0" is-path-in-cwd "^1.0.0" object-assign "^4.0.1" pify "^2.0.0" pinkie-promise "^2.0.0" rimraf "^2.2.8" delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= deprecation@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" dependencies: repeating "^2.0.0" detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" dependencies: asap "^2.0.0" wrappy "1" di@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= diff@^3.2.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" dir-glob@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" dependencies: arrify "^1.0.1" path-type "^3.0.0" doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" dependencies: esutils "^2.0.2" isarray "^1.0.0" doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" dependencies: esutils "^2.0.2" dom-serialize@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs= dependencies: custom-event "~1.0.0" ent "~2.2.0" extend "^3.0.0" void-elements "^2.0.0" domexception@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" dependencies: webidl-conversions "^4.0.2" dot-prop@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" dependencies: is-obj "^1.0.0" dot-prop@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" dependencies: is-obj "^1.0.0" duplexer@^0.1.1: version "0.1.1" resolved "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" duplexify@^3.4.2, duplexify@^3.6.0: version "3.6.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.1.tgz#b1a7a29c4abfd639585efaecce80d666b1e34125" dependencies: end-of-stream "^1.0.0" inherits "^2.0.1" readable-stream "^2.0.0" stream-shift "^1.0.0" ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.82: version "1.3.82" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.82.tgz#7d13ae4437d2a783de3f4efba96b186c540b67b1" emoji-regex@^6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.5.1.tgz#9baea929b155565c11ea41c6626eaa65cef992c2" integrity sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ== encodeurl@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" dependencies: iconv-lite "~0.4.13" end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" dependencies: once "^1.4.0" engine.io-client@~3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw== dependencies: component-emitter "1.2.1" component-inherit "0.0.3" debug "~3.1.0" engine.io-parser "~2.1.1" has-cors "1.1.0" indexof "0.0.1" parseqs "0.0.5" parseuri "0.0.5" ws "~3.3.1" xmlhttprequest-ssl "~1.5.4" yeast "0.1.2" engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6" integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA== dependencies: after "0.8.2" arraybuffer.slice "~0.0.7" base64-arraybuffer "0.1.5" blob "0.0.5" has-binary2 "~1.0.2" engine.io@~3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.1.tgz#b60281c35484a70ee0351ea0ebff83ec8c9522a2" integrity sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w== dependencies: accepts "~1.3.4" base64id "1.0.0" cookie "0.3.1" debug "~3.1.0" engine.io-parser "~2.1.0" ws "~3.3.1" ent@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" dependencies: is-arrayish "^0.2.1" es-abstract@^1.5.1, es-abstract@^1.6.1, es-abstract@^1.7.0: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" dependencies: es-to-primitive "^1.1.1" function-bind "^1.1.1" has "^1.0.1" is-callable "^1.1.3" is-regex "^1.0.4" es-to-primitive@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" is-symbol "^1.0.2" es6-promise@^4.0.3: version "4.2.5" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054" es6-promisify@^5.0.0: version "5.0.0" resolved "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" dependencies: es6-promise "^4.0.3" escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" escodegen@^1.9.1: version "1.11.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" dependencies: esprima "^3.1.3" estraverse "^4.2.0" esutils "^2.0.2" optionator "^0.8.1" optionalDependencies: source-map "~0.6.1" eslint-config-airbnb-base@^13.1.0: version "13.1.0" resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz#b5a1b480b80dfad16433d6c4ad84e6605052c05c" dependencies: eslint-restricted-globals "^0.1.1" object.assign "^4.1.0" object.entries "^1.0.4" eslint-config-airbnb@^17.1.0: version "17.1.0" resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-17.1.0.tgz#3964ed4bc198240315ff52030bf8636f42bc4732" integrity sha512-R9jw28hFfEQnpPau01NO5K/JWMGLi6aymiF6RsnMURjTk+MqZKllCqGK/0tOvHkPi/NWSSOU2Ced/GX++YxLnw== dependencies: eslint-config-airbnb-base "^13.1.0" object.assign "^4.1.0" object.entries "^1.0.4" eslint-config-prettier@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-3.1.0.tgz#2c26d2cdcfa3a05f0642cd7e6e4ef3316cdabfa2" dependencies: get-stdin "^6.0.0" eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" dependencies: debug "^2.6.9" resolve "^1.5.0" eslint-module-utils@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" dependencies: debug "^2.6.8" pkg-dir "^1.0.0" eslint-plugin-import@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" dependencies: contains-path "^0.1.0" debug "^2.6.8" doctrine "1.5.0" eslint-import-resolver-node "^0.3.1" eslint-module-utils "^2.2.0" has "^1.0.1" lodash "^4.17.4" minimatch "^3.0.3" read-pkg-up "^2.0.0" resolve "^1.6.0" eslint-plugin-jsx-a11y@^6.1.1: version "6.1.2" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.2.tgz#69bca4890b36dcf0fe16dd2129d2d88b98f33f88" integrity sha512-7gSSmwb3A+fQwtw0arguwMdOdzmKUgnUcbSNlo+GjKLAQFuC2EZxWqG9XHRI8VscBJD5a8raz3RuxQNFW+XJbw== dependencies: aria-query "^3.0.0" array-includes "^3.0.3" ast-types-flow "^0.0.7" axobject-query "^2.0.1" damerau-levenshtein "^1.0.4" emoji-regex "^6.5.1" has "^1.0.3" jsx-ast-utils "^2.0.1" eslint-plugin-react@^7.11.0: version "7.11.1" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz#c01a7af6f17519457d6116aa94fc6d2ccad5443c" integrity sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw== dependencies: array-includes "^3.0.3" doctrine "^2.1.0" has "^1.0.3" jsx-ast-utils "^2.0.1" prop-types "^15.6.2" eslint-restricted-globals@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" eslint-scope@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" eslint-utils@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" eslint@^5.8.0: version "5.8.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.8.0.tgz#91fbf24f6e0471e8fdf681a4d9dd1b2c9f28309b" dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.5.3" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" doctrine "^2.1.0" eslint-scope "^4.0.0" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" espree "^4.0.0" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^2.0.0" functional-red-black-tree "^1.0.1" glob "^7.1.2" globals "^11.7.0" ignore "^4.0.6" imurmurhash "^0.1.4" inquirer "^6.1.0" is-resolvable "^1.1.0" js-yaml "^3.12.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" lodash "^4.17.5" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" pluralize "^7.0.0" progress "^2.0.0" regexpp "^2.0.1" require-uncached "^1.0.3" semver "^5.5.1" strip-ansi "^4.0.0" strip-json-comments "^2.0.1" table "^5.0.2" text-table "^0.2.0" espree@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/espree/-/espree-4.1.0.tgz#728d5451e0fd156c04384a7ad89ed51ff54eb25f" dependencies: acorn "^6.0.2" acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" esquery@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" dependencies: estraverse "^4.1.0" estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" estree-walker@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" eventemitter3@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA== eventemitter3@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== exec-sh@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" dependencies: merge "^1.2.0" execa@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" dependencies: cross-spawn "^6.0.0" get-stream "^3.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" signal-exit "^3.0.0" strip-eof "^1.0.0" execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" signal-exit "^3.0.0" strip-eof "^1.0.0" execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" dependencies: cross-spawn "^6.0.0" get-stream "^4.0.0" is-stream "^1.1.0" npm-run-path "^2.0.0" p-finally "^1.0.0" signal-exit "^3.0.0" strip-eof "^1.0.0" exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" expand-braces@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea" integrity sha1-SIsdHSRRyz06axks/AMPRMWFX+o= dependencies: array-slice "^0.2.3" array-unique "^0.2.1" braces "^0.1.2" expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" dependencies: is-posix-bracket "^0.1.0" expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" dependencies: debug "^2.3.3" define-property "^0.2.5" extend-shallow "^2.0.1" posix-character-classes "^0.1.0" regex-not "^1.0.0" snapdragon "^0.8.1" to-regex "^3.0.1" expand-range@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044" integrity sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ= dependencies: is-number "^0.1.1" repeat-string "^0.2.2" expand-range@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" dependencies: fill-range "^2.1.0" expect@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98" dependencies: ansi-styles "^3.2.0" jest-diff "^23.6.0" jest-get-type "^22.1.0" jest-matcher-utils "^23.6.0" jest-message-util "^23.4.0" jest-regex-util "^23.3.0" extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" extend@^3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" external-editor@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" tmp "^0.0.33" extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" dependencies: is-extglob "^1.0.0" extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" dependencies: array-unique "^0.3.2" define-property "^1.0.0" expand-brackets "^2.1.4" extend-shallow "^2.0.1" fragment-cache "^0.2.1" regex-not "^1.0.0" snapdragon "^0.8.1" to-regex "^3.0.1" extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" extsprintf@^1.2.0: version "1.4.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" fast-deep-equal@^1.0.0: version "1.1.0" resolved "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" fast-glob@^2.0.2: version "2.2.3" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.3.tgz#d09d378e9ef6b0076a0fa1ba7519d9d4d9699c28" dependencies: "@mrmlnc/readdir-enhanced" "^2.2.1" "@nodelib/fs.stat" "^1.0.1" glob-parent "^3.1.0" is-glob "^4.0.0" merge2 "^1.2.1" micromatch "^3.1.10" fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" dependencies: bser "^2.0.0" figgy-pudding@^3.1.0, figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" fileset@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" dependencies: glob "^7.0.3" minimatch "^3.0.3" fill-range@^2.1.0: version "2.2.4" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" dependencies: is-number "^2.1.0" isobject "^2.0.0" randomatic "^3.0.0" repeat-element "^1.1.2" repeat-string "^1.5.2" fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" repeat-string "^1.6.1" to-regex-range "^2.1.0" finalhandler@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" integrity sha1-zgtoVbRYU+eRsvzGgARtiCU91/U= dependencies: debug "2.6.9" encodeurl "~1.0.1" escape-html "~1.0.3" on-finished "~2.3.0" parseurl "~1.3.2" statuses "~1.3.1" unpipe "~1.0.0" find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" dependencies: locate-path "^2.0.0" find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" dependencies: locate-path "^3.0.0" flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" dependencies: circular-json "^0.3.1" del "^2.0.2" graceful-fs "^4.1.2" write "^0.2.1" flush-write-stream@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" dependencies: inherits "^2.0.1" readable-stream "^2.0.4" follow-redirects@^1.0.0: version "1.5.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.9.tgz#c9ed9d748b814a39535716e531b9196a845d89c6" integrity sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w== dependencies: debug "=3.1.0" for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" dependencies: for-in "^1.0.1" forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" dependencies: asynckit "^0.4.0" combined-stream "^1.0.6" mime-types "^2.1.12" fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" dependencies: map-cache "^0.2.2" from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" dependencies: inherits "^2.0.1" readable-stream "^2.0.0" fs-access@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" integrity sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o= dependencies: null-check "^1.0.0" fs-extra@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6" dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" universalify "^0.1.0" fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" dependencies: minipass "^2.2.1" fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" dependencies: graceful-fs "^4.1.2" iferr "^0.1.5" imurmurhash "^0.1.4" readable-stream "1 || 2" fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" fsevents@^1.2.2, fsevents@^1.2.3: version "1.2.4" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" function-bind@^1.1.0, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" has-unicode "^2.0.0" object-assign "^4.1.0" signal-exit "^3.0.0" string-width "^1.0.1" strip-ansi "^3.0.1" wide-align "^1.1.0" genfun@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" get-pkg-repo@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d" dependencies: hosted-git-info "^2.1.4" meow "^3.3.0" normalize-package-data "^2.3.0" parse-github-repo-url "^1.3.0" through2 "^2.0.0" get-port@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" get-stream@^3.0.0: version "3.0.0" resolved "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" dependencies: pump "^3.0.0" get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" dependencies: assert-plus "^1.0.0" git-raw-commits@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5" integrity sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg== dependencies: dargs "^4.0.1" lodash.template "^4.0.2" meow "^4.0.0" split2 "^2.0.0" through2 "^2.0.0" git-remote-origin-url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" dependencies: gitconfiglocal "^1.0.0" pify "^2.3.0" git-semver-tags@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-2.0.2.tgz#f506ec07caade191ac0c8d5a21bdb8131b4934e3" integrity sha512-34lMF7Yo1xEmsK2EkbArdoU79umpvm0MfzaDkSNYSJqtM5QLAVTPWgpiXSVI5o/O9EvZPSrP4Zvnec/CqhSd5w== dependencies: meow "^4.0.0" semver "^5.5.0" git-up@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.1.tgz#cb2ef086653640e721d2042fe3104857d89007c0" integrity sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw== dependencies: is-ssh "^1.3.0" parse-url "^5.0.0" git-url-parse@^11.1.2: version "11.1.2" resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.1.2.tgz#aff1a897c36cc93699270587bea3dbcbbb95de67" integrity sha512-gZeLVGY8QVKMIkckncX+iCq2/L8PlwncvDFKiWkBn9EtCfYDbliRTTp6qzyQ1VMdITUfq7293zDzfpjdiGASSQ== dependencies: git-up "^4.0.0" gitconfiglocal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" dependencies: ini "^1.3.2" glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" dependencies: glob-parent "^2.0.0" is-glob "^2.0.0" glob-parent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" dependencies: is-glob "^2.0.0" glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" glob@^7.1.4: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" globals@^11.1.0, globals@^11.7.0: version "11.8.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" dependencies: array-union "^1.0.1" arrify "^1.0.0" glob "^7.0.3" object-assign "^4.0.1" pify "^2.0.0" pinkie-promise "^2.0.0" globby@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" dependencies: array-union "^1.0.1" dir-glob "^2.0.0" fast-glob "^2.0.2" glob "^7.1.2" ignore "^3.3.5" pify "^3.0.0" slash "^1.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" graceful-fs@^4.1.15: version "4.2.0" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" gzip-size-cli@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/gzip-size-cli/-/gzip-size-cli-3.0.0.tgz#b3f7ed1ad4ce70f06b2c80f749848fb5aca273fa" dependencies: gzip-size "^5.0.0" meow "^5.0.0" pretty-bytes "^5.1.0" gzip-size@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" dependencies: duplexer "^0.1.1" pify "^3.0.0" handlebars@^4.0.3: version "4.0.12" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" dependencies: async "^2.5.0" optimist "^0.6.1" source-map "^0.6.1" optionalDependencies: uglify-js "^3.1.4" handlebars@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== dependencies: neo-async "^2.6.0" optimist "^0.6.1" source-map "^0.6.1" optionalDependencies: uglify-js "^3.1.4" har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" har-validator@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" dependencies: ajv "^5.3.0" har-schema "^2.0.0" has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" dependencies: ansi-regex "^2.0.0" has-binary2@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== dependencies: isarray "2.0.1" has-cors@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" has-unicode@^2.0.0, has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" dependencies: get-value "^2.0.3" has-values "^0.1.4" isobject "^2.0.0" has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" dependencies: get-value "^2.0.6" has-values "^1.0.0" isobject "^3.0.0" has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" dependencies: is-number "^3.0.0" kind-of "^4.0.0" has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: function-bind "^1.1.1" home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.1" hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" html-encoding-sniffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" dependencies: whatwg-encoding "^1.0.1" http-cache-semantics@^3.8.1: version "3.8.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" http-errors@1.6.3, http-errors@~1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" http-proxy-agent@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" dependencies: agent-base "4" debug "3.1.0" http-proxy@^1.13.0: version "1.17.0" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a" integrity sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g== dependencies: eventemitter3 "^3.0.0" follow-redirects "^1.0.0" requires-port "^1.0.0" http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" https-proxy-agent@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" dependencies: agent-base "^4.1.0" debug "^3.1.0" humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" dependencies: ms "^2.0.0" iconv-lite@0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" dependencies: safer-buffer ">= 2.1.2 < 3" iferr@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" dependencies: minimatch "^3.0.4" ignore@^3.3.5: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" immediate@~3.0.5: version "3.0.6" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= dependencies: caller-path "^2.0.0" resolve-from "^3.0.0" import-local@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" dependencies: pkg-dir "^2.0.0" resolve-cwd "^2.0.0" imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" indent-string@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" dependencies: repeating "^2.0.0" indent-string@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" dependencies: once "^1.3.0" wrappy "1" inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" init-package-json@^1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe" dependencies: glob "^7.1.1" npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0" promzard "^0.3.0" read "~1.0.1" read-package-json "1 || 2" semver "2.x || 3.x || 4 || 5" validate-npm-package-license "^3.0.1" validate-npm-package-name "^3.0.0" inquirer@^6.1.0, inquirer@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" cli-cursor "^2.1.0" cli-width "^2.0.0" external-editor "^3.0.0" figures "^2.0.0" lodash "^4.17.10" mute-stream "0.0.7" run-async "^2.2.0" rxjs "^6.1.0" string-width "^2.1.0" strip-ansi "^4.0.0" through "^2.3.6" invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" dependencies: loose-envify "^1.0.0" invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" dependencies: kind-of "^6.0.0" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" is-builtin-module@^1.0.0: version "1.0.0" resolved "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" dependencies: builtin-modules "^1.0.0" is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" is-ci@^1.0.10: version "1.2.1" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" dependencies: ci-info "^1.5.0" is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" kind-of "^5.0.0" is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" kind-of "^6.0.2" is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" is-equal-shallow@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" dependencies: is-primitive "^2.0.0" is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" dependencies: is-plain-object "^2.0.4" is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" is-generator-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" dependencies: is-extglob "^1.0.0" is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" dependencies: is-extglob "^2.1.0" is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" dependencies: is-extglob "^2.1.1" is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= is-number@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806" integrity sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY= is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" dependencies: kind-of "^3.0.2" is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" dependencies: kind-of "^3.0.2" is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" is-obj@^1.0.0: version "1.0.1" resolved "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" is-path-in-cwd@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" dependencies: is-path-inside "^1.0.0" is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" dependencies: path-is-inside "^1.0.1" is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" dependencies: isobject "^3.0.1" is-plain-object@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== dependencies: isobject "^4.0.0" is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" dependencies: has "^1.0.1" is-resolvable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" is-ssh@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.1.tgz#f349a8cadd24e65298037a522cf7520f2e81a0f3" integrity sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg== dependencies: protocols "^1.1.0" is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" dependencies: has-symbols "^1.0.0" is-text-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-2.0.0.tgz#b2484e2b720a633feb2e85b67dc193ff72c75636" integrity sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw== dependencies: text-extensions "^2.0.0" is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" isarray@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= isbinaryfile@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== dependencies: buffer-alloc "^1.2.0" isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" isobject@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" istanbul-api@^1.3.1: version "1.3.7" resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa" dependencies: async "^2.1.4" fileset "^2.0.2" istanbul-lib-coverage "^1.2.1" istanbul-lib-hook "^1.2.2" istanbul-lib-instrument "^1.10.2" istanbul-lib-report "^1.1.5" istanbul-lib-source-maps "^1.2.6" istanbul-reports "^1.5.1" js-yaml "^3.7.0" mkdirp "^0.5.1" once "^1.4.0" istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0" istanbul-lib-hook@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86" dependencies: append-transform "^0.4.0" istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca" dependencies: babel-generator "^6.18.0" babel-template "^6.16.0" babel-traverse "^6.18.0" babel-types "^6.18.0" babylon "^6.18.0" istanbul-lib-coverage "^1.2.1" semver "^5.3.0" istanbul-lib-report@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c" dependencies: istanbul-lib-coverage "^1.2.1" mkdirp "^0.5.1" path-parse "^1.0.5" supports-color "^3.1.2" istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f" dependencies: debug "^3.1.0" istanbul-lib-coverage "^1.2.1" mkdirp "^0.5.1" rimraf "^2.6.1" source-map "^0.5.3" istanbul-reports@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a" dependencies: handlebars "^4.0.3" jasmine-core@2.6.4: version "2.6.4" resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.6.4.tgz#dec926cd0a9fa287fb6db5c755fa487e74cecac5" integrity sha1-3skmzQqfoof7bbXHVfpIfnTOysU= jest-changed-files@^23.4.2: version "23.4.2" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83" dependencies: throat "^4.0.0" jest-cli@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4" dependencies: ansi-escapes "^3.0.0" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.2" graceful-fs "^4.1.11" import-local "^1.0.0" is-ci "^1.0.10" istanbul-api "^1.3.1" istanbul-lib-coverage "^1.2.0" istanbul-lib-instrument "^1.10.1" istanbul-lib-source-maps "^1.2.4" jest-changed-files "^23.4.2" jest-config "^23.6.0" jest-environment-jsdom "^23.4.0" jest-get-type "^22.1.0" jest-haste-map "^23.6.0" jest-message-util "^23.4.0" jest-regex-util "^23.3.0" jest-resolve-dependencies "^23.6.0" jest-runner "^23.6.0" jest-runtime "^23.6.0" jest-snapshot "^23.6.0" jest-util "^23.4.0" jest-validate "^23.6.0" jest-watcher "^23.4.0" jest-worker "^23.2.0" micromatch "^2.3.11" node-notifier "^5.2.1" prompts "^0.1.9" realpath-native "^1.0.0" rimraf "^2.5.4" slash "^1.0.0" string-length "^2.0.0" strip-ansi "^4.0.0" which "^1.2.12" yargs "^11.0.0" jest-config@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d" dependencies: babel-core "^6.0.0" babel-jest "^23.6.0" chalk "^2.0.1" glob "^7.1.1" jest-environment-jsdom "^23.4.0" jest-environment-node "^23.4.0" jest-get-type "^22.1.0" jest-jasmine2 "^23.6.0" jest-regex-util "^23.3.0" jest-resolve "^23.6.0" jest-util "^23.4.0" jest-validate "^23.6.0" micromatch "^2.3.11" pretty-format "^23.6.0" jest-diff@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d" dependencies: chalk "^2.0.1" diff "^3.2.0" jest-get-type "^22.1.0" pretty-format "^23.6.0" jest-docblock@^23.2.0: version "23.2.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7" dependencies: detect-newline "^2.1.0" jest-each@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575" dependencies: chalk "^2.0.1" pretty-format "^23.6.0" jest-environment-jsdom@^23.4.0: version "23.4.0" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023" dependencies: jest-mock "^23.2.0" jest-util "^23.4.0" jsdom "^11.5.1" jest-environment-node@^23.4.0: version "23.4.0" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10" dependencies: jest-mock "^23.2.0" jest-util "^23.4.0" jest-get-type@^22.1.0: version "22.4.3" resolved "http://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" jest-haste-map@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16" dependencies: fb-watchman "^2.0.0" graceful-fs "^4.1.11" invariant "^2.2.4" jest-docblock "^23.2.0" jest-serializer "^23.0.1" jest-worker "^23.2.0" micromatch "^2.3.11" sane "^2.0.0" jest-jasmine2@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0" dependencies: babel-traverse "^6.0.0" chalk "^2.0.1" co "^4.6.0" expect "^23.6.0" is-generator-fn "^1.0.0" jest-diff "^23.6.0" jest-each "^23.6.0" jest-matcher-utils "^23.6.0" jest-message-util "^23.4.0" jest-snapshot "^23.6.0" jest-util "^23.4.0" pretty-format "^23.6.0" jest-leak-detector@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de" dependencies: pretty-format "^23.6.0" jest-matcher-utils@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80" dependencies: chalk "^2.0.1" jest-get-type "^22.1.0" pretty-format "^23.6.0" jest-message-util@^23.4.0: version "23.4.0" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f" dependencies: "@babel/code-frame" "^7.0.0-beta.35" chalk "^2.0.1" micromatch "^2.3.11" slash "^1.0.0" stack-utils "^1.0.1" jest-mock@^23.2.0: version "23.2.0" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134" jest-regex-util@^23.3.0: version "23.3.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5" jest-resolve-dependencies@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d" dependencies: jest-regex-util "^23.3.0" jest-snapshot "^23.6.0" jest-resolve@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae" dependencies: browser-resolve "^1.11.3" chalk "^2.0.1" realpath-native "^1.0.0" jest-runner@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38" dependencies: exit "^0.1.2" graceful-fs "^4.1.11" jest-config "^23.6.0" jest-docblock "^23.2.0" jest-haste-map "^23.6.0" jest-jasmine2 "^23.6.0" jest-leak-detector "^23.6.0" jest-message-util "^23.4.0" jest-runtime "^23.6.0" jest-util "^23.4.0" jest-worker "^23.2.0" source-map-support "^0.5.6" throat "^4.0.0" jest-runtime@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082" dependencies: babel-core "^6.0.0" babel-plugin-istanbul "^4.1.6" chalk "^2.0.1" convert-source-map "^1.4.0" exit "^0.1.2" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.1.11" jest-config "^23.6.0" jest-haste-map "^23.6.0" jest-message-util "^23.4.0" jest-regex-util "^23.3.0" jest-resolve "^23.6.0" jest-snapshot "^23.6.0" jest-util "^23.4.0" jest-validate "^23.6.0" micromatch "^2.3.11" realpath-native "^1.0.0" slash "^1.0.0" strip-bom "3.0.0" write-file-atomic "^2.1.0" yargs "^11.0.0" jest-serializer@^23.0.1: version "23.0.1" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165" jest-snapshot@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a" dependencies: babel-types "^6.0.0" chalk "^2.0.1" jest-diff "^23.6.0" jest-matcher-utils "^23.6.0" jest-message-util "^23.4.0" jest-resolve "^23.6.0" mkdirp "^0.5.1" natural-compare "^1.4.0" pretty-format "^23.6.0" semver "^5.5.0" jest-util@^23.4.0: version "23.4.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561" dependencies: callsites "^2.0.0" chalk "^2.0.1" graceful-fs "^4.1.11" is-ci "^1.0.10" jest-message-util "^23.4.0" mkdirp "^0.5.1" slash "^1.0.0" source-map "^0.6.0" jest-validate@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474" dependencies: chalk "^2.0.1" jest-get-type "^22.1.0" leven "^2.1.0" pretty-format "^23.6.0" jest-watcher@^23.4.0: version "23.4.0" resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c" dependencies: ansi-escapes "^3.0.0" chalk "^2.0.1" string-length "^2.0.0" jest-worker@^23.2.0: version "23.2.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9" dependencies: merge-stream "^1.0.1" jest@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d" dependencies: import-local "^1.0.0" jest-cli "^23.6.0" js-levenshtein@^1.1.3: version "1.1.4" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.4.tgz#3a56e3cbf589ca0081eb22cd9ba0b1290a16d26e" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" js-yaml@^3.12.0, js-yaml@^3.7.0: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" dependencies: argparse "^1.0.7" esprima "^4.0.0" js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== dependencies: argparse "^1.0.7" esprima "^4.0.0" jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" jsdom@^11.5.1: version "11.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" dependencies: abab "^2.0.0" acorn "^5.5.3" acorn-globals "^4.1.0" array-equal "^1.0.0" cssom ">= 0.3.2 < 0.4.0" cssstyle "^1.0.0" data-urls "^1.0.0" domexception "^1.0.1" escodegen "^1.9.1" html-encoding-sniffer "^1.0.2" left-pad "^1.3.0" nwsapi "^2.0.7" parse5 "4.0.0" pn "^1.1.0" request "^2.87.0" request-promise-native "^1.0.5" sax "^1.2.4" symbol-tree "^3.2.2" tough-cookie "^2.3.4" w3c-hr-time "^1.0.1" webidl-conversions "^4.0.2" whatwg-encoding "^1.0.3" whatwg-mimetype "^2.1.0" whatwg-url "^6.4.1" ws "^5.2.0" xml-name-validator "^3.0.0" jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" jsesc@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" optionalDependencies: graceful-fs "^4.1.6" jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" dependencies: assert-plus "1.0.0" extsprintf "1.3.0" json-schema "0.2.3" verror "1.10.0" jsx-ast-utils@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" integrity sha1-6AGxs5mF4g//yHtA43SAgOLcrH8= dependencies: array-includes "^3.0.3" jszip@^3.1.5: version "3.2.2" resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.2.2.tgz#b143816df7e106a9597a94c77493385adca5bd1d" integrity sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA== dependencies: lie "~3.3.0" pako "~1.0.2" readable-stream "~2.3.6" set-immediate-shim "~1.0.1" karma-chrome-launcher@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf" integrity sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w== dependencies: fs-access "^1.0.0" which "^1.2.1" karma-firefox-launcher@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz#2c47030452f04531eb7d13d4fc7669630bb93339" integrity sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA== karma-jasmine@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-1.1.2.tgz#394f2b25ffb4a644b9ada6f22d443e2fd08886c3" integrity sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM= karma-sauce-launcher@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/karma-sauce-launcher/-/karma-sauce-launcher-2.0.2.tgz#dbf98e70d86bf287b03a537cf637eb7aefa975c3" integrity sha512-jLUFaJhHMcKpxFWUesyWYihzM5FvQiJsDwGcCtKeOy2lsWhkVw0V0Byqb1d+wU6myU1mribBtsIcub23HS4kWA== dependencies: sauce-connect-launcher "^1.2.4" saucelabs "^1.5.0" selenium-webdriver "^4.0.0-alpha.1" karma@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/karma/-/karma-3.1.1.tgz#94c8edd20fb9597ccde343326da009737fb0423a" integrity sha512-NetT3wPCQMNB36uiL9LLyhrOt8SQwrEKt0xD3+KpTCfm0VxVyUJdPL5oTq2Ic5ouemgL/Iz4wqXEbF3zea9kQQ== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" chokidar "^2.0.3" colors "^1.1.0" combine-lists "^1.0.0" connect "^3.6.0" core-js "^2.2.0" di "^0.0.1" dom-serialize "^2.2.0" expand-braces "^0.1.1" glob "^7.1.1" graceful-fs "^4.1.2" http-proxy "^1.13.0" isbinaryfile "^3.0.0" lodash "^4.17.4" log4js "^3.0.0" mime "^2.3.1" minimatch "^3.0.2" optimist "^0.6.1" qjobs "^1.1.4" range-parser "^1.2.0" rimraf "^2.6.0" safe-buffer "^5.0.1" socket.io "2.1.1" source-map "^0.6.1" tmp "0.0.33" useragent "2.2.1" kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" kleur@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300" lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" dependencies: invert-kv "^1.0.0" lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" dependencies: invert-kv "^2.0.0" left-pad@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" lerna@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.15.0.tgz#b044dba8138d7a1a8dd48ac1d80e7541bdde0d1f" integrity sha512-kRIQ3bgzkmew5/WZQ0C9WjH0IUf3ZmTNnBwTHfXgLkVY7td0lbwMQFD7zehflUn0zG4ou54o/gn+IfjF0ti/5A== dependencies: "@lerna/add" "3.15.0" "@lerna/bootstrap" "3.15.0" "@lerna/changed" "3.15.0" "@lerna/clean" "3.15.0" "@lerna/cli" "3.13.0" "@lerna/create" "3.15.0" "@lerna/diff" "3.15.0" "@lerna/exec" "3.15.0" "@lerna/import" "3.15.0" "@lerna/init" "3.15.0" "@lerna/link" "3.15.0" "@lerna/list" "3.15.0" "@lerna/publish" "3.15.0" "@lerna/run" "3.15.0" "@lerna/version" "3.15.0" import-local "^1.0.0" npmlog "^4.1.2" leven@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" lie@~3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== dependencies: immediate "~3.0.5" load-json-file@^1.0.0: version "1.1.0" resolved "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" pify "^2.0.0" pinkie-promise "^2.0.0" strip-bom "^2.0.0" load-json-file@^2.0.0: version "2.0.0" resolved "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" dependencies: graceful-fs "^4.1.2" parse-json "^2.2.0" pify "^2.0.0" strip-bom "^3.0.0" load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" dependencies: graceful-fs "^4.1.2" parse-json "^4.0.0" pify "^3.0.0" strip-bom "^3.0.0" locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" dependencies: p-locate "^2.0.0" path-exists "^3.0.0" locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" dependencies: p-locate "^3.0.0" path-exists "^3.0.0" lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM= lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" lodash.template@^4.0.2: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" dependencies: lodash._reinterpolate "~3.0.0" lodash.templatesettings "^4.0.0" lodash.templatesettings@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" dependencies: lodash._reinterpolate "~3.0.0" lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= lodash@^4.13.1, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.5.0: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" log4js@^3.0.0: version "3.0.6" resolved "https://registry.yarnpkg.com/log4js/-/log4js-3.0.6.tgz#e6caced94967eeeb9ce399f9f8682a4b2b28c8ff" integrity sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ== dependencies: circular-json "^0.5.5" date-format "^1.2.0" debug "^3.1.0" rfdc "^1.1.2" streamroller "0.7.0" loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" dependencies: js-tokens "^3.0.0 || ^4.0.0" loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" dependencies: currently-unhandled "^0.4.1" signal-exit "^3.0.0" lru-cache@2.2.x: version "2.2.4" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" integrity sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0= lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" dependencies: pseudomap "^1.0.2" yallist "^2.1.2" lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" macos-release@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== magic-string@^0.25.1: version "0.25.1" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.1.tgz#b1c248b399cd7485da0fe7385c2fc7011843266e" dependencies: sourcemap-codec "^1.4.1" make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" dependencies: pify "^3.0.0" make-fetch-happen@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083" dependencies: agentkeepalive "^3.4.1" cacache "^11.0.1" http-cache-semantics "^3.8.1" http-proxy-agent "^2.1.0" https-proxy-agent "^2.2.1" lru-cache "^4.1.2" mississippi "^3.0.0" node-fetch-npm "^2.0.2" promise-retry "^1.1.1" socks-proxy-agent "^4.0.0" ssri "^6.0.0" makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" dependencies: tmpl "1.0.x" map-age-cleaner@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74" dependencies: p-defer "^1.0.0" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" map-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" dependencies: object-visit "^1.0.0" math-random@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= mem@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" dependencies: mimic-fn "^1.0.0" mem@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf" dependencies: map-age-cleaner "^0.1.1" mimic-fn "^1.0.0" p-is-promise "^1.1.0" meow@^3.3.0: version "3.7.0" resolved "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" dependencies: camelcase-keys "^2.0.0" decamelize "^1.1.2" loud-rejection "^1.0.0" map-obj "^1.0.1" minimist "^1.1.3" normalize-package-data "^2.3.4" object-assign "^4.0.1" read-pkg-up "^1.0.1" redent "^1.0.0" trim-newlines "^1.0.0" meow@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.1.tgz#d48598f6f4b1472f35bf6317a95945ace347f975" dependencies: camelcase-keys "^4.0.0" decamelize-keys "^1.0.0" loud-rejection "^1.0.0" minimist "^1.1.3" minimist-options "^3.0.1" normalize-package-data "^2.3.4" read-pkg-up "^3.0.0" redent "^2.0.0" trim-newlines "^2.0.0" meow@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" dependencies: camelcase-keys "^4.0.0" decamelize-keys "^1.0.0" loud-rejection "^1.0.0" minimist-options "^3.0.1" normalize-package-data "^2.3.4" read-pkg-up "^3.0.0" redent "^2.0.0" trim-newlines "^2.0.0" yargs-parser "^10.0.0" merge-stream@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" dependencies: readable-stream "^2.0.1" merge2@^1.2.1: version "1.2.3" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" merge@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" dependencies: arr-diff "^2.0.0" array-unique "^0.2.1" braces "^1.8.2" expand-brackets "^0.1.4" extglob "^0.3.1" filename-regex "^2.0.0" is-extglob "^1.0.0" is-glob "^2.0.1" kind-of "^3.0.2" normalize-path "^2.0.1" object.omit "^2.0.0" parse-glob "^3.0.4" regex-cache "^0.4.2" micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" braces "^2.3.1" define-property "^2.0.2" extend-shallow "^3.0.2" extglob "^2.0.4" fragment-cache "^0.2.1" kind-of "^6.0.2" nanomatch "^1.2.9" object.pick "^1.3.0" regex-not "^1.0.0" snapdragon "^0.8.1" to-regex "^3.0.2" mime-db@~1.37.0: version "1.37.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" mime-types@^2.1.12, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.21" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" dependencies: mime-db "~1.37.0" mime@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" integrity sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg== mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: brace-expansion "^1.1.7" minimist-options@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" dependencies: arrify "^1.0.1" is-plain-obj "^1.1.0" minimist@0.0.8: version "0.0.8" resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" minimist@~0.0.1: version "0.0.10" resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" minipass@^2.2.1, minipass@^2.3.3, minipass@^2.3.5: version "2.3.5" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" minizlib@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" dependencies: minipass "^2.2.1" minizlib@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== dependencies: minipass "^2.2.1" mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" dependencies: concat-stream "^1.5.0" duplexify "^3.4.2" end-of-stream "^1.1.0" flush-write-stream "^1.0.0" from2 "^2.1.0" parallel-transform "^1.1.0" pump "^3.0.0" pumpify "^1.3.3" stream-each "^1.1.0" through2 "^2.0.0" mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" dependencies: for-in "^1.0.2" is-extendable "^1.0.1" mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: version "0.5.1" resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" dependencies: aproba "^1.1.1" copy-concurrently "^1.0.0" fs-write-stream-atomic "^1.0.8" mkdirp "^0.5.1" rimraf "^2.5.4" run-queue "^1.0.3" ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" ms@^2.0.0, ms@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" multimatch@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" dependencies: array-differ "^1.0.0" array-union "^1.0.1" arrify "^1.0.0" minimatch "^3.0.0" mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" nan@^2.9.2: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" define-property "^2.0.2" extend-shallow "^3.0.2" fragment-cache "^0.2.1" is-windows "^1.0.2" kind-of "^6.0.2" object.pick "^1.3.0" regex-not "^1.0.0" snapdragon "^0.8.1" to-regex "^3.0.1" natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" dependencies: debug "^2.1.2" iconv-lite "^0.4.4" sax "^1.2.4" negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= neo-async@^2.6.0: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" node-fetch-npm@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" dependencies: encoding "^0.1.11" json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" node-fetch@^2.3.0, node-fetch@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== node-gyp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-4.0.0.tgz#972654af4e5dd0cd2a19081b4b46fe0442ba6f45" integrity sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA== dependencies: glob "^7.0.3" graceful-fs "^4.1.2" mkdirp "^0.5.0" nopt "2 || 3" npmlog "0 || 1 || 2 || 3 || 4" osenv "0" request "^2.87.0" rimraf "2" semver "~5.3.0" tar "^4.4.8" which "1" node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" node-notifier@^5.2.1: version "5.3.0" resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.3.0.tgz#c77a4a7b84038733d5fb351aafd8a268bfe19a01" dependencies: growly "^1.3.0" semver "^5.5.0" shellwords "^0.1.1" which "^1.3.0" node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" needle "^2.2.1" nopt "^4.0.1" npm-packlist "^1.1.6" npmlog "^4.0.2" rc "^1.2.7" rimraf "^2.6.1" semver "^5.3.0" tar "^4" node-releases@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.2.tgz#27c296d9fca3b659c64f7d43ea47a31ad2a90e4b" dependencies: semver "^5.3.0" "nopt@2 || 3": version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" dependencies: abbrev "1" nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" dependencies: abbrev "1" osenv "^0.1.4" normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" dependencies: remove-trailing-separator "^1.0.1" normalize-url@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" npm-lifecycle@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.1.1.tgz#0027c09646f0fd346c5c93377bdaba59c6748fdf" integrity sha512-+Vg6I60Z75V/09pdcH5iUo/99Q/vop35PaI99elvxk56azSVVsdsSsS/sXqKDNwbRRNN1qSxkcO45ZOu0yOWew== dependencies: byline "^5.0.0" graceful-fs "^4.1.15" node-gyp "^4.0.0" resolve-from "^4.0.0" slide "^1.1.6" uid-number "0.0.6" umask "^1.1.0" which "^1.3.1" "npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1" dependencies: hosted-git-info "^2.6.0" osenv "^0.1.5" semver "^5.5.0" validate-npm-package-name "^3.0.0" npm-packlist@^1.1.12, npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" npm-packlist@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" npm-pick-manifest@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz#32111d2a9562638bb2c8f2bf27f7f3092c8fae40" integrity sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA== dependencies: figgy-pudding "^3.5.1" npm-package-arg "^6.0.0" semver "^5.4.1" npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" dependencies: path-key "^2.0.0" "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" gauge "~2.7.3" set-blocking "~2.0.0" null-check@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0= number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" nwsapi@^2.0.7: version "2.0.9" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.9.tgz#77ac0cdfdcad52b6a1151a84e73254edc33ed016" oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" object-component@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" object-keys@^1.0.11, object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" dependencies: isobject "^3.0.0" object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" dependencies: define-properties "^1.1.2" function-bind "^1.1.1" has-symbols "^1.0.0" object-keys "^1.0.11" object.entries@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f" dependencies: define-properties "^1.1.2" es-abstract "^1.6.1" function-bind "^1.1.0" has "^1.0.1" object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" dependencies: define-properties "^1.1.2" es-abstract "^1.5.1" object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" dependencies: for-own "^0.1.4" is-extendable "^0.1.1" object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" dependencies: isobject "^3.0.1" octokit-pagination-methods@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" dependencies: mimic-fn "^1.0.0" optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: minimist "~0.0.1" wordwrap "~0.0.2" optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" dependencies: deep-is "~0.1.3" fast-levenshtein "~2.0.4" levn "~0.3.0" prelude-ls "~1.1.2" type-check "~0.3.2" wordwrap "~1.0.0" os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" os-locale@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" dependencies: execa "^0.7.0" lcid "^1.0.0" mem "^1.1.0" os-locale@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620" dependencies: execa "^0.10.0" lcid "^2.0.0" mem "^4.0.0" os-name@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg== dependencies: macos-release "^2.2.0" windows-release "^3.1.0" os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" osenv@0, osenv@^0.1.4, osenv@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" p-is-promise@^1.1.0: version "1.1.0" resolved "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" dependencies: p-try "^1.0.0" p-limit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" dependencies: p-try "^2.0.0" p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" dependencies: p-limit "^1.1.0" p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" dependencies: p-limit "^2.0.0" p-map-series@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" dependencies: p-reduce "^1.0.0" p-map@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" p-pipe@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9" p-queue@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-4.0.0.tgz#ed0eee8798927ed6f2c2f5f5b77fdb2061a5d346" integrity sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg== dependencies: eventemitter3 "^3.1.0" p-reduce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" p-try@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" p-waterfall@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-waterfall/-/p-waterfall-1.0.0.tgz#7ed94b3ceb3332782353af6aae11aa9fc235bb00" dependencies: p-reduce "^1.0.0" pako@~1.0.2: version "1.0.10" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== parallel-transform@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" dependencies: cyclist "~0.2.2" inherits "^2.0.3" readable-stream "^2.1.5" parse-github-repo-url@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" dependencies: glob-base "^0.3.0" is-dotfile "^1.0.0" is-extglob "^1.0.0" is-glob "^2.0.0" parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" dependencies: error-ex "^1.2.0" parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" dependencies: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" parse-path@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.1.tgz#0ec769704949778cb3b8eda5e994c32073a1adff" integrity sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA== dependencies: is-ssh "^1.3.0" protocols "^1.4.0" parse-url@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-5.0.1.tgz#99c4084fc11be14141efa41b3d117a96fcb9527f" integrity sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg== dependencies: is-ssh "^1.3.0" normalize-url "^3.3.0" parse-path "^4.0.0" protocols "^1.4.0" parse5@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" parseqs@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= dependencies: better-assert "~1.0.0" parseuri@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= dependencies: better-assert "~1.0.0" parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" dependencies: pinkie-promise "^2.0.0" path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" path-parse@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" dependencies: graceful-fs "^4.1.2" pify "^2.0.0" pinkie-promise "^2.0.0" path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" dependencies: pify "^2.0.0" path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" dependencies: pify "^3.0.0" performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" dependencies: pinkie "^2.0.0" pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" dependencies: find-up "^1.0.0" pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" dependencies: find-up "^2.1.0" pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" prettier@1.14.3: version "1.14.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" pretty-bytes@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.1.0.tgz#6237ecfbdc6525beaef4de722cc60a58ae0e6c6d" pretty-format@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760" dependencies: ansi-regex "^3.0.0" ansi-styles "^3.2.0" private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" progress@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31" promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" promise-retry@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" dependencies: err-code "^1.0.0" retry "^0.10.0" prompts@^0.1.9: version "0.1.14" resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2" dependencies: kleur "^2.0.1" sisteransi "^0.1.1" promzard@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" dependencies: read "1" prop-types@^15.5.7, prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== dependencies: loose-envify "^1.3.1" object-assign "^4.1.1" proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" protocols@^1.1.0, protocols@^1.4.0: version "1.4.7" resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.7.tgz#95f788a4f0e979b291ffefcf5636ad113d037d32" integrity sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg== protoduck@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.1.tgz#03c3659ca18007b69a50fd82a7ebcc516261151f" dependencies: genfun "^5.0.0" pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" psl@^1.1.24: version "1.1.29" resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" pump@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" dependencies: end-of-stream "^1.1.0" once "^1.3.1" pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" dependencies: end-of-stream "^1.1.0" once "^1.3.1" pumpify@^1.3.3: version "1.5.1" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" dependencies: duplexify "^3.6.0" inherits "^2.0.3" pump "^2.0.0" punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" qjobs@^1.1.4: version "1.2.0" resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== qs@6.5.2, qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" quick-lru@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" randomatic@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" dependencies: is-number "^4.0.0" kind-of "^6.0.0" math-random "^1.0.1" range-parser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= raw-body@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" integrity sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw== dependencies: bytes "3.0.0" http-errors "1.6.3" iconv-lite "0.4.23" unpipe "1.0.0" rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" dependencies: deep-extend "^0.6.0" ini "~1.3.0" minimist "^1.2.0" strip-json-comments "~2.0.1" react@^16.6.1: version "16.6.1" resolved "https://registry.yarnpkg.com/react/-/react-16.6.1.tgz#ee2aef4f0a09e494594882029821049772f915fe" integrity sha512-OtawJThYlvRgm9BXK+xTL7BIlDx8vv21j+fbQDjRRUyok6y7NyjlweGorielTahLZHYIdKUoK2Dp9ByVWuMqxw== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" scheduler "^0.11.0" read-cmd-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b" dependencies: graceful-fs "^4.1.2" "read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13: version "2.0.13" resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.13.tgz#2e82ebd9f613baa6d2ebe3aa72cefe3f68e41f4a" dependencies: glob "^7.1.1" json-parse-better-errors "^1.0.1" normalize-package-data "^2.0.0" slash "^1.0.0" optionalDependencies: graceful-fs "^4.1.2" read-package-tree@^5.1.6: version "5.2.1" resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.1.tgz#6218b187d6fac82289ce4387bbbaf8eef536ad63" dependencies: debuglog "^1.0.1" dezalgo "^1.0.0" once "^1.3.0" read-package-json "^2.0.0" readdir-scoped-modules "^1.0.0" read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" dependencies: find-up "^1.0.0" read-pkg "^1.0.0" read-pkg-up@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" dependencies: find-up "^2.0.0" read-pkg "^2.0.0" read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" dependencies: find-up "^2.0.0" read-pkg "^3.0.0" read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" dependencies: load-json-file "^1.0.0" normalize-package-data "^2.3.2" path-type "^1.0.0" read-pkg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" dependencies: load-json-file "^2.0.0" normalize-package-data "^2.3.2" path-type "^2.0.0" read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" dependencies: load-json-file "^4.0.0" normalize-package-data "^2.3.2" path-type "^3.0.0" read@1, read@~1.0.1: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" dependencies: mute-stream "~0.0.4" "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@~2.3.6: version "2.3.6" resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: core-util-is "~1.0.0" inherits "~2.0.3" isarray "~1.0.0" process-nextick-args "~2.0.0" safe-buffer "~5.1.1" string_decoder "~1.1.1" util-deprecate "~1.0.1" "readable-stream@2 || 3", readable-stream@^3.0.2: version "3.4.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" readdir-scoped-modules@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" dependencies: debuglog "^1.0.1" dezalgo "^1.0.0" graceful-fs "^4.1.2" once "^1.3.0" readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" readable-stream "^2.0.2" realpath-native@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.2.tgz#cd51ce089b513b45cf9b1516c82989b51ccc6560" dependencies: util.promisify "^1.0.0" redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" dependencies: indent-string "^2.1.0" strip-indent "^1.0.1" redent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" dependencies: indent-string "^3.0.0" strip-indent "^2.0.0" regenerate-unicode-properties@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c" dependencies: regenerate "^1.4.0" regenerate@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" regenerator-transform@^0.13.3: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb" dependencies: private "^0.1.6" regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" dependencies: is-equal-shallow "^0.1.3" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" regexpu-core@^4.1.3, regexpu-core@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.2.0.tgz#a3744fa03806cffe146dea4421a3e73bdcc47b1d" dependencies: regenerate "^1.4.0" regenerate-unicode-properties "^7.0.0" regjsgen "^0.4.0" regjsparser "^0.3.0" unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.0.2" regjsgen@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.4.0.tgz#c1eb4c89a209263f8717c782591523913ede2561" regjsparser@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.3.0.tgz#3c326da7fcfd69fa0d332575a41c8c0cdf588c96" dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" repeat-string@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae" integrity sha1-x6jTI2BoNiBZp+RlH8aITosftK4= repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" dependencies: is-finite "^1.0.0" request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" dependencies: lodash "^4.13.1" request-promise-native@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" dependencies: request-promise-core "1.1.1" stealthy-require "^1.1.0" tough-cookie ">=2.3.3" request@^2.87.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" dependencies: aws-sign2 "~0.7.0" aws4 "^1.8.0" caseless "~0.12.0" combined-stream "~1.0.6" extend "~3.0.2" forever-agent "~0.6.1" form-data "~2.3.2" har-validator "~5.1.0" http-signature "~1.2.0" is-typedarray "~1.0.0" isstream "~0.1.2" json-stringify-safe "~5.0.1" mime-types "~2.1.19" oauth-sign "~0.9.0" performance-now "^2.1.0" qs "~6.5.2" safe-buffer "^5.1.2" tough-cookie "~2.4.3" tunnel-agent "^0.6.0" uuid "^3.3.2" require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" dependencies: resolve-from "^3.0.0" resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" resolve@^1.1.6, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.6.0: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" dependencies: path-parse "^1.0.5" restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" dependencies: onetime "^2.0.0" signal-exit "^3.0.2" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" retry@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" rfdc@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.2.tgz#e6e72d74f5dc39de8f538f65e00c36c18018e349" integrity sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA== rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: glob "^7.0.5" rimraf@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" rollup-plugin-buble@^0.19.4: version "0.19.4" resolved "https://registry.yarnpkg.com/rollup-plugin-buble/-/rollup-plugin-buble-0.19.4.tgz#b0dde11ad2736b68e94ba2aa34de7822c6e28d24" dependencies: buble "^0.19.4" rollup-pluginutils "^2.3.3" rollup-plugin-node-resolve@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz#908585eda12e393caac7498715a01e08606abc89" integrity sha512-PJcd85dxfSBWih84ozRtBkB731OjXk0KnzN0oGp7WOWcarAFkVa71cV5hTJg2qpVsV2U8EUwrzHP3tvy9vS3qg== dependencies: builtin-modules "^2.0.0" is-module "^1.0.0" resolve "^1.1.6" rollup-plugin-uglify@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-6.0.0.tgz#15aa8919e5cdc63b7cfc9319c781788b40084ce4" dependencies: "@babel/code-frame" "^7.0.0" jest-worker "^23.2.0" serialize-javascript "^1.5.0" uglify-js "^3.4.9" rollup-pluginutils@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz#3aad9b1eb3e7fe8262820818840bf091e5ae6794" dependencies: estree-walker "^0.5.2" micromatch "^2.3.11" rollup@^0.66.5: version "0.66.6" resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.66.6.tgz#ce7d6185beb7acea644ce220c25e71ae03275482" dependencies: "@types/estree" "0.0.39" "@types/node" "*" rsvp@^3.3.3: version "3.6.2" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" dependencies: is-promise "^2.1.0" run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" dependencies: aproba "^1.1.1" rxjs@^6.1.0: version "6.3.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" dependencies: tslib "^1.9.0" safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" safe-regex@^1.1.0: version "1.1.0" resolved "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" dependencies: ret "~0.1.10" "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" sane@^2.0.0: version "2.5.2" resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa" dependencies: anymatch "^2.0.0" capture-exit "^1.2.0" exec-sh "^0.2.0" fb-watchman "^2.0.0" micromatch "^3.1.4" minimist "^1.1.1" walker "~1.0.5" watch "~0.18.0" optionalDependencies: fsevents "^1.2.3" sauce-connect-launcher@^1.2.4: version "1.2.7" resolved "https://registry.yarnpkg.com/sauce-connect-launcher/-/sauce-connect-launcher-1.2.7.tgz#c7f8b3d4eb354d07a9922b4cd67356f527192556" integrity sha512-v07+QhFrxgz3seMFuRSonu3gW1s6DbcLQlFhjsRrmKUauzPbbudHdnn91WYgEwhoZVdPNzeZpAEJwcQyd9xnTA== dependencies: adm-zip "~0.4.3" async "^2.1.2" https-proxy-agent "^2.2.1" lodash "^4.16.6" rimraf "^2.5.4" saucelabs@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.5.0.tgz#9405a73c360d449b232839919a86c396d379fd9d" integrity sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ== dependencies: https-proxy-agent "^2.2.1" sax@>=0.6.0, sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" scheduler@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.0.tgz#def1f1bfa6550cc57981a87106e65e8aea41a6b5" integrity sha512-MAYbBfmiEHxF0W+c4CxMpEqMYK+rYF584VP/qMKSiHM6lTkBKKYOJaDiSILpJHla6hBOsVd6GucPL46o2Uq3sg== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" selenium-webdriver@^4.0.0-alpha.1: version "4.0.0-alpha.4" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.4.tgz#73694490e02c941d9d0bf7a36f7c49beb9372512" integrity sha512-etJt20d8qInkxMAHIm5SEpPBSS+CdxVcybnxzSIB/GlWErb8pIWrArz/VA6VfUW0/6tIcokepXQ5ufvdzqqk1A== dependencies: jszip "^3.1.5" rimraf "^2.6.3" tmp "0.0.30" xml2js "^0.4.19" "semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" semver@^6.0.0: version "6.2.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== semver@~5.3.0: version "5.3.0" resolved "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" serialize-javascript@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.5.0.tgz#1aa336162c88a890ddad5384baebc93a655161fe" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" set-immediate-shim@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" is-plain-object "^2.0.1" to-object-path "^0.3.0" set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" is-plain-object "^2.0.3" split-string "^3.0.1" setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" shellwords@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" sisteransi@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce" slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" dependencies: is-fullwidth-code-point "^2.0.0" slide@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" smart-buffer@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3" snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" dependencies: define-property "^1.0.0" isobject "^3.0.0" snapdragon-util "^3.0.1" snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" dependencies: base "^0.11.1" debug "^2.2.0" define-property "^0.2.5" extend-shallow "^2.0.1" map-cache "^0.2.2" source-map "^0.5.6" source-map-resolve "^0.5.0" use "^3.1.0" socket.io-adapter@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" integrity sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs= socket.io-client@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f" integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ== dependencies: backo2 "1.0.2" base64-arraybuffer "0.1.5" component-bind "1.0.0" component-emitter "1.2.1" debug "~3.1.0" engine.io-client "~3.2.0" has-binary2 "~1.0.2" has-cors "1.1.0" indexof "0.0.1" object-component "0.0.3" parseqs "0.0.5" parseuri "0.0.5" socket.io-parser "~3.2.0" to-array "0.1.4" socket.io-parser@~3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA== dependencies: component-emitter "1.2.1" debug "~3.1.0" isarray "2.0.1" socket.io@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980" integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA== dependencies: debug "~3.1.0" engine.io "~3.2.0" has-binary2 "~1.0.2" socket.io-adapter "~1.1.0" socket.io-client "2.1.1" socket.io-parser "~3.2.0" socks-proxy-agent@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473" dependencies: agent-base "~4.2.0" socks "~2.2.0" socks@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9" dependencies: ip "^1.1.5" smart-buffer "^4.0.1" sort-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" dependencies: is-plain-obj "^1.0.0" source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" dependencies: atob "^2.1.1" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" dependencies: source-map "^0.5.6" source-map-support@^0.5.6: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" dependencies: buffer-from "^1.0.0" source-map "^0.6.0" source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" sourcemap-codec@^1.4.1: version "1.4.3" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.3.tgz#0ba615b73ec35112f63c2f2d9e7c3f87282b0e33" spdx-correct@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" spdx-expression-parse@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f" split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" dependencies: extend-shallow "^3.0.0" split2@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" dependencies: through2 "^2.0.2" split@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" dependencies: through "2" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: version "1.15.2" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.2.tgz#c946d6bd9b1a39d0e8635763f5242d6ed6dcb629" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" bcrypt-pbkdf "^1.0.0" dashdash "^1.12.0" ecc-jsbn "~0.1.1" getpass "^0.1.1" jsbn "~0.1.0" safer-buffer "^2.0.2" tweetnacl "~0.14.0" ssri@^6.0.0, ssri@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" dependencies: figgy-pudding "^3.5.1" stack-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" dependencies: define-property "^0.2.5" object-copy "^0.1.0" "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" integrity sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4= stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" stream-each@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" dependencies: end-of-stream "^1.1.0" stream-shift "^1.0.0" stream-shift@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" streamroller@0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-0.7.0.tgz#a1d1b7cf83d39afb0d63049a5acbf93493bdf64b" integrity sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ== dependencies: date-format "^1.2.0" debug "^3.1.0" mkdirp "^0.5.1" readable-stream "^2.3.0" string-length@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" dependencies: astral-regex "^1.0.0" strip-ansi "^4.0.0" string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" "string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" string_decoder@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== dependencies: safe-buffer "~5.1.0" string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" dependencies: safe-buffer "~5.1.0" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" dependencies: ansi-regex "^2.0.0" strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" dependencies: ansi-regex "^3.0.0" strip-bom@3.0.0, strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" dependencies: is-utf8 "^0.2.0" strip-eof@^1.0.0: version "1.0.0" resolved "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" dependencies: get-stdin "^4.0.1" strip-indent@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" strong-log-transformer@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.0.0.tgz#fa6d8e0a9e62b3c168c3cad5ae5d00dc97ba26cc" dependencies: byline "^5.0.0" duplexer "^0.1.1" minimist "^1.2.0" through "^2.3.4" supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" supports-color@^3.1.2: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: has-flag "^1.0.0" supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" dependencies: has-flag "^3.0.0" symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" table@^5.0.2: version "5.1.0" resolved "https://registry.yarnpkg.com/table/-/table-5.1.0.tgz#69a54644f6f01ad1628f8178715b408dc6bf11f7" dependencies: ajv "^6.5.3" lodash "^4.17.10" slice-ansi "1.0.0" string-width "^2.1.1" tar@^4: version "4.4.6" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" dependencies: chownr "^1.0.1" fs-minipass "^1.2.5" minipass "^2.3.3" minizlib "^1.1.0" mkdirp "^0.5.0" safe-buffer "^5.1.2" yallist "^3.0.2" tar@^4.4.8: version "4.4.10" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" minipass "^2.3.5" minizlib "^1.2.1" mkdirp "^0.5.0" safe-buffer "^5.1.2" yallist "^3.0.3" temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" temp-write@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-3.4.0.tgz#8cff630fb7e9da05f047c74ce4ce4d685457d492" dependencies: graceful-fs "^4.1.2" is-stream "^1.1.0" make-dir "^1.0.0" pify "^3.0.0" temp-dir "^1.0.0" uuid "^3.0.1" test-exclude@^4.2.1: version "4.2.3" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20" dependencies: arrify "^1.0.1" micromatch "^2.3.11" object-assign "^4.1.0" read-pkg-up "^1.0.1" require-main-filename "^1.0.1" text-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-2.0.0.tgz#43eabd1b495482fae4a2bf65e5f56c29f69220f6" integrity sha512-F91ZqLgvi1E0PdvmxMgp+gcf6q8fMH7mhdwWfzXnl1k+GbpQDmi8l7DzLC5JTASKbwpY3TfxajAUzAXcv2NmsQ== text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" through2@^2.0.0, through2@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" dependencies: readable-stream "^2.1.5" xtend "~4.0.1" through2@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== dependencies: readable-stream "2 || 3" through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: version "2.3.8" resolved "http://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" integrity sha1-ckGdSovn1s51FI/YsyTlk6cRwu0= dependencies: os-tmpdir "~1.0.1" tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" dependencies: os-tmpdir "~1.0.2" tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" to-array@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" dependencies: is-number "^3.0.0" repeat-string "^1.6.1" to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" regex-not "^1.0.2" safe-regex "^1.1.0" tough-cookie@>=2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" dependencies: psl "^1.1.24" punycode "^1.4.1" tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" dependencies: punycode "^2.1.0" trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" trim-newlines@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" trim-off-newlines@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" dependencies: prelude-ls "~1.1.2" type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== dependencies: media-typer "0.3.0" mime-types "~2.1.18" typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" uglify-js@^3.1.4, uglify-js@^3.4.9: version "3.4.9" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" dependencies: commander "~2.17.1" source-map "~0.6.1" uid-number@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== umask@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" unicode-match-property-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" dependencies: unicode-canonical-property-names-ecmascript "^1.0.4" unicode-property-aliases-ecmascript "^1.0.4" unicode-match-property-value-ecmascript@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4" unicode-property-aliases-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0" union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" dependencies: arr-union "^3.1.0" get-value "^2.0.6" is-extendable "^0.1.1" set-value "^0.4.3" unique-filename@^1.1.0, unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" dependencies: unique-slug "^2.0.0" unique-slug@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.1.tgz#5e9edc6d1ce8fb264db18a507ef9bd8544451ca6" dependencies: imurmurhash "^0.1.4" universal-user-agent@^2.0.0, universal-user-agent@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-2.1.0.tgz#5abfbcc036a1ba490cb941f8fd68c46d3669e8e4" integrity sha512-8itiX7G05Tu3mGDTdNY2fB4KJ8MgZLS54RdG6PkkfwMAavrXu1mV/lls/GABx9O3Rw4PnTtasxrvbMQoBYY92Q== dependencies: os-name "^3.0.0" universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" dependencies: has-value "^0.3.1" isobject "^3.0.0" upath@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" url-template@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" integrity sha1-/FZaPMy/93MMd19WQflVV5FDnyE= use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" useragent@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e" integrity sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4= dependencies: lru-cache "2.2.x" tmp "0.0.x" util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" util.promisify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" dependencies: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" dependencies: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" validate-npm-package-name@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" dependencies: builtins "^1.0.3" verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" vlq@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.0.tgz#8101be90843422954c2b13eb27f2f3122bdcc806" void-elements@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= w3c-hr-time@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" dependencies: browser-process-hrtime "^0.1.2" walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" dependencies: makeerror "1.0.x" watch@~0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" dependencies: exec-sh "^0.2.0" minimist "^1.2.0" wcwidth@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" dependencies: defaults "^1.0.3" webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" dependencies: iconv-lite "0.4.24" whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz#a3d58ef10b76009b042d03e25591ece89b88d171" whatwg-url@^6.4.1: version "6.5.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" dependencies: lodash.sortby "^4.7.0" tr46 "^1.0.1" webidl-conversions "^4.0.2" whatwg-url@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.0.0.tgz#fde926fa54a599f3adf82dff25a9f7be02dc6edd" dependencies: lodash.sortby "^4.7.0" tr46 "^1.0.1" webidl-conversions "^4.0.2" which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" which@1, which@^1.2.1, which@^1.2.12, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" dependencies: isexe "^2.0.0" wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" dependencies: string-width "^1.0.2 || 2" windows-release@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.2.0.tgz#8122dad5afc303d833422380680a79cdfa91785f" integrity sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA== dependencies: execa "^1.0.0" wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" wrap-ansi@^2.0.0: version "2.1.0" resolved "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" write-file-atomic@^2.0.0, write-file-atomic@^2.1.0, write-file-atomic@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" dependencies: graceful-fs "^4.1.11" imurmurhash "^0.1.4" signal-exit "^3.0.2" write-json-file@^2.2.0, write-json-file@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f" dependencies: detect-indent "^5.0.0" graceful-fs "^4.1.2" make-dir "^1.0.0" pify "^3.0.0" sort-keys "^2.0.0" write-file-atomic "^2.0.0" write-pkg@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-3.2.0.tgz#0e178fe97820d389a8928bc79535dbe68c2cff21" dependencies: sort-keys "^2.0.0" write-json-file "^2.2.0" write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" dependencies: mkdirp "^0.5.1" ws@^5.2.0: version "5.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" dependencies: async-limiter "~1.0.0" ws@~3.3.1: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" ultron "~1.1.0" xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" xml2js@^0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== dependencies: sax ">=0.6.0" xmlbuilder "~9.0.1" xmlbuilder@~9.0.1: version "9.0.7" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= xmlhttprequest-ssl@~1.5.4: version "1.5.5" resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= xregexp@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" yallist@^3.0.0, yallist@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" yallist@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== yargs-parser@^10.0.0, yargs-parser@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" dependencies: camelcase "^4.1.0" yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" dependencies: camelcase "^4.1.0" yargs@^11.0.0: version "11.1.0" resolved "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" dependencies: cliui "^4.0.0" decamelize "^1.1.1" find-up "^2.1.0" get-caller-file "^1.0.1" os-locale "^2.0.0" require-directory "^2.1.1" require-main-filename "^1.0.1" set-blocking "^2.0.0" string-width "^2.0.0" which-module "^2.0.0" y18n "^3.2.1" yargs-parser "^9.0.2" yargs@^12.0.1: version "12.0.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc" dependencies: cliui "^4.0.0" decamelize "^2.0.0" find-up "^3.0.0" get-caller-file "^1.0.1" os-locale "^3.0.0" require-directory "^2.1.1" require-main-filename "^1.0.1" set-blocking "^2.0.0" string-width "^2.0.0" which-module "^2.0.0" y18n "^3.2.1 || ^4.0.0" yargs-parser "^10.1.0" yeast@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= public/vendors/split/.prettierignore000064400000000027146725417150013713 0ustar00dist/ *.d.ts *.spec.js public/vendors/split/CONTRIBUTING.md000064400000002115146725417150013101 0ustar00# Contributing ## Developing The tooling is [Yarn](https://yarnpkg.com/), [Lerna](https://lerna.js.org/), [Prettier](https://prettier.io/) and [Eslint](https://eslint.org/). To get started: ```bash $ yarn install $ yarn run lerna link ``` It's easiest to have Prettier format your changes in your editor on save: https://prettier.io/docs/en/editors.html **Building** ```bash $ yarn run build ``` **Linting** ```bash $ yarn run lint ``` ## Testing ```bash $ yarn test ``` Each package has unit tests using Jest. `split.js` uses Jasmine 2.6 for browser testing with IE8 support. Karma is the test runner for headless browsers. Recent versions of Chrome and Firefox support headless testing locally. By default, both browsers are tested. If you want to test with just one or the other, run: ```bash $ yarn workspace split.js run test --browsers FirefoxHeadless ``` _or_ ```bash $ yarn workspace split.js run test --browsers ChromeHeadless ``` On the CI, [SauceLabs](https://saucelabs.com/) provides cross-platform testing. Headless Firefox and Chrome are also tested via Docker container. public/vendors/split/package.json000064400000002147146725417150013143 0ustar00{ "private": true, "workspaces": [ "packages/*" ], "scripts": { "build": "lerna run build", "test": "lerna run test", "lint": "lerna run lint", "saucelabs": "lerna run saucelabs" }, "version": "1.0.0", "main": "index.js", "license": "MIT", "devDependencies": { "@babel/core": "^7.1.2", "@babel/preset-env": "^7.1.0", "babel-core": "^7.0.0-bridge.0", "babel-jest": "^23.6.0", "eslint": "^5.8.0", "eslint-config-airbnb": "^17.1.0", "eslint-config-prettier": "^3.1.0", "eslint-plugin-import": "^2.14.0", "eslint-plugin-jsx-a11y": "^6.1.1", "eslint-plugin-react": "^7.11.0", "gzip-size-cli": "^3.0.0", "jasmine-core": "2.6.4", "jest": "^23.6.0", "karma": "^3.1.1", "karma-chrome-launcher": "^2.2.0", "karma-firefox-launcher": "^1.1.0", "karma-jasmine": "^1.1.2", "karma-sauce-launcher": "^2.0.2", "lerna": "^3.15.0", "prettier": "1.14.3", "react": "^16.6.1", "rollup": "^0.66.5", "rollup-plugin-buble": "^0.19.4", "rollup-plugin-node-resolve": "^3.4.0", "rollup-plugin-uglify": "^6.0.0" } } public/vendors/split/LICENSE000064400000002056146725417150011661 0ustar00MIT License Copyright (c) 2019 Nathan Cahill Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. public/vendors/split/docs/index.css000064400000023265146725417150013432 0ustar00/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}header,main,nav{display:block}[hidden]{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}strong{font-weight:inherit;font-weight:bolder}h1{font-size:2em;margin:.67em 0}img{border-style:none}code{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;overflow:visible}button,input{font:inherit;margin:0;overflow:visible}button{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}*{box-sizing:border-box}button,input{font-family:inherit;font-size:inherit;line-height:inherit}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.5;color:#24292e;background-color:#fff}a{color:#0366d6;text-decoration:none}a:active,a:hover{text-decoration:underline}strong{font-weight:600}hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border:0;border-bottom:1px solid #ddd}hr:after,hr:before{display:table;content:""}hr:after{clear:both}button{cursor:pointer}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:0}h1{font-size:32px}h1,h2{font-weight:600}h2{font-size:24px}h3{font-size:20px}h3,h4{font-weight:600}h4{font-size:16px}h5{font-size:14px}h5,h6{font-weight:600}h6{font-size:12px}p{margin-bottom:10px}p,ul{margin-top:0}ul{padding-left:0;margin-bottom:0}code{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:12px}.container{width:980px;margin-right:auto;margin-left:auto}.container:after,.container:before{display:table;content:""}.container:after{clear:both}.jumbotron{position:relative;padding-top:40px;padding-bottom:40px}@media (min-width:544px){.jumbotron{padding-top:60px;padding-bottom:60px}}@media (min-width:1280px){.jumbotron{padding-top:120px;padding-bottom:120px}}.btn{position:relative;display:inline-block;padding:6px 12px;font-size:14px;font-weight:600;line-height:20px;white-space:nowrap;vertical-align:middle;cursor:pointer;user-select:none;background-repeat:repeat-x;background-position:-1px -1px;background-size:110% 110%;border:1px solid rgba(27,31,35,.2);border-radius:.25em;appearance:none}.btn i{font-style:normal;font-weight:500;opacity:.6}.btn:hover{text-decoration:none;background-repeat:repeat-x}.btn:focus{outline:0}.btn:disabled{cursor:default;background-position:0 0}.btn{color:#24292e;background-color:#eff3f6;background-image:linear-gradient(-180deg,#fafbfc,#eff3f6 90%)}.btn:focus{box-shadow:0 0 0 .2em rgba(3,102,214,.3)}.btn:hover{background-color:#e6ebf1;background-image:linear-gradient(-180deg,#f0f3f6,#e6ebf1 90%);background-position:0 -.5em}.btn:active,.btn:hover{border-color:rgba(27,31,35,.35)}.btn:active{background-color:#e9ecef;background-image:none;box-shadow:inset 0 .15em .3em rgba(27,31,35,.15)}.btn:disabled{color:rgba(36,41,46,.4);background-color:#eff3f6;background-image:none;border-color:rgba(27,31,35,.2);box-shadow:none}.btn-outline{color:#0366d6;background-color:#fff;background-image:none}.btn-outline:active,.btn-outline:hover{color:#fff;background-color:#0366d6;background-image:none;border-color:#0366d6}.btn-outline:active .Counter,.btn-outline:hover .Counter{color:#0366d6;background-color:#fff}.btn-outline:focus{border-color:#0366d6;box-shadow:0 0 0 .2em rgba(3,102,214,.3)}.btn-outline:disabled{color:rgba(27,31,35,.3);background-color:#fff;border-color:rgba(0,0,0,.15);box-shadow:none}.btn-sm{padding:3px 10px;font-size:12px;line-height:20px}.btn-link{display:inline-block;padding:0;font-size:inherit;color:#0366d6;text-decoration:none;white-space:nowrap;cursor:pointer;user-select:none;background-color:transparent;border:0;appearance:none}.btn-link:hover{text-decoration:underline}.btn-link:disabled,.btn-link:disabled:hover{color:rgba(88,96,105,.5);cursor:default}.flash{position:relative;padding:16px;color:#032f62;background-color:#dbedff;border:1px solid rgba(27,31,35,.15);border-radius:3px}.flash p:last-child{margin-bottom:0}.flash-error{color:#86181d;background-color:#ffdce0}.flash-error,.flash-success{border-color:rgba(27,31,35,.15)}.flash-success{color:#165c26;background-color:#dcffe4}.form-control{min-height:34px;padding:6px 8px;font-size:14px;line-height:20px;color:#24292e;vertical-align:middle;background-color:#fff;background-repeat:no-repeat;background-position:right 8px center;border:1px solid #d1d5da;border-radius:3px;outline:none;box-shadow:inset 0 1px 2px rgba(27,31,35,.075)}.form-control:focus{border-color:#2188ff;outline:none;box-shadow:inset 0 1px 2px rgba(27,31,35,.075),0 0 0 .2em rgba(3,102,214,.3)}::placeholder{color:#6a737d}.input-sm{min-height:28px;padding-top:3px;padding-bottom:3px;font-size:12px;line-height:20px}input::-webkit-inner-spin-button,input::-webkit-outer-spin-button{margin:0;appearance:none}.form-group{margin:15px 0}.form-group .form-control{width:440px;max-width:100%;margin-right:5px;background-color:#fafbfc}.form-group .form-control:focus{background-color:#fff}.form-group .error,.form-group .success{display:none;font-size:12px;font-weight:600}.write-content{position:relative}.input-group{display:table}.input-group .form-control{position:relative;width:100%}.input-group .form-control:focus{z-index:1}.input-group .form-control+.btn{margin-left:0}.input-group-button,.input-group .form-control{display:table-cell}.input-group-button{width:1%;vertical-align:middle}.input-group-button:first-child .btn,.input-group .form-control:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-button:first-child .btn{margin-right:-1px}.input-group-button:last-child .btn,.input-group .form-control:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-button:last-child .btn{margin-left:-1px}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.top-0{top:0!important}.right-0{right:0!important}.left-0{left:0!important}.float-right{float:right!important}.float-left{float:left!important}@media (min-width:544px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}}.m-0{margin:0!important}.m-1{margin:4px!important}.m-2{margin:8px!important}.m-3{margin:16px!important}.m-4{margin:24px!important}.m-5{margin:32px!important}.m-6{margin:40px!important}@media (min-width:544px){.m-sm-0{margin:0!important}}@media (min-width:544px){.m-sm-1{margin:4px!important}}@media (min-width:544px){.m-sm-2{margin:8px!important}}@media (min-width:544px){.m-sm-3{margin:16px!important}}@media (min-width:544px){.m-sm-4{margin:24px!important}}@media (min-width:544px){.m-sm-5{margin:32px!important}}@media (min-width:544px){.m-sm-6{margin:40px!important}}.p-0{padding:0!important}.px-0{padding-left:0!important;padding-right:0!important}.p-1{padding:4px!important}.px-1{padding-left:4px!important;padding-right:4px!important}.p-2{padding:8px!important}.px-2{padding-left:8px!important;padding-right:8px!important}.p-3{padding:16px!important}.px-3{padding-left:16px!important;padding-right:16px!important}.p-4{padding:24px!important}.px-4{padding-left:24px!important;padding-right:24px!important}.p-5{padding:32px!important}.px-5{padding-left:32px!important;padding-right:32px!important}.p-6{padding:40px!important}.px-6{padding-left:40px!important;padding-right:40px!important}@media (min-width:544px){.p-sm-0{padding:0!important}.px-sm-0{padding-left:0!important;padding-right:0!important}}@media (min-width:544px){.p-sm-1{padding:4px!important}.px-sm-1{padding-left:4px!important;padding-right:4px!important}}@media (min-width:544px){.p-sm-2{padding:8px!important}.px-sm-2{padding-left:8px!important;padding-right:8px!important}}@media (min-width:544px){.p-sm-3{padding:16px!important}.px-sm-3{padding-left:16px!important;padding-right:16px!important}}@media (min-width:544px){.p-sm-4{padding:24px!important}.px-sm-4{padding-left:24px!important;padding-right:24px!important}}@media (min-width:544px){.p-sm-5{padding:32px!important}.px-sm-5{padding-left:32px!important;padding-right:32px!important}}@media (min-width:544px){.p-sm-6{padding:40px!important}.px-sm-6{padding-left:40px!important;padding-right:40px!important}}.h1{font-size:26px!important}@media (min-width:768px){.h1{font-size:32px!important}}.h2{font-size:22px!important}@media (min-width:768px){.h2{font-size:24px!important}}.h3{font-size:18px!important}@media (min-width:768px){.h3{font-size:20px!important}}.h4{font-size:16px!important}.h5{font-size:14px!important}.h6{font-size:12px!important}.h1,.h2,.h3,.h4,.h5,.h6{font-weight:600!important}.text-right{text-align:right!important}.text-left{text-align:left!important}@media (min-width:544px){.text-sm-right{text-align:right!important}.text-sm-left{text-align:left!important}}.avatar{display:inline-block;overflow:hidden;line-height:1;vertical-align:middle;border-radius:3px}.avatar-link{float:left;line-height:1}body{font-size:100%;line-height:1.6875em}ul{list-style:none}.ui-font{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif}.flash{display:none;margin-bottom:1em}public/vendors/split/docs/CNAME000064400000000015146725417150012343 0ustar00split.js.org public/vendors/split/docs/index.html000064400000046713146725417150013611 0ustar00 Split.js
Split.js is a 2kb unopinionated utility for resizeable split views (also called panes or frames). It handles weird edge cases so you don't have to. Split.js is CSS-driven, only using JS to recalculate CSS styles on drag. Split.js does not attach any window event listeners, instead relying on CSS for the layout when the window size changes. This keeps the JS overhead extremely low.

Get Started

Create a split view with an array of selectors or HTML elements. By default, Split.js modifies the CSS width property and nothing else. You are responsible for adding other CSS properties to create a layout. A simple way to place elements side-by-side is with a float rule. Other layout options besides width-float are possible (and encouraged), see the Advanced section below.

JS
Split(['#one', '#two']);
HTML
<div>
<div class="split" id="one"></div>
<div class="split" id="two"></div>
</div>
CSS
.split, .gutter.gutter-horizontal {
float: left;
}
.gutter.gutter-horizontal {
cursor: ew-resize;
}

Advanced

By overriding the default elementStyle and gutterStyle hooks, it's easy to change the CSS rules that Split.js modifies to support flex, grid and other CSS layouts:

JS
Split(['#one', '#two'], {
elementStyle: (dimension, size, gutterSize) => ({
'flex-basis': `calc(${size}% - ${gutterSize}px)`,
}),
gutterStyle: (dimension, gutterSize) => ({
'flex-basis': `${gutterSize}px`,
}),
})
HTML
<div class="flex">
<div id="one"></div>
<div id="two"></div>
</div>
CSS
.flex {
display: flex;
flex-direction: row;
}
.gutter.gutter-horizontal {
cursor: ew-resize;
}

React

Split.js is also available as a React component: react-split. The component accepts the same options as the Split.js constructor:

JS
import Split from 'react-split'
ReactDOM.render(
<Split sizes={[25, 75]}>
<Component />
<Component />
</Split>
)


Docs & API

Docs are available in README.md on GitHub.

public/vendors/split/docs/gist.css000064400000052334146725417150013270 0ustar00/*! * GitHub Light v0.3.0 * Copyright (c) 2012 - 2016 GitHub, Inc. * Licensed under MIT (https://github.com/primer/github-syntax-theme-generator/blob/master/LICENSE) */ .gist{font-size:16px;color:#333;text-align:left;direction:ltr}.gist .markdown-body{font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";font-size:16px;line-height:1.5;word-wrap:break-word}.gist .markdown-body::before{display:table;content:""}.gist .markdown-body::after{display:table;clear:both;content:""}.gist .markdown-body>*:first-child{margin-top:0 !important}.gist .markdown-body>*:last-child{margin-bottom:0 !important}.gist .markdown-body a:not([href]){color:inherit;text-decoration:none}.gist .markdown-body .absent{color:#cb2431}.gist .markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.gist .markdown-body .anchor:focus{outline:none}.gist .markdown-body p,.gist .markdown-body blockquote,.gist .markdown-body ul,.gist .markdown-body ol,.gist .markdown-body dl,.gist .markdown-body table,.gist .markdown-body pre{margin-top:0;margin-bottom:16px}.gist .markdown-body hr{height:0.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.gist .markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:0.25em solid #dfe2e5}.gist .markdown-body blockquote>:first-child{margin-top:0}.gist .markdown-body blockquote>:last-child{margin-bottom:0}.gist .markdown-body kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:solid 1px #c6cbd1;border-bottom-color:#959da5;border-radius:3px;box-shadow:inset 0 -1px 0 #959da5}.gist .markdown-body h1,.gist .markdown-body h2,.gist .markdown-body h3,.gist .markdown-body h4,.gist .markdown-body h5,.gist .markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.gist .markdown-body h1 .octicon-link,.gist .markdown-body h2 .octicon-link,.gist .markdown-body h3 .octicon-link,.gist .markdown-body h4 .octicon-link,.gist .markdown-body h5 .octicon-link,.gist .markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.gist .markdown-body h1:hover .anchor,.gist .markdown-body h2:hover .anchor,.gist .markdown-body h3:hover .anchor,.gist .markdown-body h4:hover .anchor,.gist .markdown-body h5:hover .anchor,.gist .markdown-body h6:hover .anchor{text-decoration:none}.gist .markdown-body h1:hover .anchor .octicon-link,.gist .markdown-body h2:hover .anchor .octicon-link,.gist .markdown-body h3:hover .anchor .octicon-link,.gist .markdown-body h4:hover .anchor .octicon-link,.gist .markdown-body h5:hover .anchor .octicon-link,.gist .markdown-body h6:hover .anchor .octicon-link{visibility:visible}.gist .markdown-body h1 tt,.gist .markdown-body h1 code,.gist .markdown-body h2 tt,.gist .markdown-body h2 code,.gist .markdown-body h3 tt,.gist .markdown-body h3 code,.gist .markdown-body h4 tt,.gist .markdown-body h4 code,.gist .markdown-body h5 tt,.gist .markdown-body h5 code,.gist .markdown-body h6 tt,.gist .markdown-body h6 code{font-size:inherit}.gist .markdown-body h1{padding-bottom:0.3em;font-size:2em;border-bottom:1px solid #eaecef}.gist .markdown-body h2{padding-bottom:0.3em;font-size:1.5em;border-bottom:1px solid #eaecef}.gist .markdown-body h3{font-size:1.25em}.gist .markdown-body h4{font-size:1em}.gist .markdown-body h5{font-size:0.875em}.gist .markdown-body h6{font-size:0.85em;color:#6a737d}.gist .markdown-body ul,.gist .markdown-body ol{padding-left:2em}.gist .markdown-body ul.no-list,.gist .markdown-body ol.no-list{padding:0;list-style-type:none}.gist .markdown-body ul ul,.gist .markdown-body ul ol,.gist .markdown-body ol ol,.gist .markdown-body ol ul{margin-top:0;margin-bottom:0}.gist .markdown-body li>p{margin-top:16px}.gist .markdown-body li+li{margin-top:0.25em}.gist .markdown-body dl{padding:0}.gist .markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.gist .markdown-body dl dd{padding:0 16px;margin-bottom:16px}.gist .markdown-body table{display:block;width:100%;overflow:auto}.gist .markdown-body table th{font-weight:600}.gist .markdown-body table th,.gist .markdown-body table td{padding:6px 13px;border:1px solid #dfe2e5}.gist .markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.gist .markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.gist .markdown-body table img{background-color:transparent}.gist .markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.gist .markdown-body img[align=right]{padding-left:20px}.gist .markdown-body img[align=left]{padding-right:20px}.gist .markdown-body .emoji{max-width:none;vertical-align:text-top;background-color:transparent}.gist .markdown-body span.frame{display:block;overflow:hidden}.gist .markdown-body span.frame>span{display:block;float:left;width:auto;padding:7px;margin:13px 0 0;overflow:hidden;border:1px solid #dfe2e5}.gist .markdown-body span.frame span img{display:block;float:left}.gist .markdown-body span.frame span span{display:block;padding:5px 0 0;clear:both;color:#24292e}.gist .markdown-body span.align-center{display:block;overflow:hidden;clear:both}.gist .markdown-body span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.gist .markdown-body span.align-center span img{margin:0 auto;text-align:center}.gist .markdown-body span.align-right{display:block;overflow:hidden;clear:both}.gist .markdown-body span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.gist .markdown-body span.align-right span img{margin:0;text-align:right}.gist .markdown-body span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.gist .markdown-body span.float-left span{margin:13px 0 0}.gist .markdown-body span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.gist .markdown-body span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.gist .markdown-body code,.gist .markdown-body tt{padding:0;padding-top:0.2em;padding-bottom:0.2em;margin:0;font-size:85%;background-color:rgba(27,31,35,0.05);border-radius:3px}.gist .markdown-body code::before,.gist .markdown-body code::after,.gist .markdown-body tt::before,.gist .markdown-body tt::after{letter-spacing:-0.2em;content:"\00a0"}.gist .markdown-body code br,.gist .markdown-body tt br{display:none}.gist .markdown-body del code{text-decoration:inherit}.gist .markdown-body pre{word-wrap:normal}.gist .markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.gist .markdown-body .highlight{margin-bottom:16px}.gist .markdown-body .highlight pre{margin-bottom:0;word-break:normal}.gist .markdown-body .highlight pre,.gist .markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.gist .markdown-body pre code,.gist .markdown-body pre tt{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.gist .markdown-body pre code::before,.gist .markdown-body pre code::after,.gist .markdown-body pre tt::before,.gist .markdown-body pre tt::after{content:normal}.gist .markdown-body .csv-data td,.gist .markdown-body .csv-data th{padding:5px;overflow:hidden;font-size:12px;line-height:1;text-align:left;white-space:nowrap}.gist .markdown-body .csv-data .blob-num{padding:10px 8px 9px;text-align:right;background:#fff;border:0}.gist .markdown-body .csv-data tr{border-top:0}.gist .markdown-body .csv-data th{font-weight:600;background:#f6f8fa;border-top:0}.gist .pl-c{color:#969896}.gist .pl-c1,.gist .pl-s .pl-v{color:#0086b3}.gist .pl-e,.gist .pl-en{color:#795da3}.gist .pl-smi,.gist .pl-s .pl-s1{color:#333}.gist .pl-ent{color:#63a35c}.gist .pl-k{color:#a71d5d}.gist .pl-s,.gist .pl-pds,.gist .pl-s .pl-pse .pl-s1,.gist .pl-sr,.gist .pl-sr .pl-cce,.gist .pl-sr .pl-sre,.gist .pl-sr .pl-sra{color:#183691}.gist .pl-v,.gist .pl-smw{color:#ed6a43}.gist .pl-bu{color:#b52a1d}.gist .pl-ii{color:#f8f8f8;background-color:#b52a1d}.gist .pl-c2{color:#f8f8f8;background-color:#b52a1d}.gist .pl-c2::before{content:"^M"}.gist .pl-sr .pl-cce{font-weight:bold;color:#63a35c}.gist .pl-ml{color:#693a17}.gist .pl-mh,.gist .pl-mh .pl-en,.gist .pl-ms{font-weight:bold;color:#1d3e81}.gist .pl-mq{color:#008080}.gist .pl-mi{font-style:italic;color:#333}.gist .pl-mb{font-weight:bold;color:#333}.gist .pl-md{color:#bd2c00;background-color:#ffecec}.gist .pl-mi1{color:#55a532;background-color:#eaffea}.gist .pl-mc{color:#ef9700;background-color:#ffe3b4}.gist .pl-mi2{color:#d8d8d8;background-color:#808080}.gist .pl-mdr{font-weight:bold;color:#795da3}.gist .pl-mo{color:#1d3e81}.gist .pl-ba{color:#595e62}.gist .pl-sg{color:#c0c0c0}.gist .pl-corl{text-decoration:underline;color:#183691}.gist .breadcrumb{margin-bottom:10px;font-size:18px;color:#586069}.gist .breadcrumb .separator::before,.gist .breadcrumb .separator::after{content:" "}.gist .breadcrumb strong.final-path{color:#24292e}.gist .breadcrumb .zeroclipboard-button{display:inline-block;margin-left:5px}.gist .breadcrumb .repo-root{font-weight:600}.gist .breadcrumb .octicon{vertical-align:-2px}.gist .editor-license-template,.gist .editor-code-of-conduct-template,.gist .editor-gitignore-template{position:relative;top:3px;display:none;float:right;font-size:14px}.gist .editor-license-template.is-visible,.gist .editor-code-of-conduct-template.is-visible,.gist .editor-gitignore-template.is-visible{display:block}.gist .editor-license-template .select-menu-git-ignore,.gist .editor-license-template .select-menu-license-picker,.gist .editor-code-of-conduct-template .select-menu-git-ignore,.gist .editor-code-of-conduct-template .select-menu-license-picker,.gist .editor-gitignore-template .select-menu-git-ignore,.gist .editor-gitignore-template .select-menu-license-picker{right:0}.gist .editor-abort{display:inline;font-size:14px}.gist .blob-interaction-bar{position:relative;background-color:#f2f2f2;border-bottom:1px solid #e5e5e5}.gist .blob-interaction-bar::before{display:table;content:""}.gist .blob-interaction-bar::after{display:table;clear:both;content:""}.gist .blob-interaction-bar .octicon-search{position:absolute;top:10px;left:10px;font-size:12px;color:#586069}.gist .blob-filter{width:100%;padding:4px 20px 5px 30px;font-size:12px;border:0;border-radius:0;outline:none}.gist .blob-filter:focus{outline:none}.gist .html-blob{margin-bottom:15px}.gist .license-summary-octicon{color:#959da5}.gist .rule-type-permissions{color:#28a745}.gist .rule-type-conditions{color:#0366d6}.gist .rule-type-limitations{color:#d73a49}.gist .blob-wrapper{overflow-x:auto;overflow-y:hidden;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.gist .diff-table{width:100%;border-collapse:separate}.gist .diff-table .line-comments{padding:10px;vertical-align:top;border-top:1px solid #e1e4e8}.gist .diff-table .line-comments:first-child+.empty-cell{border-left-width:1px}.gist .diff-table tr:not(:last-child) .line-comments{border-top:1px solid #e1e4e8;border-bottom:1px solid #e1e4e8}.gist .blob-num{width:1%;min-width:50px;padding-right:10px;padding-left:10px;font-family:"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;font-size:12px;line-height:20px;color:rgba(27,31,35,0.3);text-align:right;white-space:nowrap;vertical-align:top;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.gist .blob-num:hover{color:rgba(27,31,35,0.6)}.gist .blob-num::before{content:attr(data-line-number)}.gist .blob-num.non-expandable{cursor:default}.gist .blob-num.non-expandable:hover{color:rgba(27,31,35,0.3)}.gist .blob-code{position:relative;padding-right:10px;padding-left:10px;line-height:20px;vertical-align:top}.gist .blob-code-inner{overflow:visible;font-family:"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;font-size:12px;color:#24292e;word-wrap:normal;white-space:pre}.gist .blob-code-inner .x-first{border-top-left-radius:0.2em;border-bottom-left-radius:0.2em}.gist .blob-code-inner .x-last{border-top-right-radius:0.2em;border-bottom-right-radius:0.2em}.gist .blob-code-inner::before{content:""}.gist .soft-wrap .diff-table{table-layout:fixed}.gist .soft-wrap .blob-code{padding-left:18px;text-indent:-7px}.gist .soft-wrap .blob-code-inner{word-wrap:break-word;white-space:pre-wrap}.gist .soft-wrap .no-nl-marker{display:none}.gist .soft-wrap .add-line-comment{margin-left:-28px}.gist .blob-num-hunk,.gist .blob-code-hunk,.gist .blob-num-expandable,.gist .blob-code-expandable{color:rgba(27,31,35,0.3);vertical-align:middle}.gist .blob-num-hunk,.gist .blob-num-expandable{background-color:#e9f3ff}.gist .blob-code-hunk,.gist .blob-code-expandable{padding-top:4px;padding-bottom:4px;background-color:#f3f8ff;border-width:1px 0}.gist .blob-expanded .blob-num,.gist .blob-expanded .blob-code{background-color:#fafbfc}.gist .blob-expanded+tr:not(.blob-expanded) .blob-num,.gist .blob-expanded+tr:not(.blob-expanded) .blob-code{border-top:1px solid #eaecef}.gist .blob-expanded .blob-num-hunk{border-top:1px solid #eaecef}.gist tr:not(.blob-expanded)+.blob-expanded .blob-num,.gist tr:not(.blob-expanded)+.blob-expanded .blob-code{border-top:1px solid #eaecef}.gist .blob-num-expandable{padding:0;font-size:12px;text-align:center}.gist .blob-num-expandable .octicon{vertical-align:top}.gist .blob-num-expandable .diff-expander{display:block;width:auto;height:auto;padding:4px 11px 4px 10px;margin-right:-1px;color:#586069;cursor:pointer}.gist .blob-num-expandable .diff-expander:hover{color:#fff;text-shadow:none;background-color:#0366d6;border-color:#0366d6}.gist .blob-code-addition{background-color:#eaffea}.gist .blob-code-addition .x{color:#24292e;background-color:#a6f3a6}.gist .blob-num-addition{background-color:#dbffdb;border-color:#c1e9c1}.gist .blob-code-deletion{background-color:#ffecec}.gist .blob-code-deletion .x{color:#24292e;background-color:#f8cbcb}.gist .blob-num-deletion{background-color:#ffdddd;border-color:#f1c0c0}.gist .selected-line.blob-code{background-color:#f8eec7}.gist .selected-line.blob-code .x{background-color:transparent}.gist .selected-line.blob-num{background-color:#f6e8b5;border-color:#f0db88}.gist .add-line-comment{position:relative;z-index:5;float:left;width:22px;height:22px;margin:-2px -10px -2px -20px;line-height:21px;color:#fff;text-align:center;text-indent:0;cursor:pointer;background-color:#0366d6;background-image:-webkit-linear-gradient(#0372ef, #0366d6);background-image:linear-gradient(#0372ef, #0366d6);border-radius:3px;box-shadow:0 1px 4px rgba(27,31,35,0.15);opacity:0;-webkit-transition:-webkit-transform 0.1s ease-in-out;transition:transform 0.1s ease-in-out;-webkit-transform:scale(0.8, 0.8);transform:scale(0.8, 0.8)}.gist .add-line-comment:hover{-webkit-transform:scale(1, 1);transform:scale(1, 1)}.is-hovered .gist .add-line-comment,.gist .add-line-comment:focus{opacity:1}.gist .add-line-comment .octicon{vertical-align:text-top;pointer-events:none}.gist .add-line-comment.octicon-check{background:#333;opacity:1}.gist .inline-comment-form{border:1px solid #dfe2e5;border-radius:3px}.gist .inline-review-comment{margin-top:0 !important;margin-bottom:10px !important}.gist .inline-review-comment .gc:first-child+tr .blob-num,.gist .inline-review-comment .gc:first-child+tr .blob-code{padding-top:5px}.gist .inline-review-comment tr:last-child{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.gist .inline-review-comment tr:last-child .blob-num,.gist .inline-review-comment tr:last-child .blob-code{padding-bottom:8px}.gist .inline-review-comment tr:last-child .blob-num:first-child,.gist .inline-review-comment tr:last-child .blob-code:first-child{border-bottom-left-radius:2px}.gist .inline-review-comment tr:last-child .blob-num:last-child,.gist .inline-review-comment tr:last-child .blob-code:last-child{border-bottom-right-radius:2px}.gist .timeline-inline-comments{width:100%;table-layout:fixed}.gist .timeline-inline-comments .inline-comments,.gist .show-inline-notes .inline-comments{display:table-row}.gist .inline-comments{display:none}.gist .inline-comments.is-collapsed{display:none}.gist .inline-comments .line-comments.is-collapsed{visibility:hidden}.gist .inline-comments .line-comments+.blob-num{border-left-width:1px}.gist .inline-comments .timeline-comment{margin-bottom:10px}.gist .inline-comments .inline-comment-form,.gist .inline-comments .inline-comment-form-container{max-width:780px}.gist .comment-holder{max-width:780px}.gist .line-comments+.line-comments,.gist .empty-cell+.line-comments{border-left:1px solid #eaecef}.gist .inline-comment-form-container .inline-comment-form,.gist .inline-comment-form-container.open .inline-comment-form-actions{display:none}.gist .inline-comment-form-container .inline-comment-form-actions,.gist .inline-comment-form-container.open .inline-comment-form{display:block}.gist body.split-diff .container,.gist body.full-width .container{width:100%;padding-right:20px;padding-left:20px}.gist body.split-diff .repository-content,.gist body.full-width .repository-content{width:100%}.gist body.split-diff .new-pr-form,.gist body.full-width .new-pr-form{max-width:980px}.gist body.split-diff .new-pr-form .discussion-sidebar,.gist body.full-width .new-pr-form .discussion-sidebar{width:200px}.gist .file-diff-split{table-layout:fixed}.gist .file-diff-split .blob-code+.blob-num{border-left:1px solid #f6f8fa}.gist .file-diff-split .blob-code-inner{word-wrap:break-word;white-space:pre-wrap}.gist .file-diff-split .empty-cell{cursor:default;background-color:#fafbfc;border-right-color:#eaecef}.gist .submodule-diff-stats .octicon-diff-removed{color:#cb2431}.gist .submodule-diff-stats .octicon-diff-renamed{color:#677a85}.gist .submodule-diff-stats .octicon-diff-modified{color:#d0b44c}.gist .submodule-diff-stats .octicon-diff-added{color:#28a745}.gist .task-list-item{list-style-type:none}.gist .task-list-item label{font-weight:normal}.gist .task-list-item.enabled label{cursor:pointer}.gist .task-list-item+.task-list-item{margin-top:3px}.gist .task-list-item .handle{display:none}.gist .task-list-item-checkbox{margin:0 0.2em 0.25em -1.6em;vertical-align:middle}.gist .reorderable-task-lists .markdown-body .contains-task-list{padding:0}.gist .reorderable-task-lists .markdown-body li:not(.task-list-item){margin-left:26px}.gist .reorderable-task-lists .markdown-body ol:not(.contains-task-list) li,.gist .reorderable-task-lists .markdown-body ul:not(.contains-task-list) li{margin-left:0}.gist .reorderable-task-lists .markdown-body li p{margin-top:0}.gist .reorderable-task-lists .markdown-body .task-list-item{padding-right:15px;padding-left:42px;margin-right:-15px;margin-left:-15px;border:1px solid transparent}.gist .reorderable-task-lists .markdown-body .task-list-item+.task-list-item{margin-top:0}.gist .reorderable-task-lists .markdown-body .task-list-item .contains-task-list{padding-top:4px}.gist .reorderable-task-lists .markdown-body .task-list-item .handle{display:block;float:left;width:20px;padding:2px 0 0 2px;margin-left:-43px;opacity:0}.gist .reorderable-task-lists .markdown-body .task-list-item .drag-handle{fill:#333}.gist .reorderable-task-lists .markdown-body .task-list-item.hovered{background:#fafafa;border-top-color:#ededed;border-bottom-color:#ededed}.gist .reorderable-task-lists .markdown-body .task-list-item.hovered>.handle{opacity:1}.gist .reorderable-task-lists .markdown-body .task-list-item.is-dragging{opacity:0}.gist .reorderable-task-lists .markdown-body .task-list-item.is-ghost{border-right-color:#ededed;border-left-color:#ededed}.gist .review-comment-contents .markdown-body .task-list-item{padding-left:42px;margin-right:-12px;margin-left:-12px;border-top-left-radius:3px;border-bottom-left-radius:3px}.gist .review-comment-contents .markdown-body .task-list-item.hovered{border-left-color:#ededed}.gist .highlight{padding:0;margin:0;font-family:"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;font-size:12px;font-weight:normal;line-height:1.4;color:#333;background:#fff;border:0}.gist .render-viewer-error,.gist .render-viewer-fatal,.gist .render-viewer-invalid,.gist .octospinner{display:none}.gist iframe.render-viewer{width:100%;height:480px;overflow:hidden;border:0}.gist pre,.gist code{font-family:"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace !important;white-space:pre}.gist .gist-meta{padding:10px;overflow:hidden;font:12px -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";color:#586069;background-color:#f7f7f7;border-radius:0 0 2px 2px}.gist .gist-meta a{font-weight:600;color:#666;text-decoration:none;border:0}.gist .gist-data{overflow:auto;word-wrap:normal;background-color:#fff;border-bottom:1px solid #ddd;border-radius:2px 2px 0 0}.gist .gist-file{margin-bottom:1em;font-family:"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;border:1px solid #ddd;border-bottom:1px solid #ccc;border-radius:3px}.gist .gist-file article{padding:6px}.gist .gist-file .scroll .gist-data{position:absolute;top:0;right:0;bottom:30px;left:0;overflow:scroll}.gist .gist-file .scroll .gist-meta{position:absolute;right:0;bottom:0;left:0}.gist .blob-num{min-width:inherit;padding:1px 10px !important;background:transparent}.gist .blob-code{padding:1px 10px !important;text-align:left;background:transparent;border:0}.gist .blob-wrapper table{border-collapse:collapse}.gist .blob-wrapper tr:first-child td{padding-top:4px}.gist .markdown-body .anchor{display:none}public/vendors/split/docs/logo.svg000064400000006261146725417150013267 0ustar00public/vendors/split/docs/font.css000064400000014656146725417150013275 0ustar00html{font:100%/1.6875em Arvo,sans-serif;box-sizing:border-box;overflow-y:scroll;}*{box-sizing:inherit;}*:before{box-sizing:inherit;}*:after{box-sizing:inherit;}body{color:hsla(0,0%,0%,0.8);font-family:Arvo,sans-serif;font-weight:400;word-wrap:break-word;font-kerning:normal;-moz-font-feature-settings:"kern", "liga", "clig", "calt";-ms-font-feature-settings:"kern", "liga", "clig", "calt";-webkit-font-feature-settings:"kern", "liga", "clig", "calt";font-feature-settings:"kern", "liga", "clig", "calt";}img{max-width:100%;margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}h1{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;color:hsla(0,0%,0%,1);font-family:Montserrat,sans-serif;font-weight:700;text-rendering:optimizeLegibility;font-size:2rem;line-height:2.53125rem;}h2{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;color:hsla(0,0%,0%,1);font-family:Montserrat,sans-serif;font-weight:700;text-rendering:optimizeLegibility;font-size:1.51572rem;line-height:2.53125rem;}h3{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;color:hsla(0,0%,0%,1);font-family:Montserrat,sans-serif;font-weight:700;text-rendering:optimizeLegibility;font-size:1.31951rem;line-height:1.6875rem;}h4{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;color:hsla(0,0%,0%,1);font-family:Montserrat,sans-serif;font-weight:700;text-rendering:optimizeLegibility;font-size:1rem;line-height:1.6875rem;}h5{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;color:hsla(0,0%,0%,1);font-family:Montserrat,sans-serif;font-weight:700;text-rendering:optimizeLegibility;font-size:0.87055rem;line-height:1.6875rem;}h6{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;color:hsla(0,0%,0%,1);font-family:Montserrat,sans-serif;font-weight:700;text-rendering:optimizeLegibility;font-size:0.81225rem;line-height:1.6875rem;}hgroup{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}ul{margin-left:1.6875rem;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;list-style-position:outside;list-style-image:none;}ol{margin-left:1.6875rem;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;list-style-position:outside;list-style-image:none;}dl{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}dd{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}p{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}figure{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}pre{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;font-size:0.85rem;line-height:1.6875rem;}table{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;font-size:1rem;line-height:1.6875rem;border-collapse:collapse;width:100%;}fieldset{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}blockquote{margin-left:0;margin-right:1.6875rem;margin-top:0;padding-bottom:0;padding-left:1.37109rem;padding-right:0;padding-top:0;margin-bottom:1.6875rem;font-size:1.1487rem;line-height:1.6875rem;color:hsla(0,0%,0%,0.59);border-left:0.31641rem solid #fca206;}form{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}noscript{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}iframe{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}hr{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:calc(1.6875rem - 1px);background:hsla(0,0%,0%,0.2);border:none;height:1px;}address{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.6875rem;}b{font-weight:700;}strong{font-weight:700;}dt{font-weight:700;}th{font-weight:700;}li{margin-bottom:calc(1.6875rem / 2);}ol li{padding-left:0;}ul li{padding-left:0;}li > ol{margin-left:1.6875rem;margin-bottom:calc(1.6875rem / 2);margin-top:calc(1.6875rem / 2);}li > ul{margin-left:1.6875rem;margin-bottom:calc(1.6875rem / 2);margin-top:calc(1.6875rem / 2);}blockquote *:last-child{margin-bottom:0;}li *:last-child{margin-bottom:0;}p *:last-child{margin-bottom:0;}li > p{margin-bottom:calc(1.6875rem / 2);}code{font-size:0.85rem;line-height:1.6875rem;}kbd{font-size:0.85rem;line-height:1.6875rem;}samp{font-size:0.85rem;line-height:1.6875rem;}abbr{border-bottom:1px dotted hsla(0,0%,0%,0.5);cursor:help;}acronym{border-bottom:1px dotted hsla(0,0%,0%,0.5);cursor:help;}abbr[title]{border-bottom:1px dotted hsla(0,0%,0%,0.5);cursor:help;text-decoration:none;}thead{text-align:left;}td,th{text-align:left;border-bottom:1px solid hsla(0,0%,0%,0.12);font-feature-settings:tnum;-moz-font-feature-settings:tnum;-ms-font-feature-settings:tnum;-webkit-font-feature-settings:tnum;padding-left:1.125rem;padding-right:1.125rem;padding-top:0.84375rem;padding-bottom:calc(0.84375rem - 1px);}th:first-child,td:first-child{padding-left:0;}th:last-child,td:last-child{padding-right:0;}a{color:#d65947;text-decoration:none;}a:hover,a:active{color:hsla(0,0%,0%,0.8);}h1,h2,h3,h4,h5,h6{margin-top:3.375rem;}blockquote > :last-child{margin-bottom:0;}blockquote cite{font-size:1rem;line-height:1.6875rem;color:hsla(0,0%,0%,0.8);font-weight:400;}blockquote cite:before{content:"— ";}@media only screen and (max-width:480px){blockquote{margin-left:-1.26563rem;margin-right:0;padding-left:0.94922rem;}}public/vendors/split/docs/split.min.js000064400000013261146725417150014057 0ustar00/*! Split.js - v1.5.9 */ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Split=t()}(this,function(){"use strict";var B=window,L=B.document,T="addEventListener",N="removeEventListener",R="getBoundingClientRect",q="horizontal",H=function(){return!1},I=B.attachEvent&&!B[T],i=["","-webkit-","-moz-","-o-"].filter(function(e){var t=L.createElement("div");return t.style.cssText="width:"+e+"calc(9px)",!!t.style.length}).shift()+"calc",s=function(e){return"string"==typeof e||e instanceof String},W=function(e){if(s(e)){var t=L.querySelector(e);if(!t)throw new Error("Selector "+e+" did not match a DOM element");return t}return e},X=function(e,t,n){var r=e[t];return void 0!==r?r:n},Y=function(e,t,n,r){if(t){if("end"===r)return 0;if("center"===r)return e/2}else if(n){if("start"===r)return 0;if("center"===r)return e/2}return e},G=function(e,t){var n=L.createElement("div");return n.className="gutter gutter-"+t,n},J=function(e,t,n){var r={};return s(t)?r[e]=t:r[e]=I?t+"%":i+"("+t+"% - "+n+"px)",r},K=function(e,t){var n;return(n={})[e]=t+"px",n};return function(e,i){void 0===i&&(i={});var u,t,s,o,r,a,l=e;Array.from&&(l=Array.from(l));var c=W(l[0]).parentNode,f=getComputedStyle?getComputedStyle(c).flexDirection:null,m=X(i,"sizes")||l.map(function(){return 100/l.length}),n=X(i,"minSize",100),h=Array.isArray(n)?n:l.map(function(){return n}),d=X(i,"expandToMin",!1),g=X(i,"gutterSize",10),v=X(i,"gutterAlign","center"),p=X(i,"snapOffset",30),y=X(i,"dragInterval",1),z=X(i,"direction",q),S=X(i,"cursor",z===q?"col-resize":"row-resize"),b=X(i,"gutter",G),_=X(i,"elementStyle",J),E=X(i,"gutterStyle",K);function w(t,e,n,r){var i=_(u,e,n,r);Object.keys(i).forEach(function(e){t.style[e]=i[e]})}function k(){return a.map(function(e){return e.size})}function x(e){return"touches"in e?e.touches[0][t]:e[t]}function M(e){var t=a[this.a],n=a[this.b],r=t.size+n.size;t.size=e/this.size*r,n.size=r-e/this.size*r,w(t.element,t.size,this._b,t.i),w(n.element,n.size,this._c,n.i)}function U(){var e=a[this.a].element,t=a[this.b].element,n=e[R](),r=t[R]();this.size=n[u]+r[u]+this._b+this._c,this.start=n[s],this.end=n[o]}function O(s){var o=function(e){if(!getComputedStyle)return null;var t=getComputedStyle(e),n=e[r];return 0===n?null:n-=z===q?parseFloat(t.paddingLeft)+parseFloat(t.paddingRight):parseFloat(t.paddingTop)+parseFloat(t.paddingBottom)}(c);if(null===o)return s;var a=0,u=[],e=s.map(function(e,t){var n=o*e/100,r=Y(g,0===t,t===s.length-1,v),i=h[t]+r;return n=this.size-(r.minSize+p+this._c)&&(t=this.size-(r.minSize+this._c)),M.call(this,t),X(i,"onDrag",H)())}.bind(t),t.stop=function(){var e=this,t=a[e.a].element,n=a[e.b].element;e.dragging&&X(i,"onDragEnd",H)(k()),e.dragging=!1,B[N]("mouseup",e.stop),B[N]("touchend",e.stop),B[N]("touchcancel",e.stop),B[N]("mousemove",e.move),B[N]("touchmove",e.move),e.stop=null,e.move=null,t[N]("selectstart",H),t[N]("dragstart",H),n[N]("selectstart",H),n[N]("dragstart",H),t.style.userSelect="",t.style.webkitUserSelect="",t.style.MozUserSelect="",t.style.pointerEvents="",n.style.userSelect="",n.style.webkitUserSelect="",n.style.MozUserSelect="",n.style.pointerEvents="",e.gutter.style.cursor="",e.parent.style.cursor="",L.body.style.cursor=""}.bind(t),B[T]("mouseup",t.stop),B[T]("touchend",t.stop),B[T]("touchcancel",t.stop),B[T]("mousemove",t.move),B[T]("touchmove",t.move),n[T]("selectstart",H),n[T]("dragstart",H),r[T]("selectstart",H),r[T]("dragstart",H),n.style.userSelect="none",n.style.webkitUserSelect="none",n.style.MozUserSelect="none",n.style.pointerEvents="none",r.style.userSelect="none",r.style.webkitUserSelect="none",r.style.MozUserSelect="none",r.style.pointerEvents="none",t.gutter.style.cursor=S,t.parent.style.cursor=S,L.body.style.cursor=S,U.call(t),t.dragOffset=x(e)-t.end}}z===q?(u="width",t="clientX",s="left",o="right",r="clientWidth"):"vertical"===z&&(u="height",t="clientY",s="top",o="bottom",r="clientHeight"),m=O(m);var D=[];function A(e){var t=e.i===D.length,n=t?D[e.i-1]:D[e.i];U.call(n);var r=t?n.size-e.minSize-n._c:e.minSize+n._b;M.call(n,r)}function j(e){var s=O(e);s.forEach(function(e,t){if(0 Unopinionated utilities for resizeable split views. - **Zero Deps** - **Tiny:** Each is between 1-2kb gzipped. - **Fast:** No overhead or attached window event listeners, uses pure CSS for resizing. - **Unopinionated:** Only compute view sizes. Everything else is up to you. Two utilities: - **[Split.js](https://github.com/nathancahill/split/tree/master/packages/splitjs)** - The original library, works with `float` and `flex` layouts. Supports all browsers. - **[Split Grid](https://github.com/nathancahill/split/tree/master/packages/split-grid)** - Successor to Split.js, for `grid` layouts. Supports modern browsers. Two React wrappers: - **[React Split](https://github.com/nathancahill/split/tree/master/packages/react-split)** - Thin wrapper component for Split.js. - **[React Split Grid](https://github.com/nathancahill/split/tree/master/packages/react-split-grid)** - Thin wrapper component for Split Grid. ## Credits ### Contributors This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. ### Backers Thank you to all our backers! 🙠[[Become a backer](https://opencollective.com/splitjs#backer)] ### Sponsors Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/splitjs#sponsor)] [Sauce Labs](https://saucelabs.com) public/vendors/split/prettier.config.js000064400000000150146725417150014305 0ustar00module.exports = { trailingComma: "all", tabWidth: 4, semi: false, singleQuote: true }; public/vendors/horizontal.png000064400000000150146725417150012411 0ustar00‰PNG  IHDRhïιPLTEGpLÌÌÌòý¬tRNS@æØfIDATx^c8\Ÿy ÁÀz#`IEND®B`‚public/vendors/split.min.js000064400000013420146725417150011771 0ustar00/*! Split.js - v1.5.11 */ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Split=t()}(this,function(){"use strict";var L=window,T=L.document,N="addEventListener",R="removeEventListener",q="getBoundingClientRect",H="horizontal",I=function(){return!1},W=L.attachEvent&&!L[N],i=["","-webkit-","-moz-","-o-"].filter(function(e){var t=T.createElement("div");return t.style.cssText="width:"+e+"calc(9px)",!!t.style.length}).shift()+"calc",s=function(e){return"string"==typeof e||e instanceof String},X=function(e){if(s(e)){var t=T.querySelector(e);if(!t)throw new Error("Selector "+e+" did not match a DOM element");return t}return e},Y=function(e,t,n){var r=e[t];return void 0!==r?r:n},G=function(e,t,n,r){if(t){if("end"===r)return 0;if("center"===r)return e/2}else if(n){if("start"===r)return 0;if("center"===r)return e/2}return e},J=function(e,t){var n=T.createElement("div");return n.className="gutter gutter-"+t,n},K=function(e,t,n){var r={};return s(t)?r[e]=t:r[e]=W?t+"%":i+"("+t+"% - "+n+"px)",r},P=function(e,t){var n;return(n={})[e]=t+"px",n};return function(e,i){void 0===i&&(i={});var u,t,s,o,r,a,l=e;Array.from&&(l=Array.from(l));var c=X(l[0]).parentNode,n=getComputedStyle?getComputedStyle(c):null,f=n?n.flexDirection:null,m=Y(i,"sizes")||l.map(function(){return 100/l.length}),h=Y(i,"minSize",100),d=Array.isArray(h)?h:l.map(function(){return h}),g=Y(i,"expandToMin",!1),v=Y(i,"gutterSize",10),p=Y(i,"gutterAlign","center"),y=Y(i,"snapOffset",30),z=Y(i,"dragInterval",1),S=Y(i,"direction",H),b=Y(i,"cursor",S===H?"col-resize":"row-resize"),_=Y(i,"gutter",J),E=Y(i,"elementStyle",K),w=Y(i,"gutterStyle",P);function k(t,e,n,r){var i=E(u,e,n,r);Object.keys(i).forEach(function(e){t.style[e]=i[e]})}function x(){return a.map(function(e){return e.size})}function M(e){return"touches"in e?e.touches[0][t]:e[t]}function U(e){var t=a[this.a],n=a[this.b],r=t.size+n.size;t.size=e/this.size*r,n.size=r-e/this.size*r,k(t.element,t.size,this._b,t.i),k(n.element,n.size,this._c,n.i)}function O(){var e=a[this.a].element,t=a[this.b].element,n=e[q](),r=t[q]();this.size=n[u]+r[u]+this._b+this._c,this.start=n[s],this.end=n[o]}function C(s){var o=function(e){if(!getComputedStyle)return null;var t=getComputedStyle(e);if(!t)return null;var n=e[r];return 0===n?null:n-=S===H?parseFloat(t.paddingLeft)+parseFloat(t.paddingRight):parseFloat(t.paddingTop)+parseFloat(t.paddingBottom)}(c);if(null===o)return s;if(d.reduce(function(e,t){return e+t},0)>o)return s;var a=0,u=[],e=s.map(function(e,t){var n=o*e/100,r=G(v,0===t,t===s.length-1,p),i=d[t]+r;return n=this.size-(r.minSize+y+this._c)&&(t=this.size-(r.minSize+this._c)),U.call(this,t),Y(i,"onDrag",I)())}.bind(t),t.stop=function(){var e=this,t=a[e.a].element,n=a[e.b].element;e.dragging&&Y(i,"onDragEnd",I)(x()),e.dragging=!1,L[R]("mouseup",e.stop),L[R]("touchend",e.stop),L[R]("touchcancel",e.stop),L[R]("mousemove",e.move),L[R]("touchmove",e.move),e.stop=null,e.move=null,t[R]("selectstart",I),t[R]("dragstart",I),n[R]("selectstart",I),n[R]("dragstart",I),t.style.userSelect="",t.style.webkitUserSelect="",t.style.MozUserSelect="",t.style.pointerEvents="",n.style.userSelect="",n.style.webkitUserSelect="",n.style.MozUserSelect="",n.style.pointerEvents="",e.gutter.style.cursor="",e.parent.style.cursor="",T.body.style.cursor=""}.bind(t),L[N]("mouseup",t.stop),L[N]("touchend",t.stop),L[N]("touchcancel",t.stop),L[N]("mousemove",t.move),L[N]("touchmove",t.move),n[N]("selectstart",I),n[N]("dragstart",I),r[N]("selectstart",I),r[N]("dragstart",I),n.style.userSelect="none",n.style.webkitUserSelect="none",n.style.MozUserSelect="none",n.style.pointerEvents="none",r.style.userSelect="none",r.style.webkitUserSelect="none",r.style.MozUserSelect="none",r.style.pointerEvents="none",t.gutter.style.cursor=b,t.parent.style.cursor=b,T.body.style.cursor=b,O.call(t),t.dragOffset=M(e)-t.end}}S===H?(u="width",t="clientX",s="left",o="right",r="clientWidth"):"vertical"===S&&(u="height",t="clientY",s="top",o="bottom",r="clientHeight"),m=C(m);var A=[];function j(e){var t=e.i===A.length,n=t?A[e.i-1]:A[e.i];O.call(n);var r=t?n.size-e.minSize-n._c:e.minSize+n._b;U.call(n,r)}function F(e){var s=C(e);s.forEach(function(e,t){if(0 public/class-cf7-customizer-public.php000064400000062645146725417150014024 0ustar00 */ class Cf7_Customizer_Public { /** * The ID of this plugin. * * @since 1.0.0 * @access private * @var string $plugin_name The ID of this plugin. */ private $plugin_name; /** * The version of this plugin. * * @since 1.0.0 * @access private * @var string $version The current version of this plugin. */ private $version; /** * Initialize the class and set its properties. * * @since 1.0.0 * @param string $plugin_name The name of the plugin. * @param string $version The version of this plugin. */ public function __construct( $plugin_name, $version ) { $this->plugin_name = $plugin_name; $this->version = $version; } /** * Register the stylesheets for the public-facing side of the site. * * @since 1.0.0 */ public function enqueue_styles() { /** * This function is provided for demonstration purposes only. * * An instance of this class should be passed to the run() function * defined in Cf7_Customizer_Loader as all of the hooks are defined * in that particular class. * * The Cf7_Customizer_Loader will then create the relationship * between the defined hooks and the functions defined in this * class. */ wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/cf7-customizer-public.css', array(), $this->version . time(), 'all' ); $permalink_structure = get_option('permalink_structure'); if (!empty($permalink_structure)) { $form_id = get_query_var( 'cf7cstmzr-form' ); } else { if (!empty($_GET['cf7cstmzr_page']) && !empty($_GET['form_id'])) { $form_id = $_GET['form_id']; } } $plugin_version = Cf7_License::get_license_version(); if ($form_id) { // Backend testing $style_scheme_slug = !empty($_GET['style_scheme']) ? sanitize_text_field($_GET['style_scheme']) : 'default'; $style_schemes = get_option('cf7cstmzr_style_schemes', array()); $is_styled = get_option('cf7cstmzr-preview-styled', true); $preview_mode = get_option('cf7cstmzr-preview-mode', false); if (!empty($preview_mode)) { if ('unstyled' === $preview_mode) { $is_styled = false; } elseif ('current-style' === $preview_mode) { $is_styled = true; } else { $is_styled = true; } } if ($is_styled) { if ('split-mode' === $preview_mode) { $temp_styles = get_option('cf7cstmzr_style_schemes_preview', false); $live_style = get_post_meta( $form_id, 'cf7cstmzr_style_scheme', true ); if (empty($live_style) && 'free' !== $plugin_version) { $live_style = get_option('cf7cstmzr_enabled_globally', false); } if (!empty($live_style)) { $live_styles = array( 'preview' => array( 'title' => 'preview', 'scheme' => $style_schemes[$live_style]['scheme'], ), ); } else { $live_styles = array( 'preview' => array( 'title' => 'preview', 'scheme' => array(), ), ); } } elseif ('current-style' === $preview_mode) { $temp_styles = get_option('cf7cstmzr_style_schemes_preview', false); } else { $temp_style = get_post_meta( $form_id, 'cf7cstmzr_style_scheme', true ); if (empty($temp_style) && 'free' !== $plugin_version) { $temp_style = get_option('cf7cstmzr_enabled_globally', false); } if (!empty($temp_style)) { $temp_styles = array( 'preview' => array( 'title' => 'preview', 'scheme' => $style_schemes[$temp_style]['scheme'], ), ); } else { $temp_styles = array( 'preview' => array( 'title' => 'preview', 'scheme' => array(), ), ); } } if (!empty($live_styles)) { if (!empty($live_styles['preview']['scheme'])) { if ('free' === $plugin_version && 'current-style' !== $preview_mode) { if (!empty($live_styles['preview']["scheme"]["form"]["bg"]["img"])) $live_styles['preview']["scheme"]["form"]["bg"]["img"] = ''; if (!empty($live_styles['preview']["scheme"]["form"]["bg"]["img-position"])) $live_styles['preview']["scheme"]["form"]["bg"]["img-position"] = ''; if (!empty($live_styles['preview']["scheme"]["form"]["bg"]["img-opacity"])) $live_styles['preview']["scheme"]["form"]["bg"]["img-opacity"] = ''; if (!empty($live_styles['preview']["scheme"]["form"]["bg"]["img-size"])) $live_styles['preview']["scheme"]["form"]["bg"]["img-size"] = ''; if (!empty($live_styles['preview']["scheme"]["checkbox"]["full-width"])) $live_styles['preview']["scheme"]["checkbox"]["full-width"] = ''; if (!empty($live_styles['preview']["scheme"]["radiobutton"]["full-width"])) $live_styles['preview']["scheme"]["radiobutton"]["full-width"] = ''; } $live_custom_css = Cf7_Style_Scheme::get_inline_style_scheme($live_styles, 'preview', array(), array(), '.live-style '); } else { $live_custom_css = ''; } } if (!empty($temp_styles)) { if (!empty($temp_styles['preview']['scheme'])) { if ('free' === $plugin_version && ('current-style' !== $preview_mode && 'split-mode' !== $preview_mode)) { if (!empty($temp_styles['preview']["scheme"]["form"]["bg"]["img"])) $temp_styles['preview']["scheme"]["form"]["bg"]["img"] = ''; if (!empty($temp_styles['preview']["scheme"]["form"]["bg"]["img-position"])) $temp_styles['preview']["scheme"]["form"]["bg"]["img-position"] = ''; if (!empty($temp_styles['preview']["scheme"]["form"]["bg"]["img-opacity"])) $temp_styles['preview']["scheme"]["form"]["bg"]["img-opacity"] = ''; if (!empty($temp_styles['preview']["scheme"]["form"]["bg"]["img-size"])) $temp_styles['preview']["scheme"]["form"]["bg"]["img-size"] = ''; if (!empty($temp_styles['preview']["scheme"]["checkbox"]["full-width"])) $temp_styles['preview']["scheme"]["checkbox"]["full-width"] = ''; if (!empty($temp_styles['preview']["scheme"]["radiobutton"]["full-width"])) $temp_styles['preview']["scheme"]["radiobutton"]["full-width"] = ''; } if ('split-mode' === $preview_mode) { $custom_css = Cf7_Style_Scheme::get_inline_style_scheme($temp_styles, 'preview', array(), array(), '.current-style '); } else { $custom_css = Cf7_Style_Scheme::get_inline_style_scheme($temp_styles, 'preview', array(), array()); } } else { $custom_css = ''; } } else { if ('free' === $plugin_version) { if (!empty($style_schemes[$style_scheme_slug]["scheme"]["form"]["bg"]["img"])) $style_schemes[$style_scheme_slug]["scheme"]["form"]["bg"]["img"] = ''; if (!empty($style_schemes[$style_scheme_slug]["scheme"]["form"]["bg"]["img-position"])) $style_schemes[$style_scheme_slug]["scheme"]["form"]["bg"]["img-position"] = ''; if (!empty($style_schemes[$style_scheme_slug]["scheme"]["form"]["bg"]["img-opacity"])) $style_schemes[$style_scheme_slug]["scheme"]["form"]["bg"]["img-opacity"] = ''; if (!empty($style_schemes[$style_scheme_slug]["scheme"]["form"]["bg"]["img-size"])) $style_schemes[$style_scheme_slug]["scheme"]["form"]["bg"]["img-size"] = ''; if (!empty($style_schemes[$style_scheme_slug]["scheme"]["checkbox"]["full-width"])) $style_schemes[$style_scheme_slug]["scheme"]["checkbox"]["full-width"] = ''; if (!empty($style_schemes[$style_scheme_slug]["scheme"]["radiobutton"]["full-width"])) $style_schemes[$style_scheme_slug]["scheme"]["radiobutton"]["full-width"] = ''; } $custom_css = Cf7_Style_Scheme::get_inline_style_scheme($style_schemes, $style_scheme_slug); } wp_add_inline_style( $this->plugin_name, $custom_css ); if (!empty($live_custom_css)) { wp_add_inline_style( $this->plugin_name, $live_custom_css ); } } // delete_option('cf7cstmzr_style_schemes_preview'); } else { // Frontend use $is_body_tag = false; if ('free' !== $plugin_version) { $is_body_tag = get_option('cf7cstmzr-load-body-tag', false); } if (empty($is_body_tag)) { $enabled_globally = false; $enabled_globally_option = get_option('cf7cstmzr_enabled_globally', false); if (!empty($enabled_globally_option)) { $enabled_globally = 'default'; if ('free' !== $plugin_version) { $enabled_globally = $enabled_globally_option; } } $globally_styled_forms = Cf7_Style_Scheme::get_globally_styled_forms(); $individually_styled_forms = Cf7_Style_Scheme::get_individually_styled_forms(); $style_schemes = get_option('cf7cstmzr_style_schemes', array()); if ($enabled_globally && 'free' !== $plugin_version) { if ('free' === $plugin_version) { if (!empty($style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img"])) $style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-position"])) $style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-position"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-opacity"])) $style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-opacity"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-size"])) $style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-size"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["checkbox"]["full-width"])) $style_schemes[$enabled_globally]["scheme"]["checkbox"]["full-width"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["radiobutton"]["full-width"])) $style_schemes[$enabled_globally]["scheme"]["radiobutton"]["full-width"] = ''; } $custom_css = Cf7_Style_Scheme::get_inline_style_scheme($style_schemes, $enabled_globally, array_keys($globally_styled_forms)); wp_add_inline_style( $this->plugin_name, $custom_css ); } // if ('free' !== $plugin_version && !empty($individually_styled_forms)) { if (!empty($individually_styled_forms)) { foreach ($individually_styled_forms as $form_id => $individually_style) { if ('free' === $plugin_version) { if (!empty($style_schemes[$individually_style]["scheme"]["form"]["bg"]["img"])) $style_schemes[$individually_style]["scheme"]["form"]["bg"]["img"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-position"])) $style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-position"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-opacity"])) $style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-opacity"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-size"])) $style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-size"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["checkbox"]["full-width"])) $style_schemes[$individually_style]["scheme"]["checkbox"]["full-width"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["radiobutton"]["full-width"])) $style_schemes[$individually_style]["scheme"]["radiobutton"]["full-width"] = ''; } $custom_css = Cf7_Style_Scheme::get_inline_style_scheme($style_schemes, $individually_style, array($form_id)); wp_add_inline_style( $this->plugin_name, $custom_css ); } } } } } /** * Register the JavaScript for the public-facing side of the site. * * @since 1.0.0 */ public function enqueue_scripts() { $permalink_structure = get_option('permalink_structure'); if (!empty($permalink_structure)) { $form_id = get_query_var( 'cf7cstmzr-form' ); } else { if (!empty($_GET['cf7cstmzr_page']) && !empty($_GET['form_id'])) { $form_id = $_GET['form_id']; } } if ($form_id) { wp_enqueue_script('cf7cstmzr-split', plugin_dir_url( __FILE__ ) . 'vendors/split.min.js', array('jquery'), '1.5.11'); } wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/cf7-customizer-public.js', array( 'jquery' ), $this->version . time(), true ); wp_localize_script( $this->plugin_name, 'cf7cstmzrJsObj', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), )); } public function add_wrapper($output, $tag, $attr, $m) { if ('contact-form-7' === $tag) { $permalink_structure = get_option('permalink_structure'); if (!empty($permalink_structure)) { $form_id = get_query_var( 'cf7cstmzr-form' ); } else { if (!empty($_GET['cf7cstmzr_page']) && !empty($_GET['form_id'])) { $form_id = $_GET['form_id']; } } $plugin_version = Cf7_License::get_license_version(); $output_before = ''; $is_body_tag = false; $is_form_exists = !empty($attr["id"]) ? get_post($attr["id"]) : null; if ('free' !== $plugin_version) { $is_body_tag = get_option('cf7cstmzr-load-body-tag', false); } if ($form_id) { } else { global $post; if ('free' !== $plugin_version) { $is_page_body_tag = get_post_meta( $post->ID, 'cf7cstmzr-load-body-tag', true ); if (!empty($is_page_body_tag)) { $is_body_tag = $is_page_body_tag; } } if ('free' !== $plugin_version && current_user_can('administrator') && (is_single() || is_page())) { wp_enqueue_style( 'dashicons' ); $frontend_control_action = did_action('cf7cstmzr_frontend_control'); ob_start(); if (1 > $frontend_control_action && $is_form_exists) { do_action('cf7cstmzr_frontend_control'); ?>
$num_action) { do_action('cf7cstmzr_load_body_tag'); $enabled_globally = false; $enabled_globally_option = get_option('cf7cstmzr_enabled_globally', false); if (!empty($enabled_globally_option)) { $enabled_globally = 'default'; if ('free' !== $plugin_version) { $enabled_globally = $enabled_globally_option; } } $globally_styled_forms = Cf7_Style_Scheme::get_globally_styled_forms(); $individually_styled_forms = Cf7_Style_Scheme::get_individually_styled_forms(); $style_schemes = get_option('cf7cstmzr_style_schemes', array()); if ($enabled_globally && 'free' !== $plugin_version) { if ('free' === $plugin_version) { if (!empty($style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img"])) $style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-position"])) $style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-position"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-opacity"])) $style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-opacity"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-size"])) $style_schemes[$enabled_globally]["scheme"]["form"]["bg"]["img-size"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["checkbox"]["full-width"])) $style_schemes[$enabled_globally]["scheme"]["checkbox"]["full-width"] = ''; if (!empty($style_schemes[$enabled_globally]["scheme"]["radiobutton"]["full-width"])) $style_schemes[$enabled_globally]["scheme"]["radiobutton"]["full-width"] = ''; } $custom_css = ''; $output_before .= $custom_css; } // if ('free' !== $plugin_version && !empty($individually_styled_forms)) { if (!empty($individually_styled_forms)) { foreach ($individually_styled_forms as $form_id => $individually_style) { if ('free' === $plugin_version) { if (!empty($style_schemes[$individually_style]["scheme"]["form"]["bg"]["img"])) $style_schemes[$individually_style]["scheme"]["form"]["bg"]["img"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-position"])) $style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-position"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-opacity"])) $style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-opacity"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-size"])) $style_schemes[$individually_style]["scheme"]["form"]["bg"]["img-size"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["checkbox"]["full-width"])) $style_schemes[$individually_style]["scheme"]["checkbox"]["full-width"] = ''; if (!empty($style_schemes[$individually_style]["scheme"]["radiobutton"]["full-width"])) $style_schemes[$individually_style]["scheme"]["radiobutton"]["full-width"] = ''; } $custom_css = ''; $output_before .= $custom_css; } } } } } $output_after = ''; if ($is_form_exists) { $output_before .= '
'; $output_after .= '
'; } $output = $output_before . $output . $output_after; } return $output; } public function save_frontend_settings() { $loadBodyTag = !empty($_POST['loadBodyTag']) ? sanitize_text_field($_POST['loadBodyTag']) : false; $postId = !empty($_POST['postId']) ? sanitize_text_field($_POST['postId']) : false; if (empty($postId)) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('You can not use this settings on this page type', 'cf7-styler')); echo json_encode($response); wp_die(); } if ($loadBodyTag && 'true' === $loadBodyTag) { update_post_meta( $postId, 'cf7cstmzr-load-body-tag', 1 ); } else { delete_post_meta( $postId, 'cf7cstmzr-load-body-tag' ); } $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . __('Saved', 'cf7-styler')); echo json_encode($response); wp_die(); } } LICENSE.txt000064400000043253146725417150006412 0ustar00 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License.includes/lib/Cf7_Required_Plugin.php000064400000007152146725417150013447 0ustar00 array( 'label' => 'Contact Form 7', 'link' => 'https://wordpress.org/plugins/contact-form-7/', 'zip_path' => 'https://downloads.wordpress.org/plugin/contact-form-7.5.1.4.zip', 'slug' => 'contact-form-7/wp-contact-form-7.php', 'author' => __('By Takayuki Miyoshi', 'cf7-styler'), 'description' => '' ), ); if( !function_exists('is_plugin_active') ) { include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); } foreach ($required_plugins as $slug => $data) { if (is_plugin_active($data['slug'])) { unset($required_plugins[$slug]); } } return $required_plugins; } public static function is_plugin_installed( $plugin_slug ) { if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $all_plugins = get_plugins(); if ( !empty( $all_plugins[$plugin_slug] ) ) { return true; } else { return false; } } public static function install_plugin( $plugin_zip ) { include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; wp_cache_flush(); $upgrader = new Plugin_Upgrader(new Cf7_Quiet_Skin()); $installed = $upgrader->install( $plugin_zip ); return $installed; } public static function upgrade_plugin( $plugin_slug ) { include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; wp_cache_flush(); $upgrader = new Plugin_Upgrader(new Cf7_Quiet_Skin()); $upgraded = $upgrader->upgrade( $plugin_slug ); return $upgraded; } public static function is_plugin_newest_version($plugin_slug) { $current = get_site_transient( 'update_plugins' ); if ( ! isset( $current->response[ $plugin_slug ] ) ) { return true; } return false; } public static function install_and_activate_plugin($plugin) { $required_plugins = self::get_required_plugins(); $plugin_data = $required_plugins[$plugin]; $plugin_zip = $plugin_data['zip_path']; $plugin_slug = $plugin_data['slug']; if (!self::is_plugin_installed($plugin_slug)) { $installed = self::install_plugin($plugin_zip); if (!is_wp_error( $installed ) && $installed) { self::upgrade_plugin( $plugin_slug ); $installed = true; } } elseif(self::is_plugin_newest_version($plugin_slug)) { $installed = true; } else { self::upgrade_plugin( $plugin_slug ); $installed = true; } if ( !is_wp_error( $installed ) && $installed ) { $activate = activate_plugin( $plugin_slug ); if ( is_null($activate) ) { return true; } else { return false; } } else { return false; } } } if (!class_exists('WP_Upgrader_Skin')) { include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php'; } if(version_compare(get_bloginfo('version'),'5.3', '>=') ) { class Cf7_Quiet_Skin extends WP_Upgrader_Skin { public function feedback($string, ...$args) {} } } else { class Cf7_Quiet_Skin extends WP_Upgrader_Skin { public function feedback($string) {} } } includes/lib/Cf7_Style_Scheme.php000064400000160420146725417150012733 0ustar00 __('Default Scheme', 'cf7-styler'), 'scheme' => array( 'form' => array( 'padding' => array( 'top' => '20', 'right' => '20', 'bottom' => '20', 'left' => '20', ), 'margin' => array( 'top' => '15', 'bottom' => '15', ), 'border' => array( 'width' => array( 'top' => '1', 'right' => '1', 'bottom' => '1', 'left' => '5', ), 'radius' => '10', 'color' => '#1e73be', ), ), 'input' => array( 'full-width' => 'yes', 'text' => array( 'line-height' => '1.6' ), 'bg' => array( 'color' => '#ffffff' ), 'padding' => array( 'top' => '5', 'right' => '10', 'bottom' => '5', 'left' => '10', ), 'border' => array( 'width' => array( 'top' => '1', 'right' => '1', 'bottom' => '1', 'left' => '3', ), 'radius' => '5', 'color' => '#1e73be', ), ), 'button' => array( 'text' => array( 'color' => '#ffffff', 'color-hover' => '#1e73be', 'line-height' => '1.6', ), 'bg' => array( 'color' => '#1e73be', 'color-hover' => '#ffffff', ), 'padding' => 5, 'border' => array( 'width' => '2', 'radius' => '10', 'color' => '#1e73be', 'color-hover' => '#1e73be', ), 'shadow' => array( 'opacity' => '0.5', 'vertical-length' => '5', 'blur-radius' => '5', 'spread-radius' => '-5', 'color' => '#000000', 'position' => 'outline', ) ), ), ); } public static function normalize_style_sheme($style_schemes, $slug) { $style_scheme_settings = !empty($style_schemes[$slug]['scheme']) ? $style_schemes[$slug]['scheme'] : array(); $style_scheme = array(); // General Form Styles $style_scheme['form_text_color'] = !empty($style_scheme_settings["form"]["text"]["color"]) ? $style_scheme_settings["form"]["text"]["color"] : ''; $style_scheme['form_text_label_color'] = !empty($style_scheme_settings["form"]["text"]["label-color"]) ? $style_scheme_settings["form"]["text"]["label-color"] : ''; $style_scheme['form_text_link_color'] = !empty($style_scheme_settings["form"]["text"]["link-color"]) ? $style_scheme_settings["form"]["text"]["link-color"] : ''; $style_scheme['form_text_link_hover_color'] = !empty($style_scheme_settings["form"]["text"]["link-hover-color"]) ? $style_scheme_settings["form"]["text"]["link-hover-color"] : ''; $style_scheme['form_text_font_family'] = !empty($style_scheme_settings["form"]["text"]["font-family"]) ? $style_scheme_settings["form"]["text"]["font-family"] : ''; $style_scheme['form_bg_color'] = !empty($style_scheme_settings["form"]["bg"]["color"]) ? $style_scheme_settings["form"]["bg"]["color"]: ''; $style_scheme['form_bg_img'] = !empty($style_scheme_settings["form"]["bg"]["img"]) ? $style_scheme_settings["form"]["bg"]["img"] : ''; $style_scheme['form_bg_img_opacity'] = !empty($style_scheme_settings["form"]["bg"]["img-opacity"]) ? $style_scheme_settings["form"]["bg"]["img-opacity"] : ''; $style_scheme['form_bg_img_size'] = !empty($style_scheme_settings["form"]["bg"]["img-size"]) ? $style_scheme_settings["form"]["bg"]["img-size"] : ''; $style_scheme['form_bg_img_position'] = !empty($style_scheme_settings["form"]["bg"]["img-position"]) ? $style_scheme_settings["form"]["bg"]["img-position"] : ''; $style_scheme['form_text_size'] = !empty($style_scheme_settings["form"]["text"]["size"]) ? $style_scheme_settings["form"]["text"]["size"] : ''; $style_scheme['form_text_label_size'] = !empty($style_scheme_settings["form"]["text"]["label-size"]) ? $style_scheme_settings["form"]["text"]["label-size"] : ''; $style_scheme['form_text_label_weight'] = !empty($style_scheme_settings["form"]["text"]["label-weight"]) ? $style_scheme_settings["form"]["text"]["label-weight"] : ''; $style_scheme['form_text_label_style'] = !empty($style_scheme_settings["form"]["text"]["label-style"]) ? $style_scheme_settings["form"]["text"]["label-style"] : ''; $style_scheme['form_padding'] = !empty($style_scheme_settings["form"]["padding"]) && !is_array($style_scheme_settings["form"]["padding"]) ? $style_scheme_settings["form"]["padding"] : ''; $style_scheme['form_padding_top'] = !empty($style_scheme_settings["form"]["padding"]['top']) ? $style_scheme_settings["form"]["padding"]['top'] : ''; $style_scheme['form_padding_right'] = !empty($style_scheme_settings["form"]["padding"]['right']) ? $style_scheme_settings["form"]["padding"]['right'] : ''; $style_scheme['form_padding_bottom'] = !empty($style_scheme_settings["form"]["padding"]['bottom']) ? $style_scheme_settings["form"]["padding"]['bottom'] : ''; $style_scheme['form_padding_left'] = !empty($style_scheme_settings["form"]["padding"]['left']) ? $style_scheme_settings["form"]["padding"]['left'] : ''; $style_scheme['form_margin'] = !empty($style_scheme_settings["form"]["margin"]) && !is_array($style_scheme_settings["form"]["margin"]) ? $style_scheme_settings["form"]["margin"] : ''; $style_scheme['form_margin_top'] = !empty($style_scheme_settings["form"]["margin"]['top']) ? $style_scheme_settings["form"]["margin"]['top'] : ''; $style_scheme['form_margin_right'] = !empty($style_scheme_settings["form"]["margin"]['right']) ? $style_scheme_settings["form"]["margin"]['right'] : ''; $style_scheme['form_margin_bottom'] = !empty($style_scheme_settings["form"]["margin"]['bottom']) ? $style_scheme_settings["form"]["margin"]['bottom'] : ''; $style_scheme['form_margin_left'] = !empty($style_scheme_settings["form"]["margin"]['left']) ? $style_scheme_settings["form"]["margin"]['left'] : ''; $style_scheme['form_border_width'] = !empty($style_scheme_settings["form"]["border"]["width"]) && !is_array($style_scheme_settings["form"]["border"]["width"]) ? $style_scheme_settings["form"]["border"]["width"] : ''; $style_scheme['form_border_width_top'] = !empty($style_scheme_settings["form"]["border"]["width"]['top']) ? $style_scheme_settings["form"]["border"]["width"]['top'] : ''; $style_scheme['form_border_width_right'] = !empty($style_scheme_settings["form"]["border"]["width"]['right']) ? $style_scheme_settings["form"]["border"]["width"]['right'] : ''; $style_scheme['form_border_width_bottom'] = !empty($style_scheme_settings["form"]["border"]["width"]['bottom']) ? $style_scheme_settings["form"]["border"]["width"]['bottom'] : ''; $style_scheme['form_border_width_left'] = !empty($style_scheme_settings["form"]["border"]["width"]['left']) ? $style_scheme_settings["form"]["border"]["width"]['left'] : ''; $style_scheme['form_border_type'] = !empty($style_scheme_settings["form"]["border"]["type"]) ? $style_scheme_settings["form"]["border"]["type"] : ''; $style_scheme['form_border_radius'] = !empty($style_scheme_settings["form"]["border"]["radius"]) ? $style_scheme_settings["form"]["border"]["radius"] : ''; $style_scheme['form_border_color'] = !empty($style_scheme_settings["form"]["border"]["color"]) ? $style_scheme_settings["form"]["border"]["color"] : ''; $style_scheme['form_border_shadow_horizontal_length'] = !empty($style_scheme_settings["form"]["shadow"]["horizontal-length"]) ? $style_scheme_settings["form"]["shadow"]["horizontal-length"] : ''; $style_scheme['form_border_shadow_vertical_length'] = !empty($style_scheme_settings["form"]["shadow"]["vertical-length"]) ? $style_scheme_settings["form"]["shadow"]["vertical-length"] : ''; $style_scheme['form_border_shadow_blur_radius'] = !empty($style_scheme_settings["form"]["shadow"]["blur-radius"]) ? $style_scheme_settings["form"]["shadow"]["blur-radius"] : ''; $style_scheme['form_border_shadow_spread_radius'] = !empty($style_scheme_settings["form"]["shadow"]["spread-radius"]) ? $style_scheme_settings["form"]["shadow"]["spread-radius"] : ''; $style_scheme['form_border_shadow_color'] = !empty($style_scheme_settings["form"]["shadow"]["color"]) ? $style_scheme_settings["form"]["shadow"]["color"] : ''; $style_scheme['form_border_shadow_opacity'] = !empty($style_scheme_settings["form"]["shadow"]["opacity"]) ? $style_scheme_settings["form"]["shadow"]["opacity"] : ''; $style_scheme['form_border_shadow_position'] = !empty($style_scheme_settings["form"]["shadow"]["position"]) ? $style_scheme_settings["form"]["shadow"]["position"] : ''; $style_scheme['input_full_width'] = !empty($style_scheme_settings["input"]["full-width"]) ? $style_scheme_settings["input"]["full-width"] : ''; $style_scheme['input_text_color'] = !empty($style_scheme_settings["input"]["text"]["color"]) ? $style_scheme_settings["input"]["text"]["color"] : ''; $style_scheme['input_bg_color'] = !empty($style_scheme_settings["input"]["bg"]["color"]) ? $style_scheme_settings["input"]["bg"]["color"] : ''; $style_scheme['input_bg_color_opacity'] = !empty($style_scheme_settings["input"]["bg"]["color-opacity"]) ? $style_scheme_settings["input"]["bg"]["color-opacity"] : ''; $style_scheme['input_padding'] = !empty($style_scheme_settings["input"]["padding"]) && !is_array($style_scheme_settings["input"]["padding"]) ? $style_scheme_settings["input"]["padding"] : ''; $style_scheme['input_padding_top'] = !empty($style_scheme_settings["input"]["padding"]['top']) ? $style_scheme_settings["input"]["padding"]['top'] : ''; $style_scheme['input_padding_right'] = !empty($style_scheme_settings["input"]["padding"]['right']) ? $style_scheme_settings["input"]["padding"]['right'] : ''; $style_scheme['input_padding_bottom'] = !empty($style_scheme_settings["input"]["padding"]['bottom']) ? $style_scheme_settings["input"]["padding"]['bottom'] : ''; $style_scheme['input_padding_left'] = !empty($style_scheme_settings["input"]["padding"]['left']) ? $style_scheme_settings["input"]["padding"]['left'] : ''; $style_scheme['input_margin'] = !empty($style_scheme_settings["input"]["margin"]) && !is_array($style_scheme_settings["input"]["margin"]) ? $style_scheme_settings["input"]["margin"] : ''; $style_scheme['input_margin_top'] = !empty($style_scheme_settings["input"]["margin"]['top']) ? $style_scheme_settings["input"]["margin"]['top'] : ''; $style_scheme['input_margin_right'] = !empty($style_scheme_settings["input"]["margin"]['right']) ? $style_scheme_settings["input"]["margin"]['right'] : ''; $style_scheme['input_margin_bottom'] = !empty($style_scheme_settings["input"]["margin"]['bottom']) ? $style_scheme_settings["input"]["margin"]['bottom'] : ''; $style_scheme['input_margin_left'] = !empty($style_scheme_settings["input"]["margin"]['left']) ? $style_scheme_settings["input"]["margin"]['left'] : ''; $style_scheme['input_border_width'] = !empty($style_scheme_settings["input"]["border"]["width"]) && !is_array($style_scheme_settings["input"]["border"]["width"]) ? $style_scheme_settings["input"]["border"]["width"] : ''; $style_scheme['input_border_width_top'] = !empty($style_scheme_settings["input"]["border"]["width"]['top']) ? $style_scheme_settings["input"]["border"]["width"]['top'] : ''; $style_scheme['input_border_width_right'] = !empty($style_scheme_settings["input"]["border"]["width"]['right']) ? $style_scheme_settings["input"]["border"]["width"]['right'] : ''; $style_scheme['input_border_width_bottom'] = !empty($style_scheme_settings["input"]["border"]["width"]['bottom']) ? $style_scheme_settings["input"]["border"]["width"]['bottom'] : ''; $style_scheme['input_border_width_left'] = !empty($style_scheme_settings["input"]["border"]["width"]['left']) ? $style_scheme_settings["input"]["border"]["width"]['left'] : ''; $style_scheme['input_text_size'] = !empty($style_scheme_settings["input"]["text"]["size"]) ? $style_scheme_settings["input"]["text"]["size"] : ''; $style_scheme['input_text_line_height'] = !empty($style_scheme_settings["input"]["text"]["line-height"]) ? $style_scheme_settings["input"]["text"]["line-height"] : ''; $style_scheme['input_border_radius'] = !empty($style_scheme_settings["input"]["border"]["radius"]) ? $style_scheme_settings["input"]["border"]["radius"] : ''; $style_scheme['input_border_color'] = !empty($style_scheme_settings["input"]["border"]["color"]) ? $style_scheme_settings["input"]["border"]["color"] : ''; $style_scheme['input_border_shadow_horizontal_length'] = !empty($style_scheme_settings["input"]["shadow"]["horizontal-length"]) ? $style_scheme_settings["input"]["shadow"]["horizontal-length"] : ''; $style_scheme['input_border_shadow_vertical_length'] = !empty($style_scheme_settings["input"]["shadow"]["vertical-length"]) ? $style_scheme_settings["input"]["shadow"]["vertical-length"] : ''; $style_scheme['input_border_shadow_blur_radius'] = !empty($style_scheme_settings["input"]["shadow"]["blur-radius"]) ? $style_scheme_settings["input"]["shadow"]["blur-radius"] : ''; $style_scheme['input_border_shadow_spread_radius'] = !empty($style_scheme_settings["input"]["shadow"]["spread-radius"]) ? $style_scheme_settings["input"]["shadow"]["spread-radius"] : ''; $style_scheme['input_border_shadow_color'] = !empty($style_scheme_settings["input"]["shadow"]["color"]) ? $style_scheme_settings["input"]["shadow"]["color"] : ''; $style_scheme['input_border_shadow_opacity'] = !empty($style_scheme_settings["input"]["shadow"]["opacity"]) ? $style_scheme_settings["input"]["shadow"]["opacity"] : ''; $style_scheme['input_border_shadow_position'] = !empty($style_scheme_settings["input"]["shadow"]["position"]) ? $style_scheme_settings["input"]["shadow"]["position"] : ''; $style_scheme['checkbox_full_width'] = !empty($style_scheme_settings["checkbox"]["full-width"]) ? $style_scheme_settings["checkbox"]["full-width"] : ''; $style_scheme['radiobutton_full_width'] = !empty($style_scheme_settings["radiobutton"]["full-width"]) ? $style_scheme_settings["radiobutton"]["full-width"] : ''; $style_scheme['checkbox_text_label_size'] = !empty($style_scheme_settings["checkbox"]["text"]["label-size"]) ? $style_scheme_settings["checkbox"]["text"]["label-size"] : ''; $style_scheme['button_full_width'] = !empty($style_scheme_settings["button"]["full-width"]) ? $style_scheme_settings["button"]["full-width"] : ''; $style_scheme['button_text_color'] = !empty($style_scheme_settings["button"]["text"]["color"]) ? $style_scheme_settings["button"]["text"]["color"] : ''; $style_scheme['button_bg_color'] = !empty($style_scheme_settings["button"]["bg"]["color"]) ? $style_scheme_settings["button"]["bg"]["color"] : ''; $style_scheme['button_text_color_hover'] = !empty($style_scheme_settings["button"]["text"]["color-hover"]) ? $style_scheme_settings["button"]["text"]["color-hover"] : ''; $style_scheme['button_bg_color_hover'] = !empty($style_scheme_settings["button"]["bg"]["color-hover"]) ? $style_scheme_settings["button"]["bg"]["color-hover"] : ''; $style_scheme['button_text_size'] = !empty($style_scheme_settings["button"]["text"]["size"]) ? $style_scheme_settings["button"]["text"]["size"] : ''; $style_scheme['button_text_line_height'] = !empty($style_scheme_settings["button"]["text"]["line-height"]) ? $style_scheme_settings["button"]["text"]["line-height"] : ''; $style_scheme['button_padding'] = !empty($style_scheme_settings["button"]["padding"]) ? $style_scheme_settings["button"]["padding"] : ''; $style_scheme['button_border_width'] = !empty($style_scheme_settings["button"]["border"]["width"]) ? $style_scheme_settings["button"]["border"]["width"] : ''; $style_scheme['button_border_radius'] = !empty($style_scheme_settings["button"]["border"]["radius"]) ? $style_scheme_settings["button"]["border"]["radius"] : ''; $style_scheme['button_border_color'] = !empty($style_scheme_settings["button"]["border"]["color"]) ? $style_scheme_settings["button"]["border"]["color"] : ''; $style_scheme['button_border_color_hover'] = !empty($style_scheme_settings["button"]["border"]["color-hover"]) ? $style_scheme_settings["button"]["border"]["color-hover"] : ''; $style_scheme['button_border_shadow_horizontal_length'] = !empty($style_scheme_settings["button"]["shadow"]["horizontal-length"]) ? $style_scheme_settings["button"]["shadow"]["horizontal-length"] : ''; $style_scheme['button_border_shadow_vertical_length'] = !empty($style_scheme_settings["button"]["shadow"]["vertical-length"]) ? $style_scheme_settings["button"]["shadow"]["vertical-length"] : ''; $style_scheme['button_border_shadow_blur_radius'] = !empty($style_scheme_settings["button"]["shadow"]["blur-radius"]) ? $style_scheme_settings["button"]["shadow"]["blur-radius"] : ''; $style_scheme['button_border_shadow_spread_radius'] = !empty($style_scheme_settings["button"]["shadow"]["spread-radius"]) ? $style_scheme_settings["button"]["shadow"]["spread-radius"] : ''; $style_scheme['button_border_shadow_color'] = !empty($style_scheme_settings["button"]["shadow"]["color"]) ? $style_scheme_settings["button"]["shadow"]["color"] : ''; $style_scheme['button_border_shadow_opacity'] = !empty($style_scheme_settings["button"]["shadow"]["opacity"]) ? $style_scheme_settings["button"]["shadow"]["opacity"] : ''; $style_scheme['button_border_shadow_position'] = !empty($style_scheme_settings["button"]["shadow"]["position"]) ? $style_scheme_settings["button"]["shadow"]["position"] : ''; $style_scheme['custom_css'] = !empty($style_scheme_settings["custom"]["css"]) ? $style_scheme_settings["custom"]["css"] : ''; return $style_scheme; } public static function get_inline_style_scheme($style_schemes, $slug, $form_id = array(), $form_excluded = array(), $form_prefix = '') { $style_scheme = self::normalize_style_sheme($style_schemes, $slug); $web_safe_fonts = Cf7_Style_Scheme::get_web_safe_fonts(); $form_class = ''; // if (!empty($form_id)) { // $form_class = '.cf7cstmzr-form-' . $form_id; // } $wrappers = array(); if (!empty($form_excluded)) { foreach ($form_excluded as $form_excluded_id => $form_excluded_style) { $wrappers[] = $form_prefix . '#cf7cstmzr-form:not(.cf7cstmzr-form-'.$form_excluded_id.') '; } } elseif (!empty($form_id)) { foreach ($form_id as $item) { $wrappers[] = $form_prefix . '#cf7cstmzr-form.cf7cstmzr-form-'.$item.' '; } } else { $wrappers[] = $form_prefix . '#cf7cstmzr-form '; } ob_start(); ?> ', '', $style); $style = str_replace('', '', $style); return $style; } public static function form_preview($id) { ?>
-1, 'orderby' => 'title', 'order' => 'ASC', 'post_type' => 'wpcf7_contact_form', 'post_status' => 'publish', 'suppress_filters' => false, // подавление работы фильтров Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ SQL запроÑа 'meta_query' => array( 'relation' => 'EXISTS', array( 'key' => 'cf7cstmzr_style_scheme', ) ) ); return get_posts($cf7_scheme_args); } public static function get_forms_group_by_style_scheme() { $style_schemes = get_option('cf7cstmzr_style_schemes', array()); $forms_group_by_style_scheme = array(); $forms_with_style_schemes = self::get_forms_with_style_schemes(); if (!empty($forms_with_style_schemes)) { foreach ($forms_with_style_schemes as $form) { $cf7cstmzr_style_scheme = get_post_meta( $form->ID, 'cf7cstmzr_style_scheme', true ); if (empty($style_schemes[$cf7cstmzr_style_scheme])) { delete_post_meta( $form->ID, 'cf7cstmzr_style_scheme' ); } else { if (!empty($cf7cstmzr_style_scheme)) { $forms_group_by_style_scheme[$cf7cstmzr_style_scheme][] = $form->ID; } } } } return $forms_group_by_style_scheme; } public static function get_web_safe_fonts() { return array( 'georgia' => array ( 'Georgia', 'Georgia, serif' ), 'palatino' => array ( 'Palatino Linotype', '"Palatino Linotype", "Book Antiqua", Palatino, serif' ), 'times' => array ( 'Times New Roman', '"Times New Roman", Times, serif' ), 'arial' => array ( 'Arial', 'Arial, Helvetica, sans-serif' ), 'tahoma' => array ( 'Tahoma', 'Tahoma, Geneva, sans-serif' ), 'verdana' => array ( 'Verdana', 'Verdana, Geneva, sans-serif' ), ); } public static function show_shadow_css_rules($horizontal_length, $vertical_length, $blur_radius, $spread_radius, $opacity, $color, $position) { $default_horizontal_length = 0; $default_vertical_length = 0; $default_blur_radius = 0; $default_spread_radius = 0; $default_opacity = 0; $default_color = '#000000'; $default_position = ''; if (!empty($horizontal_length)) $default_horizontal_length = $horizontal_length; if (!empty($vertical_length)) $default_vertical_length = $vertical_length; if (!empty($blur_radius)) $default_blur_radius = $blur_radius; if (!empty($spread_radius)) $default_spread_radius = $spread_radius; if (!empty($opacity)) $default_opacity = $opacity; if (!empty($position) && 'inset' === $position) $default_position = 'inset '; if (!empty($color)) { $default_color = $color; } else { $default_opacity = 0; } list($r, $g, $b) = sscanf($default_color, "#%02x%02x%02x"); $default_color = $r.','.$g.','.$b.','; $rules = array ( '-webkit-box-shadow', '-moz-box-shadow', 'box-shadow', ); foreach ($rules as $rule) { ?> : px px px px rgba(); -1, 'orderby' => 'title', 'order' => 'ASC', 'post_type' => 'wpcf7_contact_form', 'post_status' => 'publish', 'suppress_filters' => false, // подавление работы фильтров Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ SQL запроÑа 'meta_query' => array( 'relation' => 'EXISTS', array( 'key' => 'cf7cstmzr_style_scheme', ) ) ); $cf7_forms = get_posts($args); if (!empty($cf7_forms)) { foreach ($cf7_forms as $cf_7_form) { $cf7cstmzr_style_scheme = get_post_meta( $cf_7_form->ID, 'cf7cstmzr_style_scheme', true ); $forms[$cf_7_form->ID] = $cf7cstmzr_style_scheme; } } } else { $args = array ( 'numberposts' => -1, 'orderby' => 'title', 'order' => 'ASC', 'post_type' => 'wpcf7_contact_form', 'post_status' => 'publish', 'suppress_filters' => false, // подавление работы фильтров Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ SQL запроÑа 'meta_query' => array( 'relation' => 'EXISTS', array( 'key' => 'cf7cstmzr_style_scheme', ) ) ); $cf7_forms = get_posts($args); if (!empty($cf7_forms)) { $i = 1; $styled_scheme = false; foreach ($cf7_forms as $cf_7_form) { if (!$styled_scheme) { $cf7cstmzr_style_scheme = get_post_meta( $cf_7_form->ID, 'cf7cstmzr_style_scheme', true ); if ('default' !== $cf7cstmzr_style_scheme) { delete_post_meta( $cf_7_form->ID, 'cf7cstmzr_style_scheme' ); } else { $forms[$cf_7_form->ID] = $cf7cstmzr_style_scheme; $styled_scheme = true; } } else { delete_post_meta( $cf_7_form->ID, 'cf7cstmzr_style_scheme' ); } } } } return $forms; } public static function get_globally_styled_forms() { $forms = array(); $args = array ( 'numberposts' => -1, 'orderby' => 'title', 'order' => 'ASC', 'post_type' => 'wpcf7_contact_form', 'post_status' => 'publish', 'suppress_filters' => false, // подавление работы фильтров Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ SQL запроÑа ); $cf7_forms = get_posts($args); if (!empty($cf7_forms)) { foreach ($cf7_forms as $cf_7_form) { $forms[$cf_7_form->ID] = 'default'; } } if (!empty($forms)) { $individual_forms = self::get_individually_styled_forms(); if (!empty($individual_forms)) { foreach ($individual_forms as $individual_form_id => $individual_form_style) { unset($forms[$individual_form_id]); } } } return $forms; } public static function style_selectors($selectors, $wrappers) { $selectors_wrapper = array(); foreach ($selectors as $selector) { foreach ($wrappers as $wrapper) { $selectors_wrapper[] = $wrapper . $selector; } } echo implode( ',' . PHP_EOL, $selectors_wrapper ); } }includes/lib/Cf7_Template.php000064400000012565146725417150012130 0ustar00

__('Inherit', 'cf7-styler'), 'solid' => __('Solid', 'cf7-styler'), 'dotted' => __('Dotted', 'cf7-styler'), 'dashed' => __('Dashed', 'cf7-styler'), 'double' => __('Double', 'cf7-styler'), 'groove' => __('Groove', 'cf7-styler'), 'ridge' => __('Ridge', 'cf7-styler'), 'inset' => __('Inset', 'cf7-styler'), 'outset' => __('Outset', 'cf7-styler'), ); } }includes/lib/Cf7_License.php000064400000001617146725417150011733 0ustar00is_paying_or_trial(); if ($is_paying) { return 'pro'; } if (cf7_styler()->is_paying__fs__()) { return 'pro'; } if (cf7_styler()->is_trial()) { return 'pro'; } } if ( !cf7cstmzr_is_plugin_activated( 'wp2leads', 'wp2leads.php' ) ) { return 'free'; } $wp2l_license = get_option('wp2l_license'); $wp2l_license_version = !empty($wp2l_license['version']) ? $wp2l_license['version'] : 'free'; return $wp2l_license_version; } public static function is_wp2leads_installed() { return cf7cstmzr_is_plugin_activated( 'wp2leads', 'wp2leads.php' ); } }includes/functions.php000064400000003430146725417150011107 0ustar00 */ class Cf7_Customizer_i18n { /** * Load the plugin text domain for translation. * * @since 1.0.0 */ public function load_plugin_textdomain() { add_filter( 'plugin_locale', 'Cf7_Customizer_i18n::check_de_locale'); load_plugin_textdomain( 'cf7-styler', false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/' ); remove_filter( 'plugin_locale', 'Cf7_Customizer_i18n::check_de_locale'); } public static function check_de_locale($domain) { $site_lang = get_user_locale(); $de_lang_list = array( 'de_CH_informal', 'de_DE_formal', 'de_AT', 'de_CH', 'de_DE' ); if (in_array($site_lang, $de_lang_list)) return 'de_DE'; return $domain; } } includes/class-cf7-customizer-activator.php000064400000001154146725417150015056 0ustar00 */ class Cf7_Customizer_Activator { /** * Short Description. (use period) * * Long Description. * * @since 1.0.0 */ public static function activate() { } } includes/class-cf7-customizer.php000064400000022004146725417150013061 0ustar00 */ class Cf7_Customizer { /** * The loader that's responsible for maintaining and registering all hooks that power * the plugin. * * @since 1.0.0 * @access protected * @var Cf7_Customizer_Loader $loader Maintains and registers all hooks for the plugin. */ protected $loader; /** * The unique identifier of this plugin. * * @since 1.0.0 * @access protected * @var string $plugin_name The string used to uniquely identify this plugin. */ protected $plugin_name; /** * The current version of the plugin. * * @since 1.0.0 * @access protected * @var string $version The current version of the plugin. */ protected $version; /** * Define the core functionality of the plugin. * * Set the plugin name and the plugin version that can be used throughout the plugin. * Load the dependencies, define the locale, and set the hooks for the admin area and * the public-facing side of the site. * * @since 1.0.0 */ public function __construct() { if ( defined( 'CF7_CUSTOMIZER_VERSION' ) ) { $this->version = CF7_CUSTOMIZER_VERSION; } else { $this->version = '1.0.0'; } $this->plugin_name = 'cf7-styler'; $this->load_dependencies(); $this->set_locale(); $this->define_admin_hooks(); $this->define_public_hooks(); } /** * Load the required dependencies for this plugin. * * Include the following files that make up the plugin: * * - Cf7_Customizer_Loader. Orchestrates the hooks of the plugin. * - Cf7_Customizer_i18n. Defines internationalization functionality. * - Cf7_Customizer_Admin. Defines all hooks for the admin area. * - Cf7_Customizer_Public. Defines all hooks for the public side of the site. * * Create an instance of the loader which will be used to register the hooks * with WordPress. * * @since 1.0.0 * @access private */ private function load_dependencies() { /** * The class responsible for orchestrating the actions and filters of the * core plugin. */ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-cf7-customizer-loader.php'; /** * The class responsible for defining internationalization functionality * of the plugin. */ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-cf7-customizer-i18n.php'; /** * Libraries */ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/lib/Cf7_Required_Plugin.php'; require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/lib/Cf7_Style_Scheme.php'; require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/lib/Cf7_License.php'; require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/lib/Cf7_Template.php'; /** * The class responsible for defining all actions that occur in the admin area. */ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-cf7-customizer-admin.php'; require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-cf7-customizer-admin-ajax.php'; /** * The class responsible for defining all actions that occur in the public-facing * side of the site. */ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-cf7-customizer-public.php'; $this->loader = new Cf7_Customizer_Loader(); } /** * Define the locale for this plugin for internationalization. * * Uses the Cf7_Customizer_i18n class in order to set the domain and to register the hook * with WordPress. * * @since 1.0.0 * @access private */ private function set_locale() { $plugin_i18n = new Cf7_Customizer_i18n(); $this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' ); } /** * Register all of the hooks related to the admin area functionality * of the plugin. * * @since 1.0.0 * @access private */ private function define_admin_hooks() { $plugin_admin = new Cf7_Customizer_Admin( $this->plugin_name, $this->version ); $plugin_admin_ajax = new Cf7_Customizer_Admin_Ajax( $this->plugin_name, $this->version ); $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' ); $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' ); $this->loader->add_action( 'admin_menu', $plugin_admin, 'settings_page' ); $this->loader->add_action( 'admin_menu', $plugin_admin, 'plugin_menu_optin', 50 ); $this->loader->add_action( 'init', $plugin_admin, 'rewrite_rule' ); $this->loader->add_action( 'init', $plugin_admin, 'check_installation' ); $this->loader->add_action( 'init', $plugin_admin, 'check_version' ); $this->loader->add_action( 'template_redirect', $plugin_admin, 'template_redirect' ); $this->loader->add_filter('show_admin_bar', $plugin_admin, 'show_admin_bar'); $this->loader->add_filter('admin_body_class', $plugin_admin, 'admin_body_class'); $this->loader->add_action('wp_ajax_cf7cstmzr_save_form_customizer_settings', $plugin_admin_ajax, 'save_form_customizer_settings'); $this->loader->add_action('wp_ajax_cf7cstmzr_new_form_customizer_settings', $plugin_admin_ajax, 'new_form_customizer_settings'); $this->loader->add_action('wp_ajax_cf7cstmzr_delete_form_customizer_settings', $plugin_admin_ajax, 'delete_form_customizer_settings'); $this->loader->add_action('wp_ajax_cf7cstmzr_enable_globally', $plugin_admin_ajax, 'enable_globally'); $this->loader->add_action('wp_ajax_cf7cstmzr_disable_globally', $plugin_admin_ajax, 'disable_globally'); $this->loader->add_action('wp_ajax_cf7cstmzr_enable_for_form', $plugin_admin_ajax, 'enable_for_form'); $this->loader->add_action('wp_ajax_cf7cstmzr_disable_for_form', $plugin_admin_ajax, 'disable_for_form'); $this->loader->add_action('wp_ajax_cf7cstmzr_change_form_preview', $plugin_admin_ajax, 'change_form_preview'); $this->loader->add_action('wp_ajax_cf7cstmzr_preview_form_customizer_settings', $plugin_admin_ajax, 'preview_form_customizer_settings'); $this->loader->add_action('wp_ajax_cf7cstmzr_load_body_tag', $plugin_admin_ajax, 'load_body_tag'); $this->loader->add_action('wp_ajax_cf7cstmzr_cache_form', $plugin_admin_ajax, 'cache_form'); $this->loader->add_action('wp_ajax_nopriv_cf7cstmzr_cache_form', $plugin_admin_ajax, 'cache_form'); $this->loader->add_action('wp_ajax_cf7cstmzr_install_plugin', $plugin_admin_ajax, 'install_plugin'); $this->loader->add_action('wp_ajax_cf7cstmzr_close_welcome', $plugin_admin_ajax, 'close_welcome'); $this->loader->add_filter('wpcf7_editor_panels', $plugin_admin, 'add_cf7_metabox'); $this->loader->add_action('save_post_wpcf7_contact_form', $plugin_admin, 'save_cf7_metabox', 15, 3); } /** * Register all of the hooks related to the public-facing functionality * of the plugin. * * @since 1.0.0 * @access private */ private function define_public_hooks() { $plugin_public = new Cf7_Customizer_Public( $this->get_plugin_name(), $this->get_version() ); $this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_styles' ); $this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_scripts' ); $this->loader->add_filter( 'do_shortcode_tag', $plugin_public, 'add_wrapper', 9999, 4 ); $this->loader->add_action('wp_ajax_cf7cstmzr_frontend_save', $plugin_public, 'save_frontend_settings'); $this->loader->add_action('wp_ajax_nopriv_cf7cstmzr_frontend_save', $plugin_public, 'save_frontend_settings'); } /** * Run the loader to execute all of the hooks with WordPress. * * @since 1.0.0 */ public function run() { $this->loader->run(); } /** * The name of the plugin used to uniquely identify it within the context of * WordPress and to define internationalization functionality. * * @since 1.0.0 * @return string The name of the plugin. */ public function get_plugin_name() { return $this->plugin_name; } /** * The reference to the class that orchestrates the hooks with the plugin. * * @since 1.0.0 * @return Cf7_Customizer_Loader Orchestrates the hooks of the plugin. */ public function get_loader() { return $this->loader; } /** * Retrieve the version number of the plugin. * * @since 1.0.0 * @return string The version number of the plugin. */ public function get_version() { return $this->version; } } includes/class-cf7-customizer-deactivator.php000064400000001166146725417150015372 0ustar00 */ class Cf7_Customizer_Deactivator { /** * Short Description. (use period) * * Long Description. * * @since 1.0.0 */ public static function deactivate() { } } includes/index.php000064400000000032146725417150010201 0ustar00 */ class Cf7_Customizer_Loader { /** * The array of actions registered with WordPress. * * @since 1.0.0 * @access protected * @var array $actions The actions registered with WordPress to fire when the plugin loads. */ protected $actions; /** * The array of filters registered with WordPress. * * @since 1.0.0 * @access protected * @var array $filters The filters registered with WordPress to fire when the plugin loads. */ protected $filters; /** * Initialize the collections used to maintain the actions and filters. * * @since 1.0.0 */ public function __construct() { $this->actions = array(); $this->filters = array(); } /** * Add a new action to the collection to be registered with WordPress. * * @since 1.0.0 * @param string $hook The name of the WordPress action that is being registered. * @param object $component A reference to the instance of the object on which the action is defined. * @param string $callback The name of the function definition on the $component. * @param int $priority Optional. The priority at which the function should be fired. Default is 10. * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1. */ public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) { $this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args ); } /** * Add a new filter to the collection to be registered with WordPress. * * @since 1.0.0 * @param string $hook The name of the WordPress filter that is being registered. * @param object $component A reference to the instance of the object on which the filter is defined. * @param string $callback The name of the function definition on the $component. * @param int $priority Optional. The priority at which the function should be fired. Default is 10. * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1 */ public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) { $this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args ); } /** * A utility function that is used to register the actions and hooks into a single * collection. * * @since 1.0.0 * @access private * @param array $hooks The collection of hooks that is being registered (that is, actions or filters). * @param string $hook The name of the WordPress filter that is being registered. * @param object $component A reference to the instance of the object on which the filter is defined. * @param string $callback The name of the function definition on the $component. * @param int $priority The priority at which the function should be fired. * @param int $accepted_args The number of arguments that should be passed to the $callback. * @return array The collection of actions and filters registered with WordPress. */ private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) { $hooks[] = array( 'hook' => $hook, 'component' => $component, 'callback' => $callback, 'priority' => $priority, 'accepted_args' => $accepted_args ); return $hooks; } /** * Register the filters and actions with WordPress. * * @since 1.0.0 */ public function run() { foreach ( $this->filters as $hook ) { add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] ); } foreach ( $this->actions as $hook ) { add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] ); } } } languages/cf7-styler-ru_RU.po000064400000123142146725417150012122 0ustar00msgid "" msgstr "" "Language: ru-RU\n" "POT-Creation-Date: 2020-02-06 11:35+0000\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10 >= 2 && " "n%10<=4 &&(n%100<10||n%100 >= 20)? 1 : 2);\n" "PO-Revision-Date: 2023-04-15 16:06+0000\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: WOW Style Contact Form 7\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: Russian\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Loco-Version: 2.3.3; wp-5.4" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- отключить Ñхема Ñтиль" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "- выберите -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14-дневный пробный" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%s , иÑпользуемых Ð´Ð»Ñ Ð²Ñех форм глобально, нажмите кнопку " "\"ИÑпользовать Ð´Ð»Ñ Ð²Ñех форм\", ЕÑли вы хотите иÑпользовать текущую Ñхему." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "Ðктивировать Ñтиль Ð´Ð»Ñ Ð²Ñех форм*" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Ðктивировать Ñтиль Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ формы" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "Ð’ качеÑтве альтернативы вы можете отключить очиÑтить Ñтили, как на " "процветать архитектор:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "Цвет Фона" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "Фоновое Изображение" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Перед иÑпользованием ух контактный Ñтиль Форма 7, вам нужно уÑтановить и " "активировать контактную форму 7 плагин." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "БГ цвет" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "БГ непрозрачноÑÑ‚ÑŒ" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "Ð Ð°Ð´Ð¸ÑƒÑ Ñ€Ð°Ð·Ð¼Ñ‹Ñ‚Ð¸Ñ " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "Границы" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "Цвет Границы" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "Ð Ð°Ð´Ð¸ÑƒÑ Ð“Ñ€Ð°Ð½Ð¸Ñ†Ñ‹" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "Тип Границы" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "Ширина Границы " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "Кнопки Границы" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "Кнопки" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Такаюки МиеÑи" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "Отменить" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "CF7 ÐаÑтройщик требует ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° 7 плагин должен быть уÑтановлен и " "активен. Ð’Ñ‹ можете Ñкачать %ов." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "CF7 форма Ðе выбрана" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "CF7 Стайлер" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "ЧекбокÑÑ‹ & Переключатели" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "ЧиÑтые Стили" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "ПонÑтно" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "РÑдом" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "Цвет" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "ÐšÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° 7 ÑпиÑок" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "Содержать" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Скопировать текущие наÑтройки Ñхема Ñтиль " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "Крышка" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "Создать" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "Создать неÑколько Ñхем " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "Создать новую Ñхему Ñтиль!" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Текущий Стиль" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ " "виде выполнен Ñ %- " "ОВ. Как в беÑплатной верÑии вы можете разработать только одну форму " "одновременно, и еÑли вы активируете Ñтиль Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ форме, будут удалены " "от других форма." #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð²Ð¸Ð´Ðµ выполнен Ñ %- ОВ." " Как в беÑплатной верÑии вы можете разработать только одну форму " "одновременно, и еÑли вы активируете Ñтиль Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ форме, будут удалены " "от других форма." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "ПользовательÑкие CSS" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "ПользовательÑкий код CSS " #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "Ðакатал" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "Схема По Умолчанию " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "Удалить ИзображениÑ" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "удален" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "Вид Рабочего Стола " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "Отключить Ñтиль Ð´Ð»Ñ Ð²Ñех форм" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "Отключить Ñтиль Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ формы" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "Вам нравитÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÑŒ премиум-верÑию Styler беÑплатно? Затем Введите Ñвою лицензию " "WP2LEADS pro или получите лицензию href=\"https://wp2leads-for-klick-" "tipp.com/web/go-pro-plus-get-all-done4u/\" target=\"_blank\">здеÑÑŒ !" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "Ð’Ñ‹ хотите Ñохранить изменениÑ, прежде чем покинуть Ñтраницу?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "Пунктирной" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "Двойной" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "Дублировать форму во втором Ñтолбце" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "включен Ð´Ð»Ñ Ð²Ñех форм" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "Ошибка" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "Выход Из ПолноÑкранного Режима" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "СемейÑтво Шрифтов " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "Размер Шрифта " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Стиль Шрифта " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "Ð’ÐµÑ Ð¨Ñ€Ð¸Ñ„Ñ‚Ð° " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Форма БГ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¸ цвета" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "ÐаÑтройка Форма " #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Форма Ðе выбрана" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "Форма ЗаполнениÑ, ÐŸÐ¾Ð»Ñ Ð˜ Границы" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "ТекÑÑ‚ Форма " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "Полном Экране" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "ПÐЗ" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "Ð“Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð”Ð»Ð¸Ð½Ð°" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Ðаведите БГ цвет" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "При Ðаведении Цвет" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Цвет ТекÑта При Ðаведении" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "Как превратить вашу контактную форму form7 в конвертации и проÑтое в " "иÑпользовании и профеÑÑиональный разработанный ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð°, \"опроÑ\" " "генератора лидов или привлекательные формы" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "href=\"https://wp2leads-for-klick-tipp.com/web/go-pro-plus-get-all-done4u/\" " "target=\"_blank\">" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "Я довольна Ñтим! Сохранить" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "ЕÑли вы иÑпользуете компоновщики Ñтраниц, такие как Thrive Architect, " "OptimizePress и Ñ‚. Д., ПоÑетите нашу Ñтраницу базы знаний Ð´Ð»Ñ " "уÑтранение возможных проблем" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "ЕÑли вам нужно загрузить Ñхемы внутри тега<body> тег " "только на некоторых Ñтраницах, вы можете Ñделать Ñто на frontend Ñ " "иÑпользованием \"CF7 Стайлер\" кнопку. Эта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð´Ð¾Ñтупна только Ð´Ð»Ñ " "одного типа поÑта (Ñтраницы, поÑÑ‚Ñ‹, продукты и Ñ‚. д.) и в премиум верÑии. Ð’Ñ‹ " "не можете Ñделать Ñто на Ñтраницах архивов (блог, ÑпиÑок продуктов и Ñ‚. д.) " "Ð’ Ñтом Ñлучае вы должны иÑпользовать глобальные параметры." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "ЕÑли вам нужно загрузить Ñхемы внутри тега<body> тег " "только на некоторых Ñтраницах, вы можете Ñделать Ñто на frontend Ñ " "иÑпользованием \"CF7 Стайлер\" кнопку. Эта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð´Ð¾Ñтупна только Ð´Ð»Ñ " "одного типа поÑта (Ñтраницы, поÑÑ‚Ñ‹, продукты и Ñ‚. д.). Ð’Ñ‹ не можете Ñделать " "Ñто на Ñтраницах архивов (блог, ÑпиÑок продуктов и Ñ‚. д.) Ð’ Ñтом Ñлучае вы " "должны иÑпользовать глобальные параметры." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "ÐаÑтройки фонового Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупна в режиме Live только Ð´Ð»Ñ " "профеÑÑиональной верÑии. Ð’Ñ‹ можете протеÑтировать его в режиме " "предварительного проÑмотра \"текущий Ñтиль\", но он не будет Ñохранен." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "ÐепрозрачноÑÑ‚ÑŒ Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "Положение Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "Размер Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ " #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "ÐаÑледовать" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "ÐŸÐ¾Ð»Ñ Ð’Ð²Ð¾Ð´Ð°" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "Введите название Ñхемы в Ñтиле " #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "Врезные" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "КурÑив" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "Ярлыки Цвет" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "Размер Шрифта ÐадпиÑей " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "ÐаÑтройки Метки " #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "ЛицензиÑ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "Ð›Ð¸Ð½Ð¸Ñ Ð’Ñ‹Ñота" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "Цвет СÑылки " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "СÑылки При Ðаведении Цвет" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Параметры СÑылки " #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "Жить" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "Загрузить Ñтили в тегах<Body> тег" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "" "Загрузить Ñтили внутри тега<body> тег на Ñтой Ñтранице" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "Сделать Ñлемент флажок одному в Ñтроке" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "Сделать полную ширину?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "Сделайте Ð¿Ð¾Ð»Ñ Ð´Ð»Ñ Ð²Ð²Ð¾Ð´Ð° ширины?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Сделать Ñлемент ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ RadioButton одному в Ñтроке" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "Маржа" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "Мобильный Вид" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "Ðет" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "Ðет контактной формы 7 предметов Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ проÑмотра" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "Ðет формы выполнен Ñ Ñхема Ñтиль, нажмите кнопку \"Ðктивировать Ñтиль Ð´Ð»Ñ " "текущей формы кнопки\" Применить текущие Ñхемы Ð´Ð»Ñ Ñтой формы." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "Ðет плагин выбран Ð´Ð»Ñ ÑƒÑтановки" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "Ðет Ñхемы выбранный Ñтиль" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "Ðормальный" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "КоÑой" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "Один за Ñтили линий Ð´Ð»Ñ Ð³Ð°Ð»Ð¾Ñ‡ÐºÐ¸ и переключатели в режиме Live только Ð´Ð»Ñ " "профеÑÑиональной верÑии. Ð’Ñ‹ можете протеÑтировать его в режиме " "предварительного проÑмотра \"текущий Ñтиль\", но он не будет Ñохранен." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "ÐепрозрачноÑÑ‚ÑŒ" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "Откройте Ñтайлер" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "Оригинальный размер" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "Контур" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "Прежде вÑего" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "Обивка" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "ПожалуйÑта, введите название Ñхемы в Ñтиле " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "Предварительный проÑмотр" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "Режим предварительного проÑмотра " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "Предварительный ПроÑмотр ÐеÑтилизованный" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "РадиуÑ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "Повторите оба" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "Повторите горизонтально" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "Повторить вертикальный" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð¾ умолчанию" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "Хребет" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "Сохранить" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "СпаÑ" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "Второй вид колонки " #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "Выберите Ñхему Ñтиль Ð´Ð»Ñ Ñтой формы" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "Параметры" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "ÐаÑтройки ÑохранÑÑŽÑ‚ÑÑ ÐºÐ°Ðº " #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "Тень" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "Цвет Тени" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Теневой Позиции" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "Твердые" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Ðекоторые темы или Ñтроителей Ñтранице (Фе. Процветать архитектор, " "OptimizePress и Ñ‚. д.) можно удалить вÑтроенные Ñтили внутри тег<" "head> тег. Загрузка Ñхемы в пределах <тело> тег " "будет иÑправить Ñту проблему и показать Ñвои формы в Ñтиле." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "Режим Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ " #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "Сплит вид" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "Ð Ð°Ð´Ð¸ÑƒÑ Ñ€Ð°ÑпроÑтранениÑ" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "Ðачать укладку" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "Ðачните Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñхемы Ñтиль по умолчанию " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "Ðачните Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ первого " "ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° 7" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "Ðачать Ñвой 14-дневную беÑплатную пробную верÑию Ñо вÑеми профеÑÑиональными " "функциÑми здеÑÑŒ!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "Шаг 1. Ðажмите кнопку \"Редактировать процветать архитектор ÑÑылке\" в " "ÑпиÑке Ñтраниц админ " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "Шаг 2. Ðажмите кнопку \"ÐаÑтройки\" значок на правом вертикальном меню" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "" "Шаг 3. \"Дополнительные наÑтройки\" => \"CSS в разделе <head>\"" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "Шаг 4. УбедитеÑÑŒ, что \"не полоÑÑ‹ CSS от <руководитель>\" проверÑетÑÑ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "Шаг 5. Ðажмите кнопку \"Сохранить\" кнопку" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "Стиль вÑех форм в один клик во вÑем мире" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "Стиль каждой формы Ñ Ð»ÑŽÐ±Ñ‹Ð¼ Ñхема ÑÑ‚Ð¸Ð»Ñ Ð¸Ð½Ð´Ð¸Ð²Ð¸Ð´ÑƒÐ°Ð»ÑŒÐ½Ð¾" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "Схема Ñтиль отключен Ð´Ð»Ñ Ð²Ñех форм" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "Схема Ñтиль отключена Ð´Ð»Ñ Ñтой формы" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "Схема Ñтиль Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ Ð´Ð»Ñ Ñтой формы" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "Схема Ñтиль Ðе выбран" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "СпиÑок Ñхем " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "Схемы предварительный проÑмотр Ñтилей" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "Параметры Ñхем " #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "Стиль будет загружен в тег" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "Стиль будет загружен в тег" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "УÑпех" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "Вид Планшета " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "Цвет ТекÑта" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "Эта форма выполнена Ñ %- ОВ по вÑему миру, вы можете Ñтиль " "его Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼ Ñтилем Ñхеме." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "Эта форма выполнена Ñ %- ОВ, вы можете Ñтиль его Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼ " "Ñтилем Ñхеме." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "Эта форма выполнена Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ Ñхемой Ñтиле, вы можете отключить его и " "иÑпользовать глобальные параметры." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "Эта форма не Ñтилизовано под какую-то Ñхему, Ñтиль, вы можете включить ток " "Ñхема данной формы или Ñоздавать глобальные Ñхемы Ñтиль, нажав кнопку " "\"ИÑпользовать Ð´Ð»Ñ Ð²Ñех форм\" под заголовком программы." #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "Эта Ñхема не ÑущеÑтвовала" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "Эта Ñхема Ñтиль глобально Ð´Ð»Ñ Ð²Ñех форм. ЕÑли вы хотите иÑпользовать Ñтиль " "вашей темы Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ñ‹Ð¹ формулÑÑ€ 7 Ðажмите кнопку \"Отключить\"." #. Author of the plugin msgid "Tobias Conrad" msgstr "Ð¢Ð¾Ð±Ð¸Ð°Ñ ÐšÐ¾Ð½Ñ€Ð°Ð´" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "Учебник" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "ÐеÑтилизованный" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "Обновление до Pro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "Загрузить Изображение" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "Ð’ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð”Ð»Ð¸Ð½Ð°" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "Добро пожаловать" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "Ширина" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "Вау контакт Ñтиль Форма 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "Да" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "Ð’Ñ‹ можете Ñоздать новую Ñхему в Ñтиле Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼Ð¸ наÑтройками Ñхемы. ЕÑли вы " "хотите Ñоздать флажок Ñтиль unchek Ñчем ниже." #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "Ð’Ñ‹ не можете удалить" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "Ð’Ñ‹ не можете иÑпользовать Ñти наÑтройки на Ñтого типа Ñтраницы " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "Ð’Ñ‹ не имеете никакого ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° 7 предметов" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "Ð’Ñ‹ не иÑпользуете какой-либо из Ñхем Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ñ‹Ð¹ формулÑÑ€ 7. Ðажмите " "кнопку \"ИÑпользовать Ð´Ð»Ñ Ð²Ñех форм\" иÑпользовать текущую Ñхему в " "глобальном маÑштабе." languages/cf7-styler-it_IT.mo000064400000047054146725417150012102 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'Â(#Ò)ö)*˜*%²*(Ø*Y+ [+ e+q+‚+k•+,,,.,?,O,c,v,,h“, ü, - (-#5- Y-f-m-v-}- ™-6£- Ú-ä-ë- . (.D6.ü{/x0‹0 ¥0²0Å0Û0&í0*1 ?18`2 ™2£2&ª2Ñ2Ø2ô2 3#373J3j3'‡3¯3À3Ý3 ì3ø34 )4'64Ò^4 15ÞR5À16ªò79´9Ì9Îå9 ´:¾:%Í:ó:û:;(;=;Z;b; v;‚; ; ¾;9É;Q<7U<<+©<0Õ<= ==1=¨P=3ù=/->]>e>Ám>/? 8?F?b?w?~? ?(œ? Å?Ï?â?ö?ý?@'@)=@g@ o@{@ƒ@0Ÿ@ Ð@Ý@÷@ý@A!A0(AYB iBvB‹B;ŸBVÛB2CgDDI¬DDöDX;E-”E;ÂECþE/BF.rF+¡F%ÍFóFG"0G'SG&{G ¢G ®G¼GÒG¸ãG€œHuI|“IÒJãJ üJ K KK3KCK!WK yK ƒKK»‘KMLHhL3±L¥åL ‹M–M³M`ËM- disable style scheme -- select -14-days Trial%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/Language: it-IT POT-Creation-Date: 2023-04-15 15:26+0000 Plural-Forms: nplurals=2; plural=n != 1; PO-Revision-Date: 2023-04-15 16:11+0000 X-Generator: Loco https://localise.biz/ Project-Id-Version: WOW Style Contact Form 7 Report-Msgid-Bugs-To: Last-Translator: Tobias support@saleswonder.biz Language-Team: Italian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489- disabilitare lo schema di stile -- selezionare -14 giorni di prova%s utilizzato per tutti i moduli a livello globale, fare clic su "Usa per tutti i moduli" se si desidera utilizzare lo schema corrente.Attivare lo stile per tutti i moduli*Attivare lo stile per il modulo correnteIn alternativa, è possibile disattivare la pulizia degli stili come in Thrive Architect:Colore BGOpacità BGColore di sfondoImmagine di sfondoPrima di utilizzare WOW Style Contact Form 7, è necessario installare e attivare il plugin Contact Form 7.Raggio di sfocaturaConfineColore del bordoRaggio del bordoTipo di confineLarghezza del bordoBordo del pulsantePulsantiDi Takayuki MiyoshiCF7 Customizer richiede che il plugin Contact Form 7 sia installato e attivo. È possibile scaricare %s.CF7 Il modulo non è selezionatoCF7 StylerAnnullamentoCaselle di controllo e radiobottoniStili pulitiLiberoChiudereColoreModulo di contatto 7 elencoContenereCopiare le impostazioni dello schema di stile correnteCopertinaCreareCreare più schemi di stileCreate un nuovo schema di stile!Stile attualeAttualmente il modulo %s è stilizzato con %s. Come nella versione gratuita, è possibile stilizzare solo un modulo alla volta e se si attiva lo stile per il modulo corrente, lo stile verrà rimosso dagli altri moduli.Attualmente il modulo %s è stilizzato con %s. Come nella versione gratuita, è possibile stilizzare solo un modulo alla volta e se si attiva lo stile per il modulo corrente, lo stile verrà rimosso dagli altri moduli.CSS personalizzatoCodice CSS personalizzatoTratteggiatoSchema predefinitoCancellare l'immagineVista sul desktopDisabilita lo stile per tutti i moduliDisabilita lo stile per il modulo correnteVuoi ottenere la versione premium di Styler gratuitamente? Allora inserisci la tua licenza WP2LEADS pro o ottieni una licenza qui!Volete salvare le modifiche prima di lasciare la pagina?A puntiniDoppioModulo duplicato nella seconda colonnaErroreUscita dallo schermo interoFamiglia di caratteriDimensione del carattereStile del caratterePeso del carattereImmagine BG del modulo e coloriPersonalizzazione del moduloImbottitura, margine e bordo del moduloTesto del moduloIl modulo non è selezionatoSchermo interoScanalaturaLunghezza orizzontaleColore del bordo del mouseColore HoverColore del testo al passaggio del mouseCome trasformare il vostro modulo contact form7 in un modulo di contatto che converte e che è facile da usare e in stile professionale, in un generatore di lead "survey" o in un modulo che cattura l'attenzioneSono felice di questo! RisparmioSe si utilizzano page builder come Thrive Architect, OptimizePress ecc., consultare la nostra pagina Base di conoscenza per risolvere eventuali problemiSe avete bisogno di caricare lo schema di stile all'interno del tag <body> solo su alcune pagine, potete farlo nel frontend utilizzando il pulsante "CF7 Styler". Questa funzione è disponibile solo per i tipi di post singoli (pagine, post, prodotti ecc.) e nella versione premium. Non è possibile farlo sulle pagine degli archivi (blog, elenco di prodotti, ecc.), in questo caso è necessario utilizzare le impostazioni globali.Se è necessario caricare lo schema di stile all'interno del tag <body> solo su alcune pagine, è possibile farlo nel frontend utilizzando il pulsante "CF7 Styler". Questa funzione è disponibile solo per i singoli tipi di post (pagine, post, prodotti ecc.). Non è possibile farlo sulle pagine degli archivi (blog, elenco di prodotti, ecc.), in questo caso è necessario utilizzare le impostazioni globali.Opacità dell'immaginePosizione dell'immagineDimensione dell'immagineLe impostazioni dello sfondo dell'immagine sono disponibili in modalità live solo per la versione Professional. È possibile provarle nella modalità di anteprima "stile corrente", ma non verranno salvate.EreditareCampi di inputTitolo dello schema di stile di inputInsertoCorsivoEtichette ColoreDimensione del carattere delle etichetteImpostazioni delle etichetteLicenzaAltezza della lineaLink ColoreColore del passaggio dei linkImpostazioni dei collegamentiIn direttaCaricamento degli stili nel tag <body>Caricare gli stili all'interno del tag <body> in questa paginaRendere la voce della casella di controllo una per rigaFare il pieno di larghezza?Rendere i campi di input a larghezza piena?Rendere l'elemento del radiobottone uno per rigaMargineVista mobileNONessun elemento di Contact Form 7 per l'anteprimaNessun modulo è stato creato con uno schema di stile, fare clic sul pulsante "Attiva lo stile per il modulo corrente" per applicare lo schema corrente a questo modulo.Non è stato selezionato alcun plugin da installareNon è stato selezionato alcuno schema di stileNormaleObliquoStili per riga per caselle di controllo e radiobottoni in modalità live solo per la versione Professional. È possibile provarlo in modalità anteprima "stile corrente", ma non verrà salvato.OpacitàStyler apertoOpt-in per vedere l'accountDimensione originaleSchemaEsternalizzazioneImbottituraInserire il titolo dello schema di stileAnteprimaAnteprima UnstyledModalità anteprimaRaggioRipetere entrambiRipetizione orizzontaleRipetizione verticaleRipristino delle impostazioni predefiniteCrinaleRisparmiareSalvatiVista della seconda colonnaSelezionare lo schema di stile per questo moduloImpostazioniImpostazioni salvate comeOmbraColore dell'ombraPosizione d'ombraSolidoAlcuni temi o page builder (ad esempio Thrive Architect, OptimizePress ecc.) potrebbero rimuovere gli stili in linea all'interno del tag <head>. Il caricamento dello schema di stile all'interno del tag <body> risolverà questo problema e mostrerà i moduli in stile.Modalità SplitVista divisaRaggio di diffusioneIniziare lo stylingIniziare con la creazione dello schema di stile predefinitoIniziate creando il vostro primo Contact Form 7Inizia la tua prova gratuita di 14 giorni con tutte le funzioni Professional qui!Passo 1. Fare clic sul link "Modifica con Thrive Architect" nell'elenco della pagina di amministrazionePasso 2. Fare clic sull'icona "Impostazioni" nel menu verticale di destraPasso 3. "Impostazioni avanzate" => "CSS nella sezione <head>"Passo 4. Assicurarsi che sia selezionata l'opzione "Non rimuovere i CSS da <head>"Passo 5. Fate clic sul pulsante "SALVA LAVOROModellare tutti i moduli con un solo clic a livello globaleModellare ogni modulo con qualsiasi schema di stile individualmenteSchema di stile disabilitato per tutti i moduliSchema di stile disabilitato per questo moduloSchema di stile abilitato per questo moduloLo schema di stile non è selezionatoElenco degli schemi di stileAnteprima degli schemi di stileImpostazioni degli schemi di stileLo stile verrà caricato nel tag Lo stile sarà caricato nel tag Il successoSupporto e KBVista della tavolettaColore del testoQuesto schema di stile è abilitato globalmente per tutti i moduli. Se si desidera utilizzare lo stile del proprio tema per il Modulo di contatto 7, fare clic sul pulsante "Disattiva".Questo modulo è stilizzato con %s a livello globale, è possibile stilizzarlo con lo schema di stile corrente.Questo modulo è stato creato con %s, è possibile creare uno stile con lo schema di stile corrente.Questo modulo è stilizzato con lo schema di stile corrente; è possibile disattivarlo e utilizzare le impostazioni globali.Questo modulo non ha uno schema di stile; è possibile attivare lo schema attuale per questo modulo o impostare uno schema di stile globale facendo clic su "Usa per tutti i moduli" sotto il titolo dello schema.Questo schema non esisteTobias ConradTutorialSenza stileAggiornamento a ProCarica immagineLunghezza verticaleModulo di contatto in stile WOW 7BenvenutiLarghezzaSÌÈ possibile creare un nuovo schema di stile con le impostazioni dello schema corrente. Se si desidera creare uno schema di stile vuoto, deselezionare la casella di controllo sottostante.Non è possibile eliminareNon è possibile utilizzare queste impostazioni su questo tipo di paginaNon si dispone di elementi del Modulo di contatto 7Non si utilizza nessuno degli schemi di stile per il modulo di contatto 7. Fare clic su "Usa per tutti i moduli" per utilizzare lo schema corrente a livello globale.cancellatoabilitato per tutti i modulihttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/languages/cf7-styler-hi_IN.mo000064400000071445146725417150012061 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'À(BÐ)*&%*’L*_ß+i?,ô©,ž-µ-%Ñ-%÷-3."Q/t/‡/"¥/È/è/0 0D&0 k0AŒ1Î1è1>2A2^2 q2~24Ž2Ã2rÖ2 I3 S3?`3G 3(è3š4R¬6#ÿ8#9 @9(J9 s9(”9M½9V :b:›k<==U-=ƒ=9™=%Ó=ù=%>"?>b>)€>Mª>%ø>:?%Y??%•?»?Î?ë?@C£AÔçAÒ¼CG K@K]K®tK#M,6MQcMµMÈMÞM,õM%"NHN[NxN$N%´N ÚN=çNj%OZO0ëO]PMzPÈP"ÞPQ„Q— Qq8SMªSøSTÐ TñU V:*VeV|VV©VrÂV!5W=WW+•WÁW(×W+X7,XBdX §X ±X¾X+ÒXZþXYY@rY ³YÀY&ÞYZZ\(<\%e\5‹\eÁ\¯']i×]vA_”¸_vM`¸Ä`L}awÊa­BbdðbaUca·cHd6bd+™d>ÅdMeMRe e°e"Íeðe¤ f °gå¼h(¢iÜËjJ¨l(ólm;mTm"qm(”m;½mùmn#n97n*qo™œof6p p>rDRr+—raÃr- disable style scheme -- select -14-days Trial%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/Language: hi-IN POT-Creation-Date: 2023-04-15 15:26+0000 Plural-Forms: nplurals=2; plural=n != 1; PO-Revision-Date: 2023-04-15 16:10+0000 X-Generator: Loco https://localise.biz/ Project-Id-Version: WOW Style Contact Form 7 Report-Msgid-Bugs-To: Last-Translator: Tobias support@saleswonder.biz Language-Team: Hindi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489- डिसà¥à¤•à¤¾à¤‰à¤‚ट सà¥à¤Ÿà¤¾à¤‡à¤² योजना -चà¥à¤¨à¥‡à¤‚ -14 दिन का मà¥à¤•à¤¦à¤®à¤¾%sवैशà¥à¤µà¤¿à¤• सà¥à¤¤à¤° पर सभी फॉरà¥à¤®à¥‹à¤‚ के लिठउपयोग किया जाता है, यदि आप वरà¥à¤¤à¤®à¤¾à¤¨ योजना का उपयोग करना चाहते हैं तो "सभी फॉरà¥à¤®à¥‹à¤‚ के लिठउपयोग करें" पर कà¥à¤²à¤¿à¤• करें।सभी रूपों के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करें *वरà¥à¤¤à¤®à¤¾à¤¨ फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करेंà¤à¤• विकलà¥à¤ª के रूप में आप फà¥à¤²à¥‹à¤°à¤¿à¤‚ग आरà¥à¤•à¤¿à¤Ÿà¥‡à¤•à¥à¤Ÿ जैसे शैलियों को साफ करने के लिठअकà¥à¤·à¤® कर सकते हैं:बीजी रंगBG असà¥à¤¥à¤¿à¤°à¤¤à¤¾à¤ªà¥ƒà¤·à¥à¤ à¤­à¥‚मि रंगपृषà¥à¤ à¤­à¥‚मि छविWow सà¥à¤Ÿà¤¾à¤‡à¤² संपरà¥à¤• फ़ॉरà¥à¤® 7 का उपयोग करने से पहले, आपको संपरà¥à¤• फ़ॉरà¥à¤® 7 पà¥à¤²à¤—इन सà¥à¤¥à¤¾à¤ªà¤¿à¤¤ करने और सकà¥à¤°à¤¿à¤¯ करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है।बà¥à¤²à¥‚ रेडिà¤à¤¶à¤¨à¤¸à¥€à¤®à¤¾à¤à¤‚सीमा का रंगसीमा रेडिà¤à¤¶à¤¨à¤¸à¥€à¤®à¤¾ पà¥à¤°à¤•à¤¾à¤°à¤¸à¥€à¤®à¤¾ चौड़ाबटन सीमाबटनTakayuki Miyoshi के बारे में जानकारीCf7 Customizer को सà¥à¤¥à¤¾à¤ªà¤¿à¤¤ करने और सकà¥à¤°à¤¿à¤¯ होने के लिठसंपरà¥à¤• फॉरà¥à¤® 7 पà¥à¤²à¤—इन की आवशà¥à¤¯à¤•à¤¤à¤¾ होती है। आप% S डाउनलोड कर सकते हैं।Cf7 फ़ॉरà¥à¤® नहीं चà¥à¤¨à¤¾ गया हैCf7 सà¥à¤Ÿà¤¾à¤‡à¤²à¤°à¤°à¤¦à¥à¤¦ करेंचेकबॉकà¥à¤¸ और रेडियोबॉटनसाफ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¸à¥à¤ªà¤·à¥à¤Ÿà¤¨à¤¿à¤•à¤Ÿà¤°à¤‚गोंसंपरà¥à¤• फ़ॉरà¥à¤® 7 सूचीकंटेनरवरà¥à¤¤à¤®à¤¾à¤¨ सà¥à¤Ÿà¤¾à¤‡à¤² योजना सेटिंगà¥à¤¸ को कॉपी करेंकवरबनाओकई सà¥à¤Ÿà¤¾à¤‡à¤² योजनाà¤à¤‚ बनाà¤à¤‚à¤à¤• नया सà¥à¤Ÿà¤¾à¤‡à¤² डिजाइन बनाà¤à¤‚!वरà¥à¤¤à¤®à¤¾à¤¨ सà¥à¤Ÿà¤¾à¤‡à¤²à¤µà¤°à¥à¤¤à¤®à¤¾à¤¨ में % à¤à¤¸ आकार के साथ बनाया गया है % à¤à¤¸ . मà¥à¤«à¥à¤¤ संसà¥à¤•à¤°à¤£ के रूप में आप à¤à¤• ही समय में केवल à¤à¤• फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤² कर सकते हैं और यदि आप वरà¥à¤¤à¤®à¤¾à¤¨ फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करते हैं, तो सà¥à¤Ÿà¤¾à¤‡à¤² को दूसरे फॉरà¥à¤® से हटा दिया जाà¤à¤—ा।वरà¥à¤¤à¤®à¤¾à¤¨ में % à¤à¤¸ आकार के साथ बनाया गया है % à¤à¤¸ . मà¥à¤«à¥à¤¤ संसà¥à¤•à¤°à¤£ के रूप में आप à¤à¤• ही समय में केवल à¤à¤• फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤² कर सकते हैं और यदि आप वरà¥à¤¤à¤®à¤¾à¤¨ फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करते हैं, तो सà¥à¤Ÿà¤¾à¤‡à¤² को दूसरे फॉरà¥à¤® से हटा दिया जाà¤à¤—ा।सीà¤à¤¸à¤à¤¸ के लिà¤à¤¸à¥€à¤à¤¸à¤à¤¸ कोडडैशडिफ़ॉलà¥à¤Ÿ योजनाछवि को हटानाडेसà¥à¤•à¤Ÿà¥‰à¤ª दृशà¥à¤¯à¤¸à¤­à¥€ रूपों के लिठअकà¥à¤·à¤® सà¥à¤Ÿà¤¾à¤‡à¤²à¤µà¤°à¥à¤¤à¤®à¤¾à¤¨ आकार के लिठअकà¥à¤·à¤® सà¥à¤Ÿà¤¾à¤‡à¤²à¤•à¥à¤¯à¤¾ आप मà¥à¤«à¥à¤¤ में सà¥à¤Ÿà¤¾à¤‡à¤²à¤° पà¥à¤°à¥€à¤®à¤¿à¤¯à¤® संसà¥à¤•à¤°à¤£ पà¥à¤°à¤¾à¤ªà¥à¤¤ करना चाहते हैं? और फिर अपने Wp2Leads पà¥à¤°à¥‹ लाइसेंस दरà¥à¤œ करें या à¤à¤• लाइसेंस पà¥à¤°à¤¾à¤ªà¥à¤¤ करें यहाठ!कà¥à¤¯à¤¾ आप पृषà¥à¤  छोड़ने से पहले परिवरà¥à¤¤à¤¨à¥‹à¤‚ को बचाना चाहते हैं?डà¥à¤¯à¥‚टीदोगà¥à¤¨à¤¾à¤¦à¥‚सरी सà¥à¤¤à¤‚भ में डà¥à¤ªà¥à¤²à¤¿à¤•à¥‡à¤Ÿ फॉरà¥à¤®à¤—लतियांपूरà¥à¤£ सà¥à¤•à¥à¤°à¥€à¤¨ से बाहरफ़ॉनà¥à¤Ÿ परिवारफ़ॉनà¥à¤Ÿ आकारफ़ॉनà¥à¤Ÿ सà¥à¤Ÿà¤¾à¤‡à¤²à¤µà¤œà¤¨ लिपसà¥à¤Ÿà¤¿à¤•BG छवि और रंगआकार के अनà¥à¤•à¥‚लनफॉरà¥à¤® पैडिंग, मारà¥à¤œà¤¿à¤¨ और सीमाफॉरà¥à¤® टेकà¥à¤¸à¥à¤Ÿà¤«à¥‰à¤°à¥à¤® नहीं चà¥à¤¨à¤¾ गया हैपूरà¥à¤£ सà¥à¤•à¥à¤°à¥€à¤¨à¤¬à¤¢à¤¼à¥‹à¤¤à¤°à¥€à¤•à¥à¤·à¥ˆà¤¤à¤¿à¤œ लंबाईHover BG रंगहॉवरà¥à¤¸ रंगHover पाठ रंगअपने संपरà¥à¤• फॉरà¥à¤® 7 को à¤à¤• रूपांतरण और उपयोग करने में आसान और पà¥à¤°à¥‹ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ संपरà¥à¤• फॉरà¥à¤®, "अनà¥à¤¸à¤‚धान" पाउडर जनरेटर या à¤à¤• आंख पकड़ने फॉरà¥à¤® में कैसे परिवरà¥à¤¤à¤¿à¤¤ करेंमैं इस बात से खà¥à¤¶ हूà¤! बचावयदि आप पृषà¥à¤  निरà¥à¤®à¤¾à¤¤à¤¾à¤“ं का उपयोग कर रहे हैं, जैसे कि फà¥à¤°à¥€à¤µ आरà¥à¤•à¤¿à¤Ÿà¥‡à¤•à¥à¤Ÿ, Optimizepress आदि, कृपया हमारी जांच करें जà¥à¤žà¤¾à¤¨ आधार पृषà¥à¤  संभावित मà¥à¤¦à¥à¤¦à¥‹à¤‚ को हल करने के लिà¤à¤¯à¤¦à¤¿ आपको अंदर सà¥à¤Ÿà¤¾à¤‡à¤² योजना लोड करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है केवल कà¥à¤› पृषà¥à¤ à¥‹à¤‚ पर टैग करें, आप "Cf7 सà¥à¤Ÿà¤¾à¤‡à¤²à¤°" बटन का उपयोग करके सामने पर à¤à¤¸à¤¾ कर सकते हैं। यह सà¥à¤µà¤¿à¤§à¤¾ केवल à¤à¤•à¤² पोसà¥à¤Ÿ पà¥à¤°à¤•à¤¾à¤° (पृषà¥à¤ , पोसà¥à¤Ÿ, उतà¥à¤ªà¤¾à¤¦, आदि) के लिठउपलबà¥à¤§ है। और पà¥à¤°à¥€à¤®à¤¿à¤¯à¤® संसà¥à¤•à¤°à¤£ में। आप इसे संगà¥à¤°à¤¹ पृषà¥à¤ à¥‹à¤‚ (बà¥à¤²à¥‰à¤—, उतà¥à¤ªà¤¾à¤¦ सूची आदि) पर नहीं कर सकते हैं, इस मामले में आपको वैशà¥à¤µà¤¿à¤• सेटिंगà¥à¤¸ का उपयोग करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है।यदि आपको अंदर सà¥à¤Ÿà¤¾à¤‡à¤² योजना लोड करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है केवल कà¥à¤› पृषà¥à¤ à¥‹à¤‚ पर टैग करें, आप "Cf7 सà¥à¤Ÿà¤¾à¤‡à¤²à¤°" बटन का उपयोग करके सामने पर à¤à¤¸à¤¾ कर सकते हैं। यह सà¥à¤µà¤¿à¤§à¤¾ केवल à¤à¤•à¤² पोसà¥à¤Ÿ पà¥à¤°à¤•à¤¾à¤° (पृषà¥à¤ , पोसà¥à¤Ÿ, उतà¥à¤ªà¤¾à¤¦, आदि) के लिठउपलबà¥à¤§ है। आप इसे संगà¥à¤°à¤¹ पृषà¥à¤ à¥‹à¤‚ (बà¥à¤²à¥‰à¤—, उतà¥à¤ªà¤¾à¤¦ सूची आदि) पर नहीं कर सकते हैं, इस मामले में आपको वैशà¥à¤µà¤¿à¤• सेटिंगà¥à¤¸ का उपयोग करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है।तसà¥à¤µà¥€à¤°à¥‡à¤‚ Opacityछवि सà¥à¤¥à¤¿à¤¤à¤¿à¤›à¤µà¤¿ आकारछवि पृषà¥à¤ à¤­à¥‚मि सेटिंगà¥à¤¸ केवल पेशेवर संसà¥à¤•à¤°à¤£ के लिठलाइव मोड में उपलबà¥à¤§ हैं। आप इसे पूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨ मोड "वरà¥à¤¤à¤®à¤¾à¤¨ शैली" में परीकà¥à¤·à¤£ कर सकते हैं, लेकिन यह बचाया नहीं जाà¤à¤—ा।विरासतइनपà¥à¤Ÿ के कà¥à¤·à¥‡à¤¤à¥à¤°à¤‡à¤¨à¤ªà¥à¤Ÿ सà¥à¤Ÿà¤¾à¤‡à¤² पà¥à¤°à¥‹à¤—à¥à¤°à¤¾à¤® शीरà¥à¤·à¤•à¤‡à¤‚तजारइटालियनरंग लेबललेबल फ़ॉनà¥à¤Ÿ आकारलेबल सेटिंगà¥à¤¸à¤…नà¥à¤®à¤¤à¤¿à¤²à¤¾à¤‡à¤¨ ऊंचाईबाà¤à¤‚ रंगबाईं ओर का रंगबाà¤à¤‚ सेटिंगà¥à¤¸à¤²à¤¾à¤‡à¤µà¤²à¥‹à¤¡ सà¥à¤Ÿà¤¾à¤‡à¤² में Tagआंतरिक लोड सà¥à¤Ÿà¤¾à¤‡à¤² इस पृषà¥à¤  पर टैगचेकबॉकà¥à¤¸ आइटम à¤à¤• लाइन के लिठबनाà¤à¤‚पूरी चौड़ाई बनाà¤à¤‚?इनपà¥à¤Ÿ फ़ीलà¥à¤¡ पूरी चौड़ाई बनाते हैं?Radiobutton आइटम à¤à¤• लाइन के लिठबनाà¤à¤‚मारà¥à¤œà¤¿à¤¨à¤®à¥‹à¤¬à¤¾à¤‡à¤² दृशà¥à¤¯à¤¨à¤¹à¥€à¤‚ नहींकोई संपरà¥à¤• फॉरà¥à¤® नहीं 7 वसà¥à¤¤à¥à¤“ं के लिठपूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨à¤•à¥‹à¤ˆ फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤² शेडà¥à¤¯à¥‚ल के साथ सà¥à¤Ÿà¤¾à¤‡à¤² नहीं है, इस फॉरà¥à¤® के लिठवरà¥à¤¤à¤®à¤¾à¤¨ शेडà¥à¤¯à¥‚ल लागू करने के लिठ"वरà¥à¤¤à¤®à¤¾à¤¨ फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करें" बटन पर कà¥à¤²à¤¿à¤• करें।कोई पà¥à¤²à¤—इन सà¥à¤¥à¤¾à¤ªà¤¿à¤¤ करने के लिठचà¥à¤¨à¤¾ नहीं हैकोई सà¥à¤Ÿà¤¾à¤‡à¤² योजना नहीं चà¥à¤¨à¥€ गईसामानà¥à¤¯Oblique मेंचेकबॉकà¥à¤¸ और रेडियोबॉटन के लिठलाइव मोड में केवल पेशेवर संसà¥à¤•à¤°à¤£ के लिठà¤à¤•-à¤à¤•-लाइन सà¥à¤Ÿà¤¾à¤‡à¤²à¥¤ आप इसे पूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨ मोड "वरà¥à¤¤à¤®à¤¾à¤¨ शैली" में परीकà¥à¤·à¤£ कर सकते हैं, लेकिन यह बचाया नहीं जाà¤à¤—ा।असà¥à¤¥à¤¿à¤°à¤¤à¤¾à¤–à¥à¤²à¥‡ सà¥à¤Ÿà¤¾à¤‡à¤²à¤…काउंट देखने के लिठOpt-Inमूल आकारआउटलिनबाहर निकलपदà¥à¤®à¤¾à¤µà¤¤à¥€à¤•à¥ƒà¤ªà¤¯à¤¾ सà¥à¤Ÿà¤¾à¤‡à¤² पà¥à¤°à¥‹à¤—à¥à¤°à¤¾à¤® का शीरà¥à¤·à¤• दरà¥à¤œ करेंपूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨à¤…नौपचारिक पूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨à¤ªà¥‚रà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨ मोडरेडिà¤à¤¶à¤¨à¤¦à¥‹à¤¬à¤¾à¤°à¤¾ दोहराà¤à¤‚कà¥à¤·à¥ˆà¤¤à¤¿à¤œ दोहराà¤à¤‚वरà¥à¤šà¥à¤…ल पà¥à¤¨à¤°à¤¾à¤µà¥ƒà¤¤à¥à¤¤à¤¿à¤¡à¤¿à¤«à¤¼à¥‰à¤²à¥à¤Ÿ के लिठपà¥à¤¨à¤°à¤¾à¤°à¤‚भरीजबचावबचाठगà¤à¤¦à¥‚सरा दृषà¥à¤Ÿà¤¿à¤•à¥‹à¤£à¤‡à¤¸ फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² योजना चà¥à¤¨à¥‡à¤‚सेटिंगà¥à¤¸à¤¸à¥‡à¤Ÿà¤¿à¤‚गà¥à¤¸ को बचाया गया हैछायाछाया का रंगछाया की सà¥à¤¥à¤¿à¤¤à¤¿à¤®à¤œà¤¬à¥‚तकà¥à¤› विषयों या पृषà¥à¤  निरà¥à¤®à¤¾à¤¤à¤¾à¤“ं (Fe. टà¥à¤°à¤¿à¤ª आरà¥à¤•à¤¿à¤Ÿà¥‡à¤•à¥à¤Ÿ, Optimizepress आदि) आंतरिक सà¥à¤Ÿà¤¾à¤‡à¤²à¥‹à¤‚ को हटा सकते हैं Tag है। आंतरिक लोड सà¥à¤Ÿà¤¾à¤‡à¤² सिसà¥à¤Ÿà¤® टैग इस समसà¥à¤¯à¤¾ को ठीक करेगा और आपके फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ दिखाà¤à¤—ा।विभाजित मोडविभाजित दृषà¥à¤Ÿà¤¿à¤°à¥‡à¤¡à¤¿à¤¯à¥‹ फैलानासà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤‚ग शà¥à¤°à¥‚ करेंडिफ़ॉलà¥à¤Ÿ सà¥à¤Ÿà¤¾à¤‡à¤² योजना बनाना शà¥à¤°à¥‚ करेंअपने आप को बनाने के साथ शà¥à¤°à¥‚ करें पहला संपरà¥à¤• फॉरà¥à¤® 7 सभी पेशेवर सà¥à¤µà¤¿à¤§à¤¾à¤“ं के साथ अपने 14 दिन मà¥à¤«à¥à¤¤ परीकà¥à¤·à¤£ शà¥à¤°à¥‚ करें यहाठ!चरण 1। Admin page list में "edit with thrive architect" लिंक पर कà¥à¤²à¤¿à¤• करेंचरण 2। सही ऊरà¥à¤§à¥à¤µà¤¾à¤§à¤° मेनू पर "सेटिंगà¥à¤¸" आइकन पर कà¥à¤²à¤¿à¤• करेंचरण 3। "उनà¥à¤¨à¤¤ सेटिंगà¥à¤¸" => "सीà¤à¤¸à¤à¤¸ में अनà¥à¤­à¤¾à¤— »चरण 4। यह सà¥à¤¨à¤¿à¤¶à¥à¤šà¤¿à¤¤ करें कि "सीà¤à¤¸à¤à¤¸ से बाहर न निकलें ' जांच की जा रही हैचरण 5। “Save Work†बटन पर कà¥à¤²à¤¿à¤• करेंवैशà¥à¤µà¤¿à¤• सà¥à¤¤à¤° पर à¤à¤• कà¥à¤²à¤¿à¤• में सभी फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤²à¤¸à¥à¤Ÿà¤¾à¤‡à¤² पà¥à¤°à¤¤à¥à¤¯à¥‡à¤• आकार किसी भी सà¥à¤Ÿà¤¾à¤‡à¤² योजना के साथ वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त रूप सेसà¥à¤Ÿà¤¾à¤‡à¤² योजना सभी रूपों के लिठअकà¥à¤·à¤® हैइस फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² योजना अकà¥à¤·à¤® हैइस फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² योजना सकà¥à¤·à¤® हैशैली का चयन नहीं किया गया हैशैली योजनाओं की सूचीसà¥à¤Ÿà¤¾à¤‡à¤² पà¥à¤°à¥€à¤µà¥à¤¯à¥‚सà¥à¤Ÿà¤¾à¤‡à¤² सिसà¥à¤Ÿà¤® सेटिंगà¥à¤¸à¤¸à¥à¤Ÿà¤¾à¤‡à¤² में लोड किया जाà¤à¤—ा Tagसà¥à¤Ÿà¤¾à¤‡à¤² में लोड किया जाà¤à¤—ा Tagसफलतासमरà¥à¤¥à¤¨ और KBटैबलेट दृशà¥à¤¯à¤°à¤‚ग का पाठइस शैली योजना को वैशà¥à¤µà¤¿à¤• रूप से सभी रूपों के लिठसकà¥à¤·à¤® किया गया है। यदि आप संपरà¥à¤• फॉरà¥à¤® के लिठअपने विषय के शैली का उपयोग करना चाहते हैं, तो 7 कà¥à¤²à¤¿à¤• करें "अकà¥à¤·à¤®" बटन।इस फॉरà¥à¤® के साथ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ % à¤à¤¸ वैशà¥à¤µà¤¿à¤• रूप से, आप इसे वरà¥à¤¤à¤®à¤¾à¤¨ शैली योजना के साथ सà¥à¤Ÿà¤¾à¤‡à¤² कर सकते हैं।इस फॉरà¥à¤® के साथ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ % à¤à¤¸ , आप इसे वरà¥à¤¤à¤®à¤¾à¤¨ शैली योजना के साथ सà¥à¤Ÿà¤¾à¤‡à¤² कर सकते हैं।यह फॉरà¥à¤® वरà¥à¤¤à¤®à¤¾à¤¨ शैली योजना के साथ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ है, आप इसे अकà¥à¤·à¤® कर सकते हैं और वैशà¥à¤µà¤¿à¤• सेटिंगà¥à¤¸ का उपयोग कर सकते हैं।यह फॉरà¥à¤® किसी भी शैली योजना के साथ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ नहीं है, आप इस फॉरà¥à¤® के लिठवरà¥à¤¤à¤®à¤¾à¤¨ योजना को सकà¥à¤·à¤® कर सकते हैं या "सभी फॉरà¥à¤®à¥‹à¤‚ के लिठउपयोग" पर कà¥à¤²à¤¿à¤• करके वैशà¥à¤µà¤¿à¤• शैली योजना सेट कर सकते हैं।इस योजना का असà¥à¤¤à¤¿à¤¤à¥à¤µ नहीं हैटॉबियास कॉनराडटà¥à¤¯à¥‚टोरियलअनैचà¥à¤›à¤¿à¤•Pro के लिठUpgradeImage अपलोड करेंऊरà¥à¤§à¥à¤µà¤¾à¤§à¤° लंबाWOW सà¥à¤Ÿà¤¾à¤‡à¤² संपरà¥à¤• फॉरà¥à¤® 7सà¥à¤µà¤¾à¤—त हैविशालहाठहाà¤à¤†à¤ª वरà¥à¤¤à¤®à¤¾à¤¨ योजना सेटिंगà¥à¤¸ के साथ à¤à¤• नया सà¥à¤Ÿà¤¾à¤‡à¤² योजना बना सकते हैं। यदि आप नीचे सफेद शैली Schem Unchek चेकबॉकà¥à¤¸ बनाना चाहते हैं।आप नहीं हटा सकतेआप इस पृषà¥à¤  पà¥à¤°à¤•à¤¾à¤° पर इन सेटिंगà¥à¤¸ का उपयोग नहीं कर सकते हैंआपके पास कोई संपरà¥à¤• फॉरà¥à¤® नहीं है 7 आइटमआप संपरà¥à¤• फॉरà¥à¤® 7 के लिठकिसी भी सà¥à¤Ÿà¤¾à¤‡à¤² योजना का उपयोग नहीं करते हैं। वैशà¥à¤µà¤¿à¤• सà¥à¤¤à¤° पर वरà¥à¤¤à¤®à¤¾à¤¨ योजना का उपयोग करने के लिठ"सभी फॉरà¥à¤®à¥‹à¤‚ के लिठउपयोग" पर कà¥à¤²à¤¿à¤• करें।हटाठगà¤à¤¸à¤­à¥€ रूपों के लिठउपलबà¥à¤§ हैà¤à¤šà¤Ÿà¥€à¤ªà¥€à¤à¤¸: //Saleswonder.BizHttps: //Saleswonder.Biz/Blog/4Free-Contact-Form-7-Cf7-Formular-Und-Klick-Tipp-Einfach-Verbinden/languages/cf7-styler-fr_FR.po000064400000115466146725417150012076 0ustar00msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: Wow style (ES)\n" "Language: fr-FR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "POT-Creation-Date: 2020-04-18 12:29+0000\n" "PO-Revision-Date: 2023-04-15 16:08+0000\n" "Last-Translator: Tobias support@saleswonder.biz\n" "Language-Team: French (France)\n" "Report-Msgid-Bugs-To: \n" "X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- désactiver le thème de style -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "- choisir -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "Période d'essai de 14 jours" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #| msgid "" #| "%s used for all forms globally, click \"Use for all forms\" if you want to " #| "use current Scheme." msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%s utilisés globalement pour tous les formulaires, cliquez sur « Utiliser " "pour tous les formulaires » si vous souhaitez utiliser le Thème actuel." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "Activez le style pour tous les formulaires*" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Activer le style pour le formulaire actuel" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "En option, vous pouvez désactiver le nettoyage de styles, comme dans le plug-" "in Thrive Architect :" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "Couleur de fond" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "Image de fond" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Avant d'utiliser l’extension WOW Style Contact Form 7, vous devez installer " "et activer l’extension Contact Form 7." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "Couleur de fond" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "Transparence de fond" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "Rayon de flou" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "Bordure" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "Couleur de la bordure" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "Rayon de la bordure" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "Type de la bordure" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "Largeur de la bordure" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "Bordure de bouton" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "Boutons" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Auteur : Takayuki Miyoshi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "Annuler" #: cf7-styler.php:129 msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "L’extension pour modifier les styles du Contact Form 7 nécessite " "l'installation et l'activation de l’extension du formulaire Contact Form 7. " "Vous pouvez télécharger %s." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "Le formulaire CF7 n'est pas sélectionné" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "CF7 Styler" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "Champs de sélection multiples et uniques" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "Nettoyer les styles" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "Nettoyer" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "Fermer" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "Couleur" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "Liste des formulaires CF7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "Contenir" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Copier les paramètres de le thème de style actuel" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "Couvrir" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "Créer" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "Créer plusieurs thèmes de style" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "Créer un nouveau thème de style!" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Style actuel" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "Actuellement, le formulaire " "%s est stylé avec " "%s. Comme dans la version gratuite, vous ne pouvez styler qu'un " "seul formulaire à la fois et si vous activez le style pour le formulaire en " "cours, le style sera supprimé pour les autres formulaires." #: admin/class-cf7-customizer-admin.php:481 #| msgid "" #| "Currently %s form is styled with %s. As in free version you can style only " #| "one form at a time and if you activate style for current form, style will be " #| "removed from other form." msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "Actuellement, le formulaire %s est stylé avec " "%s. Comme dans la version gratuite, vous ne pouvez styler qu'un " "seul formulaire à la fois et si vous activez le style pour le formulaire " "actuel, le style sera supprimé pour les autres formulaires." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "CSS personnalisé" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "Code CSS personnalisé" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "Un trait en pointillés (tirets)" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "Thème par défaut" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "Supprimer l'image" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "supprimée" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "Vue de bureau" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "Désactiver le style pour tous les formulaires" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "Désactiver le style du formulaire actuel" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "Voulez-vous obtenir la version premium de styler gratuitement ? Alors Entrez votre " "licence WP2LEADS pro ou obtenez une licence " "ici !" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "" "Souhaitez-vous enregistrer vos modifications avant de quitter la page ?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "Un trait en pointillés (points)" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "Trait double" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "Dupliquer le formulaire dans la deuxième colonne" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "activé pour tous les formulaires" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "Erreur" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "Sortir du plein écran" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "Famille de polices" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "Taille de police" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Style de police" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "Poids de police" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Image et couleurs de fond du formulaire" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "Personnalisation du formulaire" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Aucun formulaire n'a été sélectionné" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "Remplissage, marge et bordure du formulaire" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "Texte du formulaire" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "Plein écran" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "En relief" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "Longueur horizontale" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Couleur de fond survolé" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "Couleur survolée" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Couleur du texte survolé" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "Comment créer un formulaire de contact Contact Form 7, qui non seulement " "aura un aspect professionnel et attrayant et sera facile à utiliser, mais " "qui aura également un taux de conversion élevé et générera des demandes de " "renseignements sur les offres" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "https://saleswonder.biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "J'aime ça ! Sauvegarder" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "Si vous utilisez des constructeurs de pages, comme Thrive Architect, " "OptimizePress etc., veuillez consulter notre Page de la base de connaissances " "pour résoudre les problèmes éventuels" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "Si vous avez besoin de charger un schéma de style à l'intérieur de la balise " "<body> uniquement sur certaines pages, vous pouvez le " "faire sur le frontend en utilisant le bouton \"CF7 Styler\". Cette fonction " "n'est disponible que pour les types d'articles (pages, articles, produits, " "etc.) et dans la version premium. Vous ne pouvez pas le faire sur les pages " "d'archives (blog, liste de produits etc.) dans ce cas vous devez utiliser " "les paramètres globaux." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "Si vous avez besoin de charger un schéma de style à l'intérieur de la balise " "<body> uniquement sur certaines pages, vous pouvez le " "faire sur le frontend en utilisant le bouton \"CF7 Styler\". Cette fonction " "n'est disponible que pour les types d'articles (pages, articles, produits, " "etc.). Vous ne pouvez pas le faire sur les pages d'archives (blog, liste de " "produits etc.) dans ce cas vous devez utiliser les paramètres globaux." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "Les paramètres de l'image de fond ne sont disponibles que pour la version " "Professional en mode temps réel. Vous pouvez les essayer dans le mode de " "prévisualisation « style actuel », mais ils ne seront pas enregistrés." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "Transparence de l'image" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "Position de l'image" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "Taille de l'image" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "Hériter" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "Champs de saisie" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "Nom du thème de style de saisie" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "Effet 3D global enfoncé" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "Italique" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "Couleur des étiquettes" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "Taille de police de l'étiquette" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "Paramètres de l'étiquette" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "Licence" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "Hauteur de la ligne" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "Couleur des liens" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "Couleur des liens survolés" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Paramètres des liens" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "En direct" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "Charger les styles dans la balise <body>" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "" "Charger les styles à l'intérieur de la balise <body> sur " "cette page" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "Définir un champ à choix multiple pour chaque ligne" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "Fixer la pleine largeur?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "Configurer les champs d'entrée sur toute leur largeur?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Définir un champ de sélection unique dans chaque ligne" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "Marge" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "Vue dans la cellule" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "NON" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "Aucun élément du formulaire Contact Form 7 à visualiser" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "Aucun formulaire n'est modifié avec le thème de style. Pour appliquer le " "thème de style actuelle à ce formulaire, cliquez sur « Activer le style du " "formulaire actuel »." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "Aucune extension n'est sélectionnée pour l'installation" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "Aucun thème de style n'a été sélectionné" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "Normal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "Oblique" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "La définition d'un champ de sélection multiple et d'un champ de sélection " "unique n'est possible que dans la version Professional. Vous pouvez " "l’essayer dans le mode de prévisualisation « style actuel », mais elle ne " "sera pas enregistrée." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "Transparence" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "Ouvrez le Styler" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "S'inscrire pour voir le compte" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "Taille originale" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "Contour" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "Effet 3D global surélevé" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "Remplissage" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "Entrez un thème de style de saisie" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "Aperçu" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "Mode d’aperçu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "Aperçu du style non modifié" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "Rayon" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "Répéter les deux" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "Répéter horizontalement" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "Répéter verticalement" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Rétablir les paramètres par défaut" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "Un trait avec effet 3D: bourrelet" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "Sauvegarder" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "Sauvegardé" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "Vue de la deuxième colonne" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "Sélectionner un thème de style pour ce formulaire" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "Paramètres" #: admin/class-cf7-customizer-admin-ajax.php:210 #| msgid "Settings saved as" msgid "Settings saved as " msgstr "Paramètres enregistrés sous" #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "Ombre" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "Couleur de l’ombre" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Position de l'ombre" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "Trait plein" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 #| msgid "" #| "Some themes or page builders (e.g. Thrive Architect, OptimizePress etc.) " #| "could remove inline styles inside tag. Loading style scheme within " #| " tag will fix this issue and show your forms styled." msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Certains motifs ou assistants de création de sites (par exemple Thrive " "Architect, OptimizePress, etc.) peuvent supprimer les styles locaux (inline " "styles) à l'intérieur de la balise . L'ajout d'un thème de style à " "l'intérieur de la balise résoudra ce problème et vos formulaires " "auront un style modifié." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "Mode de vue fractionnée" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "Vue fractionnée" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "Rayon de diffusion" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "Commencez à modifier le style" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "Commencez par créer un thème de style par défaut" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "Commencez par créer votre premier " "Contact Form 7" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "Commencez votre essai gratuit de 14 jours avec toutes les fonctions " "professionnelles ici !" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "Étape 1 : Cliquez sur le lien « Edit with Thrive Architect » (Modifier avec " "Thrive Architect) dans la liste des pages administrateur" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "" "Étape 2 : Cliquez sur l'icône « Settings » (Paramètres) dans le menu " "vertical de droite" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 #| msgid "Step 3. \"Advanced settings\" => \"CSS in the section\"" msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "" "Étape 3 : « Advanced settings » (Paramètres avancés) => « CSS in the " "section» (CSS dans la section )" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 #| msgid "Step 4. Make sure that \"Do not strip CSS from \" is checked" msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "Étape 4 : Assurez-vous que l'option « Do not strip CSS from » (Ne pas " "supprimer le CSS de la section ) est cochée" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "Étape 5 : Cliquez sur le bouton « SAVE WORK » (SAUVEGARDER LE TRAVAIL)" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "Modifiez le style de tous les formulaires globalement en un seul clic" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "" "Modifiez le style de chaque formulaire individuellement en utilisant " "n'importe quel thème" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "Le thème de style est désactivé pour tous les formulaires" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "Le thème de style est désactivé pour ce formulaire" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "Le thème de style est activé pour ce formulaire" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "Le thème de style n'est pas choisi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "Liste des thèmes de style" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "Aperçu des thèmes de style" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "Paramètres des thèmes de style" #: admin/class-cf7-customizer-admin-ajax.php:298 #| msgid "Style will be loaded in tag" msgid "Style will be loaded in tag" msgstr "Le style sera chargé dans la balise" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "Le style sera chargé dans la balise " #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "Effectué avec succès" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "Support & KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "Vue dans la tablette" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "Couleur du texte" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #| msgid "" #| "This form is styled with %s globally, you can style it with current Style " #| "scheme." msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "Le style de ce formulaire est modifié globalement avec %s, vous pouvez le " "modifier avec le thème de style actuel." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #| msgid "" #| "This form is styled with %s, you can style it with current Style scheme." msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "Le style de ce formulaire est modifié avec %s, vous pouvez le modifier avec " "le thème de style actuel." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "Le style de ce formulaire est modifié avec le Thème de style actuel, vous " "pouvez le désactiver et utiliser les paramètres globaux." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "Le style de ce formulaire n'est modifié par aucun thème de style, vous " "pouvez soit activer le thème actuel pour ce formulaire, soit définir le " "modèle de style global en cliquant sur « Utiliser pour tous les formulaires " "» sous le nom du thème." #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "Ce thème n'existe pas" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "Ce thème de style est activé globalement pour tous les formulaires. Si vous " "souhaitez utiliser un style de votre motif pour le formulaire Contact Form 7," " cliquez sur le bouton « Désactiver »." #. Author of the plugin msgid "Tobias Conrad" msgstr "Tobias Conrad" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "Tutoriel" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "Style non modifié" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "Mise à jour vers la version Pro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "Charger l'image" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "Longueur verticale" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "Bienvenu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "Largeur" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "WOW Style Contact Form 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "OUI" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 #| msgid "" #| "You can create new style scheme with current scheme settings. If you want to " #| "create blank style scheme uncheck checkbox below." msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "Vous pouvez créer un nouveau thème de style avec les paramètres du thème " "actuel. Si vous souhaitez créer un thème de style vide, décochez la case ci-" "dessous." #: admin/class-cf7-customizer-admin-ajax.php:237 #| msgid "You cannot delete" msgid "You can not delete" msgstr "Vous ne pouvez pas supprimer" #: public/class-cf7-customizer-public.php:471 #| msgid "You cannot use this settings on this page type" msgid "You can not use this settings on this page type" msgstr "" "Vous ne pouvez pas utiliser ces paramètres sur des pages comme celle-ci" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "Vous n'avez pas d'éléments de formulaire Contact Form 7" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "Vous n'utilisez aucun thème de style pour le formulaire Contact Form 7. " "Cliquez sur « Utiliser pour tous les formulaires » pour utiliser la thème " "actuel de façon globale." languages/cf7-styler-de_DE.po000064400000111154146725417150012026 0ustar00msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-02-06 11:35+0000\n" "PO-Revision-Date: 2023-04-15 16:02+0000\n" "Last-Translator: Tobias support@saleswonder.biz\n" "Language-Team: German\n" "Language: de-DE\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Loco https://localise.biz/\n" "X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- Style deaktivieren -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "- wähle -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14 Tage testen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%s-Style ist derzeit für alle Formulare aktiviert. Klicke " "auf den Button \"Aktiviere den Style für alle Formulare\" um den " "ausgewählten Style für alle Formulare zu nutzen. *Einzeln gestylte Formulare " "behalten ihren Style" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "Aktiviere den Style für alle Formulare*" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Aktiviere den Style für das ausgewählte Formular" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "Alternative kannst du das Entfernen der Styles deaktivieren wie im Beispiel " "Thrive Architect:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "Hintergrundfarbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "Hintergrundbild" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Bevor mit WOW-Stil Contact Form 7, müssen Sie installieren und aktivieren " "Contact Form 7 plugin." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "Hintergrund-Farbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "Hintergrund-Deckkraft" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "Weichzeichner-Radius" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "Rahmen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "Rahmenfarbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "Rahmen-Radius" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "Rahmen-Style" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "Rahmenbreite" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "Button-Rahmen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "Button(s)" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Von Takayuki Miyoshi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "Abbrechen" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "Contact Form 7 Styler erfordert ein installiertes und aktiviertes Contact " "Form 7-Plugin. Du kannst es hier herunterladen %s." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "Bitte wähle ein CF7-Formular" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "CF7 Styler" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "Checkboxen & Radiobuttons" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "Auf Default-Style zurücksetzen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "Leeren" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "Schließen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "Farbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "Contact Form 7-Auswahl" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "enthalten" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Kopiere die aktuellen Style-Einstellungen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "gefüllt" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "Erstellen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "Erstelle mehrere Style-Vorlagen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "Neuen Style erstellen!" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Vorschau" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "Im Moment ist das Formular " "%s ist mit Style " "%s gestyled. Nachdem du in der Free Version nur ein Formular " "zurzeit stylen kannst, wird bei Auswahl eines anderen Formulars das zuletzt " "gestylte Formular ungestyled." #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "Im Moment ist das Formular %s ist mit Style " "%s gestyled. Nachdem du in der Free Version nur ein Formular " "zurzeit stylen kannst, wird bei Auswahl eines anderen Formulars das zuletzt " "gestylte Formular ungestyled." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "Benutzerdefiniertes CSS" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "Benutzerdefinierter CSS-Code" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "Gestrichelte" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "Standard-Style" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "Bild löschen" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "gelöscht" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "Desktop-Ansicht" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "Deaktiviere den Style für alle Formulare" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "Deaktiviere den Style für das aktuelle Formular" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "Möchtest du die Styler Premium Version for free? Dann gebe hier deine WP2LEADS Pro Lizenz-" "Daten ein oder hole dir hier jetzt eine Lizenz und " "verbinde deine WordPress-Plugins mit Klick-Tipp!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "Möchtest du die Einstellungen speichern bevor du die Seite verlässt?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "Gepunktet" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "Doppelt" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "Dupliziere Formular in der zweiten Spalte" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "Aktiviere den Style für alle Formulare" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "Achtung!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "Vollbildmodus verlassen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "Schriftfamilie" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "Schriftgröße" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Schrift-Stil" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "Schrift-Stärke" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Formular-Hintergrundbild & Farbe" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "Formular-Anpassung" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Kein Formular ausgewählt" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "Formular-Abstände, Rahmen & Schatten" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "Formular-Text, Links & Labels" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "Vollbild" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "Groove" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "Horizontale Breite" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Hover-Hintergrundfarbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "Hover-Farbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Hover-Text Farbe" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "Wie Sie Ihren Kontakt form7 form in a-Konvertierung und einfach zu bedienen " "und pro-styled Kontaktformular, \"Umfrage\" lead-generator oder eine " "auffällige form" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "https://saleswonder.biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "Ich bin glücklich sowie es ist! Bitte speichern!" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "Wenn du deinen Style nur auf bestimmten Seiten mit dem <body>" " Tag laden möchtest, nimm die Einstellungen direkt auf der Seite vor. " "Dazu kannst du dort den \"CF7 Styler\" Button nutzen. \n" "Diese Funktion ist nur single post types wie Seiten, Beiträge, Produkte usw. " "und in der Premium Version verfügbar. Für Archiv-Seiten (Blog, Products " "Listen usw. steht diese Funktion nicht zur Verfügung. Nutze in diesem Fall " "die globale Einstellung direkt über diesem Text." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "Wenn du deinen Style nur auf bestimmten Seiten mit dem <body>" " Tag laden möchtest, nimm die Einstellungen direkt auf der Seite vor. " "Dazu kannst du dort den \"CF7 Styler\" Button nutzen. \n" "Diese Funktion ist nur single post types wie Seiten, Beiträge, Produkte usw. " "und in der Premium Version verfügbar. Für Archiv-Seiten (Blog, Products " "Listen usw. steht diese Funktion nicht zur Verfügung. Nutze in diesem Fall " "die globale Einstellung direkt über diesem Text." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "Die Hintergrund-Einstellungen bleiben der Pro Version vorbehalten. Du kannst " "jedoch das Ergebnis in der Vorschau-Ansicht testen, jedoch nicht speichern." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "Bild Deckkraft" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "Bild-Position" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "Füll-Eigenschaften" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "Vererbt" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "Eingabe-Felder" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "Benenne deinen Style" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "Innen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "Kursiv" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "Label-Farbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "Schriftgröße" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "Label-Einstellungen" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "Lizenz" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "Zeilenhöhe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "Link Farbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "Link hover Farbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Link-Einstellungen" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "Live" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "Lade Styles im <body> Tag" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "" "Lade die Styles über den
HTML-<body>-Tag in diese " "Seite." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "Nur eine Checkbox pro Zeile" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "In voller Breite anzeigen?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "Möchtest du die Eingabefelder in voller Breite?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Nur ein Radiobutton pro Zeile" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "Äußerer Abstand" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "Mobile-Ansicht" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "Nein" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "Kein Contact Form 7 Formular für die Vorschau vorhanden" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "Keines deiner Formulare ist gestyled. Klicke \"Aktiviere den Style für das " "aktuelle Formular\" um das ausgewählte Formular zu stylen." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "Kein Plugin zur Installation ausgewählt" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "Kein Style ausgewählt" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "Normal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "Oblique" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "Das untereinander Anordnen der Checkboxen und Radiobuttons bleibt der Pro " "Version vorbehalten. Du kannst jedoch das Ergebnis in der Vorschau-Ansicht " "testen, jedoch nicht speichern." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "Deckkraft" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "Öffne CF7 Styler" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "Opt-in um Konto zu sehen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "original Größe" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "Außen" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "Outset" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "Innere Abstand" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "Gib deinem Style einen Namen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "Ansicht" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "Ansicht" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "Vorschau deaktivieren" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "Radius" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "vertikal & horizontal wiederholt" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "horizontal wiederholt" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "vertikal wiederholt" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Zum Default-Style" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "Ridge" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "Speichern" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "Gespeichert" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "Ansicht der zweiten Spalte" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "Wähle den Style für dieses Formular" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "Einstellungen" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "Dein Style wurde gespeichert unter " #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "Schatten" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "Schatten-Farbe" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Schatten-Position" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "Solid" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Nutze diese Funktion wenn deine Formulare gar nicht gestyled werden. Da " "einige Themes oder Page Builder wie Thrive Architect, OptimizePress usw. die " "Styles aus dem <head> Tag entfernen können, gibt es die " "Option die Styles im <body> Tag zu Laden. Dadurch werden " "deine Formulare wieder gestyled." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "Geteilt" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "Geteilte Ansicht" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "Schatten-Größe" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "Beginne mit dem stylen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "Beginne mit dem Erstellen des Standard-Styles" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "Beginne mit dem Erstellen deines ersten " "Contact Form 7 Formulars" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "Starte deine 14-Tage-Testversion mit allen Pro-Funktionen hier!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "Schritt 1: In der Admin-Seiten-Ãœbersicht klicke auf den \"Edit with Thrive " "Architect\" -Link der Seite mit dem Formular." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "" "Schritt 2: Klicke auf das \"Settings\" - Symbol im rechten vertikalen Menü" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "" "Schritt 3: Klicke \"Erweiterte Einstellungen\" => \"CSS in the <" "head> section\"" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "Schritt 4: Stelle sicher, dass \"Do not strip CSS from <head>" "\" ausgewählt ist" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "Schritt 5. Klicke auf den \"SAVE WORK\" Button" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "Style alle Formulare global" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "Style jedes Formular in einem anderen Style" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "Deaktiviere den Style für alle Formulare" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "Der Style ist für dieses Formular ist deaktiviert " #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "Der Style ist für dieses Formular ist aktiviert " #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "Kein Style ausgewählt" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "CF7-Style-Auswahl" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "Formular-Vorschau" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "CF7-Style-Einstellungen" #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "Style wird im <body> Tag geladen" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "Style wird im -Tag geladen" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "Erfolgreich" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "Unterstützung & KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "Tablet-Ansicht" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "Text Farbe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "Das derzeitige und andere Formulare sind mit dem %s-Style " "gestaltet. Du kannst mit einem Klick auch den derzeitigen Style aktivieren." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "Der zur Zeit genutzte Style des Formulars ist %s. Du kannst " "auch unten klicken und den ausgewählten Style anwenden." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "Für dieses Formular ist der aktuelle Style aktiviert. Du kannst diesen Style " "deaktivieren und so zum globalen Style zurückkehren." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "Dieses Formular benutzt noch keinen Style. Du kannst den derzeitigen Style " "für das angezeigte Formular aktivieren oder mit dem Klick auf \"Aktiviere " "Style für alle Formulare\" den Style generell für alle Formulare festlegen. " "*Einzeln gestylte Formulare behalten ihren Style" #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "Dieser Style existiert nicht" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "Dieser Style ist global für alle Formulare aktiviert. Wenn du den Style " "deines Themes nutzen möchtest, dann klicken auf den \"Deaktiviere den Style " "für alle Formulare\"-Button. *Einzeln gestylte Formulare behalten ihren Style" #. Author of the plugin msgid "Tobias Conrad" msgstr "Tobias Conrad" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "Tutorial" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "Ohne Style" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "Upgrade auf Pro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "Bild hochladen" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "Vertikaler Breite" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "Willkommen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "Breite" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "WOW Style Contact Form 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "Ja" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "Du kannst hier ein Style mit den aktuellen Einstellungen abspeichern. Wenn " "du einen leeren Style abspeichern möchtest entferne den Haken." #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "Löschen nicht möglich" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "Du kannst diese Einstellungen nicht für diesen Seitentyp nutzen." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "Du hast noch kein Contact Form 7 Formular erstellt" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "Du verwendest derzeit keinen Style für deine Contact Form 7 Formulare. " "Klicke auf \"Aktiviere den Style für alle Formulare\", um den angezeigten " "Style global zu aktivieren. *Einzeln gestylte Formulare behalten ihren Style" languages/cf7-styler.pot000064400000066270146725417150011264 0ustar00#, fuzzy msgid "" msgstr "" "Language: \n" "POT-Creation-Date: 2023-04-15 16:12+0000\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: Loco https://localise.biz/" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "" #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" #. Author of the plugin msgid "Tobias Conrad" msgstr "" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" languages/cf7-styler-vi.po000064400000113720146725417150011505 0ustar00msgid "" msgstr "" "Language: vi\n" "POT-Creation-Date: 2020-02-06 11:35+0000\n" "Plural-Forms: nplurals=1; plural=0;\n" "PO-Revision-Date: 2023-04-15 16:10+0000\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: WOW Style Contact Form 7\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: Tobias support@saleswonder.biz\n" "Language-Team: Vietnamese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- Chế Ä‘á»™ phong cách -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "Chá»n -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14 Ngày Tòa án" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "% s Äược sá»­ dụng cho tất cả các biểu mẫu trên toàn cầu, hãy " "bấm \"sá»­ dụng cho tất cả các biểu mẫu\" nếu bạn muốn sá»­ dụng biểu mẫu hiện " "tại." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "Tích hoạt phong cách cho tất cả các hình thức *" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Tích hoạt phong cách cho hình thức hiện tại" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "Là má»™t lá»±a chá»n thay thế, bạn có thể vô hiệu hóa việc làm sạch các phong " "cách nhÆ° trên phrive architect:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "Màu ná»n" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "Hình ná»n" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "TrÆ°á»›c khi sá»­ dụng biểu mẫu liên hệ kiểu Wow 7, bạn cần cài đặt và kích hoạt " "biểu mẫu liên hệ 7 Plugin." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "Bg Màu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "Bg Khả năng" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "Bạch á»c" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "biên giá»›i" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "Màu biên giá»›i" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "Biên giá»›i radius" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "Loại biên giá»›i" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "biên giá»›i rá»™ng" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "nút biên giá»›i" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "Bút" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Tác giả: Takayuki Miyoshi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "hủy" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "Cf7 Customizer yêu cầu biểu mẫu liên hệ 7 Plugin để cài đặt và hoạt Ä‘á»™ng. " "Bạn có thể tải xuống % S." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "Cf7 không được chá»n" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "Cf7 phong cách" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "Chế Ä‘á»™ kiểm tra & Radiobuttons" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "phong cách sạch" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "rõ ràng" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "gần" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "Màu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "Hình thức liên hệ 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "Ná»™i dung" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Sao chép các cài đặt phong cách hiện tại" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "Màn hình Cover" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "tạo ra" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "Tạo nhiá»u phong cách" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "Tạo má»™t phong cách má»›i!" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Phong cách hiện tại" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "Hiện tại % s Hình thức " "được thiết kế vá»›i % s " ". NhÆ° trong phiên bản miá»…n phí bạn có thể phong cách chỉ má»™t biểu " "mẫu cùng má»™t lúc và nếu bạn kích hoạt phong cách cho biểu mẫu hiện tại, " "phong cách sẽ được loại bá» từ biểu mẫu khác." #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "Hiện tại % s Hình thức được thiết kế vá»›i % s " ". NhÆ° trong phiên bản miá»…n phí bạn có thể phong cách chỉ má»™t biểu " "mẫu cùng má»™t lúc và nếu bạn kích hoạt phong cách cho biểu mẫu hiện tại, " "phong cách sẽ được loại bá» từ biểu mẫu khác." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "Tùy chỉnh CSS" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "Mã CSS tùy chỉnh" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "Dashuất" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "Hệ thống mặc định" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "xóa hình ảnh" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "xóa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "Màn hình Desktop" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "Loại phong cách vô hiệu cho tất cả các hình thức" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "Chặn phong cách cho hình thức hiện tại" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "Bạn có muốn có được phiên bản Premium Styler miá»…n phí không? Sau đó Nhập Wp2Leads Pro " "License của bạn Hoặc có giấy phép Ở đây " "!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "Bạn muốn lÆ°u các thay đổi trÆ°á»›c khi rá»i khá»i trang?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "DOTTED" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "Double Äôi" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "Duplicate form trong cá»™t thứ hai" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "Có sẵn cho tất cả các hình thức" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "Lá»—i" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "Màn hình Full Screen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "Font gia đình" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "font kích thÆ°á»›c" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Phong cách Font" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "font trá»ng lượng" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Hình ảnh BG & Màu sắc" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "Hình thức Customize" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Hình thức không được chá»n" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "Hình thức padding, margin & border" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "Form văn bản" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "màn hình đầy đủ" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "Trưởng" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "Chiá»u dài horizontal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Màu sắc Hover BG" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "Hover Màu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Hover Text Màu sắc" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "Làm thế nào để biến hình thức liên hệ của bạn Form7 thành má»™t hình thức " "chuyển đổi và dá»… sá»­ dụng và hình thức liên hệ theo phong cách chuyên nghiệp, " "máy phát sáng \"há»c\" hoặc hình thức chụp mắt" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "Https: //Saleswonder.biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "Https: //Saleswonder.Biz/Blog/4Free-Contact-Form-7-Cf7-Formular-Und-Klick-" "Tipp-Einfach-Verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "Tôi hài lòng vá»›i Ä‘iá»u này! tiết kiệm" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "Nếu bạn Ä‘ang sá»­ dụng các nhà xây dá»±ng trang, chẳng hạn nhÆ° thrive architect, " "Optimizepress vv, vui lòng kiểm tra chúng tôi Trang cÆ¡ sở kiến thức Äể giải " "quyết các vấn Ä‘á» có thể" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "Nếu bạn cần để tải lên phong cách kế hoạch bên trong Nhãn " "chỉ trên má»™t số trang, bạn có thể làm Ä‘iá»u đó trên frontend bằng cách sá»­ " "dụng nút \"Cf7 Styler\". Tính năng này chỉ có sẵn cho các loại bài đăng duy " "nhất (các trang, bài đăng, sản phẩm, v.v.) Và trong phiên bản premium. Bạn " "không thể làm Ä‘iá»u đó trên các trang lÆ°u trữ (Blog, danh sách sản phẩm, v.v.)" " trong trÆ°á»ng hợp này bạn cần sá»­ dụng cài đặt toàn cầu." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "Nếu bạn cần để tải lên phong cách kế hoạch bên trong Nhãn " "chỉ trên má»™t số trang, bạn có thể làm Ä‘iá»u đó trên frontend bằng cách sá»­ " "dụng nút \"Cf7 Styler\". Tính năng này chỉ có sẵn cho các loại bài đăng duy " "nhất (các trang, bài đăng, sản phẩm, vv). Bạn không thể làm Ä‘iá»u đó trên các " "trang lÆ°u trữ (Blog, danh sách sản phẩm, v.v.) trong trÆ°á»ng hợp này bạn cần " "sá»­ dụng cài đặt toàn cầu." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "Cài đặt ná»n hình ảnh có sẵn trong chế Ä‘á»™ sống chỉ cho phiên bản chuyên " "nghiệp. Bạn có thể kiểm tra nó trong chế Ä‘á»™ xem trÆ°á»›c \"trình hiện tại\", " "nhÆ°ng nó sẽ không được tiết kiệm." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "Hình ảnh Opacity" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "Hình ảnh Position" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "hình ảnh kích thÆ°á»›c" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "Di sản" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "Các trÆ°á»ng nhập" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "Tiêu Ä‘á» Input Style Scheme" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "Ấn Äá»™" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "Ã" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "Tags màu sắc" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "Tag: font kích thÆ°á»›c" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "Label thiết lập" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "Giấy phép" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "Ä‘Æ°á»ng cao" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "Màu trái" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "Màu trái hover" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Cài đặt Links" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "Sống" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "Load Styles trong Tag" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "Load Styles bên trong Tag trên trang này" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "Tạo Checkbox item má»™t theo dòng" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "Tải rá»™ng đầy đủ?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "Làm cho các lÄ©nh vá»±c nhập rá»™ng đầy đủ?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Tạo các mục Radiobutton má»™t cho má»—i dòng" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "Margin" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "Mobile xem" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "Không" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "Không có biểu mẫu liên hệ 7 mục để xem trÆ°á»›c" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "Không có biểu mẫu được phong cách vá»›i biểu mẫu phong cách, nhấp vào nút " "\"Aktivate style for current form\" để áp dụng biểu mẫu hiện tại cho biểu " "mẫu này." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "Không có plugin được chá»n để cài đặt" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "Không có phong cách được lá»±a chá»n" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "bình thÆ°á»ng" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "Oblique" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "Má»™t theo dòng phong cách cho Checkboxes và Radiobuttons trong chế Ä‘á»™ sống " "chỉ cho phiên bản chuyên nghiệp. Bạn có thể kiểm tra nó trong chế Ä‘á»™ xem " "trÆ°á»›c \"trình hiện tại\", nhÆ°ng nó sẽ không được tiết kiệm." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "Opacity" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "Mở Styler" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "Opt-in để xem tài khoản" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "Kích thÆ°á»›c gốc" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "Outline Khác" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "ngoài ra" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "Padding" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "Vui lòng nhập kiểu scheme title" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "Dá»± báo" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "chế Ä‘á»™ Preview" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "Preview không thể" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "Radius" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "Lặp lại cả hai" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "Lặp lại horizontal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "Lặp lại vertical" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Khởi Ä‘á»™ng trở lại default" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "Ridge" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "tiết kiệm" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "cứu rá»—i" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "Nhìn Column 2" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "Chá»n biểu mẫu kiểu cho biểu mẫu này" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "Cài đặt" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "Cài đặt được tiết kiệm nhÆ°" #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "bóng tối" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "Màu bóng" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Vị trí bóng" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "Sức mạnh" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Má»™t số chủ Ä‘á» hoặc xây dá»±ng trang (Fe. Thrive kiến trúc sÆ°, Optimizepress vv)" " Có thể loại bá» các phong cách Inline bên trong Tag . " "Loading style scheme trong Tag sẽ khắc phục vấn Ä‘á» này và " "hiển thị các biểu mẫu của bạn được phong cách." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "Mô hình Split" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "View phân chia" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "Tải ra radius" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "Bắt đầu styling" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "Bắt đầu vá»›i việc tạo má»™t kế hoạch phong cách mặc định" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "Bắt đầu bằng cách tạo ra bạn Hình thức " "liên lạc đầu tiên 7 " #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "Bắt đầu thá»­ nghiệm miá»…n phí 14 ngày của bạn vá»›i tất cả các chức năng chuyên " "nghiệp Ở đây !" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "BÆ°á»›c 1 Nhấp vào liên kết \"ed with thrive architect\" trong danh sách trang " "Admin" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "BÆ°á»›c 2 Nhấp vào biểu tượng \"Settings\" trên menu thẳng" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "BÆ°á»›c 3 “Cài đặt nâng cao†=> “CSS trong Phần »" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "BÆ°á»›c 4 Hãy chắc chắn rằng \"không xóa CSS từ » Äã kiểm tra" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "BÆ°á»›c 5 Nhấp vào nút \"save work\"" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "Phong cách tất cả các hình thức trong má»™t cú nhấp chuá»™t toàn cầu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "Phong cách má»—i hình thức vá»›i bất kỳ phong cách kế hoạch riêng lẻ" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "Thiết kế phong cách bị chặn cho tất cả các hình thức" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "Chế Ä‘á»™ phong cách bị chặn cho hình thức này" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "Chế Ä‘á»™ phong cách được kích hoạt cho hình thức này" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "Chế Ä‘á»™ phong cách không được chá»n" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "Danh sách Style Schemes" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "Phong cách Preview" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "Thiết lập Style Schemes" #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "Phong cách sẽ được tải lên trong Tag" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "Phong cách sẽ được tải lên trong Tag" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "Thành công" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "Há»— trợ & KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "Hình ảnh Tablet" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "Text màu sắc" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "Hình thức này được thiết kế vá»›i % s Trên toàn cầu, bạn có " "thể phong cách nó vá»›i phong cách hiện tại." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "Hình thức này được thiết kế vá»›i % s , bạn có thể phong cách " "nó vá»›i phong cách hiện tại." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "Hình thức này được phong cách vá»›i biểu mẫu phong cách hiện tại, bạn có thể " "tắt nó và sá»­ dụng cài đặt toàn cầu." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "Hình thức này không được phong cách vá»›i bất kỳ biểu mẫu phong cách nào, bạn " "có thể bật biểu mẫu hiện tại cho biểu mẫu này hoặc thiết lập biểu mẫu phong " "cách toàn cầu bằng cách nhấp chuá»™t \"làm cho tất cả các biểu mẫu\" bên dÆ°á»›i " "tiêu Ä‘á» biểu mẫu." #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "Hệ thống này không tồn tại" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "Phong cách này cho phép toàn cầu cho tất cả các hình thức. Nếu bạn muốn sá»­ " "dụng phong cách chủ Ä‘á» của bạn cho biểu mẫu liên hệ 7 nhấp vào nút \"không " "thể\"." #. Author of the plugin msgid "Tobias Conrad" msgstr "Äạo diá»…n Tobias Conrad" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "hÆ°á»›ng dẫn" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "không phong cách" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "nâng cấp lên pro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "Tải hình ảnh" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "chiá»u dài vertical" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "Chào mừng" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "rá»™ng" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "Hình thức liên hệ WOW 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "Có" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "Bạn có thể tạo má»™t biểu mẫu phong cách má»›i vá»›i các cài đặt biểu mẫu hiện tại." " Nếu bạn muốn tạo phong cách trắng Schem Unchek Checkbox bên dÆ°á»›i." #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "Bạn không thể xóa" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "Bạn không thể sá»­ dụng cài đặt này trên kiểu trang này" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "Bạn không có bất kỳ hình thức liên lạc 7 mục" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "Bạn không sá»­ dụng bất kỳ biểu mẫu kiểu nào cho biểu mẫu liên hệ 7. Nhấp vào " "\"sá»­ dụng cho tất cả các biểu mẫu\" để sá»­ dụng biểu mẫu hiện tại trên toàn " "cầu." languages/cf7-styler-ja.po000064400000111572146725417150011464 0ustar00msgid "" msgstr "" "Language: ja\n" "POT-Creation-Date: 2020-02-06 11:35+0000\n" "Plural-Forms: nplurals=1; plural=0;\n" "PO-Revision-Date: 2023-04-15 16:09+0000\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: WOW Style Contact Form 7\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Loco-Version: 2.3.3; wp-5.4" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "-を無効ã«ã™ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "-é¸æŠž-" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14日間ã®è©¦ç”¨" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "ã„%s\" " "使用ã®ãŸã‚ã®ã™ã¹ã¦ã®å½¢ã®ä¸–界をクリックã—\"利用ã®ãŸã‚ã®ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ¼ãƒ \"を利用ã™ã‚‹å ´åˆã¯ç¾åœ¨ã®ã‚¹ã‚­ãƒ¼ãƒ ã§ã™ã€‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "起動スタイルã®ãŸã‚ã®ã™ã¹ã¦ã®å½¢æ…‹*" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "起動スタイルをç¾åœ¨ã®å½¢" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "ã®ä»£æ›¿ã¨ã—ã¦ç„¡æ•°ã®çµ„ã¿åˆã‚ã›ã§è‡ªåˆ†ã ã‘ã®ã‚¯ãƒªãƒ¼ãƒ³ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚ˆã†ã«ç”Ÿå»ºç¯‰å®¶:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "背景色" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "背景画åƒ" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "使用å‰ã«ãªã‚“ã¨ã‚¹ã‚¿ã‚¤ãƒ«ã®Contact Form7ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã€æ´»æ€§åŒ–ã®Contact Form7ã®å¼•ã出ã—ãŠã‚ˆã³è¨­å®šãŒã§ãã¾ã™" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "背景ã®è‰²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "BGä¸é€æ˜Žåº¦" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "ブåŠå¾„" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "ボーダー" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "ボーダーã®è‰²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "ボーダーã®åŠå¾„" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "ボーダータイプ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "ボーダー幅" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "ボタンã®å›½å¢ƒ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "ボタン" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "ã«ã‚ˆã‚‹ä¸‰å¥½å­ä¹‹" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "消" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "CF7\"カスタマイズãŒå¿…è¦ã§Contact Form7ã®ãƒ—ラグインを設置ã™ã‚‹å¿…è¦ãŒã‚る。 ダウンロードã§ã%s\"." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "CF7å½¢ãŒé¸æŠžã•ã‚Œã¦ã„ãªã„" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "CF7Styler" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹&Radiobuttons" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "クリーンスタイル" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "明らã‹" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "è¿‘" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "色" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "Contact form7ã®ãƒªã‚¹ãƒˆ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "ã‚’å«ã‚€" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "コピースタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã«è¨­å®š" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "ã‚«ãƒãƒ¼" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "ã®ä½œæˆ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "複数作æˆã™ã‚‹ã‚¹ã‚¿ã‚¤ãƒ«ã‚¹ã‚­ãƒ¼ãƒ " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "æ–°ã—ã„スタイルã®ã‚¹ã‚­ãƒ¼ãƒ !" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "ç¾åœ¨ %s å½¢å¼ã¨ã® %s\". " "ã¨ã—ã¦ç„¡æ–™ç‰ˆã§ãるスタイルã®ä¸€å½¢æ…‹ã§ã‚ã‚Œã°èµ·å‹•ã‚¹ã‚¿ã‚¤ãƒ«ã®ã¾ã¾ã®å½¢ã§ã¯ã€ã‚¹ã‚¿ã‚¤ãƒ«ã‹ã‚‰å‰Šé™¤ã•ã‚Œã‚‹ã‹ã€‚" #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "ç¾åœ¨ %s å½¢å¼ã¨ã® %s\". " "ã¨ã—ã¦ç„¡æ–™ç‰ˆã§ãるスタイルã®ä¸€å½¢æ…‹ã§ã‚ã‚Œã°èµ·å‹•ã‚¹ã‚¿ã‚¤ãƒ«ã®ã¾ã¾ã®å½¢ã§ã¯ã€ã‚¹ã‚¿ã‚¤ãƒ«ã‹ã‚‰å‰Šé™¤ã•ã‚Œã‚‹ã‹ã€‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "カスタムCSS" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "カスタムCSSコード" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "疾走" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "デフォルトã®ã‚¹ã‚­ãƒ¼ãƒ " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "ç”»åƒã®å‰Šé™¤" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "削除" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "デスクトップビュー" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "無効化スタイルã®ãŸã‚ã®ã™ã¹ã¦ã®å½¢æ…‹" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "無効化スタイルをç¾åœ¨ã®å½¢" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "スタイラープレミアムãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ç„¡æ–™ã§å…¥æ‰‹ã—ãŸã„ã§ã™ã‹ï¼Ÿ 次ã«ã€ WP2LEADS proライセンスを入力ã™ã‚‹ã‹ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’å–å¾—ã—ã¾ã™ã“ã¡ã‚‰ï¼" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "ã„変更をä¿å­˜å‰ã®ãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã™ã¹ã事ã¯ä½•ã‹ï¼Ÿ" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "点在" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "ダブル" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "é‡è¤‡ã—ãŸå½¢æ…‹ã®ç¬¬äºŒã®æŸ±" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "有効ãªã™ã¹ã¦ã®å½¢æ…‹" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "エラー" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "å£å…¨ç”»é¢" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "フォントファミリ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "文字サイズ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "フォントスタイル" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "フォントé‡é‡" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "形態画åƒã¨è‰²" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "å½¢å¼ã®ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚º" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "å½¢ãŒé¸æŠžã•ã‚Œã¦ã„ãªã„" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "å½¢ã®ãƒ‘ディングã€ãƒžãƒ¼ã‚¸ãƒ³&ボーダー" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "テキスト形å¼" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "全画é¢" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "æº" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "横ã®é•·ã•" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "ホãƒãƒ¼èƒŒæ™¯ã®è‰²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "ホãƒãƒ¼è‰²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "ホテキストカラーを設定ã—ã¾ã™ã€‚" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "ã©ã®ã‚ˆã†ã«ã”連絡をãŠform7å½¢å¼ã«å¤‰æ›ã™ã‚‹ä½¿ã„ã‚„ã™ãã€ãƒ—ロアã¯ã€ãŠå•ã„åˆã‚ã›ãƒ•ã‚©ãƒ¼ãƒ \"調査\"ã®ç™ºç”Ÿã¾ãŸã¯ç›®ã‚’引ãå½¢" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "https://saleswonder.biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "嬉ã—ã„ã§ã™ã€‚ ä¿å­˜" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "Thrive Architectã€OptimizePressãªã©ã®ãƒšãƒ¼ã‚¸ãƒ“ルダーを使用ã—ã¦ã„ã‚‹å ´åˆã¯ã€ãƒŠãƒ¬ãƒƒã‚¸ãƒ™ãƒ¼ã‚¹ãƒšãƒ¼ã‚¸" "を確èªã—ã¦ãã ã•ã„ 考ãˆã‚‰ã‚Œã‚‹å•é¡Œã®ä¿®æ­£" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "ãŒå¿…è¦ãªå ´åˆã¯è² è·ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ å†…ã® <body> " "ã‚¿ã‚°ã®ã¿ä¸€éƒ¨ã®ãƒšãƒ¼ã‚¸ã§ããªãƒ•ãƒ­ãƒ³ãƒˆã‚¨ãƒ³ãƒ‰ã‚’使用\"CF7Styler\"ボタンを押ã—ã¾ã™ã€‚ ã“ã®æ©Ÿèƒ½ã¯ã‚·ãƒ³ã‚°ãƒ«ãƒã‚¹ãƒˆåž‹(ページã€è£½å“等) " "やプレミアムãƒãƒ¼ã‚¸ãƒ§ãƒ³ã€‚ ã§ãã¾ã›ã‚“アーカイブã®ãƒšãƒ¼ã‚¸ã®ãƒ–ログã§ã¯ã€è£½å“リストãªã©ï¼‰ã‚’ãŠä½¿ã„ã«ãªã‚‹å ´åˆã¯ã‚°ãƒ­ãƒ¼ãƒãƒ«ã‚’設定ã—ã¾ã™ã€‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "ãŒå¿…è¦ãªå ´åˆã¯è² è·ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ å†…ã® <body> " "ã‚¿ã‚°ã®ã¿ä¸€éƒ¨ã®ãƒšãƒ¼ã‚¸ã§ããªãƒ•ãƒ­ãƒ³ãƒˆã‚¨ãƒ³ãƒ‰ã‚’使用\"CF7Styler\"ボタンを押ã—ã¾ã™ã€‚ ã“ã®æ©Ÿèƒ½ã¯ã‚·ãƒ³ã‚°ãƒ«ãƒã‚¹ãƒˆåž‹(ページã€è£½å“ã¾ã™ã€‚ " "ã§ãã¾ã›ã‚“アーカイブã®ãƒšãƒ¼ã‚¸ã®ãƒ–ログã§ã¯ã€è£½å“リストãªã©ï¼‰ã‚’ãŠä½¿ã„ã«ãªã‚‹å ´åˆã¯ã‚°ãƒ­ãƒ¼ãƒãƒ«ã‚’設定ã—ã¾ã™ã€‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "背景画åƒã®è¨­å®šã‚’有ライブモードã®ã¿ã®ãŸã‚ã®å°‚é–€ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã€‚ ã§ãる試験ã§ã®ãƒ—レビューモード\"ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«\"ã§ä¿å­˜ã•ã‚Œã¾ã›ã‚“。" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "ç”»åƒã®ä¸é€æ˜Žåº¦" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "ç”»åƒã®ä½ç½®" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "ç”»åƒã‚µã‚¤ã‚º" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "継承" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "入力分野" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "入力スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã‚¿ã‚¤ãƒˆãƒ«" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "挿入図" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "Italic" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "ラベルã®è‰²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "ラベルフォントサイズ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "ラベル設定" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "ライセンス" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "ライン高ã•" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "リンクã®è‰²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "リンクホãƒãƒ¼è‰²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "リンクã®è¨­å®š" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "ライブ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "è² è·ã‚¹ã‚¿ã‚¤ãƒ«ã§ã® <body> ã‚¿ã‚°" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "è² è·ã‚¹ã‚¿ã‚¤ãƒ«å†…ã« <body> ã‚¿ã‚°ã“ã®ãƒšãƒ¼ã‚¸" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "ã‚’ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹é …ç›®ã®é…ç·š" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "全幅?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "入力分野全幅?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "ã†ãƒ©ã‚¸ã‚ªãƒœã‚¿ãƒ³ã‚’商å“一行ã«ä¸€ã¤ã®" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "証拠金" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "モãƒã‚¤ãƒ«ç«¯æœ«ä¸Šã®è¡¨ç¤º" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "NO" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "ãªã„å½¢ã§7項目プレビュー" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "ç„¡å½¢å¼ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ \"をクリックã—起動スタイルをç¾åœ¨ã®ãƒ•ã‚©ãƒ¼ãƒ \"ボタンã®é©ç”¨ã‚’ç¾è¡Œã‚¹ã‚­ãƒ¼ãƒ ã™ã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚" #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "ãªã„プラグインã®é¸æŠžã‚¤" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "ãªã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’é¸æŠž" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "通常ã®" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "æ–œã‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "一行ã«ä¸€ã¤ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã¨radiobuttonsライブモードã®ã¿ã®ãŸã‚ã®å°‚é–€ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã€‚ " "ã§ãる試験ã§ã®ãƒ—レビューモード\"ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«\"ã§ä¿å­˜ã•ã‚Œã¾ã›ã‚“。" #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "ä¸é€æ˜Žåº¦" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "開放感" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "オプトインã§ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’見る" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "オリジナルサイズ" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "概è¦" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "当åˆ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "パディング" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "ã”入力ãã ã•ã„スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã‚¿ã‚¤ãƒˆãƒ«" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "プレビュー" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "プレビュー表示モード" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "プレビュー Unstyled" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "åŠå¾„" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "ç¹°ã‚Šè¿”ã—両" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "ç¹°ã‚Šè¿”ã—æ°´å¹³" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "ç¹°ã‚Šè¿”ã—åž‚ç›´" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "デフォルトã«ãƒªã‚»ãƒƒãƒˆ" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "尾根" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "ä¿å­˜" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "ä¿å­˜" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "第二列ビュー" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "é¸æŠžã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã®ãŸã‚ã®ã“" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "設定" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "設定ã¨ã—ã¦ä¿å­˜ " #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "å½±" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "å½±ã®è‰²" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "å½±ã®ä½ç½®" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "固体" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "一部ã®ãƒ†ãƒ¼ãƒžã‚„ページビルダー(feã§ã‚る。 ç¹æ „建築家OptimizePress等) を除去ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã‚ã‚‹ã“ã¨ã‚¤ãƒ³ãƒ©ã‚¤ãƒ³ã®ã‚¹ã‚¿ã‚¤ãƒ«å†…ã® " "<head> ã‚¿ã‚°ã§ã™ã€‚ è·ç©ã¿ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ å†…ã® <body> " "ã‚¿ã‚°ã®çµ„ã¿åˆã‚ã›ãŒæ±ºå®šã•ã‚Œã‚‹ã“ã®å•é¡Œæ示ã®å½¢å¼." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "分割モード" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "分割ビュー" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "広ãŒã‚‹åŠå¾„" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "スタイリング開始" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "最åˆã«ä½œæˆãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ " #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "タを作æˆã™ã‚‹ 最åˆã®Contact Form7" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "始ã¾ã‚Šã¯14日間無料ãŠè©¦ã—ã™ã¹ã¦ã®ãƒ—ロã®æ©Ÿèƒ½ ãŒã“ã“ã«!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "ステップ1ã§ã™ã€‚ 編集\"をクリックã—ã¨ç¹æ „建築家\"ã®ãƒªãƒ³ã‚¯ã‚’クリック管ç†è€…ページリスト" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "ステップ2ã«é€²ã¿ã¾ã™ã€‚ をクリックã—\"設定\"アイコンをå³ã«ç¸¦ãƒ¡ãƒ‹ãƒ¥ãƒ¼" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "Step3. \"詳細設定\"=>\"CSSã®<head>セクション\"" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "Step4. ã«ãªã£ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ãªã„ストリップCSSã‹ã‚‰ã®<head>\"ã«ãƒã‚§ãƒƒã‚¯" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "ステップ5ã§ã™ã€‚ \"ä¿å­˜\"ボタンをクリックã—ã¾ã™ä»•äº‹\"ボタン" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "スタイル全ã¦ã«ãƒ¯ãƒ³ã‚¯ãƒªãƒƒã‚¯ã§ä¸–界的ã«" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "スタイルãã‚Œãžã‚Œã®å½¢æ…‹ã¨ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’個別ã«" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’無効ã«ã™ã¹ã¦ã®å½¢æ…‹" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’無効ã«ã™ã‚‹ã“ã¨ã‚’å‰æ" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’有効ã«ã™ã‚‹ã“ã¨ã‚’å‰æ" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ãŒé¸æŠžã•ã‚Œã¦ã„ãªã„" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "スタイルスキーム一覧" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "スタイルスキームã®ãƒ—レビュー" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "スタイルスキームã«è¨­å®š" #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "スタイルãŒèª­ã¿è¾¼ã¾ã‚Œ ã‚¿ã‚°" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "スタイルãŒèª­ã¿è¾¼ã¾ã‚Œ ã‚¿ã‚°" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "æˆåŠŸ" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "サãƒãƒ¼ãƒˆï¼†KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "タブレットビュー" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "テキストカラーを設定ã—ã¾ã™ã€‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "ã“ã®å½¢å¼ã¨ã® %s\" 世界ã§ãるスタイルã§ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«ã‚¹ã‚­ãƒ¼ãƒ ã§ã™ã€‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "ã“ã®å½¢å¼ã¨ã® %s\"ãスタイルã§ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«ã‚¹ã‚­ãƒ¼ãƒ ã§ã™ã€‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "ã“ã®å½¢å¼ã®ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã«ã‚ªãƒ•ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã—ã€ã‚°ãƒ­ãƒ¼ãƒãƒ«ã‚’設定ã—ã¾ã™ã€‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "ã“ã®å½¢å¼ã¯è¡¨ã®ã¨ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’å¾—ã‚‹ã“ã¨ãŒã§ãç¾åœ¨ã®ã‚¹ã‚­ãƒ¼ãƒ ã¯ã“ã®å½¢å¼ã‹ã‚‰ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆãŒä¸–界中ã§ç”»ä¸€çš„ãªã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’クリック\"使用ã®ãŸã‚ã®ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ¼ãƒ ã¯ä¸‹è¨˜ã‚¹ã‚­ãƒ¼ãƒ ã®ã‚¿ã‚¤ãƒˆãƒ«ã€‚" #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "ã“ã®ã‚¹ã‚­ãƒ¼ãƒ ãŒå­˜åœ¨ã—ã¦ã„ãªã„" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "ã“ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’有効ã«ä¸–ç•Œã®ã™ã¹ã¦ã®å½¢æ…‹ãŒã‚る。 " "使用ã™ã‚‹å ´åˆã«ãƒ—レゼンテーションã®ã‚¹ã‚¿ã‚¤ãƒ«ã‚’å•åˆã›ãƒ•ã‚©ãƒ¼ãƒ 7\"をクリックを無効ã«ã™\"ボタンを押ã—ã¾ã™ã€‚" #. Author of the plugin msgid "Tobias Conrad" msgstr "Tobiasコンラッド" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "Unstyled" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "プPro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "ç”»åƒã‚¢ãƒƒãƒ—ロード" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "縦方å‘ã®é•·ã•" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "æ­“è¿Ž" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "å¹…" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "ãªã‚“ã¨ã‚¹ã‚¿ã‚¤ãƒ«ã®Contact Form7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "ã‚ã‚Š" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "を作æˆã§ãã¾ã™æ–°ã—ã„スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã®ç¾åœ¨ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’設定ã—ã¾ã™ã€‚ を処ç†ã—ãªã‘ã‚Œã°ã„ã‘ãªã„空白ã®ã‚¹ã‚¿ã‚¤ãƒ«schem unchekãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã§ã™ã€‚" #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "ã ã‘を削除ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "使用ã§ãã¾ã›ã‚“ã“ã®è¨­å®šã¯ã“ã®ãƒšãƒ¼ã‚¸ã‚¿ã‚¤ãƒ—" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "一切ã—ã¦ã„ãªã„ã®Contact Form7é …ç›®" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "使ã„ã§ãªã„スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã®ãŸã‚ã®å•åˆã›ãƒ•ã‚©ãƒ¼ãƒ 7. クリック\"使用ã®ãŸã‚ã®ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ¼ãƒ \"ç¾åœ¨ã®ã‚¹ã‚­ãƒ¼ãƒ ã§ã™ã€‚" languages/cf7-styler-de_DE.mo000064400000046565146725417150012040 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'©(¹) Ð)Ü)ïë)(Û*2+]7+•+§+½+Î+aÞ+@,U, \, h, v, ƒ, , ž,¨,|½,:- X- c-m-‡-§- ®-¹-¿- Ö-)à- . ..=.T.<].ôš/0§0 Ä0Ñ0 à0î0)þ00(1]Y1F·2 þ23)3:3C3[3j3 y3†3 –3·3%Ê3ð34(41484K4 b4n4Ÿ415ÐQ5á"6á8æ9 õ9:˜:°:¸:Ç:Ü:â: é:õ:;; ; +;6;G;Z;,_;QŒ;Þ;ú;0<F<d<v<…<8Š<…Ã<(I=r=‰==´˜= M>W>i>‚>“>š>¡>°>Í>Õ>ë>ó> ú>?1?E?W? ]? g?s?%Ž? ´?#Â?æ?ï?þ?@M@dAlA}AŽA-¥AgÓAù;Bx5CI®C^øC`WD,¸DåD+E)-E3WE1‹E½EÔEæEøE3F DF eFqF…F ”FâŸF–‚G…HƒŸH#I6J SJaJ jJuJ…J”J¦J ¿JÊJÑJŠÔJ_KAwK2¹KÝìK ÊL'ÔLüL`M- disable style scheme -- select -14-days Trial%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/Project-Id-Version: Report-Msgid-Bugs-To: POT-Creation-Date: 2020-02-06 11:35+0000 PO-Revision-Date: 2023-04-15 16:02+0000 Last-Translator: Tobias support@saleswonder.biz Language-Team: German Language: de-DE Plural-Forms: nplurals=2; plural=n != 1; MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Loco https://localise.biz/ X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489- Style deaktivieren -- wähle -14 Tage testen%s-Style ist derzeit für alle Formulare aktiviert. Klicke auf den Button "Aktiviere den Style für alle Formulare" um den ausgewählten Style für alle Formulare zu nutzen. *Einzeln gestylte Formulare behalten ihren StyleAktiviere den Style für alle Formulare*Aktiviere den Style für das ausgewählte FormularAlternative kannst du das Entfernen der Styles deaktivieren wie im Beispiel Thrive Architect:Hintergrund-FarbeHintergrund-DeckkraftHintergrundfarbeHintergrundbildBevor mit WOW-Stil Contact Form 7, müssen Sie installieren und aktivieren Contact Form 7 plugin.Weichzeichner-RadiusRahmenRahmenfarbeRahmen-RadiusRahmen-StyleRahmenbreiteButton-RahmenButton(s)Von Takayuki MiyoshiContact Form 7 Styler erfordert ein installiertes und aktiviertes Contact Form 7-Plugin. Du kannst es hier herunterladen %s.Bitte wähle ein CF7-FormularCF7 StylerAbbrechenCheckboxen & RadiobuttonsAuf Default-Style zurücksetzenLeerenSchließenFarbeContact Form 7-AuswahlenthaltenKopiere die aktuellen Style-EinstellungengefülltErstellenErstelle mehrere Style-VorlagenNeuen Style erstellen!VorschauIm Moment ist das Formular %s ist mit Style %s gestyled. Nachdem du in der Free Version nur ein Formular zurzeit stylen kannst, wird bei Auswahl eines anderen Formulars das zuletzt gestylte Formular ungestyled.Im Moment ist das Formular %s ist mit Style %s gestyled. Nachdem du in der Free Version nur ein Formular zurzeit stylen kannst, wird bei Auswahl eines anderen Formulars das zuletzt gestylte Formular ungestyled.Benutzerdefiniertes CSSBenutzerdefinierter CSS-CodeGestrichelteStandard-StyleBild löschenDesktop-AnsichtDeaktiviere den Style für alle FormulareDeaktiviere den Style für das aktuelle FormularMöchtest du die Styler Premium Version for free? Dann gebe hier deine WP2LEADS Pro Lizenz-Daten ein oder hole dir hier jetzt eine Lizenz und verbinde deine WordPress-Plugins mit Klick-Tipp!Möchtest du die Einstellungen speichern bevor du die Seite verlässt?GepunktetDoppeltDupliziere Formular in der zweiten SpalteAchtung!Vollbildmodus verlassenSchriftfamilieSchriftgrößeSchrift-StilSchrift-StärkeFormular-Hintergrundbild & FarbeFormular-AnpassungFormular-Abstände, Rahmen & SchattenFormular-Text, Links & LabelsKein Formular ausgewähltVollbildGrooveHorizontale BreiteHover-HintergrundfarbeHover-FarbeHover-Text FarbeWie Sie Ihren Kontakt form7 form in a-Konvertierung und einfach zu bedienen und pro-styled Kontaktformular, "Umfrage" lead-generator oder eine auffällige formIch bin glücklich sowie es ist! Bitte speichern!If you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesWenn du deinen Style nur auf bestimmten Seiten mit dem <body> Tag laden möchtest, nimm die Einstellungen direkt auf der Seite vor. Dazu kannst du dort den "CF7 Styler" Button nutzen. Diese Funktion ist nur single post types wie Seiten, Beiträge, Produkte usw. und in der Premium Version verfügbar. Für Archiv-Seiten (Blog, Products Listen usw. steht diese Funktion nicht zur Verfügung. Nutze in diesem Fall die globale Einstellung direkt über diesem Text.Wenn du deinen Style nur auf bestimmten Seiten mit dem <body> Tag laden möchtest, nimm die Einstellungen direkt auf der Seite vor. Dazu kannst du dort den "CF7 Styler" Button nutzen. Diese Funktion ist nur single post types wie Seiten, Beiträge, Produkte usw. und in der Premium Version verfügbar. Für Archiv-Seiten (Blog, Products Listen usw. steht diese Funktion nicht zur Verfügung. Nutze in diesem Fall die globale Einstellung direkt über diesem Text.Bild DeckkraftBild-PositionFüll-EigenschaftenDie Hintergrund-Einstellungen bleiben der Pro Version vorbehalten. Du kannst jedoch das Ergebnis in der Vorschau-Ansicht testen, jedoch nicht speichern.VererbtEingabe-FelderBenenne deinen StyleInnenKursivLabel-FarbeSchriftgrößeLabel-EinstellungenLizenzZeilenhöheLink FarbeLink hover FarbeLink-EinstellungenLiveLade Styles im <body> TagLade die Styles über den
HTML-<body>-Tag in diese Seite.Nur eine Checkbox pro ZeileIn voller Breite anzeigen?Möchtest du die Eingabefelder in voller Breite?Nur ein Radiobutton pro ZeileÄußerer AbstandMobile-AnsichtNeinKein Contact Form 7 Formular für die Vorschau vorhandenKeines deiner Formulare ist gestyled. Klicke "Aktiviere den Style für das aktuelle Formular" um das ausgewählte Formular zu stylen.Kein Plugin zur Installation ausgewähltKein Style ausgewähltNormalObliqueDas untereinander Anordnen der Checkboxen und Radiobuttons bleibt der Pro Version vorbehalten. Du kannst jedoch das Ergebnis in der Vorschau-Ansicht testen, jedoch nicht speichern.DeckkraftÖffne CF7 StylerOpt-in um Konto zu sehenoriginal GrößeAußenOutsetInnere AbstandGib deinem Style einen NamenAnsichtVorschau deaktivierenAnsichtRadiusvertikal & horizontal wiederholthorizontal wiederholtvertikal wiederholtZum Default-StyleRidgeSpeichernGespeichertAnsicht der zweiten SpalteWähle den Style für dieses FormularEinstellungenDein Style wurde gespeichert unter SchattenSchatten-FarbeSchatten-PositionSolidNutze diese Funktion wenn deine Formulare gar nicht gestyled werden. Da einige Themes oder Page Builder wie Thrive Architect, OptimizePress usw. die Styles aus dem <head> Tag entfernen können, gibt es die Option die Styles im <body> Tag zu Laden. Dadurch werden deine Formulare wieder gestyled.GeteiltGeteilte AnsichtSchatten-GrößeBeginne mit dem stylenBeginne mit dem Erstellen des Standard-StylesBeginne mit dem Erstellen deines ersten Contact Form 7 FormularsStarte deine 14-Tage-Testversion mit allen Pro-Funktionen hier!Schritt 1: In der Admin-Seiten-Ãœbersicht klicke auf den "Edit with Thrive Architect" -Link der Seite mit dem Formular.Schritt 2: Klicke auf das "Settings" - Symbol im rechten vertikalen MenüSchritt 3: Klicke "Erweiterte Einstellungen" => "CSS in the <head> section"Schritt 4: Stelle sicher, dass "Do not strip CSS from <head>" ausgewählt istSchritt 5. Klicke auf den "SAVE WORK" ButtonStyle alle Formulare globalStyle jedes Formular in einem anderen StyleDeaktiviere den Style für alle FormulareDer Style ist für dieses Formular ist deaktiviert Der Style ist für dieses Formular ist aktiviert Kein Style ausgewähltCF7-Style-AuswahlFormular-VorschauCF7-Style-EinstellungenStyle wird im <body> Tag geladenStyle wird im -Tag geladenErfolgreichUnterstützung & KBTablet-AnsichtText FarbeDieser Style ist global für alle Formulare aktiviert. Wenn du den Style deines Themes nutzen möchtest, dann klicken auf den "Deaktiviere den Style für alle Formulare"-Button. *Einzeln gestylte Formulare behalten ihren StyleDas derzeitige und andere Formulare sind mit dem %s-Style gestaltet. Du kannst mit einem Klick auch den derzeitigen Style aktivieren.Der zur Zeit genutzte Style des Formulars ist %s. Du kannst auch unten klicken und den ausgewählten Style anwenden.Für dieses Formular ist der aktuelle Style aktiviert. Du kannst diesen Style deaktivieren und so zum globalen Style zurückkehren.Dieses Formular benutzt noch keinen Style. Du kannst den derzeitigen Style für das angezeigte Formular aktivieren oder mit dem Klick auf "Aktiviere Style für alle Formulare" den Style generell für alle Formulare festlegen. *Einzeln gestylte Formulare behalten ihren StyleDieser Style existiert nichtTobias ConradTutorialOhne StyleUpgrade auf ProBild hochladenVertikaler BreiteWOW Style Contact Form 7WillkommenBreiteJaDu kannst hier ein Style mit den aktuellen Einstellungen abspeichern. Wenn du einen leeren Style abspeichern möchtest entferne den Haken.Löschen nicht möglichDu kannst diese Einstellungen nicht für diesen Seitentyp nutzen.Du hast noch kein Contact Form 7 Formular erstelltDu verwendest derzeit keinen Style für deine Contact Form 7 Formulare. Klicke auf "Aktiviere den Style für alle Formulare", um den angezeigten Style global zu aktivieren. *Einzeln gestylte Formulare behalten ihren StylegelöschtAktiviere den Style für alle Formularehttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/languages/cf7-styler-pl_PL.po000064400000113631146725417150012076 0ustar00msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: Wow style (ES)\n" "Language: pl-PL\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-04-18 12:29+0000\n" "PO-Revision-Date: 2023-04-15 16:04+0000\n" "Last-Translator: Tobias support@saleswonder.biz\n" "Language-Team: Polish\n" "X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- wyÅ‚Ä…cz szablon stylu -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "- wybierz -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14-dniowy okres próbny" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #| msgid "" #| "%s used for all forms globally, click \"Use for all forms\" if you want to " #| "use current Scheme." msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%s używany dla wszystkich formularzy globalnie, kliknij " "\"Użyj dla wszystkich formularzy\", jeÅ›li chcesz użyć bieżącego schematu." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "Aktywuj styl do wszystkich formularzy*" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Aktywuj styl dla aktualnego formularza" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "Opcjonalnie możesz wyÅ‚Ä…czyć czyszczenie stylów podobnie jak we wtyczce " "Thrive Architect:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "Kolor tÅ‚a" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "Obraz tÅ‚a" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Przed użyciem wtyczki WOW Style Contact Form 7, musisz zainstalować i " "aktywować wtyczkÄ™ Contact Form 7." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "Kolor tÅ‚a" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "Przezroczystość tÅ‚a" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "PromieÅ„ rozmycia" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "Obramowanie" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "Kolor obramowania" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "PromieÅ„ obramowania" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "Rodzaj obramowania" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "Szerokość obramowania" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "Obramowanie przycisku" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "Przyciski" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Autor: Takayuki Miyoshi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "Anuluj" #: cf7-styler.php:129 msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "Wtyczka do modyfikacji stylów formularza Contact Form 7 wymaga " "zainstalowania i aktywacji wtyczki Contact Form 7. Możesz pobrać %s." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "Formularz CF7 nie jest wybrany." #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "CF7 Styler" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "Pola wielokrotnego i jednokrotnego wyboru" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "Wyczyść style" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "Wyczyść" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "Zamknij" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "Kolor" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "Lista formularzy CF7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "Zmieść" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Skopiuj ustawienia bieżącego szablonu stylu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "Pokryj" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "Utwórz" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "Utwórz wiele szablonów stylu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "Utwórz nowy szablon stylu!" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Aktualny styl" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "Obecnie %s formularz " "jest stylizowany za pomocÄ… " "%s. Tak jak w wersji darmowej możesz stylizować tylko jeden " "formularz w tym samym czasie i jeÅ›li aktywujesz styl dla bieżącego " "formularza, styl zostanie usuniÄ™ty z innych formularzy." #: admin/class-cf7-customizer-admin.php:481 #| msgid "" #| "Currently %s form is styled with %s. As in free version you can style only " #| "one form at a time and if you activate style for current form, style will be " #| "removed from other form." msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "Aktualnie styl formularza %s jest skonfigurowany przy pomocy %s. Ponieważ w " "wersji darmowej w danym momencie możesz modyfikować styl tylko jednego " "formularza, jeÅ›li aktywujesz styl dla aktualnego formularza, styl zostanie " "usuniÄ™ty z innego formularza." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "Niestandardowy CSS" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "Niestandardowy kod CSS" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "Kreskowane" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "Szablon domyÅ›lny" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "UsuÅ„ obraz" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "usuniÄ™ty" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "Widok pulpitu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "WyÅ‚Ä…czenie stylu dla wszystkich formularzy" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "WyÅ‚Ä…cz styl dla aktualnego formularza" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "Czy chcesz otrzymać wersjÄ™ premium stylera za darmo? NastÄ™pnie Wprowadź swojÄ… licencjÄ™ " "WP2LEADS pro lub zdobÄ…dź licencjÄ™ tutaj!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "Chcesz zapisać zmiany przed opuszczeniem strony?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "Kropkowane" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "Podwójne" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "Duplikuj formularz w drugiej kolumnie" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "wÅ‚Ä…czony dla wszystkich formularzy" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "BÅ‚Ä…d" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "Wyjdź z peÅ‚nego ekranu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "Rodzina czcionek" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "Rozmiar czcionki" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Styl czcionki" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "Waga czcionki" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Obraz i kolory tÅ‚a formularza" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "Dostosowanie formularza" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Nie wybrano formularza" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "WypeÅ‚nienie, margines i obramowanie formularza" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "Tekst formularza" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "PeÅ‚ny ekran" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "WklÄ™sÅ‚e" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "DÅ‚ugość pozioma" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Kolor tÅ‚a po najechaniu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "Kolor po najechaniu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Kolor tekstu po najechaniu" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "Jak z formularza kontaktowego Contact Form 7 zrobić formularz kontaktowy, " "który nie tylko bÄ™dzie miaÅ‚ przyciÄ…gajÄ…cy uwagÄ™ profesjonalny wyglÄ…d oraz " "bÄ™dzie Å‚atwy w użyciu, ale także bÄ™dzie miaÅ‚ wysoki współczynnik konwersji i " " bÄ™dzie generowaÅ‚ zapytania o oferty." #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "https://saleswonder.biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "Podoba mi siÄ™! Zapisz" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "JeÅ›li używasz page builderów, takich jak Thrive Architect, OptimizePress itp." ", sprawdź naszÄ… bazÄ™ wiedzy, aby naprawić ewentualne bÅ‚Ä™dy" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "JeÅ›li potrzebujesz zaÅ‚adować schemat stylu wewnÄ…trz <body>" " tagu tylko na niektórych stronach, możesz to zrobić na frontend za pomocÄ… " "przycisku \"CF7 Styler\". Ta funkcja jest dostÄ™pna tylko dla pojedynczych " "typów postów (stron, postów, produktów itp.) i w wersji premium. Nie możesz " "tego zrobić na stronach archiwalnych (blog, lista produktów itp.) W tym " "przypadku musisz użyć ustawieÅ„ globalnych." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "JeÅ›li potrzebujesz zaÅ‚adować schemat stylu wewnÄ…trz <body>" " tagu tylko na niektórych stronach, możesz to zrobić na frontend za pomocÄ… " "przycisku \"CF7 Styler\". Ta funkcja jest dostÄ™pna tylko dla pojedynczych " "typów postów (stron, postów, produktów itp.). Nie możesz tego zrobić na " "stronach archiwalnych (blog, lista produktów itp.) W tym przypadku musisz " "użyć ustawieÅ„ globalnych." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "Ustawienia obrazu tÅ‚a dostÄ™pne sÄ… w trybie podglÄ…du na żywo tylko dla wersji " "Professional. Możesz je wypróbować w trybie podglÄ…du ,,aktualny stylâ€, ale " "nie zostanÄ… one zapisane." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "Przezroczystość obrazu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "Pozycja obrazu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "Rozmiar obrazu" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "Dziedzicz" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "Pola wejÅ›ciowe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "Nazwa szablonu stylu wejÅ›ciowego" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "WklejajÄ…ce" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "Kursywa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "Kolor etykiet" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "Rozmiar czcionki etykiet" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "Ustawienia etykiet" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "Licencja" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "Wysokość linii" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "Kolor odsyÅ‚aczy" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "Kolor odsyÅ‚aczy po najechaniu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Ustawienia odsyÅ‚aczy" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "Na żywo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "ZaÅ‚aduj style w znaczniku <body>" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "ZaÅ‚aduj style wewnÄ…trz tagu <body> na tej stronie" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "Ustaw po jednym polu wielokrotnego wyboru w wierszu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "Ustawić peÅ‚nÄ… szerokość?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "Ustawić pola wejÅ›ciowe na peÅ‚nÄ… szerokość?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Ustaw po jednym polu jednokrotnego wyboru w wierszu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "Margines" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "Widok w komórce" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "NIE" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "Brak pozycji formularza Contact Form 7 do podglÄ…du" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "Å»aden formularz nie jest zmodyfikowany przy pomocy szablonu stylu. Aby " "zastosować aktualny szablon do tego formularza kliknij ,,Aktywuj styl do " "aktualnego formularzaâ€." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "Nie wybrano żadnej wtyczki do zainstalowania" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "Nie wybrano żadnego szablonu stylu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "Normalny" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "Kursywa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "Ustawienie jednego pola wielokrotnego i jednokrotnego wyboru w wierszu jest " "możliwe tylko w wersji Professional. Możesz je wypróbować w trybie podglÄ…du ," ",aktualny stylâ€, ale nie zostanÄ… one zapisane." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "Przezroczystość" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "Otwórz Styler" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "Zaloguj siÄ™, aby zobaczyć konto" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "Oryginalny rozmiar" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "Kontur" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "UwypuklajÄ…ce" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "WypeÅ‚nienie" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "Wprowadź szablonu stylu wejÅ›ciowego" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "PodglÄ…d" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "Tryb podglÄ…du" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "PodglÄ…d niezmodyfikowanego stylu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "PromieÅ„" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "Powtórz obydwa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "Powtórz poziomo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "Powtórz pionowo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Przywróć ustawienia domyÅ›lne" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "WypukÅ‚e" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "Zapisz" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "Zapisano" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "Widok drugiej kolumny" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "Wybierz szablon stylu dla tego formularza" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "Ustawienia" #: admin/class-cf7-customizer-admin-ajax.php:210 #| msgid "Settings saved as" msgid "Settings saved as " msgstr "Ustawienia zapisane jako" #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "CieÅ„" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "Kolor cienia" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Pozycja cienia" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "Jednolite ciÄ…gÅ‚e" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 #| msgid "" #| "Some themes or page builders (e.g. Thrive Architect, OptimizePress etc.) " #| "could remove inline styles inside tag. Loading style scheme within " #| " tag will fix this issue and show your forms styled." msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Niektóre motywy lub kreatory stron (np. Thrive Architect, OptimizePress itp.)" " mogÄ… usuwać style lokalne (inline styles) wewnÄ…trz tagu . Dodanie " "szablonu stylu wewnÄ…trz tagu naprawi ten problem i twoje formularze " "bÄ™dÄ… miaÅ‚y zmodyfikowany styl." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "Tryb podzielonego widoku" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "Widok podzielony" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "PromieÅ„ rozproszenia" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "Zacznij modyfikować styl" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "Zacznij od utworzenia DomyÅ›lnego szablonu stylu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "Zacznij od stworzenia swojego " "pierwszego Contact Form 7" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "Rozpocznij 14-dniowy bezpÅ‚atny okres próbny ze wszystkimi funkcjami " "Professional tutaj!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "Krok 1. Kliknij na link ,,Edit with Thrive Architect\" (Edytuj z Thrive " "Architect) na liÅ›cie stron administratora" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "Krok 2. Kliknij ikonÄ™ ,,Settings†(Ustawienia) w prawym pionowym menu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 #| msgid "Step 3. \"Advanced settings\" => \"CSS in the section\"" msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "" "Krok 3. ,,Advanced settings†(Ustawienia zaawansowane) => ,,CSS in the " " section†(CSS w sekcji )" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 #| msgid "Step 4. Make sure that \"Do not strip CSS from \" is checked" msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "Krok 4. Upewnij siÄ™, że opcja ,,Do not strip CSS from †(Nie usuwaj " "CSS z sekcji) jest zaznaczona" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "Krok 5. Kliknij przycisk ,,SAVE WORK†(ZAPISZ PRACĘ)" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "Modyfikuj globalnie jednym klikniÄ™ciem styl wszystkich formularzy" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "" "Modyfikuj indywidualnie styl każdego formularza przy pomocy dowolnego " "szablonu" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "Szablon stylu jest wyÅ‚Ä…czony dla wszystkich formularzy" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "Szablon stylu jest wyÅ‚Ä…czony dla tego formularza" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "Szablon stylu jest wÅ‚Ä…czony dla tego formularza" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "Szablon stylu nie jest wybrany" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "Lista szablonów stylów" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "PodglÄ…d szablonów stylów" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "Ustawienia szablonów stylów" #: admin/class-cf7-customizer-admin-ajax.php:298 #| msgid "Style will be loaded in tag" msgid "Style will be loaded in tag" msgstr "Styl zostanie dodany do tagu" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "Styl zostanie zaÅ‚adowany w tagu " #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "UdaÅ‚o siÄ™" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "Wsparcie i KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "Widok w tablecie" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "Kolor tekstu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #| msgid "" #| "This form is styled with %s globally, you can style it with current Style " #| "scheme." msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "Styl tego formularza modyfikowany jest globalnie przy pomocy %s, możesz go " "modyfikować przy pomocy aktualnego Szablonu stylu." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #| msgid "" #| "This form is styled with %s, you can style it with current Style scheme." msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "Styl tego formularza modyfikowany jest przy pomocy %s, możesz go modyfikować " "przy pomocy aktualnego Szablonu stylu." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "Styl tego formularza modyfikowany jest przy pomocy aktualnego Szablonu stylu," " możesz go wyÅ‚Ä…czyć i użyć ustawieÅ„ globalnych." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "Styl tego formularza nie jest modyfikowany przy pomocy żadnego Szablonu " "stylu, możesz wÅ‚Ä…czyć aktualny Szablon dla tego formularza albo ustawić " "globalny Szablon stylu klikajÄ…c na ,,Użyj do wszystkich formularzy†poniżej " "nazwy szablonu." #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "Ten szablon nie istnieje" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "Ten Szablon stylu jest wÅ‚Ä…czony globalnie dla wszystkich formularzy. Jeżeli " "do formularza Contact Form 7 chcesz użyć stylu z twojego motywu kliknij " "przycisk ,,WyÅ‚Ä…czâ€." #. Author of the plugin msgid "Tobias Conrad" msgstr "Tobias Conrad" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "Tutorial" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "Niezmodyfikowany styl" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "Uaktualnij do wersji Pro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "ZaÅ‚aduj obraz" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "DÅ‚ugość pionowa" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "Witaj" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "Szerokość" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "WOW Style Contact Form 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "TAK" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 #| msgid "" #| "You can create new style scheme with current scheme settings. If you want to " #| "create blank style scheme uncheck checkbox below." msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "Możesz utworzyć nowy szablon stylu z aktualnymi ustawieniami szablonu. JeÅ›li " "chcesz utworzyć pusty szablon stylu odznacz pole wyboru poniżej." #: admin/class-cf7-customizer-admin-ajax.php:237 #| msgid "You cannot delete" msgid "You can not delete" msgstr "Nie można usunąć" #: public/class-cf7-customizer-public.php:471 #| msgid "You cannot use this settings on this page type" msgid "You can not use this settings on this page type" msgstr "Nie można używać tych ustawieÅ„ na stronach tego typu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "Nie masz żadnych pozycji formularza Contact Form 7" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "Nie używasz żadnych Szablonów stylów do formularza Contact Form 7. Kliknij ,," "Użyj do wszystkich formularzyâ€, aby używać aktualnego Szablonu globalnie." languages/cf7-styler-vi.mo000064400000051370146725417150011504 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'½(Í)é)ò)Ñ*;Ö*6+ƒI+Í+Õ+ ä+ ï+‰û+ …, ‘,ž,°,Ä,Ø,ì,þ,-ƒ -¤-¿-Ï-%Õ-û- ...#. =.3H.|..–.°.Ï.šè.Rƒ0Ö1ç1 ü12!222>E20„2Fµ2Cü3@4 G4$T4y44–4¦4º4Ë4á4ý4%5:5#J5n5 †55¨5 ¼5Ç5þÝ51Ü6%7#48X:[<o<„<íŸ<=–=¬= Ë=Ö=Ù=é=> > #> 1><>M>_>(f>>>$Î>ó>5?2D?w? ~?‰?=?ÁÎ?3@,Ä@ñ@A A B B B>B SB aBkB$sB ˜B¢B·BËBÒBçBþB"C6C %s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/Language: vi POT-Creation-Date: 2020-02-06 11:35+0000 Plural-Forms: nplurals=1; plural=0; PO-Revision-Date: 2023-04-15 16:10+0000 X-Generator: Loco https://localise.biz/ Project-Id-Version: WOW Style Contact Form 7 Report-Msgid-Bugs-To: Last-Translator: Tobias support@saleswonder.biz Language-Team: Vietnamese MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489- Chế Ä‘á»™ phong cách -Chá»n -14 Ngày Tòa án% s Äược sá»­ dụng cho tất cả các biểu mẫu trên toàn cầu, hãy bấm "sá»­ dụng cho tất cả các biểu mẫu" nếu bạn muốn sá»­ dụng biểu mẫu hiện tại.Tích hoạt phong cách cho tất cả các hình thức *Tích hoạt phong cách cho hình thức hiện tạiLà má»™t lá»±a chá»n thay thế, bạn có thể vô hiệu hóa việc làm sạch các phong cách nhÆ° trên phrive architect:Bg MàuBg Khả năngMàu ná»nHình ná»nTrÆ°á»›c khi sá»­ dụng biểu mẫu liên hệ kiểu Wow 7, bạn cần cài đặt và kích hoạt biểu mẫu liên hệ 7 Plugin.Bạch á»cbiên giá»›iMàu biên giá»›iBiên giá»›i radiusLoại biên giá»›ibiên giá»›i rá»™ngnút biên giá»›iBútTác giả: Takayuki MiyoshiCf7 Customizer yêu cầu biểu mẫu liên hệ 7 Plugin để cài đặt và hoạt Ä‘á»™ng. Bạn có thể tải xuống % S.Cf7 không được chá»nCf7 phong cáchhủyChế Ä‘á»™ kiểm tra & Radiobuttonsphong cách sạchrõ rànggầnMàuHình thức liên hệ 7Ná»™i dungSao chép các cài đặt phong cách hiện tạiMàn hình Covertạo raTạo nhiá»u phong cáchTạo má»™t phong cách má»›i!Phong cách hiện tạiHiện tại % s Hình thức được thiết kế vá»›i % s . NhÆ° trong phiên bản miá»…n phí bạn có thể phong cách chỉ má»™t biểu mẫu cùng má»™t lúc và nếu bạn kích hoạt phong cách cho biểu mẫu hiện tại, phong cách sẽ được loại bá» từ biểu mẫu khác.Hiện tại % s Hình thức được thiết kế vá»›i % s . NhÆ° trong phiên bản miá»…n phí bạn có thể phong cách chỉ má»™t biểu mẫu cùng má»™t lúc và nếu bạn kích hoạt phong cách cho biểu mẫu hiện tại, phong cách sẽ được loại bá» từ biểu mẫu khác.Tùy chỉnh CSSMã CSS tùy chỉnhDashuấtHệ thống mặc địnhxóa hình ảnhMàn hình DesktopLoại phong cách vô hiệu cho tất cả các hình thứcChặn phong cách cho hình thức hiện tạiBạn có muốn có được phiên bản Premium Styler miá»…n phí không? Sau đó Nhập Wp2Leads Pro License của bạn Hoặc có giấy phép Ở đây !Bạn muốn lÆ°u các thay đổi trÆ°á»›c khi rá»i khá»i trang?DOTTEDDouble ÄôiDuplicate form trong cá»™t thứ haiLá»—iMàn hình Full ScreenFont gia đìnhfont kích thÆ°á»›cPhong cách Fontfont trá»ng lượngHình ảnh BG & Màu sắcHình thức CustomizeHình thức padding, margin & borderForm văn bảnHình thức không được chá»nmàn hình đầy đủTrưởngChiá»u dài horizontalMàu sắc Hover BGHover MàuHover Text Màu sắcLàm thế nào để biến hình thức liên hệ của bạn Form7 thành má»™t hình thức chuyển đổi và dá»… sá»­ dụng và hình thức liên hệ theo phong cách chuyên nghiệp, máy phát sáng "há»c" hoặc hình thức chụp mắtTôi hài lòng vá»›i Ä‘iá»u này! tiết kiệmNếu bạn Ä‘ang sá»­ dụng các nhà xây dá»±ng trang, chẳng hạn nhÆ° thrive architect, Optimizepress vv, vui lòng kiểm tra chúng tôi Trang cÆ¡ sở kiến thức Äể giải quyết các vấn Ä‘á» có thểNếu bạn cần để tải lên phong cách kế hoạch bên trong Nhãn chỉ trên má»™t số trang, bạn có thể làm Ä‘iá»u đó trên frontend bằng cách sá»­ dụng nút "Cf7 Styler". Tính năng này chỉ có sẵn cho các loại bài đăng duy nhất (các trang, bài đăng, sản phẩm, v.v.) Và trong phiên bản premium. Bạn không thể làm Ä‘iá»u đó trên các trang lÆ°u trữ (Blog, danh sách sản phẩm, v.v.) trong trÆ°á»ng hợp này bạn cần sá»­ dụng cài đặt toàn cầu.Nếu bạn cần để tải lên phong cách kế hoạch bên trong Nhãn chỉ trên má»™t số trang, bạn có thể làm Ä‘iá»u đó trên frontend bằng cách sá»­ dụng nút "Cf7 Styler". Tính năng này chỉ có sẵn cho các loại bài đăng duy nhất (các trang, bài đăng, sản phẩm, vv). Bạn không thể làm Ä‘iá»u đó trên các trang lÆ°u trữ (Blog, danh sách sản phẩm, v.v.) trong trÆ°á»ng hợp này bạn cần sá»­ dụng cài đặt toàn cầu.Hình ảnh OpacityHình ảnh Positionhình ảnh kích thÆ°á»›cCài đặt ná»n hình ảnh có sẵn trong chế Ä‘á»™ sống chỉ cho phiên bản chuyên nghiệp. Bạn có thể kiểm tra nó trong chế Ä‘á»™ xem trÆ°á»›c "trình hiện tại", nhÆ°ng nó sẽ không được tiết kiệm.Di sảnCác trÆ°á»ng nhậpTiêu Ä‘á» Input Style SchemeẤn Äá»™ÃTags màu sắcTag: font kích thÆ°á»›cLabel thiết lậpGiấy phépÄ‘Æ°á»ng caoMàu tráiMàu trái hoverCài đặt LinksSốngLoad Styles trong TagLoad Styles bên trong Tag trên trang nàyTạo Checkbox item má»™t theo dòngTải rá»™ng đầy đủ?Làm cho các lÄ©nh vá»±c nhập rá»™ng đầy đủ?Tạo các mục Radiobutton má»™t cho má»—i dòngMarginMobile xemKhôngKhông có biểu mẫu liên hệ 7 mục để xem trÆ°á»›cKhông có biểu mẫu được phong cách vá»›i biểu mẫu phong cách, nhấp vào nút "Aktivate style for current form" để áp dụng biểu mẫu hiện tại cho biểu mẫu này.Không có plugin được chá»n để cài đặtKhông có phong cách được lá»±a chá»nbình thÆ°á»ngObliqueMá»™t theo dòng phong cách cho Checkboxes và Radiobuttons trong chế Ä‘á»™ sống chỉ cho phiên bản chuyên nghiệp. Bạn có thể kiểm tra nó trong chế Ä‘á»™ xem trÆ°á»›c "trình hiện tại", nhÆ°ng nó sẽ không được tiết kiệm.OpacityMở StylerOpt-in để xem tài khoảnKích thÆ°á»›c gốcOutline Khácngoài raPaddingVui lòng nhập kiểu scheme titleDá»± báoPreview không thểchế Ä‘á»™ PreviewRadiusLặp lại cả haiLặp lại horizontalLặp lại verticalKhởi Ä‘á»™ng trở lại defaultRidgetiết kiệmcứu rá»—iNhìn Column 2Chá»n biểu mẫu kiểu cho biểu mẫu nàyCài đặtCài đặt được tiết kiệm nhÆ°bóng tốiMàu bóngVị trí bóngSức mạnhMá»™t số chủ Ä‘á» hoặc xây dá»±ng trang (Fe. Thrive kiến trúc sÆ°, Optimizepress vv) Có thể loại bá» các phong cách Inline bên trong Tag . Loading style scheme trong Tag sẽ khắc phục vấn Ä‘á» này và hiển thị các biểu mẫu của bạn được phong cách.Mô hình SplitView phân chiaTải ra radiusBắt đầu stylingBắt đầu vá»›i việc tạo má»™t kế hoạch phong cách mặc địnhBắt đầu bằng cách tạo ra bạn Hình thức liên lạc đầu tiên 7 Bắt đầu thá»­ nghiệm miá»…n phí 14 ngày của bạn vá»›i tất cả các chức năng chuyên nghiệp Ở đây !BÆ°á»›c 1 Nhấp vào liên kết "ed with thrive architect" trong danh sách trang AdminBÆ°á»›c 2 Nhấp vào biểu tượng "Settings" trên menu thẳngBÆ°á»›c 3 “Cài đặt nâng cao†=> “CSS trong Phần »BÆ°á»›c 4 Hãy chắc chắn rằng "không xóa CSS từ » Äã kiểm traBÆ°á»›c 5 Nhấp vào nút "save work"Phong cách tất cả các hình thức trong má»™t cú nhấp chuá»™t toàn cầuPhong cách má»—i hình thức vá»›i bất kỳ phong cách kế hoạch riêng lẻThiết kế phong cách bị chặn cho tất cả các hình thứcChế Ä‘á»™ phong cách bị chặn cho hình thức nàyChế Ä‘á»™ phong cách được kích hoạt cho hình thức nàyChế Ä‘á»™ phong cách không được chá»nDanh sách Style SchemesPhong cách PreviewThiết lập Style SchemesPhong cách sẽ được tải lên trong TagPhong cách sẽ được tải lên trong TagThành côngHá»— trợ & KBHình ảnh TabletText màu sắcPhong cách này cho phép toàn cầu cho tất cả các hình thức. Nếu bạn muốn sá»­ dụng phong cách chủ Ä‘á» của bạn cho biểu mẫu liên hệ 7 nhấp vào nút "không thể".Hình thức này được thiết kế vá»›i % s Trên toàn cầu, bạn có thể phong cách nó vá»›i phong cách hiện tại.Hình thức này được thiết kế vá»›i % s , bạn có thể phong cách nó vá»›i phong cách hiện tại.Hình thức này được phong cách vá»›i biểu mẫu phong cách hiện tại, bạn có thể tắt nó và sá»­ dụng cài đặt toàn cầu.Hình thức này không được phong cách vá»›i bất kỳ biểu mẫu phong cách nào, bạn có thể bật biểu mẫu hiện tại cho biểu mẫu này hoặc thiết lập biểu mẫu phong cách toàn cầu bằng cách nhấp chuá»™t "làm cho tất cả các biểu mẫu" bên dÆ°á»›i tiêu Ä‘á» biểu mẫu.Hệ thống này không tồn tạiÄạo diá»…n Tobias ConradhÆ°á»›ng dẫnkhông phong cáchnâng cấp lên proTải hình ảnhchiá»u dài verticalHình thức liên hệ WOW 7Chào mừngrá»™ngCóBạn có thể tạo má»™t biểu mẫu phong cách má»›i vá»›i các cài đặt biểu mẫu hiện tại. Nếu bạn muốn tạo phong cách trắng Schem Unchek Checkbox bên dÆ°á»›i.Bạn không thể xóaBạn không thể sá»­ dụng cài đặt này trên kiểu trang nàyBạn không có bất kỳ hình thức liên lạc 7 mụcBạn không sá»­ dụng bất kỳ biểu mẫu kiểu nào cho biểu mẫu liên hệ 7. Nhấp vào "sá»­ dụng cho tất cả các biểu mẫu" để sá»­ dụng biểu mẫu hiện tại trên toàn cầu.xóaCó sẵn cho tất cả các hình thứcHttps: //Saleswonder.bizHttps: //Saleswonder.Biz/Blog/4Free-Contact-Form-7-Cf7-Formular-Und-Klick-Tipp-Einfach-Verbinden/languages/cf7-styler-es_MX.mo000064400000046364146725417150012110 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'Ë(#Û)ÿ)*"*-À*+î*P+k+ t+€++aŸ+,,,., >,L,^,o,w,bŒ,'ï, -"-,+-X-h-n-u-{-š-6£-Ú-â-ç- . (.P6.ê‡/r0„0ž0¥0 º0È0/Ü0. 1;19Y2“2š2* 2Ë2Ñ2ë2þ23 323I3&i33¥3À3Ò3Ù3í3 ö3!4Å$4"ê4ò 5¹6ªº7e9{9’9¬§9T:\:(n:—: :¨:¸:Ô:æ:ï: ;;#; =;6H;N;Î;ì;"<('<P< W<d<7g<ŸŸ<2?=/r=¢=©=ȱ=z>ƒ> —>¢>³>»> Â>+Ì> ø>??0? 6?C?V?g?‡?Ž?–?Ÿ?4»?ð?ø?@ @#@7@7?@ wA…A”A©A0½AZîAIBgcCIËCFDG\D(¤D;ÍDH E8RE2‹E/¾E*îEF&5F!\F*~F+©FÕF ÜFéFúF¨ Gy³Gm-Hx›HäIùI JJ (J3J DJRJ"dJ ‡J’JšJ’žJ1K=DK(‚K¡«K ML#WL{L`“L- disable style scheme -- select -14-days Trial%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/Language: es-MX POT-Creation-Date: 2023-04-15 15:26+0000 Plural-Forms: nplurals=2; plural=n != 1; PO-Revision-Date: 2023-04-15 16:10+0000 X-Generator: Loco https://localise.biz/ Project-Id-Version: WOW Style Contact Form 7 Report-Msgid-Bugs-To: Last-Translator: Tobias support@saleswonder.biz Language-Team: Spanish (Mexico) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489- desactivar el esquema de estilo -- seleccionar -14 días de prueba%s utilizado para todos los formularios globalmente, haga clic en "Utilizar para todos los formularios" si desea utilizar el Esquema actual.Activar el estilo para todos los formularios*Activar el estilo para el formulario actualComo alternativa puedes desactivar limpiar los estilos como en Thrive architect:Color BGOpacidad BGColor de fondoImagen de fondoAntes de utilizar WOW Style Contact Form 7, necesita instalar y activar el plugin Contact Form 7.Radio de desenfoqueFronteraColor del bordeRadio del bordeTipo de bordeAnchura del bordeBorde del botónBotonesPor Takayuki MiyoshiCF7 Customizer requiere que el plugin Contact Form 7 esté instalado y activo. Puede descargar %s.El formulario CF7 no está seleccionadoCF7 StylerCancelarCasillas de verificación y botones de radioEstilos limpiosClaroCerrarColorFormulario de contacto 7 listaContieneCopiar la configuración actual del esquema de estilosPortadaCreeCrear varios esquemas de estiloCrear un nuevo esquema de estiloEstilo actualActualmente %s formulario tiene estilo con %s. Al igual que en la versión gratuita, sólo puede aplicar estilo a un formulario a la vez y si activa el estilo para el formulario actual, el estilo se eliminará del otro formulario.Actualmente el formulario %s está estilizado con %s. Como en la versión gratuita puede estilo sólo una forma a la vez y si activa el estilo para la forma actual, estilo se eliminará de otra forma.CSS personalizadoCódigo CSS personalizadoDashedRégimen por defectoBorrar imagenVista de escritorioDesactivar el estilo para todos los formulariosDesactivar el estilo para el formulario actualTe gusta conseguir styler versión premium gratis? ¡Entonces Introduzca su licencia WP2LEADS pro u obtenga una licencia aquí!¿Desea guardar los cambios antes de salir de la página?PuntosDobleFormulario duplicado en la segunda columnaErrorSalir a pantalla completaFamilia de fuentesTamaño de letraEstilo de fuentePeso de la fuenteForm BG Image & ColorsPersonalización de formulariosRelleno, margen y borde del formularioTexto del formularioFormulario no seleccionadoPantalla completaRanuraLongitud horizontalColor BGColor HoverColor del texto sobreimpresionadoCómo convertir su formulario de contacto form7 en un formulario de contacto de conversión, fácil de usar y con estilo profesional, un generador de prospectos "encuesta" o un formulario llamativo¡Estoy contento con esto! GuardarSi está utilizando constructores de páginas, como Thrive Architect, OptimizePress, etc., consulte nuestra página Base de conocimientos para solucionar posibles problemasSi necesita cargar esquema de estilo dentro de <body> etiqueta sólo en algunas páginas, puede hacerlo en frontend usando "CF7 Styler" botón. Esta función sólo está disponible para los tipos de mensajes individuales (páginas, mensajes, productos, etc) y en la versión premium. No se puede hacer en las páginas de archivos (blog, lista de productos, etc) en este caso es necesario utilizar la configuración global.Si necesita cargar el esquema de estilo dentro de la etiqueta <body> sólo en algunas páginas, puede hacerlo en frontend usando el botón "CF7 Styler". Esta función sólo está disponible para los tipos de entradas individuales (páginas, entradas, productos, etc.). No se puede hacer en las páginas de archivos (blog, lista de productos, etc) en este caso es necesario utilizar la configuración global.Opacidad de la imagenPosición de la imagenTamaño de la imagenLa configuración del fondo de la imagen sólo está disponible en la versión Profesional. Puede probarlo en el modo de vista previa "estilo actual", pero no se guardará.HeredarCampos de entradaTítulo del esquema de estilo de entradaInsertarCursivaEtiquetas ColorEtiquetas Tamaño de fuenteEtiquetas AjustesLicenciaAltura de líneaEnlaces ColorColor de los enlacesConfiguración de enlacesEn directoCargar estilos en la etiqueta <body><body> en esta páginaMarque una casilla por línea¿Hacer ancho completo?¿Completar los campos de entrada?Hacer un elemento radiobutton por líneaMargenVista móvilNONo hay elementos de Contact Form 7 para la vista previaNingún formulario tiene un esquema de estilo, haga clic en el botón "Activar estilo para formulario actual" para aplicar el esquema actual a este formulario.No se ha seleccionado ningún plugin para instalarNo se ha seleccionado ningún esquema de estiloNormalOblicuoEstilos uno por línea para casillas de verificación y radiobuttons en modo activo sólo para la versión Profesional. Puede probarlo en el modo de vista previa "estilo actual", pero no se guardará.OpacidadEstilizador abiertoVer cuentaTamaño originalEsquemaSalidaAcolchadoIntroduzca el título del esquema de estiloVista previaVista previa UnstyledModo de vista previaRadioRepita ambosRepetir horizontalRepetir verticalRestablecer valores por defectoCrestaGuardarGuardadoVista de la segunda columnaSeleccione el esquema de estilo para este formularioAjustesAjustes guardados comoSombraSombra ColorPosición de sombraSólidoAlgunos temas o constructores de página (fe. Thrive Architect, OptimizePress etc.) podrían eliminar estilos en línea dentro de la etiqueta <head>. Cargar el esquema de estilo dentro de la etiqueta <body> solucionará este problema y mostrará sus formularios con estilo.Modo divididoVista divididaRadio de dispersiónEmpezar a estilizarEmpezar creando un esquema de estilo por defectoComienza creando tu primer Formulario de Contacto 7¡Comience su prueba gratuita de 14 días con todas las funciones profesionales aquí!Paso 1. Haga clic en el enlace "Editar con Thrive architect" en la lista de páginas de administraciónPaso 2. Haga clic en el icono "Configuración" del menú vertical derechoPaso 3. "Configuración avanzada" => "CSS en la sección <head>"Paso 4. Asegúrese de que "No quitar CSS de <head>" está marcadaPaso 5. Pulse el botón "GUARDAR TRABAJOEstiliza todos los formularios globalmente con un solo clicEstiliza cada formulario individualmente con cualquier esquema de estiloEsquema de estilo desactivado para todos los formulariosEsquema de estilo desactivado para este formularioEsquema de estilo activado para este formularioEl esquema de estilo no está seleccionadoLista de esquemas de estiloVista previa de los esquemas de estiloAjustes de los esquemas de estiloEl estilo se cargará en la etiqueta ÉxitoSoporte y KBVista de tabletaColor del textoEste esquema de estilo habilitado a nivel mundial para todas las formas. Si desea utilizar el estilo de su tema para Contact Form 7 haga clic en el botón "Desactivar".Este formulario está estilizado con %s globalmente, puedes estilizarlo con el esquema de Estilo actual.Este formulario está estilizado con %s, puedes estilizarlo con el esquema de Estilo actual.Este formulario está diseñado con el esquema de estilo actual, puede desactivarlo y utilizar la configuración global.Este formulario no tiene ningún esquema de estilo, puede activar el esquema actual para este formulario o configurar un esquema de estilo global haciendo clic en "Usar para todos los formularios" debajo del título del esquema.Este régimen no existeTobias ConradTutorialSin estiloActualizar a ProCargar imagenLongitud verticalFormulario de contacto WOW Style 7BienvenidoAnchuraSÃPuede crear un nuevo esquema de estilo con la configuración actual. Si desea crear un esquema de estilo en blanco, desmarque la casilla de abajo.No se puede borrarNo puede utilizar esta configuración en este tipo de páginaNo tiene ningún elemento Contact Form 7No utiliza ninguno de los esquemas de estilo para Contact Form 7. Haga clic en "Usar para todos los formularios" para utilizar el esquema actual de forma global.suprimidoactivado para todos los formularioshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/languages/cf7-styler-it_IT.po000064400000111444146725417150012100 0ustar00msgid "" msgstr "" "Language: it-IT\n" "POT-Creation-Date: 2023-04-15 15:26+0000\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "PO-Revision-Date: 2023-04-15 16:10+0000\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: WOW Style Contact Form 7\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: Tobias support@saleswonder.biz\n" "Language-Team: Italian\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- disabilitare lo schema di stile -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "- selezionare -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14 giorni di prova" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%s utilizzato per tutti i moduli a livello globale, fare " "clic su \"Usa per tutti i moduli\" se si desidera utilizzare lo schema " "corrente." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "Attivare lo stile per tutti i moduli*" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Attivare lo stile per il modulo corrente" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "In alternativa, è possibile disattivare la pulizia degli stili come in " "Thrive Architect:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "Colore di sfondo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "Immagine di sfondo" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Prima di utilizzare WOW Style Contact Form 7, è necessario installare e " "attivare il plugin Contact Form 7." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "Colore BG" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "Opacità BG" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "Raggio di sfocatura" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "Confine" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "Colore del bordo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "Raggio del bordo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "Tipo di confine" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "Larghezza del bordo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "Bordo del pulsante" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "Pulsanti" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Di Takayuki Miyoshi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "Annullamento" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "CF7 Customizer richiede che il plugin Contact Form 7 sia installato e attivo." " È possibile scaricare %s." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "CF7 Il modulo non è selezionato" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "CF7 Styler" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "Caselle di controllo e radiobottoni" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "Stili puliti" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "Libero" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "Chiudere" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "Colore" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "Modulo di contatto 7 elenco" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "Contenere" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Copiare le impostazioni dello schema di stile corrente" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "Copertina" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "Creare" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "Creare più schemi di stile" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "Create un nuovo schema di stile!" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Stile attuale" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "Attualmente il modulo %s " "è stilizzato con %s" ". Come nella versione gratuita, è possibile stilizzare solo un modulo alla " "volta e se si attiva lo stile per il modulo corrente, lo stile verrà rimosso " "dagli altri moduli." #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "Attualmente il modulo %s è stilizzato con " "%s. Come nella versione gratuita, è possibile stilizzare solo un " "modulo alla volta e se si attiva lo stile per il modulo corrente, lo stile " "verrà rimosso dagli altri moduli." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "CSS personalizzato" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "Codice CSS personalizzato" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "Tratteggiato" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "Schema predefinito" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "Cancellare l'immagine" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "cancellato" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "Vista sul desktop" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "Disabilita lo stile per tutti i moduli" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "Disabilita lo stile per il modulo corrente" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "Vuoi ottenere la versione premium di Styler gratuitamente? Allora inserisci la tua licenza " "WP2LEADS pro o ottieni una licenza qui!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "Volete salvare le modifiche prima di lasciare la pagina?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "A puntini" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "Doppio" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "Modulo duplicato nella seconda colonna" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "abilitato per tutti i moduli" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "Errore" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "Uscita dallo schermo intero" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "Famiglia di caratteri" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "Dimensione del carattere" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Stile del carattere" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "Peso del carattere" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Immagine BG del modulo e colori" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "Personalizzazione del modulo" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Il modulo non è selezionato" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "Imbottitura, margine e bordo del modulo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "Testo del modulo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "Schermo intero" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "Scanalatura" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "Lunghezza orizzontale" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Colore del bordo del mouse" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "Colore Hover" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Colore del testo al passaggio del mouse" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "Come trasformare il vostro modulo contact form7 in un modulo di contatto che " "converte e che è facile da usare e in stile professionale, in un generatore " "di lead \"survey\" o in un modulo che cattura l'attenzione" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "https://saleswonder.biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "Sono felice di questo! Risparmio" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "Se si utilizzano page builder come Thrive Architect, OptimizePress ecc., " "consultare la nostra pagina Base di conoscenza per risolvere eventuali " "problemi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "Se avete bisogno di caricare lo schema di stile all'interno del tag " "<body> solo su alcune pagine, potete farlo nel frontend " "utilizzando il pulsante \"CF7 Styler\". Questa funzione è disponibile solo " "per i tipi di post singoli (pagine, post, prodotti ecc.) e nella versione " "premium. Non è possibile farlo sulle pagine degli archivi (blog, elenco di " "prodotti, ecc.), in questo caso è necessario utilizzare le impostazioni " "globali." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "Se è necessario caricare lo schema di stile all'interno del tag <" "body> solo su alcune pagine, è possibile farlo nel frontend " "utilizzando il pulsante \"CF7 Styler\". Questa funzione è disponibile solo " "per i singoli tipi di post (pagine, post, prodotti ecc.). Non è possibile " "farlo sulle pagine degli archivi (blog, elenco di prodotti, ecc.), in questo " "caso è necessario utilizzare le impostazioni globali." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "Le impostazioni dello sfondo dell'immagine sono disponibili in modalità live " "solo per la versione Professional. È possibile provarle nella modalità di " "anteprima \"stile corrente\", ma non verranno salvate." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "Opacità dell'immagine" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "Posizione dell'immagine" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "Dimensione dell'immagine" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "Ereditare" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "Campi di input" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "Titolo dello schema di stile di input" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "Inserto" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "Corsivo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "Etichette Colore" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "Dimensione del carattere delle etichette" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "Impostazioni delle etichette" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "Licenza" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "Altezza della linea" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "Link Colore" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "Colore del passaggio dei link" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Impostazioni dei collegamenti" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "In diretta" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "Caricamento degli stili nel tag <body>" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "" "Caricare gli stili all'interno del tag <body> in questa " "pagina" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "Rendere la voce della casella di controllo una per riga" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "Fare il pieno di larghezza?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "Rendere i campi di input a larghezza piena?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Rendere l'elemento del radiobottone uno per riga" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "Margine" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "Vista mobile" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "NO" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "Nessun elemento di Contact Form 7 per l'anteprima" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "Nessun modulo è stato creato con uno schema di stile, fare clic sul pulsante " "\"Attiva lo stile per il modulo corrente\" per applicare lo schema corrente " "a questo modulo." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "Non è stato selezionato alcun plugin da installare" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "Non è stato selezionato alcuno schema di stile" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "Normale" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "Obliquo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "Stili per riga per caselle di controllo e radiobottoni in modalità live solo " "per la versione Professional. È possibile provarlo in modalità anteprima " "\"stile corrente\", ma non verrà salvato." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "Opacità" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "Styler aperto" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "Opt-in per vedere l'account" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "Dimensione originale" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "Schema" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "Esternalizzazione" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "Imbottitura" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "Inserire il titolo dello schema di stile" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "Anteprima" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "Modalità anteprima" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "Anteprima Unstyled" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "Raggio" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "Ripetere entrambi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "Ripetizione orizzontale" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "Ripetizione verticale" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Ripristino delle impostazioni predefinite" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "Crinale" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "Risparmiare" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "Salvati" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "Vista della seconda colonna" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "Selezionare lo schema di stile per questo modulo" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "Impostazioni" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "Impostazioni salvate come" #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "Ombra" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "Colore dell'ombra" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Posizione d'ombra" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "Solido" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Alcuni temi o page builder (ad esempio Thrive Architect, OptimizePress ecc.) " "potrebbero rimuovere gli stili in linea all'interno del tag <" "head>. Il caricamento dello schema di stile all'interno del tag " "<body> risolverà questo problema e mostrerà i moduli in " "stile." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "Modalità Split" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "Vista divisa" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "Raggio di diffusione" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "Iniziare lo styling" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "Iniziare con la creazione dello schema di stile predefinito" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "Iniziate creando il vostro primo " "Contact Form 7" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "Inizia la tua prova gratuita di 14 giorni con tutte le funzioni Professional " "qui!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "Passo 1. Fare clic sul link \"Modifica con Thrive Architect\" nell'elenco " "della pagina di amministrazione" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "" "Passo 2. Fare clic sull'icona \"Impostazioni\" nel menu verticale di destra" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "" "Passo 3. \"Impostazioni avanzate\" => \"CSS nella sezione <head>\"" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "Passo 4. Assicurarsi che sia selezionata l'opzione \"Non rimuovere i CSS da " "<head>\"" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "Passo 5. Fate clic sul pulsante \"SALVA LAVORO" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "Modellare tutti i moduli con un solo clic a livello globale" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "Modellare ogni modulo con qualsiasi schema di stile individualmente" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "Schema di stile disabilitato per tutti i moduli" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "Schema di stile disabilitato per questo modulo" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "Schema di stile abilitato per questo modulo" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "Lo schema di stile non è selezionato" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "Elenco degli schemi di stile" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "Anteprima degli schemi di stile" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "Impostazioni degli schemi di stile" #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "Lo stile verrà caricato nel tag " #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "Lo stile sarà caricato nel tag " #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "Il successo" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "Supporto e KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "Vista della tavoletta" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "Colore del testo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "Questo modulo è stilizzato con %s a livello globale, è " "possibile stilizzarlo con lo schema di stile corrente." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "Questo modulo è stato creato con %s, è possibile creare uno " "stile con lo schema di stile corrente." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "Questo modulo è stilizzato con lo schema di stile corrente; è possibile " "disattivarlo e utilizzare le impostazioni globali." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "Questo modulo non ha uno schema di stile; è possibile attivare lo schema " "attuale per questo modulo o impostare uno schema di stile globale facendo " "clic su \"Usa per tutti i moduli\" sotto il titolo dello schema." #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "Questo schema non esiste" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "Questo schema di stile è abilitato globalmente per tutti i moduli. Se si " "desidera utilizzare lo stile del proprio tema per il Modulo di contatto 7, " "fare clic sul pulsante \"Disattiva\"." #. Author of the plugin msgid "Tobias Conrad" msgstr "Tobias Conrad" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "Tutorial" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "Senza stile" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "Aggiornamento a Pro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "Carica immagine" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "Lunghezza verticale" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "Benvenuti" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "Larghezza" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "Modulo di contatto in stile WOW 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "SÃŒ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "È possibile creare un nuovo schema di stile con le impostazioni dello schema " "corrente. Se si desidera creare uno schema di stile vuoto, deselezionare la " "casella di controllo sottostante." #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "Non è possibile eliminare" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "" "Non è possibile utilizzare queste impostazioni su questo tipo di pagina" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "Non si dispone di elementi del Modulo di contatto 7" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "Non si utilizza nessuno degli schemi di stile per il modulo di contatto 7. " "Fare clic su \"Usa per tutti i moduli\" per utilizzare lo schema corrente a " "livello globale." languages/cf7-styler-es_ES.po000064400000113146146725417150012067 0ustar00msgid "" msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: Wow style (ES)\n" "Language: es-ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "POT-Creation-Date: 2020-04-18 12:29+0000\n" "PO-Revision-Date: 2023-04-15 16:05+0000\n" "Last-Translator: Tobias support@saleswonder.biz\n" "Language-Team: Spanish (Spain)\n" "Report-Msgid-Bugs-To: \n" "X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- desactivar el esquema de estilo -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "- seleccionar -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14 días de prueba" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #| msgid "" #| "%s used for all forms globally, click \"Use for all forms\" if you want to " #| "use current Scheme." msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%s utilizado para todos los formularios globalmente, haga " "clic en \"Utilizar para todos los formularios\" si desea utilizar el Esquema " "actual." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "Activar el estilo para todos los formularios*" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Activar el estilo para el formulario actual" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "Como alternativa puedes desactivar limpiar los estilos como en Thrive " "architect:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "Color de fondo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "Imagen de fondo" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Antes de utilizar WOW Style Contact Form 7, necesita instalar y activar el " "plugin Contact Form 7." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "Color BG" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "Opacidad BG" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "Radio de desenfoque" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "Frontera" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "Color del borde" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "Radio del borde" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "Tipo de borde" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "Anchura del borde" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "Borde del botón" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "Botones" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Por Takayuki Miyoshi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "Cancelar" #: cf7-styler.php:129 msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "CF7 Customizer requiere que el plugin Contact Form 7 esté instalado y activo." " Puede descargar %s." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "El formulario CF7 no está seleccionado" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "CF7 Styler" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "Casillas de verificación y botones de radio" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "Estilos limpios" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "Claro" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "Cerrar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "Color" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "Formulario de contacto 7 lista" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "Contiene" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Copiar la configuración actual del esquema de estilos" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "Portada" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "Cree" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "Crear varios esquemas de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "Crear un nuevo esquema de estilo" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Estilo actual" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "Actualmente %s " "formulario tiene estilo con " "%s. Al igual que en la versión gratuita, sólo puede aplicar estilo " "a un formulario a la vez y si activa el estilo para el formulario actual, el " "estilo se eliminará del otro formulario." #: admin/class-cf7-customizer-admin.php:481 #| msgid "" #| "Currently %s form is styled with %s. As in free version you can style only " #| "one form at a time and if you activate style for current form, style will be " #| "removed from other form." msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "Actualmente el formulario %s está estilizado con " "%s. Como en la versión gratuita puede estilo sólo una forma a la " "vez y si activa el estilo para la forma actual, estilo se eliminará de otra " "forma." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "CSS personalizado" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "Código CSS personalizado" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "Dashed" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "Régimen por defecto" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "Borrar imagen" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "suprimido" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "Vista de escritorio" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "Desactivar el estilo para todos los formularios" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "Desactivar el estilo para el formulario actual" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "Te gusta conseguir styler versión premium gratis? ¡Entonces Introduzca su licencia " "WP2LEADS pro u obtenga una licencia aquí!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "¿Desea guardar los cambios antes de salir de la página?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "Puntos" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "Doble" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "Formulario duplicado en la segunda columna" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "activado para todos los formularios" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "Error" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "Salir a pantalla completa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "Familia de fuentes" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "Tamaño de letra" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Estilo de fuente" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "Peso de la fuente" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Form BG Image & Colors" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "Personalización de formularios" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Formulario no seleccionado" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "Relleno, margen y borde del formulario" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "Texto del formulario" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "Pantalla completa" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "Ranura" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "Longitud horizontal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Color BG" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "Color Hover" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Color del texto sobreimpresionado" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "Cómo convertir su formulario de contacto form7 en un formulario de contacto " "de conversión, fácil de usar y con estilo profesional, un generador de " "prospectos \"encuesta\" o un formulario llamativo" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "https://saleswonder.biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "¡Estoy contento con esto! Guardar" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "Si está utilizando constructores de páginas, como Thrive Architect, " "OptimizePress, etc., consulte nuestra página Base de conocimientos " "para solucionar posibles problemas" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "Si necesita cargar esquema de estilo dentro de <body> " "etiqueta sólo en algunas páginas, puede hacerlo en frontend usando \"CF7 " "Styler\" botón. Esta función sólo está disponible para los tipos de mensajes " "individuales (páginas, mensajes, productos, etc) y en la versión premium. No " "se puede hacer en las páginas de archivos (blog, lista de productos, etc) en " "este caso es necesario utilizar la configuración global." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "Si necesita cargar el esquema de estilo dentro de la etiqueta <" "body> sólo en algunas páginas, puede hacerlo en frontend usando el " "botón \"CF7 Styler\". Esta función sólo está disponible para los tipos de " "entradas individuales (páginas, entradas, productos, etc.). No se puede " "hacer en las páginas de archivos (blog, lista de productos, etc) en este " "caso es necesario utilizar la configuración global." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "La configuración del fondo de la imagen sólo está disponible en la versión " "Profesional. Puede probarlo en el modo de vista previa \"estilo actual\", " "pero no se guardará." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "Opacidad de la imagen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "Posición de la imagen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "Tamaño de la imagen" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "Heredar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "Campos de entrada" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "Título del esquema de estilo de entrada" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "Insertar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "Cursiva" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "Etiquetas Color" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "Etiquetas Tamaño de fuente" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "Etiquetas Ajustes" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "Licencia" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "Altura de línea" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "Enlaces Color" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "Color de los enlaces" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Configuración de enlaces" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "En directo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "Cargar estilos en la etiqueta <body><body> tag on this page" msgstr "" "Cargar estilos dentro de la etiqueta <body> en esta página" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "Marque una casilla por línea" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "¿Hacer ancho completo?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "¿Completar los campos de entrada?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Hacer un elemento radiobutton por línea" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "Margen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "Vista móvil" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "NO" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "No hay elementos de Contact Form 7 para la vista previa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "Ningún formulario tiene un esquema de estilo, haga clic en el botón " "\"Activar estilo para formulario actual\" para aplicar el esquema actual a " "este formulario." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "No se ha seleccionado ningún plugin para instalar" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "No se ha seleccionado ningún esquema de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "Normal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "Oblicuo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "Estilos uno por línea para casillas de verificación y radiobuttons en modo " "actual sólo para la versión Profesional. Puede probarlo en el modo de vista " "previa \"estilo actual\", pero no se guardará." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "Opacidad" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "Estilizador abierto" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "Ver cuenta" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "Tamaño original" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "Esquema" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "Salida" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "Acolchado" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "Introduzca el título del esquema de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "Vista previa" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "Modo de vista previa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "Vista previa Unstyled" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "Radio" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "Repita ambos" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "Repetir horizontal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "Repetir vertical" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Restablecer valores por defecto" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "Cresta" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "Guardar" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "Guardado" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "Vista de la segunda columna" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "Seleccione el esquema de estilo para este formulario" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "Ajustes" #: admin/class-cf7-customizer-admin-ajax.php:210 #| msgid "Settings saved as" msgid "Settings saved as " msgstr "Ajustes guardados como" #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "Sombra" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "Sombra Color" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Posición de sombra" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "Sólido" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 #| msgid "" #| "Some themes or page builders (e.g. Thrive Architect, OptimizePress etc.) " #| "could remove inline styles inside tag. Loading style scheme within " #| " tag will fix this issue and show your forms styled." msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Algunos temas o constructores de página (fe. Thrive Architect, OptimizePress " "etc.) podrían eliminar estilos en línea dentro de la etiqueta <" "head>. Cargar el esquema de estilo dentro de la etiqueta <" "body> solucionará este problema y mostrará sus formularios con " "estilo." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "Modo dividido" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "Vista dividida" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "Radio de dispersión" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "Empezar a estilizar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "Empezar creando un esquema de estilo por defecto" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "Comienza creando tu primer Formulario " "de Contacto 7" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "¡Comience su prueba gratuita de 14 días con todas las funciones " "profesionales aquí!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "Paso 1. Haga clic en el enlace \"Editar con Thrive architect\" en la lista " "de páginas de administración" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "" "Paso 2. Haga clic en el icono \"Configuración\" del menú vertical derecho" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 #| msgid "Step 3. \"Advanced settings\" => \"CSS in the section\"" msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "" "Paso 3. \"Configuración avanzada\" => \"CSS en la sección <head>\"" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 #| msgid "Step 4. Make sure that \"Do not strip CSS from \" is checked" msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "Paso 4. Asegúrese de que \"No quitar CSS de <head>\" está marcada" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "Paso 5. Pulse el botón \"GUARDAR TRABAJO" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "Estiliza todos los formularios globalmente con un solo clic" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "" "Estiliza cada formulario individualmente con cualquier esquema de estilo" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "Esquema de estilo desactivado para todos los formularios" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "Esquema de estilo desactivado para este formulario" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "Esquema de estilo habilitado para este formulario" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "El esquema de estilo no está seleccionado" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "Lista de esquemas de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "Vista previa de los esquemas de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "Ajustes de los esquemas de estilo" #: admin/class-cf7-customizer-admin-ajax.php:298 #| msgid "Style will be loaded in tag" msgid "Style will be loaded in tag" msgstr "El estilo se cargará en la etiqueta tag" msgstr "El estilo se cargará en la etiqueta " #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "Éxito" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "Soporte y KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "Vista de tableta" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "Color del texto" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #| msgid "" #| "This form is styled with %s globally, you can style it with current Style " #| "scheme." msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "Este formulario está estilizado con %s globalmente, puedes " "estilizarlo con el esquema de Estilo actual." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #| msgid "" #| "This form is styled with %s, you can style it with current Style scheme." msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "Este formulario está estilizado con %s, puedes estilizarlo " "con el esquema de Estilo actual." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "Este formulario está diseñado con el esquema de estilo actual, puede " "desactivarlo y utilizar la configuración global." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "Este formulario no tiene ningún esquema de estilo, puede activar el esquema " "actual para este formulario o configurar un esquema de estilo global " "haciendo clic en \"Usar para todos los formularios\" debajo del título del " "esquema." #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "Este régimen no existe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "Este esquema de estilo habilitado a nivel mundial para todas las formas. Si " "desea utilizar el estilo de su tema para Contact Form 7 haga clic en el " "botón \"Desactivar\"." #. Author of the plugin msgid "Tobias Conrad" msgstr "Tobias Conrad" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "Tutorial" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "Sin estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "Actualizar a Pro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "Cargar imagen" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "Longitud vertical" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "Bienvenido" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "Anchura" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "Formulario de contacto WOW Style 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "SÃ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 #| msgid "" #| "You can create new style scheme with current scheme settings. If you want to " #| "create blank style scheme uncheck checkbox below." msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "Puede crear un nuevo esquema de estilo con la configuración actual. Si desea " "crear un esquema de estilo en blanco, desmarque la casilla de abajo." #: admin/class-cf7-customizer-admin-ajax.php:237 #| msgid "You cannot delete" msgid "You can not delete" msgstr "No se puede borrar" #: public/class-cf7-customizer-public.php:471 #| msgid "You cannot use this settings on this page type" msgid "You can not use this settings on this page type" msgstr "No puede utilizar esta configuración en este tipo de página" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "No tiene ningún elemento Contact Form 7" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "No utiliza ninguno de los esquemas de estilo para Contact Form 7. Haga clic " "en \"Usar para todos los formularios\" para utilizar el esquema actual de " "forma global." languages/cf7-styler-hi_IN.po000064400000133766146725417150012071 0ustar00msgid "" msgstr "" "Language: hi-IN\n" "POT-Creation-Date: 2023-04-15 15:26+0000\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "PO-Revision-Date: 2023-04-15 16:10+0000\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: WOW Style Contact Form 7\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: Tobias support@saleswonder.biz\n" "Language-Team: Hindi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- डिसà¥à¤•à¤¾à¤‰à¤‚ट सà¥à¤Ÿà¤¾à¤‡à¤² योजना -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "चà¥à¤¨à¥‡à¤‚ -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14 दिन का मà¥à¤•à¤¦à¤®à¤¾" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%sवैशà¥à¤µà¤¿à¤• सà¥à¤¤à¤° पर सभी फॉरà¥à¤®à¥‹à¤‚ के लिठउपयोग किया जाता है, " "यदि आप वरà¥à¤¤à¤®à¤¾à¤¨ योजना का उपयोग करना चाहते हैं तो \"सभी फॉरà¥à¤®à¥‹à¤‚ के लिठउपयोग " "करें\" पर कà¥à¤²à¤¿à¤• करें।" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "सभी रूपों के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करें *" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "वरà¥à¤¤à¤®à¤¾à¤¨ फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करें" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "à¤à¤• विकलà¥à¤ª के रूप में आप फà¥à¤²à¥‹à¤°à¤¿à¤‚ग आरà¥à¤•à¤¿à¤Ÿà¥‡à¤•à¥à¤Ÿ जैसे शैलियों को साफ करने के लिठ" "अकà¥à¤·à¤® कर सकते हैं:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "पृषà¥à¤ à¤­à¥‚मि रंग" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "पृषà¥à¤ à¤­à¥‚मि छवि" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Wow सà¥à¤Ÿà¤¾à¤‡à¤² संपरà¥à¤• फ़ॉरà¥à¤® 7 का उपयोग करने से पहले, आपको संपरà¥à¤• फ़ॉरà¥à¤® 7 " "पà¥à¤²à¤—इन सà¥à¤¥à¤¾à¤ªà¤¿à¤¤ करने और सकà¥à¤°à¤¿à¤¯ करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है।" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "बीजी रंग" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "BG असà¥à¤¥à¤¿à¤°à¤¤à¤¾" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "बà¥à¤²à¥‚ रेडिà¤à¤¶à¤¨" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "सीमाà¤à¤‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "सीमा का रंग" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "सीमा रेडिà¤à¤¶à¤¨" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "सीमा पà¥à¤°à¤•à¤¾à¤°" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "सीमा चौड़ा" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "बटन सीमा" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "बटन" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Takayuki Miyoshi के बारे में जानकारी" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "रदà¥à¤¦ करें" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "Cf7 Customizer को सà¥à¤¥à¤¾à¤ªà¤¿à¤¤ करने और सकà¥à¤°à¤¿à¤¯ होने के लिठसंपरà¥à¤• फॉरà¥à¤® 7 पà¥à¤²à¤—इन " "की आवशà¥à¤¯à¤•à¤¤à¤¾ होती है। आप% S डाउनलोड कर सकते हैं।" #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "Cf7 फ़ॉरà¥à¤® नहीं चà¥à¤¨à¤¾ गया है" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "Cf7 सà¥à¤Ÿà¤¾à¤‡à¤²à¤°" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "चेकबॉकà¥à¤¸ और रेडियोबॉटन" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "साफ सà¥à¤Ÿà¤¾à¤‡à¤²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "सà¥à¤ªà¤·à¥à¤Ÿ" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "निकट" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "रंगों" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "संपरà¥à¤• फ़ॉरà¥à¤® 7 सूची" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "कंटेनर" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "वरà¥à¤¤à¤®à¤¾à¤¨ सà¥à¤Ÿà¤¾à¤‡à¤² योजना सेटिंगà¥à¤¸ को कॉपी करें" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "कवर" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "बनाओ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "कई सà¥à¤Ÿà¤¾à¤‡à¤² योजनाà¤à¤‚ बनाà¤à¤‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "à¤à¤• नया सà¥à¤Ÿà¤¾à¤‡à¤² डिजाइन बनाà¤à¤‚!" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "वरà¥à¤¤à¤®à¤¾à¤¨ सà¥à¤Ÿà¤¾à¤‡à¤²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "वरà¥à¤¤à¤®à¤¾à¤¨ में % à¤à¤¸ आकार के " "साथ बनाया गया है % à¤à¤¸ " ". मà¥à¤«à¥à¤¤ संसà¥à¤•à¤°à¤£ के रूप में आप à¤à¤• ही समय में केवल à¤à¤• फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤² कर " "सकते हैं और यदि आप वरà¥à¤¤à¤®à¤¾à¤¨ फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करते हैं, तो सà¥à¤Ÿà¤¾à¤‡à¤² को " "दूसरे फॉरà¥à¤® से हटा दिया जाà¤à¤—ा।" #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "वरà¥à¤¤à¤®à¤¾à¤¨ में % à¤à¤¸ आकार के साथ बनाया गया है % à¤à¤¸ " ". मà¥à¤«à¥à¤¤ संसà¥à¤•à¤°à¤£ के रूप में आप à¤à¤• ही समय में केवल à¤à¤• फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤² कर " "सकते हैं और यदि आप वरà¥à¤¤à¤®à¤¾à¤¨ फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करते हैं, तो सà¥à¤Ÿà¤¾à¤‡à¤² को " "दूसरे फॉरà¥à¤® से हटा दिया जाà¤à¤—ा।" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "सीà¤à¤¸à¤à¤¸ के लिà¤" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "सीà¤à¤¸à¤à¤¸ कोड" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "डैश" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "डिफ़ॉलà¥à¤Ÿ योजना" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "छवि को हटाना" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "हटाठगà¤" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "डेसà¥à¤•à¤Ÿà¥‰à¤ª दृशà¥à¤¯" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "सभी रूपों के लिठअकà¥à¤·à¤® सà¥à¤Ÿà¤¾à¤‡à¤²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "वरà¥à¤¤à¤®à¤¾à¤¨ आकार के लिठअकà¥à¤·à¤® सà¥à¤Ÿà¤¾à¤‡à¤²" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "कà¥à¤¯à¤¾ आप मà¥à¤«à¥à¤¤ में सà¥à¤Ÿà¤¾à¤‡à¤²à¤° पà¥à¤°à¥€à¤®à¤¿à¤¯à¤® संसà¥à¤•à¤°à¤£ पà¥à¤°à¤¾à¤ªà¥à¤¤ करना चाहते हैं? और फिर अपने Wp2Leads पà¥à¤°à¥‹ " "लाइसेंस दरà¥à¤œ करें या à¤à¤• लाइसेंस पà¥à¤°à¤¾à¤ªà¥à¤¤ करें यहाठ" "!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "कà¥à¤¯à¤¾ आप पृषà¥à¤  छोड़ने से पहले परिवरà¥à¤¤à¤¨à¥‹à¤‚ को बचाना चाहते हैं?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "डà¥à¤¯à¥‚टी" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "दोगà¥à¤¨à¤¾" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "दूसरी सà¥à¤¤à¤‚भ में डà¥à¤ªà¥à¤²à¤¿à¤•à¥‡à¤Ÿ फॉरà¥à¤®" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "सभी रूपों के लिठउपलबà¥à¤§ है" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "गलतियां" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "पूरà¥à¤£ सà¥à¤•à¥à¤°à¥€à¤¨ से बाहर" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "फ़ॉनà¥à¤Ÿ परिवार" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "फ़ॉनà¥à¤Ÿ आकार" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "फ़ॉनà¥à¤Ÿ सà¥à¤Ÿà¤¾à¤‡à¤²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "वजन लिपसà¥à¤Ÿà¤¿à¤•" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "BG छवि और रंग" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "आकार के अनà¥à¤•à¥‚लन" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "फॉरà¥à¤® नहीं चà¥à¤¨à¤¾ गया है" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "फॉरà¥à¤® पैडिंग, मारà¥à¤œà¤¿à¤¨ और सीमा" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "फॉरà¥à¤® टेकà¥à¤¸à¥à¤Ÿ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "पूरà¥à¤£ सà¥à¤•à¥à¤°à¥€à¤¨" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "बढ़ोतरी" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "कà¥à¤·à¥ˆà¤¤à¤¿à¤œ लंबाई" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Hover BG रंग" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "हॉवरà¥à¤¸ रंग" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Hover पाठ रंग" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "अपने संपरà¥à¤• फॉरà¥à¤® 7 को à¤à¤• रूपांतरण और उपयोग करने में आसान और पà¥à¤°à¥‹ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ " "संपरà¥à¤• फॉरà¥à¤®, \"अनà¥à¤¸à¤‚धान\" पाउडर जनरेटर या à¤à¤• आंख पकड़ने फॉरà¥à¤® में कैसे " "परिवरà¥à¤¤à¤¿à¤¤ करें" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "à¤à¤šà¤Ÿà¥€à¤ªà¥€à¤à¤¸: //Saleswonder.Biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "Https: //Saleswonder.Biz/Blog/4Free-Contact-Form-7-Cf7-Formular-Und-Klick-" "Tipp-Einfach-Verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "मैं इस बात से खà¥à¤¶ हूà¤! बचाव" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "यदि आप पृषà¥à¤  निरà¥à¤®à¤¾à¤¤à¤¾à¤“ं का उपयोग कर रहे हैं, जैसे कि फà¥à¤°à¥€à¤µ आरà¥à¤•à¤¿à¤Ÿà¥‡à¤•à¥à¤Ÿ, " "Optimizepress आदि, कृपया हमारी जांच करें जà¥à¤žà¤¾à¤¨ आधार पृषà¥à¤  संभावित मà¥à¤¦à¥à¤¦à¥‹à¤‚ " "को हल करने के लिà¤" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "यदि आपको अंदर सà¥à¤Ÿà¤¾à¤‡à¤² योजना लोड करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है केवल " "कà¥à¤› पृषà¥à¤ à¥‹à¤‚ पर टैग करें, आप \"Cf7 सà¥à¤Ÿà¤¾à¤‡à¤²à¤°\" बटन का उपयोग करके सामने पर à¤à¤¸à¤¾ " "कर सकते हैं। यह सà¥à¤µà¤¿à¤§à¤¾ केवल à¤à¤•à¤² पोसà¥à¤Ÿ पà¥à¤°à¤•à¤¾à¤° (पृषà¥à¤ , पोसà¥à¤Ÿ, उतà¥à¤ªà¤¾à¤¦, आदि) के " "लिठउपलबà¥à¤§ है। और पà¥à¤°à¥€à¤®à¤¿à¤¯à¤® संसà¥à¤•à¤°à¤£ में। आप इसे संगà¥à¤°à¤¹ पृषà¥à¤ à¥‹à¤‚ (बà¥à¤²à¥‰à¤—, उतà¥à¤ªà¤¾à¤¦ " "सूची आदि) पर नहीं कर सकते हैं, इस मामले में आपको वैशà¥à¤µà¤¿à¤• सेटिंगà¥à¤¸ का उपयोग " "करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है।" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "यदि आपको अंदर सà¥à¤Ÿà¤¾à¤‡à¤² योजना लोड करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है केवल " "कà¥à¤› पृषà¥à¤ à¥‹à¤‚ पर टैग करें, आप \"Cf7 सà¥à¤Ÿà¤¾à¤‡à¤²à¤°\" बटन का उपयोग करके सामने पर à¤à¤¸à¤¾ " "कर सकते हैं। यह सà¥à¤µà¤¿à¤§à¤¾ केवल à¤à¤•à¤² पोसà¥à¤Ÿ पà¥à¤°à¤•à¤¾à¤° (पृषà¥à¤ , पोसà¥à¤Ÿ, उतà¥à¤ªà¤¾à¤¦, आदि) के " "लिठउपलबà¥à¤§ है। आप इसे संगà¥à¤°à¤¹ पृषà¥à¤ à¥‹à¤‚ (बà¥à¤²à¥‰à¤—, उतà¥à¤ªà¤¾à¤¦ सूची आदि) पर नहीं कर " "सकते हैं, इस मामले में आपको वैशà¥à¤µà¤¿à¤• सेटिंगà¥à¤¸ का उपयोग करने की आवशà¥à¤¯à¤•à¤¤à¤¾ है।" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "छवि पृषà¥à¤ à¤­à¥‚मि सेटिंगà¥à¤¸ केवल पेशेवर संसà¥à¤•à¤°à¤£ के लिठलाइव मोड में उपलबà¥à¤§ हैं। " "आप इसे पूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨ मोड \"वरà¥à¤¤à¤®à¤¾à¤¨ शैली\" में परीकà¥à¤·à¤£ कर सकते हैं, लेकिन यह " "बचाया नहीं जाà¤à¤—ा।" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "तसà¥à¤µà¥€à¤°à¥‡à¤‚ Opacity" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "छवि सà¥à¤¥à¤¿à¤¤à¤¿" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "छवि आकार" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "विरासत" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "इनपà¥à¤Ÿ के कà¥à¤·à¥‡à¤¤à¥à¤°" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "इनपà¥à¤Ÿ सà¥à¤Ÿà¤¾à¤‡à¤² पà¥à¤°à¥‹à¤—à¥à¤°à¤¾à¤® शीरà¥à¤·à¤•" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "इंतजार" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "इटालियन" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "रंग लेबल" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "लेबल फ़ॉनà¥à¤Ÿ आकार" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "लेबल सेटिंगà¥à¤¸" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "अनà¥à¤®à¤¤à¤¿" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "लाइन ऊंचाई" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "बाà¤à¤‚ रंग" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "बाईं ओर का रंग" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "बाà¤à¤‚ सेटिंगà¥à¤¸" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "लाइव" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "लोड सà¥à¤Ÿà¤¾à¤‡à¤² में Tag" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "आंतरिक लोड सà¥à¤Ÿà¤¾à¤‡à¤² इस पृषà¥à¤  पर टैग" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "चेकबॉकà¥à¤¸ आइटम à¤à¤• लाइन के लिठबनाà¤à¤‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "पूरी चौड़ाई बनाà¤à¤‚?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "इनपà¥à¤Ÿ फ़ीलà¥à¤¡ पूरी चौड़ाई बनाते हैं?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Radiobutton आइटम à¤à¤• लाइन के लिठबनाà¤à¤‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "मारà¥à¤œà¤¿à¤¨" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "मोबाइल दृशà¥à¤¯" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "नहीं नहीं" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "कोई संपरà¥à¤• फॉरà¥à¤® नहीं 7 वसà¥à¤¤à¥à¤“ं के लिठपूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "कोई फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤² शेडà¥à¤¯à¥‚ल के साथ सà¥à¤Ÿà¤¾à¤‡à¤² नहीं है, इस फॉरà¥à¤® के लिठवरà¥à¤¤à¤®à¤¾à¤¨ " "शेडà¥à¤¯à¥‚ल लागू करने के लिठ\"वरà¥à¤¤à¤®à¤¾à¤¨ फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² सकà¥à¤°à¤¿à¤¯ करें\" बटन पर " "कà¥à¤²à¤¿à¤• करें।" #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "कोई पà¥à¤²à¤—इन सà¥à¤¥à¤¾à¤ªà¤¿à¤¤ करने के लिठचà¥à¤¨à¤¾ नहीं है" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "कोई सà¥à¤Ÿà¤¾à¤‡à¤² योजना नहीं चà¥à¤¨à¥€ गई" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "सामानà¥à¤¯" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "Oblique में" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "चेकबॉकà¥à¤¸ और रेडियोबॉटन के लिठलाइव मोड में केवल पेशेवर संसà¥à¤•à¤°à¤£ के लिठà¤à¤•-à¤à¤•-" "लाइन सà¥à¤Ÿà¤¾à¤‡à¤²à¥¤ आप इसे पूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨ मोड \"वरà¥à¤¤à¤®à¤¾à¤¨ शैली\" में परीकà¥à¤·à¤£ कर सकते हैं," " लेकिन यह बचाया नहीं जाà¤à¤—ा।" #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "असà¥à¤¥à¤¿à¤°à¤¤à¤¾" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "खà¥à¤²à¥‡ सà¥à¤Ÿà¤¾à¤‡à¤²" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "अकाउंट देखने के लिठOpt-In" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "मूल आकार" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "आउटलिन" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "बाहर निकल" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "पदà¥à¤®à¤¾à¤µà¤¤à¥€" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "कृपया सà¥à¤Ÿà¤¾à¤‡à¤² पà¥à¤°à¥‹à¤—à¥à¤°à¤¾à¤® का शीरà¥à¤·à¤• दरà¥à¤œ करें" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "पूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "पूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨ मोड" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "अनौपचारिक पूरà¥à¤µà¤¾à¤µà¤²à¥‹à¤•à¤¨" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "रेडिà¤à¤¶à¤¨" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "दोबारा दोहराà¤à¤‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "कà¥à¤·à¥ˆà¤¤à¤¿à¤œ दोहराà¤à¤‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "वरà¥à¤šà¥à¤…ल पà¥à¤¨à¤°à¤¾à¤µà¥ƒà¤¤à¥à¤¤à¤¿" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "डिफ़ॉलà¥à¤Ÿ के लिठपà¥à¤¨à¤°à¤¾à¤°à¤‚भ" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "रीज" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "बचाव" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "बचाठगà¤" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "दूसरा दृषà¥à¤Ÿà¤¿à¤•à¥‹à¤£" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "इस फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² योजना चà¥à¤¨à¥‡à¤‚" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "सेटिंगà¥à¤¸" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "सेटिंगà¥à¤¸ को बचाया गया है" #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "छाया" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "छाया का रंग" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "छाया की सà¥à¤¥à¤¿à¤¤à¤¿" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "मजबूत" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "कà¥à¤› विषयों या पृषà¥à¤  निरà¥à¤®à¤¾à¤¤à¤¾à¤“ं (Fe. टà¥à¤°à¤¿à¤ª आरà¥à¤•à¤¿à¤Ÿà¥‡à¤•à¥à¤Ÿ, Optimizepress आदि) " "आंतरिक सà¥à¤Ÿà¤¾à¤‡à¤²à¥‹à¤‚ को हटा सकते हैं Tag है। आंतरिक लोड सà¥à¤Ÿà¤¾à¤‡à¤² " "सिसà¥à¤Ÿà¤® टैग इस समसà¥à¤¯à¤¾ को ठीक करेगा और आपके फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ " "दिखाà¤à¤—ा।" #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "विभाजित मोड" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "विभाजित दृषà¥à¤Ÿà¤¿" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "रेडियो फैलाना" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤‚ग शà¥à¤°à¥‚ करें" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "डिफ़ॉलà¥à¤Ÿ सà¥à¤Ÿà¤¾à¤‡à¤² योजना बनाना शà¥à¤°à¥‚ करें" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "अपने आप को बनाने के साथ शà¥à¤°à¥‚ करें पहला " "संपरà¥à¤• फॉरà¥à¤® 7 " #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "सभी पेशेवर सà¥à¤µà¤¿à¤§à¤¾à¤“ं के साथ अपने 14 दिन मà¥à¤«à¥à¤¤ परीकà¥à¤·à¤£ शà¥à¤°à¥‚ करें यहाठ!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "चरण 1। Admin page list में \"edit with thrive architect\" लिंक पर कà¥à¤²à¤¿à¤• करें" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "चरण 2। सही ऊरà¥à¤§à¥à¤µà¤¾à¤§à¤° मेनू पर \"सेटिंगà¥à¤¸\" आइकन पर कà¥à¤²à¤¿à¤• करें" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "चरण 3। \"उनà¥à¤¨à¤¤ सेटिंगà¥à¤¸\" => \"सीà¤à¤¸à¤à¤¸ में अनà¥à¤­à¤¾à¤— »" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "चरण 4। यह सà¥à¤¨à¤¿à¤¶à¥à¤šà¤¿à¤¤ करें कि \"सीà¤à¤¸à¤à¤¸ से बाहर न निकलें ' जांच की जा रही " "है" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "चरण 5। “Save Work†बटन पर कà¥à¤²à¤¿à¤• करें" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "वैशà¥à¤µà¤¿à¤• सà¥à¤¤à¤° पर à¤à¤• कà¥à¤²à¤¿à¤• में सभी फॉरà¥à¤® सà¥à¤Ÿà¤¾à¤‡à¤²" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "सà¥à¤Ÿà¤¾à¤‡à¤² पà¥à¤°à¤¤à¥à¤¯à¥‡à¤• आकार किसी भी सà¥à¤Ÿà¤¾à¤‡à¤² योजना के साथ वà¥à¤¯à¤•à¥à¤¤à¤¿à¤—त रूप से" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "सà¥à¤Ÿà¤¾à¤‡à¤² योजना सभी रूपों के लिठअकà¥à¤·à¤® है" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "इस फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² योजना अकà¥à¤·à¤® है" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "इस फॉरà¥à¤® के लिठसà¥à¤Ÿà¤¾à¤‡à¤² योजना सकà¥à¤·à¤® है" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "शैली का चयन नहीं किया गया है" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "शैली योजनाओं की सूची" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "सà¥à¤Ÿà¤¾à¤‡à¤² पà¥à¤°à¥€à¤µà¥à¤¯à¥‚" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "सà¥à¤Ÿà¤¾à¤‡à¤² सिसà¥à¤Ÿà¤® सेटिंगà¥à¤¸" #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "सà¥à¤Ÿà¤¾à¤‡à¤² में लोड किया जाà¤à¤—ा Tag" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "सà¥à¤Ÿà¤¾à¤‡à¤² में लोड किया जाà¤à¤—ा Tag" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "सफलता" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "समरà¥à¤¥à¤¨ और KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "टैबलेट दृशà¥à¤¯" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "रंग का पाठ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "इस फॉरà¥à¤® के साथ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ % à¤à¤¸ वैशà¥à¤µà¤¿à¤• रूप से, आप इसे " "वरà¥à¤¤à¤®à¤¾à¤¨ शैली योजना के साथ सà¥à¤Ÿà¤¾à¤‡à¤² कर सकते हैं।" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "इस फॉरà¥à¤® के साथ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ % à¤à¤¸ , आप इसे वरà¥à¤¤à¤®à¤¾à¤¨ शैली योजना " "के साथ सà¥à¤Ÿà¤¾à¤‡à¤² कर सकते हैं।" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "यह फॉरà¥à¤® वरà¥à¤¤à¤®à¤¾à¤¨ शैली योजना के साथ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ है, आप इसे अकà¥à¤·à¤® कर सकते हैं और " "वैशà¥à¤µà¤¿à¤• सेटिंगà¥à¤¸ का उपयोग कर सकते हैं।" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "यह फॉरà¥à¤® किसी भी शैली योजना के साथ सà¥à¤Ÿà¤¾à¤‡à¤²à¤¿à¤¶ नहीं है, आप इस फॉरà¥à¤® के लिठ" "वरà¥à¤¤à¤®à¤¾à¤¨ योजना को सकà¥à¤·à¤® कर सकते हैं या \"सभी फॉरà¥à¤®à¥‹à¤‚ के लिठउपयोग\" पर कà¥à¤²à¤¿à¤• " "करके वैशà¥à¤µà¤¿à¤• शैली योजना सेट कर सकते हैं।" #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "इस योजना का असà¥à¤¤à¤¿à¤¤à¥à¤µ नहीं है" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "इस शैली योजना को वैशà¥à¤µà¤¿à¤• रूप से सभी रूपों के लिठसकà¥à¤·à¤® किया गया है। यदि आप " "संपरà¥à¤• फॉरà¥à¤® के लिठअपने विषय के शैली का उपयोग करना चाहते हैं, तो 7 कà¥à¤²à¤¿à¤• " "करें \"अकà¥à¤·à¤®\" बटन।" #. Author of the plugin msgid "Tobias Conrad" msgstr "टॉबियास कॉनराड" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "टà¥à¤¯à¥‚टोरियल" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "अनैचà¥à¤›à¤¿à¤•" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "Pro के लिठUpgrade" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "Image अपलोड करें" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "ऊरà¥à¤§à¥à¤µà¤¾à¤§à¤° लंबा" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "सà¥à¤µà¤¾à¤—त है" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "विशाल" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "WOW सà¥à¤Ÿà¤¾à¤‡à¤² संपरà¥à¤• फॉरà¥à¤® 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "हाठहाà¤" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "आप वरà¥à¤¤à¤®à¤¾à¤¨ योजना सेटिंगà¥à¤¸ के साथ à¤à¤• नया सà¥à¤Ÿà¤¾à¤‡à¤² योजना बना सकते हैं। यदि आप " "नीचे सफेद शैली Schem Unchek चेकबॉकà¥à¤¸ बनाना चाहते हैं।" #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "आप नहीं हटा सकते" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "आप इस पृषà¥à¤  पà¥à¤°à¤•à¤¾à¤° पर इन सेटिंगà¥à¤¸ का उपयोग नहीं कर सकते हैं" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "आपके पास कोई संपरà¥à¤• फॉरà¥à¤® नहीं है 7 आइटम" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "आप संपरà¥à¤• फॉरà¥à¤® 7 के लिठकिसी भी सà¥à¤Ÿà¤¾à¤‡à¤² योजना का उपयोग नहीं करते हैं। " "वैशà¥à¤µà¤¿à¤• सà¥à¤¤à¤° पर वरà¥à¤¤à¤®à¤¾à¤¨ योजना का उपयोग करने के लिठ\"सभी फॉरà¥à¤®à¥‹à¤‚ के लिठ" "उपयोग\" पर कà¥à¤²à¤¿à¤• करें।" languages/cf7-styler-pt_BR.mo000064400000046324146725417150012077 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'¢(²) Ñ) ß)†*$‡*!¬*VÎ* %+ 3+ @+M+|]+ Ú+ æ+ ð+ ý+ ,,*,>,F,ƒ[,'ß, ---5-D-J-Q-!U-w-1~- °-º- À-á- ÿ-< .ôI/>0P0 j0t0 „0#’0%¶0%Ü01="2 `2k2(q2š2Ÿ2·2Ò2ã2 ó2 3"37B3z3#‰3 ­3¸3¿3Ù3õ3 4®&4Õ4òõ4¬è5˜•7.9B9V9·h9 :':'9: a:l:u:…: :½:Æ: Ö:ä:ö:;4;HL;&•;¼;)Ò;&ü;#<*<D<7K<œƒ<' =H=g=n=Îw= F> P>]>s>„>š> ¢>0°>á>õ>?0? 5???Q?a?z?€?‡??3§? Û?è?@ @@-@!6@ XA eApA…A7—AhÏA8B_JCGªCIòCW%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/Language: pt-BR POT-Creation-Date: 2020-02-06 11:35+0000 Plural-Forms: nplurals=2; plural=n != 1; PO-Revision-Date: 2023-04-15 16:06+0000 X-Generator: Loco https://localise.biz/ Project-Id-Version: WOW Style Contact Form 7 Report-Msgid-Bugs-To: Last-Translator: Language-Team: Portuguese (Brazil) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Loco-Version: 2.3.3; wp-5.4- desative o estilo do esquema- selecione -14 dias de período Experimental%s usados para todas as formas globalmente, clique em "Usar de todas as formas" se você quiser usar o Esquema atual.Activar estilo para todas as formas*Activar estilo para a forma atualComo alternativa, você pode desativar limpar os estilos, como em Prosperar arquiteto:VERSO a CoresBG OpacidadeCor De FundoImagem De FundoAntes de utilizar WOW Estilo Formulário de Contato 7, você precisará instalar e ativar o Formulário de Contato 7 plugin.Blur radiusFronteiraCor Da BordaBorder RadiusTipo De BordaLargura Da BordaBotão De FronteiraBotõesPor Takayuki MiyoshiCF7 Personalizador de sistemas requer o Formulário de Contato 7 plugin para ser instalado e ativo. Você pode fazer o download %s.CF7 Formulário não está seleccionadaCF7 StylerCancelarCaixas & RadiobuttonsLimpar EstilosClaroFecharCorFormulário de contato 7 lista deConterCopiar um estilo atual esquema de configuraçõesCoberturaCriarCriar vários esquemas de estiloCriar novo estilo de esquema!Estilo AtualActualmente %s formulário é denominado com %s. Como na versão gratuita, você pode estilo apenas uma forma de cada vez e se você ativar o estilo para a forma atual, o estilo vai ser removido de outra forma.Actualmente %s formulário é denominado com %s. Como na versão gratuita, você pode estilo apenas uma forma de cada vez e se você ativar o estilo para a forma atual, o estilo vai ser removido de outra forma.CSS personalizadoCSS personalizado CódigoTracejadaEsquema PadrãoApagar ImagemVisualização Da Ãrea De TrabalhoDesativar estilo para todas as formasDesativar o estilo para a forma atual¿Te gusta obtener la versión premium de styler gratis? Luego, ingrese su licencia WP2LEADS pro u obtenga una licencia aquí !Você deseja salvar as alterações antes de sair da página?PontilhadaDuploFormulário duplicados em segunda colunaErroSaída De Ecrã InteiroFamília De Tipos De LetraTamanho Da FonteEstilo Da FontePeso Da FonteFormulário BG Image & CoresFormulário De PersonalizaçãoFormulário De Preenchimento, De Margem E De FronteirasTexto De FormaFormulário não está seleccionadaTela CheiaGrooveHorizontal De ComprimentoPasse o mouse VERSO a CoresPasse O Mouse A CorPasse O Mouse A Cor Do TextoComo transformar o seu contato form7 forma em uma conversão e fácil de usar e pro estilo formulário de contato, "pesquisa" gerador de chumbo ou um olho captura formulárioEu estou feliz com isso! SalvarSi está utilizando creadores de páginas, como Thrive Architect, OptimizePress, etc., consulte nuestra página de base de conocimiento para arreglando posibles problemasSe você precisar de carregar o estilo esquema dentro do <body> tag apenas em algumas páginas, você pode fazê-lo no frontend usando "CF7 Styler" botão. Esta função só está disponível para um único post types (páginas, posts, produtos etc.) e na versão premium. Você não pode fazê-lo em arquivos de páginas (blog, lista de produtos, etc), neste caso, você precisa usar configurações globais.Se você precisar de carregar o estilo esquema dentro do <body> tag apenas em algumas páginas, você pode fazê-lo no frontend usando "CF7 Styler" botão. Esta função só está disponível para um único post types (páginas, posts, produtos, etc.). Você não pode fazê-lo em arquivos de páginas (blog, lista de produtos, etc), neste caso, você precisa usar configurações globais.Opacidade Da ImagemPosição Da ImagemTamanho Da ImagemImagem de fundo definições disponíveis no modo de viver apenas para a versão Professional. Você pode testá-lo no modo de visualização atual "estilo", mas ele não será salvo.HerdamCampos De EntradaEstilo de entrada do esquema de títuloInserçãoItálicoRótulos De CorEtiquetas Tamanho Da FonteEtiquetas De ConfiguraçõesLicençaAltura Da LinhaCor Dos LinksLinks Passe A CorConfigurações De LinksAo vivoCarregar estilos de no <body> tagCarga estilos dentro do <body> tag sobre esta páginaFazer a seleção de um item por linhaFazer toda a largura?Fazer campos de entrada de largura total?Fazer radiobutton de um item por linhaMargemModo De Exibição MóvelNENHUMNão Formulário de Contato 7 itens para visualizaçãoDe qualquer forma é decorado com estilo de esquema, clique em "Ativar estilo para a forma atual" botão para aplicar o esquema atual para este formulário.Nenhum plugin selecionado para instalarSem estilo esquema selecionadoNormalOblíquaUm por linha estilos para caixas de verificação e radiobuttons no modo de viver apenas para a versão Professional. Você pode testá-lo no modo de visualização atual "estilo", mas ele não será salvo.OpacidadeAbrir stylerOptar por ver a contaTamanho OriginalEstrutura de tópicosInícioPreenchimentoPor favor, introduza o estilo esquema de títuloPré-visualizaçãoPré-Visualização Sem EstiloModo de pré-visualizaçãoRaioRepita asRepita horizontalRepita verticalRedefinir para o padrãoRidgeSalvarSalvoSegundo a coluna de vistaSelecione o estilo de esquema para este formulárioDefiniçõesConfigurações salvas como SombraA Cor Da SombraSombra PosiçãoSólidosAlguns temas ou página de construtores (fe. Prosperar Arquiteto, OptimizePress etc.) pode remover estilos inline dentro de <head> tag. Carregamento de estilo esquema dentro do <body> tag irá corrigir este problema e mostrar as suas formas de estilo.O modo SplitSplit viewPropagação do raioInício de estiloComeçar com a criação de Estilo Padrão do Regime deComeçar com a criação de seu primeiro Formulário de Contato 7Inicie seu teste gratuito de 14 dias com todas as funções Profissionais aqui!Passo 1. Clique em "Editar com Prosperar arquiteto" link na página de administração de listaPasso 2. Clique em "Configurações" ícone no direito de menu verticalPasso 3. "Configurações avançadas" => "CSS na seção <head>"Passo 4. Certifique-se de que "não extrair CSS a partir de <head>" está marcadaPasso 5. Clique em "SALVAR o TRABALHO" botãoO estilo de todas as formas em um clique globalmenteEstilo de cada um formulário com qualquer estilo de esquema individualmenteEstilo esquema desabilitado para todas as formasEstilo esquema desabilitado para este formulárioEstilo regime habilitado para este formulárioEstilo de esquema não é selecionadoEstilo regimes listaEstilo de esquemas de pré-visualizaçãoEstilo esquemas de configuraçõesO estilo vai ser carregado em marcaO estilo vai ser carregado em marcaSucessoSuporte e KBTablet VistaCor Do TextoEste Estilo Esquema ativado globalmente para todas as formas. Se você quiser usar o tema do estilo para o Formulário de Contato 7 clique em botão "Desabilitar".Este formulário é denominado com %s no mundo, você pode personalizá-la com Estilo atual regime.Este formulário é denominado com %s, você pode personalizá-la com Estilo atual regime.Este formulário está decorado com um Estilo atual Regime, você pode desativá-lo e usar configurações globais.Este formulário não decorados com qualquer Estilo de esquema, você pode habilitar o Esquema atual para este formulário ou conjunto global de Estilo de Esquema clicando em "Usar de todas as formas" abaixo, o esquema de título.Este esquema não existiuTobias ConradTutorialSem estiloA atualização para o ProUpload De ImagemA Extensão VerticalWOW Estilo Formulário de Contato 7Bem-vindoLarguraSIMVocê pode criar novo estilo de esquema com o atual esquema de configurações. Se você deseja criar em branco estilo schem unchek caixa de seleção abaixo.Você não pode apagarVocê não pode usar esse definições deste tipo de páginaVocê não tem nenhum Formulário de Contato 7 itensVocê não utilizar qualquer Estilo de Esquemas para Formulário de Contato 7. Clique em "Usar de todas as formas" usar atual Esquema global.excluídoshabilitado para todas as formashttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/languages/cf7-styler-pt_BR.po000064400000110665146725417150012102 0ustar00msgid "" msgstr "" "Language: pt-BR\n" "POT-Creation-Date: 2020-02-06 11:35+0000\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "PO-Revision-Date: 2023-04-15 16:06+0000\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: WOW Style Contact Form 7\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: Portuguese (Brazil)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Loco-Version: 2.3.3; wp-5.4" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- desative o estilo do esquema" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "- selecione -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14 dias de período Experimental" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%s usados para todas as formas globalmente, clique em " "\"Usar de todas as formas\" se você quiser usar o Esquema atual." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "Activar estilo para todas as formas*" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Activar estilo para a forma atual" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "Como alternativa, você pode desativar limpar os estilos, como em Prosperar " "arquiteto:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "Cor De Fundo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "Imagem De Fundo" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Antes de utilizar WOW Estilo Formulário de Contato 7, você precisará " "instalar e ativar o Formulário de Contato 7 plugin." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "VERSO a Cores" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "BG Opacidade" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "Blur radius" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "Fronteira" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "Cor Da Borda" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "Border Radius" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "Tipo De Borda" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "Largura Da Borda" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "Botão De Fronteira" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "Botões" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Por Takayuki Miyoshi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "Cancelar" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "CF7 Personalizador de sistemas requer o Formulário de Contato 7 plugin para " "ser instalado e ativo. Você pode fazer o download %s." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "CF7 Formulário não está seleccionada" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "CF7 Styler" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "Caixas & Radiobuttons" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "Limpar Estilos" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "Claro" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "Fechar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "Cor" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "Formulário de contato 7 lista de" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "Conter" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Copiar um estilo atual esquema de configurações" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "Cobertura" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "Criar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "Criar vários esquemas de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "Criar novo estilo de esquema!" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Estilo Atual" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "Actualmente %s " "formulário é denominado com " "%s. Como na versão gratuita, você pode estilo apenas uma forma de " "cada vez e se você ativar o estilo para a forma atual, o estilo vai ser " "removido de outra forma." #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "Actualmente %s formulário é denominado com " "%s. Como na versão gratuita, você pode estilo apenas uma forma de " "cada vez e se você ativar o estilo para a forma atual, o estilo vai ser " "removido de outra forma." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "CSS personalizado" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "CSS personalizado Código" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "Tracejada" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "Esquema Padrão" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "Apagar Imagem" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "excluídos" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "Visualização Da Ãrea De Trabalho" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "Desativar estilo para todas as formas" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "Desativar o estilo para a forma atual" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "¿Te gusta obtener la versión premium de styler gratis? Luego, ingrese su licencia " "WP2LEADS pro u obtenga una licencia aquí !" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "Você deseja salvar as alterações antes de sair da página?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "Pontilhada" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "Duplo" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "Formulário duplicados em segunda coluna" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "habilitado para todas as formas" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "Erro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "Saída De Ecrã Inteiro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "Família De Tipos De Letra" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "Tamanho Da Fonte" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Estilo Da Fonte" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "Peso Da Fonte" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Formulário BG Image & Cores" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "Formulário De Personalização" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Formulário não está seleccionada" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "Formulário De Preenchimento, De Margem E De Fronteiras" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "Texto De Forma" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "Tela Cheia" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "Groove" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "Horizontal De Comprimento" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Passe o mouse VERSO a Cores" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "Passe O Mouse A Cor" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Passe O Mouse A Cor Do Texto" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "Como transformar o seu contato form7 forma em uma conversão e fácil de usar " "e pro estilo formulário de contato, \"pesquisa\" gerador de chumbo ou um " "olho captura formulário" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "https://saleswonder.biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "Eu estou feliz com isso! Salvar" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "Si está utilizando creadores de páginas, como Thrive Architect, " "OptimizePress, etc., consulte nuestra página de base de conocimiento " "para arreglando posibles problemas" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "Se você precisar de carregar o estilo esquema dentro do <body>" " tag apenas em algumas páginas, você pode fazê-lo no frontend usando " "\"CF7 Styler\" botão. Esta função só está disponível para um único post " "types (páginas, posts, produtos etc.) e na versão premium. Você não pode " "fazê-lo em arquivos de páginas (blog, lista de produtos, etc), neste caso, " "você precisa usar configurações globais." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "Se você precisar de carregar o estilo esquema dentro do <body>" " tag apenas em algumas páginas, você pode fazê-lo no frontend usando " "\"CF7 Styler\" botão. Esta função só está disponível para um único post " "types (páginas, posts, produtos, etc.). Você não pode fazê-lo em arquivos de " "páginas (blog, lista de produtos, etc), neste caso, você precisa usar " "configurações globais." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "Imagem de fundo definições disponíveis no modo de viver apenas para a versão " "Professional. Você pode testá-lo no modo de visualização atual \"estilo\", " "mas ele não será salvo." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "Opacidade Da Imagem" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "Posição Da Imagem" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "Tamanho Da Imagem" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "Herdam" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "Campos De Entrada" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "Estilo de entrada do esquema de título" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "Inserção" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "Itálico" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "Rótulos De Cor" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "Etiquetas Tamanho Da Fonte" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "Etiquetas De Configurações" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "Licença" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "Altura Da Linha" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "Cor Dos Links" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "Links Passe A Cor" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Configurações De Links" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "Ao vivo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "Carregar estilos de no <body> tag" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "" "Carga estilos dentro do <body> tag sobre esta página" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "Fazer a seleção de um item por linha" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "Fazer toda a largura?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "Fazer campos de entrada de largura total?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Fazer radiobutton de um item por linha" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "Margem" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "Modo De Exibição Móvel" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "NENHUM" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "Não Formulário de Contato 7 itens para visualização" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "De qualquer forma é decorado com estilo de esquema, clique em \"Ativar " "estilo para a forma atual\" botão para aplicar o esquema atual para este " "formulário." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "Nenhum plugin selecionado para instalar" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "Sem estilo esquema selecionado" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "Normal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "Oblíqua" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "Um por linha estilos para caixas de verificação e radiobuttons no modo de " "viver apenas para a versão Professional. Você pode testá-lo no modo de " "visualização atual \"estilo\", mas ele não será salvo." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "Opacidade" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "Abrir styler" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "Optar por ver a conta" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "Tamanho Original" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "Estrutura de tópicos" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "Início" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "Preenchimento" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "Por favor, introduza o estilo esquema de título" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "Pré-visualização" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "Modo de pré-visualização" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "Pré-Visualização Sem Estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "Raio" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "Repita as" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "Repita horizontal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "Repita vertical" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Redefinir para o padrão" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "Ridge" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "Salvar" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "Salvo" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "Segundo a coluna de vista" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "Selecione o estilo de esquema para este formulário" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "Definições" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "Configurações salvas como " #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "Sombra" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "A Cor Da Sombra" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Sombra Posição" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "Sólidos" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Alguns temas ou página de construtores (fe. Prosperar Arquiteto, " "OptimizePress etc.) pode remover estilos inline dentro de <head>" " tag. Carregamento de estilo esquema dentro do <body>" " tag irá corrigir este problema e mostrar as suas formas de estilo." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "O modo Split" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "Split view" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "Propagação do raio" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "Início de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "Começar com a criação de Estilo Padrão do Regime de" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "Começar com a criação de seu primeiro " "Formulário de Contato 7" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "Inicie seu teste gratuito de 14 dias com todas as funções Profissionais aqui!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "Passo 1. Clique em \"Editar com Prosperar arquiteto\" link na página de " "administração de lista" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "Passo 2. Clique em \"Configurações\" ícone no direito de menu vertical" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "" "Passo 3. \"Configurações avançadas\" => \"CSS na seção <head>\"" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "Passo 4. Certifique-se de que \"não extrair CSS a partir de <head>\" " "está marcada" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "Passo 5. Clique em \"SALVAR o TRABALHO\" botão" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "O estilo de todas as formas em um clique globalmente" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "" "Estilo de cada um formulário com qualquer estilo de esquema individualmente" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "Estilo esquema desabilitado para todas as formas" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "Estilo esquema desabilitado para este formulário" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "Estilo regime habilitado para este formulário" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "Estilo de esquema não é selecionado" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "Estilo regimes lista" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "Estilo de esquemas de pré-visualização" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "Estilo esquemas de configurações" #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "O estilo vai ser carregado em marca" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "O estilo vai ser carregado em marca" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "Sucesso" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "Suporte e KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "Tablet Vista" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "Cor Do Texto" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "Este formulário é denominado com %s no mundo, você pode " "personalizá-la com Estilo atual regime." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "Este formulário é denominado com %s, você pode personalizá-" "la com Estilo atual regime." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "Este formulário está decorado com um Estilo atual Regime, você pode desativá-" "lo e usar configurações globais." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "Este formulário não decorados com qualquer Estilo de esquema, você pode " "habilitar o Esquema atual para este formulário ou conjunto global de Estilo " "de Esquema clicando em \"Usar de todas as formas\" abaixo, o esquema de " "título." #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "Este esquema não existiu" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "Este Estilo Esquema ativado globalmente para todas as formas. Se você quiser " "usar o tema do estilo para o Formulário de Contato 7 clique em botão " "\"Desabilitar\"." #. Author of the plugin msgid "Tobias Conrad" msgstr "Tobias Conrad" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "Tutorial" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "Sem estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "A atualização para o Pro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "Upload De Imagem" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "A Extensão Vertical" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "Bem-vindo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "Largura" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "WOW Estilo Formulário de Contato 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "SIM" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "Você pode criar novo estilo de esquema com o atual esquema de configurações. " "Se você deseja criar em branco estilo schem unchek caixa de seleção abaixo." #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "Você não pode apagar" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "Você não pode usar esse definições deste tipo de página" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "Você não tem nenhum Formulário de Contato 7 itens" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "Você não utilizar qualquer Estilo de Esquemas para Formulário de Contato 7. " "Clique em \"Usar de todas as formas\" usar atual Esquema global." languages/cf7-styler-es_ES.mo000064400000046355146725417150012073 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'Â(#Ò)ö)**-·*+å*P+b+ k+w+†+a–+ø+ ,,%, 5,C,U,f,n,bƒ,'æ, --,"-O-_-e-l-r-‘-6š-Ñ-Ù-Þ- þ- .P-.ê~/i0{0•0œ0 ±0¿0/Ó0.1219P2Š2‘2*—2Â2È2â2õ233)3@3&`3‡3œ3·3É3Ð3ä3 í3!ù3Å4"á4ò5¹÷5ª±7\9r9‰9¬ž9K:S:(e:Ž:—:Ÿ:¯:Ë:Ý:æ: ÷:;; 4;6?;Nv;Å;ã;"û;(<G< N<[<7^<Ÿ–<26=/i=™= =Ȩ=q>z> Ž>™>ª>²> ¹>+Ã> ï>ü>?'? -?:?M?^?~?…??–?4²?ç?ï?@ @@.@76@ nA|A‹A A0´AZåA@BgZCIÂCF DGSD(›D;ÄDHE8IE2‚E1µE*çEF&.F!UF*wF+¢FÎF ÕFâFóF¨Gy¬Gm&Hx”Hä IòI JJ !J,J =JKJ"]J €J‹J“J’—J*K==K({K¡¤K FL#PLtL`ŒL- disable style scheme -- select -14-days Trial%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Loco https://localise.biz/ Project-Id-Version: Wow style (ES) Language: es-ES Plural-Forms: nplurals=2; plural=(n != 1); POT-Creation-Date: 2020-04-18 12:29+0000 PO-Revision-Date: 2023-04-15 16:05+0000 Last-Translator: Tobias support@saleswonder.biz Language-Team: Spanish (Spain) Report-Msgid-Bugs-To: X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489- desactivar el esquema de estilo -- seleccionar -14 días de prueba%s utilizado para todos los formularios globalmente, haga clic en "Utilizar para todos los formularios" si desea utilizar el Esquema actual.Activar el estilo para todos los formularios*Activar el estilo para el formulario actualComo alternativa puedes desactivar limpiar los estilos como en Thrive architect:Color BGOpacidad BGColor de fondoImagen de fondoAntes de utilizar WOW Style Contact Form 7, necesita instalar y activar el plugin Contact Form 7.Radio de desenfoqueFronteraColor del bordeRadio del bordeTipo de bordeAnchura del bordeBorde del botónBotonesPor Takayuki MiyoshiCF7 Customizer requiere que el plugin Contact Form 7 esté instalado y activo. Puede descargar %s.El formulario CF7 no está seleccionadoCF7 StylerCancelarCasillas de verificación y botones de radioEstilos limpiosClaroCerrarColorFormulario de contacto 7 listaContieneCopiar la configuración actual del esquema de estilosPortadaCreeCrear varios esquemas de estiloCrear un nuevo esquema de estiloEstilo actualActualmente %s formulario tiene estilo con %s. Al igual que en la versión gratuita, sólo puede aplicar estilo a un formulario a la vez y si activa el estilo para el formulario actual, el estilo se eliminará del otro formulario.Actualmente el formulario %s está estilizado con %s. Como en la versión gratuita puede estilo sólo una forma a la vez y si activa el estilo para la forma actual, estilo se eliminará de otra forma.CSS personalizadoCódigo CSS personalizadoDashedRégimen por defectoBorrar imagenVista de escritorioDesactivar el estilo para todos los formulariosDesactivar el estilo para el formulario actualTe gusta conseguir styler versión premium gratis? ¡Entonces Introduzca su licencia WP2LEADS pro u obtenga una licencia aquí!¿Desea guardar los cambios antes de salir de la página?PuntosDobleFormulario duplicado en la segunda columnaErrorSalir a pantalla completaFamilia de fuentesTamaño de letraEstilo de fuentePeso de la fuenteForm BG Image & ColorsPersonalización de formulariosRelleno, margen y borde del formularioTexto del formularioFormulario no seleccionadoPantalla completaRanuraLongitud horizontalColor BGColor HoverColor del texto sobreimpresionadoCómo convertir su formulario de contacto form7 en un formulario de contacto de conversión, fácil de usar y con estilo profesional, un generador de prospectos "encuesta" o un formulario llamativo¡Estoy contento con esto! GuardarSi está utilizando constructores de páginas, como Thrive Architect, OptimizePress, etc., consulte nuestra página Base de conocimientos para solucionar posibles problemasSi necesita cargar esquema de estilo dentro de <body> etiqueta sólo en algunas páginas, puede hacerlo en frontend usando "CF7 Styler" botón. Esta función sólo está disponible para los tipos de mensajes individuales (páginas, mensajes, productos, etc) y en la versión premium. No se puede hacer en las páginas de archivos (blog, lista de productos, etc) en este caso es necesario utilizar la configuración global.Si necesita cargar el esquema de estilo dentro de la etiqueta <body> sólo en algunas páginas, puede hacerlo en frontend usando el botón "CF7 Styler". Esta función sólo está disponible para los tipos de entradas individuales (páginas, entradas, productos, etc.). No se puede hacer en las páginas de archivos (blog, lista de productos, etc) en este caso es necesario utilizar la configuración global.Opacidad de la imagenPosición de la imagenTamaño de la imagenLa configuración del fondo de la imagen sólo está disponible en la versión Profesional. Puede probarlo en el modo de vista previa "estilo actual", pero no se guardará.HeredarCampos de entradaTítulo del esquema de estilo de entradaInsertarCursivaEtiquetas ColorEtiquetas Tamaño de fuenteEtiquetas AjustesLicenciaAltura de líneaEnlaces ColorColor de los enlacesConfiguración de enlacesEn directoCargar estilos en la etiqueta <body><body> en esta páginaMarque una casilla por línea¿Hacer ancho completo?¿Completar los campos de entrada?Hacer un elemento radiobutton por líneaMargenVista móvilNONo hay elementos de Contact Form 7 para la vista previaNingún formulario tiene un esquema de estilo, haga clic en el botón "Activar estilo para formulario actual" para aplicar el esquema actual a este formulario.No se ha seleccionado ningún plugin para instalarNo se ha seleccionado ningún esquema de estiloNormalOblicuoEstilos uno por línea para casillas de verificación y radiobuttons en modo actual sólo para la versión Profesional. Puede probarlo en el modo de vista previa "estilo actual", pero no se guardará.OpacidadEstilizador abiertoVer cuentaTamaño originalEsquemaSalidaAcolchadoIntroduzca el título del esquema de estiloVista previaVista previa UnstyledModo de vista previaRadioRepita ambosRepetir horizontalRepetir verticalRestablecer valores por defectoCrestaGuardarGuardadoVista de la segunda columnaSeleccione el esquema de estilo para este formularioAjustesAjustes guardados comoSombraSombra ColorPosición de sombraSólidoAlgunos temas o constructores de página (fe. Thrive Architect, OptimizePress etc.) podrían eliminar estilos en línea dentro de la etiqueta <head>. Cargar el esquema de estilo dentro de la etiqueta <body> solucionará este problema y mostrará sus formularios con estilo.Modo divididoVista divididaRadio de dispersiónEmpezar a estilizarEmpezar creando un esquema de estilo por defectoComienza creando tu primer Formulario de Contacto 7¡Comience su prueba gratuita de 14 días con todas las funciones profesionales aquí!Paso 1. Haga clic en el enlace "Editar con Thrive architect" en la lista de páginas de administraciónPaso 2. Haga clic en el icono "Configuración" del menú vertical derechoPaso 3. "Configuración avanzada" => "CSS en la sección <head>"Paso 4. Asegúrese de que "No quitar CSS de <head>" está marcadaPaso 5. Pulse el botón "GUARDAR TRABAJOEstiliza todos los formularios globalmente con un solo clicEstiliza cada formulario individualmente con cualquier esquema de estiloEsquema de estilo desactivado para todos los formulariosEsquema de estilo desactivado para este formularioEsquema de estilo habilitado para este formularioEl esquema de estilo no está seleccionadoLista de esquemas de estiloVista previa de los esquemas de estiloAjustes de los esquemas de estiloEl estilo se cargará en la etiqueta ÉxitoSoporte y KBVista de tabletaColor del textoEste esquema de estilo habilitado a nivel mundial para todas las formas. Si desea utilizar el estilo de su tema para Contact Form 7 haga clic en el botón "Desactivar".Este formulario está estilizado con %s globalmente, puedes estilizarlo con el esquema de Estilo actual.Este formulario está estilizado con %s, puedes estilizarlo con el esquema de Estilo actual.Este formulario está diseñado con el esquema de estilo actual, puede desactivarlo y utilizar la configuración global.Este formulario no tiene ningún esquema de estilo, puede activar el esquema actual para este formulario o configurar un esquema de estilo global haciendo clic en "Usar para todos los formularios" debajo del título del esquema.Este régimen no existeTobias ConradTutorialSin estiloActualizar a ProCargar imagenLongitud verticalFormulario de contacto WOW Style 7BienvenidoAnchuraSÃPuede crear un nuevo esquema de estilo con la configuración actual. Si desea crear un esquema de estilo en blanco, desmarque la casilla de abajo.No se puede borrarNo puede utilizar esta configuración en este tipo de páginaNo tiene ningún elemento Contact Form 7No utiliza ninguno de los esquemas de estilo para Contact Form 7. Haga clic en "Usar para todos los formularios" para utilizar el esquema actual de forma global.suprimidoactivado para todos los formularioshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/languages/cf7-styler-fr_FR.mo000064400000050650146725417150012064 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'Á("Ñ) ô)*•*+³**ß*c +n+~+“+ £+v±+ (,6,>,T,h,{,‘,£,«,¯Å,)u- Ÿ-ª-)²-Ü-ð-ù-..".3+._.g.!n.". ³.aÀ."0:1L1 c1„1—1 ©1.·1)æ1"2G33 {3 œ31©3Û3â3ù3 44-4'=4e4+„4°4(Ä4 í4 ú45525D5^5a6z6Ü|7ÁY9;3;G;ßY;9<B< S<t<<–< ®<Ï<ë<ó<==5= K=;U=X‘=5ê= >79>8q>ª>°>Ä>:È>®?9²?-ì?@!@ö)@ A-A>A]AnAvA ‘A#AÁAÉAçAøAþAB+B%CB!iB ‹B —B£B3¿B óBÿBC#C8C LCEXCžD·DÈDÛD3úDX.E&‡E‡®F\6Gx“G‚ HIHEÙHZI<zI5·I1íI#JCJ^J {J$œJ+ÁJíJ KK&KÄ7KsüKgpL†ØLú_MZN qNNˆN ›N¼NÌNßNøNO O¤ O²OHÏO9P¯RP Q! Q/Q`GQ- disable style scheme -- select -14-days Trial%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Loco https://localise.biz/ Project-Id-Version: Wow style (ES) Language: fr-FR Plural-Forms: nplurals=2; plural=(n > 1); POT-Creation-Date: 2020-04-18 12:29+0000 PO-Revision-Date: 2023-04-15 16:08+0000 Last-Translator: Tobias support@saleswonder.biz Language-Team: French (France) Report-Msgid-Bugs-To: X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489- désactiver le thème de style -- choisir -Période d'essai de 14 jours%s utilisés globalement pour tous les formulaires, cliquez sur « Utiliser pour tous les formulaires » si vous souhaitez utiliser le Thème actuel.Activez le style pour tous les formulaires*Activer le style pour le formulaire actuelEn option, vous pouvez désactiver le nettoyage de styles, comme dans le plug-in Thrive Architect :Couleur de fondTransparence de fondCouleur de fondImage de fondAvant d'utiliser l’extension WOW Style Contact Form 7, vous devez installer et activer l’extension Contact Form 7.Rayon de flouBordureCouleur de la bordureRayon de la bordureType de la bordureLargeur de la bordureBordure de boutonBoutonsAuteur : Takayuki MiyoshiL’extension pour modifier les styles du Contact Form 7 nécessite l'installation et l'activation de l’extension du formulaire Contact Form 7. Vous pouvez télécharger %s.Le formulaire CF7 n'est pas sélectionnéCF7 StylerAnnulerChamps de sélection multiples et uniquesNettoyer les stylesNettoyerFermerCouleurListe des formulaires CF7ContenirCopier les paramètres de le thème de style actuelCouvrirCréerCréer plusieurs thèmes de styleCréer un nouveau thème de style!Style actuelActuellement, le formulaire %s est stylé avec %s. Comme dans la version gratuite, vous ne pouvez styler qu'un seul formulaire à la fois et si vous activez le style pour le formulaire en cours, le style sera supprimé pour les autres formulaires.Actuellement, le formulaire %s est stylé avec %s. Comme dans la version gratuite, vous ne pouvez styler qu'un seul formulaire à la fois et si vous activez le style pour le formulaire actuel, le style sera supprimé pour les autres formulaires.CSS personnaliséCode CSS personnaliséUn trait en pointillés (tirets)Thème par défautSupprimer l'imageVue de bureauDésactiver le style pour tous les formulairesDésactiver le style du formulaire actuelVoulez-vous obtenir la version premium de styler gratuitement ? Alors Entrez votre licence WP2LEADS pro ou obtenez une licence ici !Souhaitez-vous enregistrer vos modifications avant de quitter la page ?Un trait en pointillés (points)Trait doubleDupliquer le formulaire dans la deuxième colonneErreurSortir du plein écranFamille de policesTaille de policeStyle de policePoids de policeImage et couleurs de fond du formulairePersonnalisation du formulaireRemplissage, marge et bordure du formulaireTexte du formulaireAucun formulaire n'a été sélectionnéPlein écranEn reliefLongueur horizontaleCouleur de fond survoléCouleur survoléeCouleur du texte survoléComment créer un formulaire de contact Contact Form 7, qui non seulement aura un aspect professionnel et attrayant et sera facile à utiliser, mais qui aura également un taux de conversion élevé et générera des demandes de renseignements sur les offresJ'aime ça ! SauvegarderSi vous utilisez des constructeurs de pages, comme Thrive Architect, OptimizePress etc., veuillez consulter notre Page de la base de connaissances pour résoudre les problèmes éventuelsSi vous avez besoin de charger un schéma de style à l'intérieur de la balise <body> uniquement sur certaines pages, vous pouvez le faire sur le frontend en utilisant le bouton "CF7 Styler". Cette fonction n'est disponible que pour les types d'articles (pages, articles, produits, etc.) et dans la version premium. Vous ne pouvez pas le faire sur les pages d'archives (blog, liste de produits etc.) dans ce cas vous devez utiliser les paramètres globaux.Si vous avez besoin de charger un schéma de style à l'intérieur de la balise <body> uniquement sur certaines pages, vous pouvez le faire sur le frontend en utilisant le bouton "CF7 Styler". Cette fonction n'est disponible que pour les types d'articles (pages, articles, produits, etc.). Vous ne pouvez pas le faire sur les pages d'archives (blog, liste de produits etc.) dans ce cas vous devez utiliser les paramètres globaux.Transparence de l'imagePosition de l'imageTaille de l'imageLes paramètres de l'image de fond ne sont disponibles que pour la version Professional en mode temps réel. Vous pouvez les essayer dans le mode de prévisualisation « style actuel », mais ils ne seront pas enregistrés.HériterChamps de saisieNom du thème de style de saisieEffet 3D global enfoncéItaliqueCouleur des étiquettesTaille de police de l'étiquetteParamètres de l'étiquetteLicenceHauteur de la ligneCouleur des liensCouleur des liens survolésParamètres des liensEn directCharger les styles dans la balise <body>Charger les styles à l'intérieur de la balise <body> sur cette pageDéfinir un champ à choix multiple pour chaque ligneFixer la pleine largeur?Configurer les champs d'entrée sur toute leur largeur?Définir un champ de sélection unique dans chaque ligneMargeVue dans la celluleNONAucun élément du formulaire Contact Form 7 à visualiserAucun formulaire n'est modifié avec le thème de style. Pour appliquer le thème de style actuelle à ce formulaire, cliquez sur « Activer le style du formulaire actuel ».Aucune extension n'est sélectionnée pour l'installationAucun thème de style n'a été sélectionnéNormalObliqueLa définition d'un champ de sélection multiple et d'un champ de sélection unique n'est possible que dans la version Professional. Vous pouvez l’essayer dans le mode de prévisualisation « style actuel », mais elle ne sera pas enregistrée.TransparenceOuvrez le StylerS'inscrire pour voir le compteTaille originaleContourEffet 3D global surélevéRemplissageEntrez un thème de style de saisieAperçuAperçu du style non modifiéMode d’aperçuRayonRépéter les deuxRépéter horizontalementRépéter verticalementRétablir les paramètres par défautUn trait avec effet 3D: bourreletSauvegarderSauvegardéVue de la deuxième colonneSélectionner un thème de style pour ce formulaireParamètresParamètres enregistrés sousOmbreCouleur de l’ombrePosition de l'ombreTrait pleinCertains motifs ou assistants de création de sites (par exemple Thrive Architect, OptimizePress, etc.) peuvent supprimer les styles locaux (inline styles) à l'intérieur de la balise . L'ajout d'un thème de style à l'intérieur de la balise résoudra ce problème et vos formulaires auront un style modifié.Mode de vue fractionnéeVue fractionnéeRayon de diffusionCommencez à modifier le styleCommencez par créer un thème de style par défautCommencez par créer votre premier Contact Form 7Commencez votre essai gratuit de 14 jours avec toutes les fonctions professionnelles ici !Étape 1 : Cliquez sur le lien « Edit with Thrive Architect » (Modifier avec Thrive Architect) dans la liste des pages administrateurÉtape 2 : Cliquez sur l'icône « Settings » (Paramètres) dans le menu vertical de droiteÉtape 3 : « Advanced settings » (Paramètres avancés) => « CSS in the section» (CSS dans la section )Étape 4 : Assurez-vous que l'option « Do not strip CSS from » (Ne pas supprimer le CSS de la section ) est cochéeÉtape 5 : Cliquez sur le bouton « SAVE WORK » (SAUVEGARDER LE TRAVAIL)Modifiez le style de tous les formulaires globalement en un seul clicModifiez le style de chaque formulaire individuellement en utilisant n'importe quel thèmeLe thème de style est désactivé pour tous les formulairesLe thème de style est désactivé pour ce formulaireLe thème de style est activé pour ce formulaireLe thème de style n'est pas choisiListe des thèmes de styleAperçu des thèmes de styleParamètres des thèmes de styleLe style sera chargé dans la baliseLe style sera chargé dans la balise Effectué avec succèsSupport & KBVue dans la tabletteCouleur du texteCe thème de style est activé globalement pour tous les formulaires. Si vous souhaitez utiliser un style de votre motif pour le formulaire Contact Form 7, cliquez sur le bouton « Désactiver ».Le style de ce formulaire est modifié globalement avec %s, vous pouvez le modifier avec le thème de style actuel.Le style de ce formulaire est modifié avec %s, vous pouvez le modifier avec le thème de style actuel.Le style de ce formulaire est modifié avec le Thème de style actuel, vous pouvez le désactiver et utiliser les paramètres globaux.Le style de ce formulaire n'est modifié par aucun thème de style, vous pouvez soit activer le thème actuel pour ce formulaire, soit définir le modèle de style global en cliquant sur « Utiliser pour tous les formulaires » sous le nom du thème.Ce thème n'existe pasTobias ConradTutorielStyle non modifiéMise à jour vers la version ProCharger l'imageLongueur verticaleWOW Style Contact Form 7BienvenuLargeurOUIVous pouvez créer un nouveau thème de style avec les paramètres du thème actuel. Si vous souhaitez créer un thème de style vide, décochez la case ci-dessous.Vous ne pouvez pas supprimerVous ne pouvez pas utiliser ces paramètres sur des pages comme celle-ciVous n'avez pas d'éléments de formulaire Contact Form 7Vous n'utilisez aucun thème de style pour le formulaire Contact Form 7. Cliquez sur « Utiliser pour tous les formulaires » pour utiliser la thème actuel de façon globale.suppriméeactivé pour tous les formulaireshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/languages/cf7-styler-ru_RU.mo000064400000060433146725417150012122 0ustar00Þ•»ôÌ Ì Í æ ñ mÿ m ‹ P« ü   ! ^2 ‘  ¤ ± ¿ Ë Ø æ î ^a z…Œ ¦³¹¿ÅÙ"á / HVÒq DO_f u ‚« Ê0Ø 7= N Z d o{’£ ÁË àìó  ’1ÄÐÞf¯O ft ƒšŽ) 1>W] dq‚’ š ¦²ÄÓ,Ø=Cct"’µ ¼È#Ëzïjˆ¡¨ª°[ c o}…Œ”´¼ ÍÚ áíÿ &+1!Dfo‚ ‰–¦ò¬ Ÿ ª µ Ã(ÑTúüOBL 4 @Ä F! L!%m!2“!#Æ!#ê!""1"N"a"w""Ž""±"Ô" Ü" è"‚ó"bv#YÙ#Z3$©Ž$8% S%a%j%s% ‚%%Ÿ%¸%À%Æ%|Ê%G&/Z&(Š&q³&%'-'`C'â¤'*‡)²) Ç)ûè)=ä*D"+¥g+ ,!,=,%O,Íu,C-b-q-‰-¥-»-Ø- ô-.¼."Ø.û./1/Q/i/ x/ƒ/.Œ/»/OÎ/ 0+0+:00f0—0ѱ0‰ƒ2$ 4,24_4#n4%’4#¸46Ü4>5sR5oÆ667K7BZ7 79ª7"ä78"8;84P8…8;¤8à8÷8909'79_9"~9/¡9RÑ90$;RU;Ó¨<±|?4.B*cB$ŽBf³BD1D9EDD ŽD›D+±DÝDüD E%E/%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/Language: ru-RU POT-Creation-Date: 2020-02-06 11:35+0000 Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10 >= 2 && n%10<=4 &&(n%100<10||n%100 >= 20)? 1 : 2); PO-Revision-Date: 2023-04-15 16:06+0000 X-Generator: Loco https://localise.biz/ Project-Id-Version: WOW Style Contact Form 7 Report-Msgid-Bugs-To: Last-Translator: Language-Team: Russian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Loco-Version: 2.3.3; wp-5.4- отключить Ñхема Ñтиль- выберите -14-дневный пробный%s , иÑпользуемых Ð´Ð»Ñ Ð²Ñех форм глобально, нажмите кнопку "ИÑпользовать Ð´Ð»Ñ Ð²Ñех форм", ЕÑли вы хотите иÑпользовать текущую Ñхему.Ðктивировать Ñтиль Ð´Ð»Ñ Ð²Ñех форм*Ðктивировать Ñтиль Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ формыВ качеÑтве альтернативы вы можете отключить очиÑтить Ñтили, как на процветать архитектор:БГ цветБГ непрозрачноÑтьЦвет ФонаФоновое ИзображениеПеред иÑпользованием ух контактный Ñтиль Форма 7, вам нужно уÑтановить и активировать контактную форму 7 плагин.Ð Ð°Ð´Ð¸ÑƒÑ Ñ€Ð°Ð·Ð¼Ñ‹Ñ‚Ð¸Ñ Ð“Ñ€Ð°Ð½Ð¸Ñ†Ñ‹Ð¦Ð²ÐµÑ‚ Ð“Ñ€Ð°Ð½Ð¸Ñ†Ñ‹Ð Ð°Ð´Ð¸ÑƒÑ Ð“Ñ€Ð°Ð½Ð¸Ñ†Ñ‹Ð¢Ð¸Ð¿ ГраницыШирина Границы Кнопки ГраницыКнопкиТакаюки МиеÑиCF7 ÐаÑтройщик требует ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° 7 плагин должен быть уÑтановлен и активен. Ð’Ñ‹ можете Ñкачать %ов.CF7 форма Ðе выбранаCF7 СтайлерОтменитьЧекбокÑÑ‹ & ПереключателиЧиÑтые СтилиПонÑтноРÑÐ´Ð¾Ð¼Ð¦Ð²ÐµÑ‚ÐšÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° 7 ÑпиÑокСодержатьСкопировать текущие наÑтройки Ñхема Ñтиль КрышкаСоздатьСоздать неÑколько Ñхем Создать новую Ñхему Ñтиль!Текущий СтильВ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð²Ð¸Ð´Ðµ выполнен Ñ %- ОВ. Как в беÑплатной верÑии вы можете разработать только одну форму одновременно, и еÑли вы активируете Ñтиль Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ форме, будут удалены от других форма.Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð²Ð¸Ð´Ðµ выполнен Ñ %- ОВ. Как в беÑплатной верÑии вы можете разработать только одну форму одновременно, и еÑли вы активируете Ñтиль Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ форме, будут удалены от других форма.ПользовательÑкие CSSПользовательÑкий код CSS ÐакаталСхема По Умолчанию Удалить ИзображениÑВид Рабочего Стола Отключить Ñтиль Ð´Ð»Ñ Ð²Ñех формОтключить Ñтиль Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ формыВам нравитÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÑŒ премиум-верÑию Styler беÑплатно? Затем Введите Ñвою лицензию WP2LEADS pro или получите лицензию href="https://wp2leads-for-klick-tipp.com/web/go-pro-plus-get-all-done4u/" target="_blank">здеÑÑŒ !Ð’Ñ‹ хотите Ñохранить изменениÑ, прежде чем покинуть Ñтраницу?ПунктирнойДвойнойДублировать форму во втором ÑтолбцеОшибкаВыход Из ПолноÑкранного РежимаСемейÑтво Шрифтов Размер Шрифта Стиль Шрифта Ð’ÐµÑ Ð¨Ñ€Ð¸Ñ„Ñ‚Ð° Форма БГ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¸ цветаÐаÑтройка Форма Форма ЗаполнениÑ, ÐŸÐ¾Ð»Ñ Ð˜ ГраницыТекÑÑ‚ Форма Форма Ðе выбранаПолном ЭкранеПÐÐ—Ð“Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð”Ð»Ð¸Ð½Ð°Ðаведите БГ цветПри Ðаведении ЦветЦвет ТекÑта При ÐаведенииКак превратить вашу контактную форму form7 в конвертации и проÑтое в иÑпользовании и профеÑÑиональный разработанный ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð°, "опроÑ" генератора лидов или привлекательные формыЯ довольна Ñтим! СохранитьЕÑли вы иÑпользуете компоновщики Ñтраниц, такие как Thrive Architect, OptimizePress и Ñ‚. Д., ПоÑетите нашу Ñтраницу базы знаний Ð´Ð»Ñ ÑƒÑтранение возможных проблемЕÑли вам нужно загрузить Ñхемы внутри тега<body> тег только на некоторых Ñтраницах, вы можете Ñделать Ñто на frontend Ñ Ð¸Ñпользованием "CF7 Стайлер" кнопку. Эта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð´Ð¾Ñтупна только Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ типа поÑта (Ñтраницы, поÑÑ‚Ñ‹, продукты и Ñ‚. д.) и в премиум верÑии. Ð’Ñ‹ не можете Ñделать Ñто на Ñтраницах архивов (блог, ÑпиÑок продуктов и Ñ‚. д.) Ð’ Ñтом Ñлучае вы должны иÑпользовать глобальные параметры.ЕÑли вам нужно загрузить Ñхемы внутри тега<body> тег только на некоторых Ñтраницах, вы можете Ñделать Ñто на frontend Ñ Ð¸Ñпользованием "CF7 Стайлер" кнопку. Эта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð´Ð¾Ñтупна только Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ типа поÑта (Ñтраницы, поÑÑ‚Ñ‹, продукты и Ñ‚. д.). Ð’Ñ‹ не можете Ñделать Ñто на Ñтраницах архивов (блог, ÑпиÑок продуктов и Ñ‚. д.) Ð’ Ñтом Ñлучае вы должны иÑпользовать глобальные параметры.ÐепрозрачноÑÑ‚ÑŒ Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÐŸÐ¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ðµ Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð Ð°Ð·Ð¼ÐµÑ€ Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÐаÑтройки фонового Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупна в режиме Live только Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ„ÐµÑÑиональной верÑии. Ð’Ñ‹ можете протеÑтировать его в режиме предварительного проÑмотра "текущий Ñтиль", но он не будет Ñохранен.ÐаÑÐ»ÐµÐ´Ð¾Ð²Ð°Ñ‚ÑŒÐŸÐ¾Ð»Ñ Ð’Ð²Ð¾Ð´Ð°Ð’Ð²ÐµÐ´Ð¸Ñ‚Ðµ название Ñхемы в Ñтиле ВрезныеКурÑивЯрлыки ЦветРазмер Шрифта ÐадпиÑей ÐаÑтройки Метки ЛицензиÑÐ›Ð¸Ð½Ð¸Ñ Ð’Ñ‹ÑотаЦвет СÑылки СÑылки При Ðаведении ЦветПараметры СÑылки ЖитьЗагрузить Ñтили в тегах<Body> тегЗагрузить Ñтили внутри тега<body> тег на Ñтой ÑтраницеСделать Ñлемент флажок одному в ÑтрокеСделать полную ширину?Сделайте Ð¿Ð¾Ð»Ñ Ð´Ð»Ñ Ð²Ð²Ð¾Ð´Ð° ширины?Сделать Ñлемент ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ RadioButton одному в ÑтрокеМаржаМобильный ВидÐетÐет контактной формы 7 предметов Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ проÑмотраÐет формы выполнен Ñ Ñхема Ñтиль, нажмите кнопку "Ðктивировать Ñтиль Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ формы кнопки" Применить текущие Ñхемы Ð´Ð»Ñ Ñтой формы.Ðет плагин выбран Ð´Ð»Ñ ÑƒÑтановкиÐет Ñхемы выбранный ÑтильÐормальныйКоÑойОдин за Ñтили линий Ð´Ð»Ñ Ð³Ð°Ð»Ð¾Ñ‡ÐºÐ¸ и переключатели в режиме Live только Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ„ÐµÑÑиональной верÑии. Ð’Ñ‹ можете протеÑтировать его в режиме предварительного проÑмотра "текущий Ñтиль", но он не будет Ñохранен.ÐепрозрачноÑтьОткройте ÑтайлерОригинальный размерКонтурПрежде вÑегоОбивкаПожалуйÑта, введите название Ñхемы в Ñтиле Предварительный проÑмотрПредварительный ПроÑмотр ÐеÑтилизованныйРежим предварительного проÑмотра РадиуÑПовторите обаПовторите горизонтальноПовторить Ð²ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ñ‹Ð¹Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð¾ умолчаниюХребетСохранитьСпаÑВторой вид колонки Выберите Ñхему Ñтиль Ð´Ð»Ñ Ñтой формыПараметрыÐаÑтройки ÑохранÑÑŽÑ‚ÑÑ ÐºÐ°Ðº ТеньЦвет ТениТеневой ПозицииТвердыеÐекоторые темы или Ñтроителей Ñтранице (Фе. Процветать архитектор, OptimizePress и Ñ‚. д.) можно удалить вÑтроенные Ñтили внутри тег<head> тег. Загрузка Ñхемы в пределах <тело> тег будет иÑправить Ñту проблему и показать Ñвои формы в Ñтиле.Режим Ñ€Ð°Ð·Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¡Ð¿Ð»Ð¸Ñ‚ Ð²Ð¸Ð´Ð Ð°Ð´Ð¸ÑƒÑ Ñ€Ð°ÑпроÑтранениÑÐачать укладкуÐачните Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñхемы Ñтиль по умолчанию Ðачните Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ первого ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° 7Ðачать Ñвой 14-дневную беÑплатную пробную верÑию Ñо вÑеми профеÑÑиональными функциÑми здеÑÑŒ!Шаг 1. Ðажмите кнопку "Редактировать процветать архитектор ÑÑылке" в ÑпиÑке Ñтраниц админ Шаг 2. Ðажмите кнопку "ÐаÑтройки" значок на правом вертикальном менюШаг 3. "Дополнительные наÑтройки" => "CSS в разделе <head>"Шаг 4. УбедитеÑÑŒ, что "не полоÑÑ‹ CSS от <руководитель>" проверÑетÑÑШаг 5. Ðажмите кнопку "Сохранить" кнопкуСтиль вÑех форм в один клик во вÑем миреСтиль каждой формы Ñ Ð»ÑŽÐ±Ñ‹Ð¼ Ñхема ÑÑ‚Ð¸Ð»Ñ Ð¸Ð½Ð´Ð¸Ð²Ð¸Ð´ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð¡Ñ…ÐµÐ¼Ð° Ñтиль отключен Ð´Ð»Ñ Ð²Ñех формСхема Ñтиль отключена Ð´Ð»Ñ Ñтой формыСхема Ñтиль Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ Ð´Ð»Ñ Ñтой формыСхема Ñтиль Ðе выбранСпиÑок Ñхем Схемы предварительный проÑмотр ÑтилейПараметры Ñхем Стиль будет загружен в тегСтиль будет загружен в тегУÑпехВид Планшета Цвет ТекÑтаЭта Ñхема Ñтиль глобально Ð´Ð»Ñ Ð²Ñех форм. ЕÑли вы хотите иÑпользовать Ñтиль вашей темы Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ñ‹Ð¹ формулÑÑ€ 7 Ðажмите кнопку "Отключить".Эта форма выполнена Ñ %- ОВ по вÑему миру, вы можете Ñтиль его Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼ Ñтилем Ñхеме.Эта форма выполнена Ñ %- ОВ, вы можете Ñтиль его Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼ Ñтилем Ñхеме.Эта форма выполнена Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ Ñхемой Ñтиле, вы можете отключить его и иÑпользовать глобальные параметры.Эта форма не Ñтилизовано под какую-то Ñхему, Ñтиль, вы можете включить ток Ñхема данной формы или Ñоздавать глобальные Ñхемы Ñтиль, нажав кнопку "ИÑпользовать Ð´Ð»Ñ Ð²Ñех форм" под заголовком программы.Эта Ñхема не ÑущеÑÑ‚Ð²Ð¾Ð²Ð°Ð»Ð°Ð¢Ð¾Ð±Ð¸Ð°Ñ ÐšÐ¾Ð½Ñ€Ð°Ð´Ð£Ñ‡ÐµÐ±Ð½Ð¸ÐºÐеÑтилизованныйОбновление до ProЗагрузить Ð˜Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸ÐµÐ’ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð”Ð»Ð¸Ð½Ð°Ð’Ð°Ñƒ контакт Ñтиль Форма 7Добро пожаловатьШиринаДаВы можете Ñоздать новую Ñхему в Ñтиле Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ð¼Ð¸ наÑтройками Ñхемы. ЕÑли вы хотите Ñоздать флажок Ñтиль unchek Ñчем ниже.Ð’Ñ‹ не можете удалитьВы не можете иÑпользовать Ñти наÑтройки на Ñтого типа Ñтраницы Ð’Ñ‹ не имеете никакого ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð° 7 предметовВы не иÑпользуете какой-либо из Ñхем Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ñ‹Ð¹ формулÑÑ€ 7. Ðажмите кнопку "ИÑпользовать Ð´Ð»Ñ Ð²Ñех форм" иÑпользовать текущую Ñхему в глобальном маÑштабе.удаленвключен Ð´Ð»Ñ Ð²Ñех формhref="https://wp2leads-for-klick-tipp.com/web/go-pro-plus-get-all-done4u/" target="_blank">languages/cf7-styler-es_MX.po000064400000110744146725417150012105 0ustar00msgid "" msgstr "" "Language: es-MX\n" "POT-Creation-Date: 2023-04-15 15:26+0000\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "PO-Revision-Date: 2023-04-15 16:10+0000\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: WOW Style Contact Form 7\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: Tobias support@saleswonder.biz\n" "Language-Team: Spanish (Mexico)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- desactivar el esquema de estilo -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "- seleccionar -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14 días de prueba" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%s utilizado para todos los formularios globalmente, haga " "clic en \"Utilizar para todos los formularios\" si desea utilizar el Esquema " "actual." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "Activar el estilo para todos los formularios*" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Activar el estilo para el formulario actual" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "Como alternativa puedes desactivar limpiar los estilos como en Thrive " "architect:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "Color de fondo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "Imagen de fondo" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Antes de utilizar WOW Style Contact Form 7, necesita instalar y activar el " "plugin Contact Form 7." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "Color BG" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "Opacidad BG" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "Radio de desenfoque" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "Frontera" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "Color del borde" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "Radio del borde" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "Tipo de borde" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "Anchura del borde" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "Borde del botón" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "Botones" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Por Takayuki Miyoshi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "Cancelar" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "CF7 Customizer requiere que el plugin Contact Form 7 esté instalado y activo." " Puede descargar %s." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "El formulario CF7 no está seleccionado" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "CF7 Styler" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "Casillas de verificación y botones de radio" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "Estilos limpios" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "Claro" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "Cerrar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "Color" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "Formulario de contacto 7 lista" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "Contiene" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Copiar la configuración actual del esquema de estilos" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "Portada" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "Cree" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "Crear varios esquemas de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "Crear un nuevo esquema de estilo" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Estilo actual" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "Actualmente %s " "formulario tiene estilo con " "%s. Al igual que en la versión gratuita, sólo puede aplicar estilo " "a un formulario a la vez y si activa el estilo para el formulario actual, el " "estilo se eliminará del otro formulario." #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "Actualmente el formulario %s está estilizado con " "%s. Como en la versión gratuita puede estilo sólo una forma a la " "vez y si activa el estilo para la forma actual, estilo se eliminará de otra " "forma." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "CSS personalizado" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "Código CSS personalizado" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "Dashed" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "Régimen por defecto" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "Borrar imagen" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "suprimido" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "Vista de escritorio" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "Desactivar el estilo para todos los formularios" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "Desactivar el estilo para el formulario actual" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "Te gusta conseguir styler versión premium gratis? ¡Entonces Introduzca su licencia " "WP2LEADS pro u obtenga una licencia aquí!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "¿Desea guardar los cambios antes de salir de la página?" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "Puntos" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "Doble" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "Formulario duplicado en la segunda columna" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "activado para todos los formularios" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "Error" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "Salir a pantalla completa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "Familia de fuentes" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "Tamaño de letra" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Estilo de fuente" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "Peso de la fuente" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Form BG Image & Colors" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "Personalización de formularios" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Formulario no seleccionado" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "Relleno, margen y borde del formulario" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "Texto del formulario" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "Pantalla completa" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "Ranura" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "Longitud horizontal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Color BG" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "Color Hover" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Color del texto sobreimpresionado" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "Cómo convertir su formulario de contacto form7 en un formulario de contacto " "de conversión, fácil de usar y con estilo profesional, un generador de " "prospectos \"encuesta\" o un formulario llamativo" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "https://saleswonder.biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "¡Estoy contento con esto! Guardar" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "Si está utilizando constructores de páginas, como Thrive Architect, " "OptimizePress, etc., consulte nuestra página Base de conocimientos " "para solucionar posibles problemas" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "Si necesita cargar esquema de estilo dentro de <body> " "etiqueta sólo en algunas páginas, puede hacerlo en frontend usando \"CF7 " "Styler\" botón. Esta función sólo está disponible para los tipos de mensajes " "individuales (páginas, mensajes, productos, etc) y en la versión premium. No " "se puede hacer en las páginas de archivos (blog, lista de productos, etc) en " "este caso es necesario utilizar la configuración global." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "Si necesita cargar el esquema de estilo dentro de la etiqueta <" "body> sólo en algunas páginas, puede hacerlo en frontend usando el " "botón \"CF7 Styler\". Esta función sólo está disponible para los tipos de " "entradas individuales (páginas, entradas, productos, etc.). No se puede " "hacer en las páginas de archivos (blog, lista de productos, etc) en este " "caso es necesario utilizar la configuración global." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "La configuración del fondo de la imagen sólo está disponible en la versión " "Profesional. Puede probarlo en el modo de vista previa \"estilo actual\", " "pero no se guardará." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "Opacidad de la imagen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "Posición de la imagen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "Tamaño de la imagen" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "Heredar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "Campos de entrada" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "Título del esquema de estilo de entrada" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "Insertar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "Cursiva" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "Etiquetas Color" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "Etiquetas Tamaño de fuente" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "Etiquetas Ajustes" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "Licencia" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "Altura de línea" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "Enlaces Color" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "Color de los enlaces" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Configuración de enlaces" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "En directo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "Cargar estilos en la etiqueta <body><body> tag on this page" msgstr "" "Cargar estilos dentro de la etiqueta <body> en esta página" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "Marque una casilla por línea" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "¿Hacer ancho completo?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "¿Completar los campos de entrada?" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Hacer un elemento radiobutton por línea" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "Margen" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "Vista móvil" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "NO" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "No hay elementos de Contact Form 7 para la vista previa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "Ningún formulario tiene un esquema de estilo, haga clic en el botón " "\"Activar estilo para formulario actual\" para aplicar el esquema actual a " "este formulario." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "No se ha seleccionado ningún plugin para instalar" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "No se ha seleccionado ningún esquema de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "Normal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "Oblicuo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "Estilos uno por línea para casillas de verificación y radiobuttons en modo " "activo sólo para la versión Profesional. Puede probarlo en el modo de vista " "previa \"estilo actual\", pero no se guardará." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "Opacidad" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "Estilizador abierto" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "Ver cuenta" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "Tamaño original" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "Esquema" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "Salida" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "Acolchado" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "Introduzca el título del esquema de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "Vista previa" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "Modo de vista previa" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "Vista previa Unstyled" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "Radio" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "Repita ambos" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "Repetir horizontal" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "Repetir vertical" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Restablecer valores por defecto" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "Cresta" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "Guardar" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "Guardado" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "Vista de la segunda columna" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "Seleccione el esquema de estilo para este formulario" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "Ajustes" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "Ajustes guardados como" #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "Sombra" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "Sombra Color" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Posición de sombra" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "Sólido" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Algunos temas o constructores de página (fe. Thrive Architect, OptimizePress " "etc.) podrían eliminar estilos en línea dentro de la etiqueta <" "head>. Cargar el esquema de estilo dentro de la etiqueta <" "body> solucionará este problema y mostrará sus formularios con " "estilo." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "Modo dividido" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "Vista dividida" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "Radio de dispersión" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "Empezar a estilizar" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "Empezar creando un esquema de estilo por defecto" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "Comienza creando tu primer Formulario " "de Contacto 7" #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "¡Comience su prueba gratuita de 14 días con todas las funciones " "profesionales aquí!" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "Paso 1. Haga clic en el enlace \"Editar con Thrive architect\" en la lista " "de páginas de administración" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "" "Paso 2. Haga clic en el icono \"Configuración\" del menú vertical derecho" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "" "Paso 3. \"Configuración avanzada\" => \"CSS en la sección <head>\"" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "Paso 4. Asegúrese de que \"No quitar CSS de <head>\" está marcada" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "Paso 5. Pulse el botón \"GUARDAR TRABAJO" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "Estiliza todos los formularios globalmente con un solo clic" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "" "Estiliza cada formulario individualmente con cualquier esquema de estilo" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "Esquema de estilo desactivado para todos los formularios" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "Esquema de estilo desactivado para este formulario" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "Esquema de estilo activado para este formulario" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "El esquema de estilo no está seleccionado" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "Lista de esquemas de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "Vista previa de los esquemas de estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "Ajustes de los esquemas de estilo" #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "El estilo se cargará en la etiqueta tag" msgstr "El estilo se cargará en la etiqueta " #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "Éxito" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "Soporte y KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "Vista de tableta" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "Color del texto" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "Este formulario está estilizado con %s globalmente, puedes " "estilizarlo con el esquema de Estilo actual." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "Este formulario está estilizado con %s, puedes estilizarlo " "con el esquema de Estilo actual." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "Este formulario está diseñado con el esquema de estilo actual, puede " "desactivarlo y utilizar la configuración global." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "Este formulario no tiene ningún esquema de estilo, puede activar el esquema " "actual para este formulario o configurar un esquema de estilo global " "haciendo clic en \"Usar para todos los formularios\" debajo del título del " "esquema." #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "Este régimen no existe" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "Este esquema de estilo habilitado a nivel mundial para todas las formas. Si " "desea utilizar el estilo de su tema para Contact Form 7 haga clic en el " "botón \"Desactivar\"." #. Author of the plugin msgid "Tobias Conrad" msgstr "Tobias Conrad" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "Tutorial" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "Sin estilo" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "Actualizar a Pro" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "Cargar imagen" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "Longitud vertical" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "Bienvenido" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "Anchura" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "Formulario de contacto WOW Style 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "SÃ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "Puede crear un nuevo esquema de estilo con la configuración actual. Si desea " "crear un esquema de estilo en blanco, desmarque la casilla de abajo." #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "No se puede borrar" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "No puede utilizar esta configuración en este tipo de página" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "No tiene ningún elemento Contact Form 7" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "No utiliza ninguno de los esquemas de estilo para Contact Form 7. Haga clic " "en \"Usar para todos los formularios\" para utilizar el esquema actual de " "forma global." languages/cf7-styler-pl_PL.mo000064400000047074146725417150012102 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'ó(* ***—B*&Ú*&+](+ †+‘+ ¨+ ³+k¾+*, <,H,Z,o,‚,š, °,º,†Ò,Y- y-„-)‹-µ- Å-Ï-×-Ý-ò--û-).0.8.W. s.W.Ù/Ú0í0 11 !1 -1,;1'h1&11·2 é2 ô2%þ2$3+3D3U3 f3 t3‚3¡3/¹3é3ú3 4 4(4;4T4h4ƒ45Ö´5±‹6ž=8Ü9õ9:½: Ñ:Û:!ë: ;; !;/;H;[;d;u;†;¥;»;4Ä;Fù;3@<t<0’<3Ã<÷<==3=«I=-õ=##>G>P>ÏX>(?:?!I?k?~? …? “?% ?Æ?!Ï?ñ?@ @@*@;@[@d@k@t@)Š@ ´@¿@Ø@ Þ@ë@ú@ AB.B?BUB0oB^ BÿBqDHŠDpÓDqDE7¶EBîEO1F8F2ºF1íFG>GWGsG‘G'®G ÖG âGðG H°H¿Hu?IƒµIö9J0K IKWK`KvKKžK±KÊK ÐKÜK’àKsL8‡L3ÀLŸôL ”M$žMÃM`ÛM- disable style scheme -- select -14-days Trial%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Loco https://localise.biz/ Project-Id-Version: Wow style (ES) Language: pl-PL Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); Report-Msgid-Bugs-To: POT-Creation-Date: 2020-04-18 12:29+0000 PO-Revision-Date: 2023-04-15 16:04+0000 Last-Translator: Tobias support@saleswonder.biz Language-Team: Polish X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489- wyÅ‚Ä…cz szablon stylu -- wybierz -14-dniowy okres próbny%s używany dla wszystkich formularzy globalnie, kliknij "Użyj dla wszystkich formularzy", jeÅ›li chcesz użyć bieżącego schematu.Aktywuj styl do wszystkich formularzy*Aktywuj styl dla aktualnego formularzaOpcjonalnie możesz wyÅ‚Ä…czyć czyszczenie stylów podobnie jak we wtyczce Thrive Architect:Kolor tÅ‚aPrzezroczystość tÅ‚aKolor tÅ‚aObraz tÅ‚aPrzed użyciem wtyczki WOW Style Contact Form 7, musisz zainstalować i aktywować wtyczkÄ™ Contact Form 7.PromieÅ„ rozmyciaObramowanieKolor obramowaniaPromieÅ„ obramowaniaRodzaj obramowaniaSzerokość obramowaniaObramowanie przyciskuPrzyciskiAutor: Takayuki MiyoshiWtyczka do modyfikacji stylów formularza Contact Form 7 wymaga zainstalowania i aktywacji wtyczki Contact Form 7. Możesz pobrać %s.Formularz CF7 nie jest wybrany.CF7 StylerAnulujPola wielokrotnego i jednokrotnego wyboruWyczyść styleWyczyśćZamknijKolorLista formularzy CF7ZmieśćSkopiuj ustawienia bieżącego szablonu styluPokryjUtwórzUtwórz wiele szablonów styluUtwórz nowy szablon stylu!Aktualny stylObecnie %s formularz jest stylizowany za pomocÄ… %s. Tak jak w wersji darmowej możesz stylizować tylko jeden formularz w tym samym czasie i jeÅ›li aktywujesz styl dla bieżącego formularza, styl zostanie usuniÄ™ty z innych formularzy.Aktualnie styl formularza %s jest skonfigurowany przy pomocy %s. Ponieważ w wersji darmowej w danym momencie możesz modyfikować styl tylko jednego formularza, jeÅ›li aktywujesz styl dla aktualnego formularza, styl zostanie usuniÄ™ty z innego formularza.Niestandardowy CSSNiestandardowy kod CSSKreskowaneSzablon domyÅ›lnyUsuÅ„ obrazWidok pulpituWyÅ‚Ä…czenie stylu dla wszystkich formularzyWyÅ‚Ä…cz styl dla aktualnego formularzaCzy chcesz otrzymać wersjÄ™ premium stylera za darmo? NastÄ™pnie Wprowadź swojÄ… licencjÄ™ WP2LEADS pro lub zdobÄ…dź licencjÄ™ tutaj!Chcesz zapisać zmiany przed opuszczeniem strony?KropkowanePodwójneDuplikuj formularz w drugiej kolumnieBÅ‚Ä…dWyjdź z peÅ‚nego ekranuRodzina czcionekRozmiar czcionkiStyl czcionkiWaga czcionkiObraz i kolory tÅ‚a formularzaDostosowanie formularzaWypeÅ‚nienie, margines i obramowanie formularzaTekst formularzaNie wybrano formularzaPeÅ‚ny ekranWklÄ™sÅ‚eDÅ‚ugość poziomaKolor tÅ‚a po najechaniuKolor po najechaniuKolor tekstu po najechaniuJak z formularza kontaktowego Contact Form 7 zrobić formularz kontaktowy, który nie tylko bÄ™dzie miaÅ‚ przyciÄ…gajÄ…cy uwagÄ™ profesjonalny wyglÄ…d oraz bÄ™dzie Å‚atwy w użyciu, ale także bÄ™dzie miaÅ‚ wysoki współczynnik konwersji i bÄ™dzie generowaÅ‚ zapytania o oferty.Podoba mi siÄ™! ZapiszJeÅ›li używasz page builderów, takich jak Thrive Architect, OptimizePress itp., sprawdź naszÄ… bazÄ™ wiedzy, aby naprawić ewentualne bÅ‚Ä™dyJeÅ›li potrzebujesz zaÅ‚adować schemat stylu wewnÄ…trz <body> tagu tylko na niektórych stronach, możesz to zrobić na frontend za pomocÄ… przycisku "CF7 Styler". Ta funkcja jest dostÄ™pna tylko dla pojedynczych typów postów (stron, postów, produktów itp.) i w wersji premium. Nie możesz tego zrobić na stronach archiwalnych (blog, lista produktów itp.) W tym przypadku musisz użyć ustawieÅ„ globalnych.JeÅ›li potrzebujesz zaÅ‚adować schemat stylu wewnÄ…trz <body> tagu tylko na niektórych stronach, możesz to zrobić na frontend za pomocÄ… przycisku "CF7 Styler". Ta funkcja jest dostÄ™pna tylko dla pojedynczych typów postów (stron, postów, produktów itp.). Nie możesz tego zrobić na stronach archiwalnych (blog, lista produktów itp.) W tym przypadku musisz użyć ustawieÅ„ globalnych.Przezroczystość obrazuPozycja obrazuRozmiar obrazuUstawienia obrazu tÅ‚a dostÄ™pne sÄ… w trybie podglÄ…du na żywo tylko dla wersji Professional. Możesz je wypróbować w trybie podglÄ…du ,,aktualny stylâ€, ale nie zostanÄ… one zapisane.DziedziczPola wejÅ›cioweNazwa szablonu stylu wejÅ›ciowegoWklejajÄ…ceKursywaKolor etykietRozmiar czcionki etykietUstawienia etykietLicencjaWysokość liniiKolor odsyÅ‚aczyKolor odsyÅ‚aczy po najechaniuUstawienia odsyÅ‚aczyNa żywoZaÅ‚aduj style w znaczniku <body>ZaÅ‚aduj style wewnÄ…trz tagu <body> na tej stronieUstaw po jednym polu wielokrotnego wyboru w wierszuUstawić peÅ‚nÄ… szerokość?Ustawić pola wejÅ›ciowe na peÅ‚nÄ… szerokość?Ustaw po jednym polu jednokrotnego wyboru w wierszuMarginesWidok w komórceNIEBrak pozycji formularza Contact Form 7 do podglÄ…duÅ»aden formularz nie jest zmodyfikowany przy pomocy szablonu stylu. Aby zastosować aktualny szablon do tego formularza kliknij ,,Aktywuj styl do aktualnego formularzaâ€.Nie wybrano żadnej wtyczki do zainstalowaniaNie wybrano żadnego szablonu styluNormalnyKursywaUstawienie jednego pola wielokrotnego i jednokrotnego wyboru w wierszu jest możliwe tylko w wersji Professional. Możesz je wypróbować w trybie podglÄ…du ,,aktualny stylâ€, ale nie zostanÄ… one zapisane.PrzezroczystośćOtwórz StylerZaloguj siÄ™, aby zobaczyć kontoOryginalny rozmiarKonturUwypuklajÄ…ceWypeÅ‚nienieWprowadź szablonu stylu wejÅ›ciowegoPodglÄ…dPodglÄ…d niezmodyfikowanego styluTryb podglÄ…duPromieÅ„Powtórz obydwaPowtórz poziomoPowtórz pionowoPrzywróć ustawienia domyÅ›lneWypukÅ‚eZapiszZapisanoWidok drugiej kolumnyWybierz szablon stylu dla tego formularzaUstawieniaUstawienia zapisane jakoCieÅ„Kolor cieniaPozycja cieniaJednolite ciÄ…gÅ‚eNiektóre motywy lub kreatory stron (np. Thrive Architect, OptimizePress itp.) mogÄ… usuwać style lokalne (inline styles) wewnÄ…trz tagu . Dodanie szablonu stylu wewnÄ…trz tagu naprawi ten problem i twoje formularze bÄ™dÄ… miaÅ‚y zmodyfikowany styl.Tryb podzielonego widokuWidok podzielonyPromieÅ„ rozproszeniaZacznij modyfikować stylZacznij od utworzenia DomyÅ›lnego szablonu styluZacznij od stworzenia swojego pierwszego Contact Form 7Rozpocznij 14-dniowy bezpÅ‚atny okres próbny ze wszystkimi funkcjami Professional tutaj!Krok 1. Kliknij na link ,,Edit with Thrive Architect" (Edytuj z Thrive Architect) na liÅ›cie stron administratoraKrok 2. Kliknij ikonÄ™ ,,Settings†(Ustawienia) w prawym pionowym menuKrok 3. ,,Advanced settings†(Ustawienia zaawansowane) => ,,CSS in the section†(CSS w sekcji )Krok 4. Upewnij siÄ™, że opcja ,,Do not strip CSS from †(Nie usuwaj CSS z sekcji) jest zaznaczonaKrok 5. Kliknij przycisk ,,SAVE WORK†(ZAPISZ PRACĘ)Modyfikuj globalnie jednym klikniÄ™ciem styl wszystkich formularzyModyfikuj indywidualnie styl każdego formularza przy pomocy dowolnego szablonuSzablon stylu jest wyÅ‚Ä…czony dla wszystkich formularzySzablon stylu jest wyÅ‚Ä…czony dla tego formularzaSzablon stylu jest wÅ‚Ä…czony dla tego formularzaSzablon stylu nie jest wybranyLista szablonów stylówPodglÄ…d szablonów stylówUstawienia szablonów stylówStyl zostanie dodany do taguStyl zostanie zaÅ‚adowany w tagu UdaÅ‚o siÄ™Wsparcie i KBWidok w tablecieKolor tekstuTen Szablon stylu jest wÅ‚Ä…czony globalnie dla wszystkich formularzy. Jeżeli do formularza Contact Form 7 chcesz użyć stylu z twojego motywu kliknij przycisk ,,WyÅ‚Ä…czâ€.Styl tego formularza modyfikowany jest globalnie przy pomocy %s, możesz go modyfikować przy pomocy aktualnego Szablonu stylu.Styl tego formularza modyfikowany jest przy pomocy %s, możesz go modyfikować przy pomocy aktualnego Szablonu stylu.Styl tego formularza modyfikowany jest przy pomocy aktualnego Szablonu stylu, możesz go wyÅ‚Ä…czyć i użyć ustawieÅ„ globalnych.Styl tego formularza nie jest modyfikowany przy pomocy żadnego Szablonu stylu, możesz wÅ‚Ä…czyć aktualny Szablon dla tego formularza albo ustawić globalny Szablon stylu klikajÄ…c na ,,Użyj do wszystkich formularzy†poniżej nazwy szablonu.Ten szablon nie istniejeTobias ConradTutorialNiezmodyfikowany stylUaktualnij do wersji ProZaÅ‚aduj obrazDÅ‚ugość pionowaWOW Style Contact Form 7WitajSzerokośćTAKMożesz utworzyć nowy szablon stylu z aktualnymi ustawieniami szablonu. JeÅ›li chcesz utworzyć pusty szablon stylu odznacz pole wyboru poniżej.Nie można usunąćNie można używać tych ustawieÅ„ na stronach tego typuNie masz żadnych pozycji formularza Contact Form 7Nie używasz żadnych Szablonów stylów do formularza Contact Form 7. Kliknij ,,Użyj do wszystkich formularzyâ€, aby używać aktualnego Szablonu globalnie.usuniÄ™tywÅ‚Ä…czony dla wszystkich formularzyhttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/languages/cf7-styler-ja.mo000064400000047527146725417150011471 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'(,Ÿ)Ì)Õ)¶ç)1ž*!Ð*pò* c+p+ + ‰+¤–+ ;, E,R,e,{,‘,¡, ´,¾,Ô,!T- v-€-)„-®- Ç-Ñ-Õ-Ù- ó--ý- +. 5.*?.%j..¦.ν/Œ0œ0µ0¼0Û0ë031$;1Z`1B»2þ2 3!3 13 ;3H3a3q3Š33°35Ì344 44>4 B4O4 e4-r4  4A5ý[5ÅY6£8Ã9Ù9é9ºù9´: »:-È: ö:;;;6;F;V;f;v;Œ; Ÿ;9©;Hã;*,<W<_<0s< ¤<®<Í<"Ð<ªó<!ž='À= è=ò=çù= á> î>*ø>#?%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/Language: ja POT-Creation-Date: 2020-02-06 11:35+0000 Plural-Forms: nplurals=1; plural=0; PO-Revision-Date: 2023-04-15 16:09+0000 X-Generator: Loco https://localise.biz/ Project-Id-Version: WOW Style Contact Form 7 Report-Msgid-Bugs-To: Last-Translator: Language-Team: Japanese MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Loco-Version: 2.3.3; wp-5.4-を無効ã«ã™ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ --é¸æŠž-14日間ã®è©¦ç”¨ã„%s" 使用ã®ãŸã‚ã®ã™ã¹ã¦ã®å½¢ã®ä¸–界をクリックã—"利用ã®ãŸã‚ã®ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ¼ãƒ "を利用ã™ã‚‹å ´åˆã¯ç¾åœ¨ã®ã‚¹ã‚­ãƒ¼ãƒ ã§ã™ã€‚起動スタイルã®ãŸã‚ã®ã™ã¹ã¦ã®å½¢æ…‹*起動スタイルをç¾åœ¨ã®å½¢ã®ä»£æ›¿ã¨ã—ã¦ç„¡æ•°ã®çµ„ã¿åˆã‚ã›ã§è‡ªåˆ†ã ã‘ã®ã‚¯ãƒªãƒ¼ãƒ³ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚ˆã†ã«ç”Ÿå»ºç¯‰å®¶:背景ã®è‰²BGä¸é€æ˜Žåº¦èƒŒæ™¯è‰²èƒŒæ™¯ç”»åƒä½¿ç”¨å‰ã«ãªã‚“ã¨ã‚¹ã‚¿ã‚¤ãƒ«ã®Contact Form7ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã€æ´»æ€§åŒ–ã®Contact Form7ã®å¼•ã出ã—ãŠã‚ˆã³è¨­å®šãŒã§ãã¾ã™ãƒ–åŠå¾„ボーダーボーダーã®è‰²ãƒœãƒ¼ãƒ€ãƒ¼ã®åŠå¾„ボーダータイプボーダー幅ボタンã®å›½å¢ƒãƒœã‚¿ãƒ³ã«ã‚ˆã‚‹ä¸‰å¥½å­ä¹‹CF7"カスタマイズãŒå¿…è¦ã§Contact Form7ã®ãƒ—ラグインを設置ã™ã‚‹å¿…è¦ãŒã‚る。 ダウンロードã§ã%s".CF7å½¢ãŒé¸æŠžã•ã‚Œã¦ã„ãªã„CF7Styler消ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹&Radiobuttonsクリーンスタイル明らã‹è¿‘色Contact form7ã®ãƒªã‚¹ãƒˆã‚’å«ã‚€ã‚³ãƒ”ースタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã«è¨­å®šã‚«ãƒãƒ¼ã®ä½œæˆè¤‡æ•°ä½œæˆã™ã‚‹ã‚¹ã‚¿ã‚¤ãƒ«ã‚¹ã‚­ãƒ¼ãƒ æ–°ã—ã„スタイルã®ã‚¹ã‚­ãƒ¼ãƒ !ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«ç¾åœ¨ %s å½¢å¼ã¨ã® %s". ã¨ã—ã¦ç„¡æ–™ç‰ˆã§ãるスタイルã®ä¸€å½¢æ…‹ã§ã‚ã‚Œã°èµ·å‹•ã‚¹ã‚¿ã‚¤ãƒ«ã®ã¾ã¾ã®å½¢ã§ã¯ã€ã‚¹ã‚¿ã‚¤ãƒ«ã‹ã‚‰å‰Šé™¤ã•ã‚Œã‚‹ã‹ã€‚ç¾åœ¨ %s å½¢å¼ã¨ã® %s". ã¨ã—ã¦ç„¡æ–™ç‰ˆã§ãるスタイルã®ä¸€å½¢æ…‹ã§ã‚ã‚Œã°èµ·å‹•ã‚¹ã‚¿ã‚¤ãƒ«ã®ã¾ã¾ã®å½¢ã§ã¯ã€ã‚¹ã‚¿ã‚¤ãƒ«ã‹ã‚‰å‰Šé™¤ã•ã‚Œã‚‹ã‹ã€‚カスタムCSSカスタムCSSコード疾走デフォルトã®ã‚¹ã‚­ãƒ¼ãƒ ç”»åƒã®å‰Šé™¤ãƒ‡ã‚¹ã‚¯ãƒˆãƒƒãƒ—ビュー無効化スタイルã®ãŸã‚ã®ã™ã¹ã¦ã®å½¢æ…‹ç„¡åŠ¹åŒ–スタイルをç¾åœ¨ã®å½¢ã‚¹ã‚¿ã‚¤ãƒ©ãƒ¼ãƒ—レミアムãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ç„¡æ–™ã§å…¥æ‰‹ã—ãŸã„ã§ã™ã‹ï¼Ÿ 次ã«ã€ WP2LEADS proライセンスを入力ã™ã‚‹ã‹ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’å–å¾—ã—ã¾ã™ã“ã¡ã‚‰ï¼ã„変更をä¿å­˜å‰ã®ãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã™ã¹ã事ã¯ä½•ã‹ï¼Ÿç‚¹åœ¨ãƒ€ãƒ–ルé‡è¤‡ã—ãŸå½¢æ…‹ã®ç¬¬äºŒã®æŸ±ã‚¨ãƒ©ãƒ¼å£å…¨ç”»é¢ãƒ•ã‚©ãƒ³ãƒˆãƒ•ã‚¡ãƒŸãƒªæ–‡å­—サイズフォントスタイルフォントé‡é‡å½¢æ…‹ç”»åƒã¨è‰²å½¢å¼ã®ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚ºå½¢ã®ãƒ‘ディングã€ãƒžãƒ¼ã‚¸ãƒ³&ボーダーテキスト形å¼å½¢ãŒé¸æŠžã•ã‚Œã¦ã„ãªã„全画é¢æºæ¨ªã®é•·ã•ãƒ›ãƒãƒ¼èƒŒæ™¯ã®è‰²ãƒ›ãƒãƒ¼è‰²ãƒ›ãƒ†ã‚­ã‚¹ãƒˆã‚«ãƒ©ãƒ¼ã‚’設定ã—ã¾ã™ã€‚ã©ã®ã‚ˆã†ã«ã”連絡をãŠform7å½¢å¼ã«å¤‰æ›ã™ã‚‹ä½¿ã„ã‚„ã™ãã€ãƒ—ロアã¯ã€ãŠå•ã„åˆã‚ã›ãƒ•ã‚©ãƒ¼ãƒ "調査"ã®ç™ºç”Ÿã¾ãŸã¯ç›®ã‚’引ã形嬉ã—ã„ã§ã™ã€‚ ä¿å­˜Thrive Architectã€OptimizePressãªã©ã®ãƒšãƒ¼ã‚¸ãƒ“ルダーを使用ã—ã¦ã„ã‚‹å ´åˆã¯ã€ãƒŠãƒ¬ãƒƒã‚¸ãƒ™ãƒ¼ã‚¹ãƒšãƒ¼ã‚¸ã‚’確èªã—ã¦ãã ã•ã„ 考ãˆã‚‰ã‚Œã‚‹å•é¡Œã®ä¿®æ­£ãŒå¿…è¦ãªå ´åˆã¯è² è·ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ å†…ã® <body> ã‚¿ã‚°ã®ã¿ä¸€éƒ¨ã®ãƒšãƒ¼ã‚¸ã§ããªãƒ•ãƒ­ãƒ³ãƒˆã‚¨ãƒ³ãƒ‰ã‚’使用"CF7Styler"ボタンを押ã—ã¾ã™ã€‚ ã“ã®æ©Ÿèƒ½ã¯ã‚·ãƒ³ã‚°ãƒ«ãƒã‚¹ãƒˆåž‹(ページã€è£½å“等) やプレミアムãƒãƒ¼ã‚¸ãƒ§ãƒ³ã€‚ ã§ãã¾ã›ã‚“アーカイブã®ãƒšãƒ¼ã‚¸ã®ãƒ–ログã§ã¯ã€è£½å“リストãªã©ï¼‰ã‚’ãŠä½¿ã„ã«ãªã‚‹å ´åˆã¯ã‚°ãƒ­ãƒ¼ãƒãƒ«ã‚’設定ã—ã¾ã™ã€‚ãŒå¿…è¦ãªå ´åˆã¯è² è·ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ å†…ã® <body> ã‚¿ã‚°ã®ã¿ä¸€éƒ¨ã®ãƒšãƒ¼ã‚¸ã§ããªãƒ•ãƒ­ãƒ³ãƒˆã‚¨ãƒ³ãƒ‰ã‚’使用"CF7Styler"ボタンを押ã—ã¾ã™ã€‚ ã“ã®æ©Ÿèƒ½ã¯ã‚·ãƒ³ã‚°ãƒ«ãƒã‚¹ãƒˆåž‹(ページã€è£½å“ã¾ã™ã€‚ ã§ãã¾ã›ã‚“アーカイブã®ãƒšãƒ¼ã‚¸ã®ãƒ–ログã§ã¯ã€è£½å“リストãªã©ï¼‰ã‚’ãŠä½¿ã„ã«ãªã‚‹å ´åˆã¯ã‚°ãƒ­ãƒ¼ãƒãƒ«ã‚’設定ã—ã¾ã™ã€‚ç”»åƒã®ä¸é€æ˜Žåº¦ç”»åƒã®ä½ç½®ç”»åƒã‚µã‚¤ã‚ºèƒŒæ™¯ç”»åƒã®è¨­å®šã‚’有ライブモードã®ã¿ã®ãŸã‚ã®å°‚é–€ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã€‚ ã§ãる試験ã§ã®ãƒ—レビューモード"ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«"ã§ä¿å­˜ã•ã‚Œã¾ã›ã‚“。継承入力分野入力スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã‚¿ã‚¤ãƒˆãƒ«æŒ¿å…¥å›³Italicラベルã®è‰²ãƒ©ãƒ™ãƒ«ãƒ•ã‚©ãƒ³ãƒˆã‚µã‚¤ã‚ºãƒ©ãƒ™ãƒ«è¨­å®šãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ©ã‚¤ãƒ³é«˜ã•ãƒªãƒ³ã‚¯ã®è‰²ãƒªãƒ³ã‚¯ãƒ›ãƒãƒ¼è‰²ãƒªãƒ³ã‚¯ã®è¨­å®šãƒ©ã‚¤ãƒ–è² è·ã‚¹ã‚¿ã‚¤ãƒ«ã§ã® <body> ã‚¿ã‚°è² è·ã‚¹ã‚¿ã‚¤ãƒ«å†…ã« <body> ã‚¿ã‚°ã“ã®ãƒšãƒ¼ã‚¸ã‚’ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹é …ç›®ã®é…線全幅?入力分野全幅?ã†ãƒ©ã‚¸ã‚ªãƒœã‚¿ãƒ³ã‚’商å“一行ã«ä¸€ã¤ã®è¨¼æ‹ é‡‘モãƒã‚¤ãƒ«ç«¯æœ«ä¸Šã®è¡¨ç¤ºNOãªã„å½¢ã§7項目プレビュー無形å¼ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ "をクリックã—起動スタイルをç¾åœ¨ã®ãƒ•ã‚©ãƒ¼ãƒ "ボタンã®é©ç”¨ã‚’ç¾è¡Œã‚¹ã‚­ãƒ¼ãƒ ã™ã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ãªã„プラグインã®é¸æŠžã‚¤ãªã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’é¸æŠžé€šå¸¸ã®æ–œã‚一行ã«ä¸€ã¤ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã¨radiobuttonsライブモードã®ã¿ã®ãŸã‚ã®å°‚é–€ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã€‚ ã§ãる試験ã§ã®ãƒ—レビューモード"ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«"ã§ä¿å­˜ã•ã‚Œã¾ã›ã‚“。ä¸é€æ˜Žåº¦é–‹æ”¾æ„Ÿã‚ªãƒ—トインã§ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’見るオリジナルサイズ概è¦å½“åˆãƒ‘ディングã”入力ãã ã•ã„スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã‚¿ã‚¤ãƒˆãƒ«ãƒ—レビュープレビュー Unstyledプレビュー表示モードåŠå¾„ç¹°ã‚Šè¿”ã—両繰り返ã—水平繰り返ã—垂直デフォルトã«ãƒªã‚»ãƒƒãƒˆå°¾æ ¹ä¿å­˜ä¿å­˜ç¬¬äºŒåˆ—ビューé¸æŠžã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã®ãŸã‚ã®ã“設定設定ã¨ã—ã¦ä¿å­˜ 影影ã®è‰²å½±ã®ä½ç½®å›ºä½“一部ã®ãƒ†ãƒ¼ãƒžã‚„ページビルダー(feã§ã‚る。 ç¹æ „建築家OptimizePress等) を除去ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã‚ã‚‹ã“ã¨ã‚¤ãƒ³ãƒ©ã‚¤ãƒ³ã®ã‚¹ã‚¿ã‚¤ãƒ«å†…ã® <head> ã‚¿ã‚°ã§ã™ã€‚ è·ç©ã¿ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ å†…ã® <body> ã‚¿ã‚°ã®çµ„ã¿åˆã‚ã›ãŒæ±ºå®šã•ã‚Œã‚‹ã“ã®å•é¡Œæ示ã®å½¢å¼.分割モード分割ビュー広ãŒã‚‹åŠå¾„スタイリング開始最åˆã«ä½œæˆãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚¿ã‚’作æˆã™ã‚‹ 最åˆã®Contact Form7始ã¾ã‚Šã¯14日間無料ãŠè©¦ã—ã™ã¹ã¦ã®ãƒ—ロã®æ©Ÿèƒ½ ãŒã“ã“ã«!ステップ1ã§ã™ã€‚ 編集"をクリックã—ã¨ç¹æ „建築家"ã®ãƒªãƒ³ã‚¯ã‚’クリック管ç†è€…ページリストステップ2ã«é€²ã¿ã¾ã™ã€‚ をクリックã—"設定"アイコンをå³ã«ç¸¦ãƒ¡ãƒ‹ãƒ¥ãƒ¼Step3. "詳細設定"=>"CSSã®<head>セクション"Step4. ã«ãªã£ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ãªã„ストリップCSSã‹ã‚‰ã®<head>"ã«ãƒã‚§ãƒƒã‚¯ã‚¹ãƒ†ãƒƒãƒ—5ã§ã™ã€‚ "ä¿å­˜"ボタンをクリックã—ã¾ã™ä»•äº‹"ボタンスタイル全ã¦ã«ãƒ¯ãƒ³ã‚¯ãƒªãƒƒã‚¯ã§ä¸–界的ã«ã‚¹ã‚¿ã‚¤ãƒ«ãã‚Œãžã‚Œã®å½¢æ…‹ã¨ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’個別ã«ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’無効ã«ã™ã¹ã¦ã®å½¢æ…‹ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’無効ã«ã™ã‚‹ã“ã¨ã‚’å‰æスタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’有効ã«ã™ã‚‹ã“ã¨ã‚’å‰æスタイルã®ã‚¹ã‚­ãƒ¼ãƒ ãŒé¸æŠžã•ã‚Œã¦ã„ãªã„スタイルスキーム一覧スタイルスキームã®ãƒ—レビュースタイルスキームã«è¨­å®šã‚¹ã‚¿ã‚¤ãƒ«ãŒèª­ã¿è¾¼ã¾ã‚Œ タグスタイルãŒèª­ã¿è¾¼ã¾ã‚Œ ã‚¿ã‚°æˆåŠŸã‚µãƒãƒ¼ãƒˆï¼†KBタブレットビューテキストカラーを設定ã—ã¾ã™ã€‚ã“ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’有効ã«ä¸–ç•Œã®ã™ã¹ã¦ã®å½¢æ…‹ãŒã‚る。 使用ã™ã‚‹å ´åˆã«ãƒ—レゼンテーションã®ã‚¹ã‚¿ã‚¤ãƒ«ã‚’å•åˆã›ãƒ•ã‚©ãƒ¼ãƒ 7"をクリックを無効ã«ã™"ボタンを押ã—ã¾ã™ã€‚ã“ã®å½¢å¼ã¨ã® %s" 世界ã§ãるスタイルã§ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«ã‚¹ã‚­ãƒ¼ãƒ ã§ã™ã€‚ã“ã®å½¢å¼ã¨ã® %s"ãスタイルã§ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«ã‚¹ã‚­ãƒ¼ãƒ ã§ã™ã€‚ã“ã®å½¢å¼ã®ç¾åœ¨ã®ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã«ã‚ªãƒ•ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã—ã€ã‚°ãƒ­ãƒ¼ãƒãƒ«ã‚’設定ã—ã¾ã™ã€‚ã“ã®å½¢å¼ã¯è¡¨ã®ã¨ã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’å¾—ã‚‹ã“ã¨ãŒã§ãç¾åœ¨ã®ã‚¹ã‚­ãƒ¼ãƒ ã¯ã“ã®å½¢å¼ã‹ã‚‰ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆãŒä¸–界中ã§ç”»ä¸€çš„ãªã‚¹ã‚¿ã‚¤ãƒ«ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’クリック"使用ã®ãŸã‚ã®ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ¼ãƒ ã¯ä¸‹è¨˜ã‚¹ã‚­ãƒ¼ãƒ ã®ã‚¿ã‚¤ãƒˆãƒ«ã€‚ã“ã®ã‚¹ã‚­ãƒ¼ãƒ ãŒå­˜åœ¨ã—ã¦ã„ãªã„Tobiasコンラッドãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«UnstyledプProç”»åƒã‚¢ãƒƒãƒ—ロード縦方å‘ã®é•·ã•ãªã‚“ã¨ã‚¹ã‚¿ã‚¤ãƒ«ã®Contact Form7æ­“è¿Žå¹…ã‚りを作æˆã§ãã¾ã™æ–°ã—ã„スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã®ç¾åœ¨ã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’設定ã—ã¾ã™ã€‚ を処ç†ã—ãªã‘ã‚Œã°ã„ã‘ãªã„空白ã®ã‚¹ã‚¿ã‚¤ãƒ«schem unchekãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã§ã™ã€‚ã ã‘を削除ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“使用ã§ãã¾ã›ã‚“ã“ã®è¨­å®šã¯ã“ã®ãƒšãƒ¼ã‚¸ã‚¿ã‚¤ãƒ—一切ã—ã¦ã„ãªã„ã®Contact Form7項目使ã„ã§ãªã„スタイルã®ã‚¹ã‚­ãƒ¼ãƒ ã®ãŸã‚ã®å•åˆã›ãƒ•ã‚©ãƒ¼ãƒ 7. クリック"使用ã®ãŸã‚ã®ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ¼ãƒ "ç¾åœ¨ã®ã‚¹ã‚­ãƒ¼ãƒ ã§ã™ã€‚削除有効ãªã™ã¹ã¦ã®å½¢æ…‹https://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/languages/cf7-styler-ur.mo000064400000056632146725417150011522 0ustar00Þ•¾ ü ü ý  ! m/  » PÛ , 5 @ Q ^b Á Í Ô á ï û ^2‘ ªµ¼ Öãéïõ "4:A_ x†Ò¡ t– ¥ ²¿Û ú09@Ggm ~ Š ” Ÿ«ÂÓ ñû #5 DP’aôÐfßOF –¤ ³š¾Y an‡ ”¡²Â Ê Öâô,=5s“¤"Âå ìø#ûzš¸ÑØªà‹ “Ÿ µÃËÒÚú   '3EUflqw!Š¬µÈ ÏÜìòò å ð û (T@ü•B’ 4Õ @ !FK! ’!%³!2Ù!# "#0""T"w"”"§"½""Ô""÷"# "# /# ;#‚F#bÉ#Y,$Z†$©á$‹% ¦%´%½%Æ% Õ%â%ò% &&&|&š&/­&(Ý&q'x'€'–'`®'¼(+Ì)ø)*&*>9+<x+¶µ+l,"}, ,º,¹Ø,’- ¦-³-È-Þ-ô- . .!+.¥M.3ó.'/ 8/(C/l/ ~/ Œ/ š/¥/»/HÍ/ 0 !0+,03X0Œ0ê¤0¢224'L4t4ƒ4—4µ4:Ò4: 5ŒH5tÕ6 J7 U7.`77.˜7Ç7Ý7ï78"898.P88*8º8 Ð8Û8ñ899*9(J:os:¨ã;tŒ>(A*AGA$`A …BB$«B ÐBÛBîB#C%C ;CHCeCwCC ¬C6·CNîCA=D(D8¨D=áD E,EFEGXE EX§F5G 6GCG7LG„H—H,¯HÜHìHüHIJIdI!sI•I ´I¿I(ßIJ-'J UJ`JiJ#rJJ–JáJ0ðJ !K/KDK _KŠlK÷LM$M(5MI^M|¨M@%NffOYÍOI'P†qP9øPH2Qe{QJáQB,R?oR8¯RèR#S 'S>HS>‡SÆSÚSïST T¿;U¨ûUФVSuW&ÉXðXYY))YSYsY$‰Y®YÀY ÉYâÕY'¸ZdàZHE[Ž[­\,½\Mê\a8]- disable style scheme -- select -14-days Trial%s used for all forms globally, click "Use for all forms" if you want to use current Scheme.Activate style for all forms*Activate style for current formAs an alternative you can disable clean out the styles like on Thrive architect:BG ColorBG OpacityBackground ColorBackground ImageBefore using WOW Style Contact Form 7, you need to install and activate Contact Form 7 plugin.Blur radiusBorderBorder ColorBorder RadiusBorder TypeBorder WidthButton BorderButtonsBy Takayuki MiyoshiCF7 Customizer requires Contact Form 7 plugin to be installed and active. You can download %s.CF7 Form is not selectedCF7 StylerCancelCheckboxes & RadiobuttonsClean StylesClearCloseColorContact form 7 listContainCopy current style scheme settingsCoverCreateCreate multiple style schemesCreate new style scheme!Current StyleCurrently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Currently %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.Custom CSSCustom CSS CodeDashedDefault SchemeDelete ImageDesktop ViewDisable style for all formsDisable style for current formDo you like to get styler premium version for free? Then Enter your WP2LEADS pro license or get a license here!Do you want to save changes before leaving page?DottedDoubleDuplicate form in second columnErrorExit Full ScreenFont FamilyFont SizeFont StyleFont WeightForm BG Image & ColorsForm CustomizingForm Padding, Margin & BorderForm TextForm is not selectedFull ScreenGrooveHorizontal LengthHover BG ColorHover ColorHover Text ColorHow to turn your contact form7 form into a converting and easy to use and pro styled contact form, "survey" lead generator or an eye catching formI'm happy with this! SaveIf you are using page builders, like Thrive Architect, OptimizePress etc., please check our Knowledge Base page for fixing possible issuesIf you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.) and in premium version. You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.If you need to load style scheme inside <body> tag only on some pages, you can do it on frontend using "CF7 Styler" button. This function is only available for single post types (pages, posts, products etc.). You can not do it on archives pages (blog, products list etc) in this case you need to use global settings.Image OpacityImage PositionImage SizeImage background settings available in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.InheritInput FieldsInput style scheme titleInsetItalicLabels ColorLabels Font SizeLabels SettingsLicenseLine HeightLinks ColorLinks Hover ColorLinks SettingsLiveLoad styles in <body> tagLoad styles inside <body> tag on this pageMake checkbox item one per lineMake full width?Make input fields full width?Make radiobutton item one per lineMarginMobile ViewNONo Contact Form 7 items for previewNo form is styled with style scheme, click "Activate style for current form" button to apply current scheme for this form.No plugin selected to installNo style scheme selectedNormalObliqueOne per line styles for checkboxes and radiobuttons in live mode only for Professional version. You can test it in preview mode "current style", but it will not be saved.OpacityOpen stylerOpt-in to see accountOriginal sizeOutlineOutsetPaddingPlease input style scheme titlePreviewPreview UnstyledPreview modeRadiusRepeat bothRepeat horizontalRepeat verticalReset to defaultRidgeSaveSavedSecond column viewSelect style scheme for this formSettingsSettings saved as ShadowShadow ColorShadow PositionSolidSome themes or page builders (fe. Thrive Architect, OptimizePress etc.) could remove inline styles inside <head> tag. Loading style scheme within <body> tag will fix this issue and show your forms styled.Split modeSplit viewSpread radiusStart stylingStart with creating Default Style SchemeStart with creating your first Contact Form 7Start your 14-day free trial with all Professional functions here!Step 1. Click "Edit with Thrive architect" link in admin page listStep 2. Click "Settings" icon on right vertical menuStep 3. "Advanced settings" => "CSS in the <head> section"Step 4. Make sure that "Do not strip CSS from <head>" is checkedStep 5. Click "SAVE WORK" buttonStyle all forms in one click globallyStyle each form with any style scheme individuallyStyle scheme disabled for all formsStyle scheme disabled for this formStyle scheme enabled for this formStyle scheme is not selectedStyle schemes listStyle schemes previewStyle schemes settingsStyle will be loaded in tagStyle will be loaded in tagSuccessSupport & KBTablet ViewText ColorThis Style Scheme enabled globally for all forms. If you want to use your theme's style for Contact Form 7 click "Disable" button.This form is styled with %s globally, you can style it with current Style scheme.This form is styled with %s, you can style it with current Style scheme.This form is styled with current Style Scheme, you can disable it and use global settings.This form not styled with any Style scheme, you can enable current Scheme for this form or set up global Style Scheme by clicking "Use for all forms" below scheme title.This scheme is not existedTobias ConradTutorialUnstyledUpgrade to ProUpload ImageVertical LengthWOW Style Contact Form 7WelcomeWidthYESYou can create new style scheme with current scheme settings. If you want to create blank style schem unchek checkbox below.You can not deleteYou can not use this settings on this page typeYou do not have any Contact Form 7 itemsYou do not use any of Style Schemes for Contact Form 7. Click "Use for all forms" to use current Scheme globally.deletedenabled for all formshttps://saleswonder.bizhttps://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-tipp-einfach-verbinden/Language: ur POT-Creation-Date: 2023-04-15 15:26+0000 Plural-Forms: nplurals=2; plural=n != 1; PO-Revision-Date: 2023-04-15 16:01+0000 X-Generator: Loco https://localise.biz/ Project-Id-Version: WOW Style Contact Form 7 Report-Msgid-Bugs-To: Last-Translator: Tobias support@saleswonder.biz Language-Team: Urdu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489- غیر Ùعال سٹائل ڈیزائن -منتخب کریں -14 دن Ú©ÛŒ سماعت%s عالمی سطح پر تمام Ùارم Ú©Û’ لئے استعمال کیا جاتا ÛÛ’ØŒ اگر آپ Ù…ÙˆØ¬ÙˆØ¯Û Ù†Ø¸Ø§Ù… کا استعمال کرنا چاÛتے Ûیں تو "تمام Ùارم Ú©Û’ لئے استعمال کریں" پر Ú©Ù„Ú© کریں.تمام شکلوں Ú©Û’ لئے سٹائل Ùعال کریں *Ù…ÙˆØ¬ÙˆØ¯Û Ø´Ú©Ù„ Ú©Û’ لئے سٹائل Ùعال کریںایک متبادل Ú©Û’ طور پر آپ Ú©Ùˆ اس طرح Ú©Û’ سٹائل Ú©Ùˆ صا٠کرنے Ú©ÛŒ اجازت Ù†Ûیں دے سکتے Ûیں جیسا Ú©Û Ùریو آرکیٹیکٹ:بی سی رنگبی جے Ù¾ÛŒ Ú©Û’ متنازعÛپس منظر کا رنگتصویر Ú©Û’ پس منظرWow سٹائل Ø±Ø§Ø¨Ø·Û Ùارم 7 کا استعمال کرنے سے Ù¾ÛÙ„Û’ØŒ آپ Ú©Ùˆ انسٹال اور Ùعال کرنے Ú©ÛŒ ضرورت ÛÛ’ Ø±Ø§Ø¨Ø·Û Ùارم 7 پلگ ان.بلیو ریڈیوسرحدیںسرحد کا رنگسرحد راجستÛسرحدی اقسامسرحد Ú©ÛŒ وسیعبٹن Ú©ÛŒ سرحدبٹنیںکی طر٠سے Takayuki MiyoshiCf7 Customizer Ø±Ø§Ø¨Ø·Û Ùارم 7 پلگ ان Ú©Ùˆ انسٹال اور Ùعال کرنے Ú©ÛŒ ضرورت ÛÛ’. آپ Ú©Ùˆ % S ڈاؤن لوڈ کر سکتے Ûیں.Cf7 Ùارم منتخب Ù†Ûیں کیا گیا ÛÛ’Cf7 سٹائلرمنسوخچیک باکس اور ریڈیو بٹنصا٠سٹائلواضح Ûےقریب ÛےرنگیںÙÛرست نمبر 7شامل Ú©Ø±ÛŒÚºÙ…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ سکرپٹ Ú©ÛŒ ترتیبات کاپی کریںکوریجتخلیقکثیر سٹائل سکرپٹ بنائیںایک نئے سٹائل ڈیزائن بنائیں!Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ÙÛŒ الحال % Ú©Û’ s Ø´Ú©Ù„ Ú©Û’ ساتھ اسٹائل کیا جاتا ÛÛ’ % Ú©Û’ s → جیسا Ú©Û Ù…Ùت ورژن میں آپ صر٠ایک Ùارم Ú©Ùˆ ایک بار میں سٹائل کر سکتے Ûیں اور اگر آپ Ù…ÙˆØ¬ÙˆØ¯Û Ùارم Ú©Û’ لئے سٹائل Ú©Ùˆ Ùعال کرتے Ûیں تو سٹائل Ú©Ùˆ دوسرے Ùارم سے Ûٹا دیا جائے گا.ÙÛŒ الحال % Ú©Û’ s Ø´Ú©Ù„ Ú©Û’ ساتھ اسٹائل کیا جاتا ÛÛ’ % Ú©Û’ s → جیسا Ú©Û Ù…Ùت ورژن میں آپ صر٠ایک Ùارم Ú©Ùˆ ایک بار میں سٹائل کر سکتے Ûیں اور اگر آپ Ù…ÙˆØ¬ÙˆØ¯Û Ùارم Ú©Û’ لئے سٹائل Ú©Ùˆ Ùعال کرتے Ûیں تو سٹائل Ú©Ùˆ دوسرے Ùارم سے Ûٹا دیا جائے گا.CSS Ú©Û’ مترادÙاتCSS Ú©ÙˆÚˆ کا استعمال کریںڈھونڈناڈÙالٹ سسٹمتصویر Ú©Ùˆ Ûٹا دیںڈیسک ٹاپ دیکھیںتمام شکلوں Ú©Û’ لئے غیر Ùعال Ø³Ù¹Ø§Ø¦Ù„Ù…ÙˆØ¬ÙˆØ¯Û Ø´Ú©Ù„ Ú©Û’ لئے غیر Ùعال سٹائلکیا آپ Ù…Ùت Ú©Û’ لئے Styler پریمیوم ورژن حاصل کرنا چاÛتے Ûیں؟ اور پھر آپ Ú©Û’ Wp2Leads پرو لائسنس میں داخل کریں یا لائسنس حاصل کریں ÛŒÛاں ÛŒÛاں ÛÛ’ !کیا آپ صÙحات Ú©Ùˆ Ú†Ú¾ÙˆÚ‘Ù†Û’ سے Ù¾ÛÙ„Û’ تبدیلیوں Ú©Ùˆ محÙوظ کرنا چاÛتے Ûیں؟ڈوٹنگدوÛرادوسری ستون میں دوگنا Ùارمغلطیمکمل اسکرین سے باÛر نکلناÙینٹ خاندانÙونٹ سائزÙونٹ سٹائلوزن کا چمچشکل BG تصویر اور رنگشکل Ú©ÛŒ تصدیقÙارم پڈنگ، مارجن اور سرحدÙارم متنÙورم منتخب Ù†Ûیں کیا گیاپورے اسکرینزراعتاÙÙ‚ÛŒ لمبائیHover BG رنگÛاؤس رنگHover متن کا رنگآپ Ú©Û’ رابطے Ùارم 7 Ú©Ùˆ تبدیل کرنے Ú©Û’ لئے کس طرح ایک تبدیل کرنے اور استعمال کرنے Ú©Û’ لئے آسان اور پرو سٹائل رابطے Ùارم، "سائن اپ" پاؤڈر جنریٹر یا ایک آنکھ Ù¾Ú©Ú‘Ù†Û’ Ùارممیں اس سے خوش ÛÙˆÚº! بچاؤاگر آپ صÙحات Ú©ÛŒ تعمیر کرنے والے استعمال کر رÛÛ’ Ûیں، جیسے Ùریم آرکیٹیکٹ، Optimizepress وغیرÛØŒ Ø¨Ø±Ø§Û Ù…Ûربانی Ûماری چیک کریں علم Ú©ÛŒ بنیاد پر صÙØ­Û Ù…Ù…Ú©Ù†Û Ù…Ø³Ø§Ø¦Ù„ Ú©Ùˆ حل کرنے Ú©Û’ لئےاگر آپ Ú©Û’ اندر اندر سٹائل ڈیزائن لوڈ کرنے Ú©ÛŒ ضرورت ÛÛ’ صر٠کچھ صÙحات پر ٹیگ کریں، آپ "Cf7 Styler" بٹن کا استعمال کرتے Ûوئے frontend پر کر سکتے Ûیں. ÛŒÛ Ø®ØµÙˆØµÛŒØª صر٠ایک پوسٹ قسم Ú©Û’ لئے دستیاب ÛÛ’ (صÙحات، پوسٹس، مصنوعات وغیرÛ) اس Ú©Û’ علاوÛØŒ پرمیوم ورژن میں. آپ اس آرکائیو صÙحات پر Ù†Ûیں کر سکتے Ûیں (بلاگ، مصنوعات Ú©ÛŒ ÙÛرست وغیرÛ) اس صورت میں آپ Ú©Ùˆ عالمی ترتیبات کا استعمال کرنے Ú©ÛŒ ضرورت ÛÛ’.اگر آپ Ú©Û’ اندر اندر سٹائل ڈیزائن لوڈ کرنے Ú©ÛŒ ضرورت ÛÛ’ صر٠کچھ صÙحات پر ٹیگ کریں، آپ "Cf7 Styler" بٹن کا استعمال کرتے Ûوئے frontend پر کر سکتے Ûیں. ÛŒÛ Ø®ØµÙˆØµÛŒØª صر٠ایک پوسٹ قسم (صÙحات، پوسٹس، مصنوعات وغیرÛ) Ú©Û’ لئے دستیاب ÛÛ’. آپ اس آرکائیو صÙحات پر Ù†Ûیں کر سکتے Ûیں (بلاگ، مصنوعات Ú©ÛŒ ÙÛرست وغیرÛ) اس صورت میں آپ Ú©Ùˆ عالمی ترتیبات کا استعمال کرنے Ú©ÛŒ ضرورت ÛÛ’.تصویر Ú©Û’ مترادÙات Opacityتصویر Ú©ÛŒ پوزیشنتصویر Ú©ÛŒ سائزتصویر Ú©Û’ پس منظر Ú©ÛŒ ترتیبات ØµØ±Ù Ù¾ÛŒØ´Û ÙˆØ±Ø§Ù†Û ÙˆØ±Ú˜Ù† Ú©Û’ لئے لائیو موڈ میں دستیاب Ûیں. آپ اسے "ابھی Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„" موڈ میں ٹیسٹ کر سکتے Ûیں، لیکن ÛŒÛ Ù…Ø­Ùوظ Ù†Ûیں کیا جائے گا.Ù…ÛŒØ±Ø§Ø«Ø¯Ø§Ø®Ù„Û Ú©Û’ میدانانٹرویو سٹائل سکرپٹانسٹاایتالیائیٹیگ Ú©Û’ رنگٹیگ کیا گیا ÛÛ’ Font SizeLabels ترتیباتلائسنسلائن Ú©ÛŒ اونچائیبائیں رنگÛاؤس Ûاؤس رنگچپ رÛÙ†Û’ کا نظاملائیوپرنٹ سٹائل میں Tag کےانٹرویو سٹائل Ø¯Ø§Ø®Ù„Û Tag اس صÙØ­Û’ پرچیک باکس اشیاء Ú©Ùˆ ایک لائن پر بنائیںمکمل طور پر پھیلاؤ Ûے؟انٹرویو Ùیلڈ مکمل وسیع بنائیں؟Radiobutton اشیاء Ú©Ùˆ ایک لائن پر بنائیںمارکیٹموبائل دیکھیںنÛیں Ù†Ûیںکوئی Ø±Ø§Ø¨Ø·Û Ùارم 7 اشیاء Ú©Û’ لئے پیش نظارÛکوئی Ùارم اسٹائل ڈیزائن Ú©Û’ ساتھ سٹائل Ù†Ûیں ÛÛ’ØŒ اس Ùارم Ú©Û’ لئے Ù…ÙˆØ¬ÙˆØ¯Û ÚˆÛŒØ²Ø§Ø¦Ù† Ú©Ùˆ لاگو کرنے Ú©Û’ لئے "آج Ú©Û’ Ùارم Ú©Û’ لئے سٹائل Ùعال کریں" بٹن پر Ú©Ù„Ú© کریں.کوئی پلگ ان منتخب Ù†Ûیں کیا گیا انسٹال کرنے Ú©Û’ لئےکوئی Ù†Ù…ÙˆÙ†Û Ù…Ù†ØªØ®Ø¨ Ù†Ûیں کیا گیامعمولیبلیکچیک باکس اور ریڈیو بٹونز Ú©Û’ لئے ایک لائن سٹائل لائیو موڈ میں ØµØ±Ù Ù¾ÛŒØ´Û ÙˆØ± ÙˆØ±Ø§Ù†Û ÙˆØ±Ú˜Ù† Ú©Û’ لئے. آپ اسے "ابھی Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„" موڈ میں ٹیسٹ کر سکتے Ûیں، لیکن ÛŒÛ Ù…Ø­Ùوظ Ù†Ûیں کیا جائے گا.ناخوشگوارکھولیں سٹائلاکاؤنٹ دیکھنے Ú©Û’ لئے opt-inاصل سائزآؤٹ لائنباÛر Ù†Ú©Ù„Ù†Ø§Ù¾ÚˆÙ†Ú¯Ø¨Ø±Ø§Û Ù…Ûربانی داخل کریں سٹائل سکرپٹ عنوانپیشگوئیغیر معمولی پیش نظرپیشگوئی کا طریقÛریڈیودو بار تکرار کریںاÙÙ‚ÛŒ طور پر تکرار کریںورٹیکاٹ Ú©ÛŒ ØªÚ©Ø±Ø§Ø±Ø¯ÙˆØ¨Ø§Ø±Û ÚˆØ§Ø¤Ù† لوڈ کریں defaultریڈنگبچاؤبچاؤدوسری سٹائل کا منظراس Ùارم Ú©Û’ لئے سٹائل سکرپٹ کا انتخاب کریںترتیباتترتیبات Ú©Ùˆ محÙوظ کریں Ø¬ÛŒØ³Û’Ø³Ø§ÛŒÛ ÛÛ’Ø³Ø§ÛŒÛ Ú©Ø§ Ø±Ù†Ú¯Ø³Ø§ÛŒÛ Ú©ÛŒ پوزیشنمضبوطیکچھ موضوعات یا صÙØ­Û Ø¨Ù†Ø§Ù†Û’ والے (Fe. ٹریو آرکیٹیکٹ، Optimizepress ÙˆØºÛŒØ±Û Ø§Ù†Ù¹Ø±ÙˆÛŒÙˆ سٹائل Ú©Ùˆ داخل کر سکتے Ûیں ٹیگ کریں لوڈنگ سٹائل Ú©Û’ نظام Ú©Û’ اندر اندر ٹیگ اس مسئلے Ú©Ùˆ درست کرے گا اور آپ Ú©Û’ Ùارم سٹائل دکھائیں Ú¯Û’.تقسیم کا طریقÛتقسیم نظرراجکماریشروع کرنے Ú©Û’ لئے سٹائلڈیÙالٹ سٹائل سکرپٹ Ú©ÛŒ تخلیق سے شروع کریںآپ Ú©ÛŒ تخلیق Ú©Û’ ساتھ شروع سب سے Ù¾ÛÙ„Û’ Ø±Ø§Ø¨Ø·Û Ù†Ù…Ø¨Ø± 7 تمام Ù¾ÛŒØ´Û ÙˆØ±Ø§Ù†Û Ø®ØµÙˆØµÛŒØ§Øª Ú©Û’ ساتھ آپ Ú©Û’ 14 دن Ù…Ùت ٹیسٹ شروع کریں ÛŒÛاں ÛŒÛاں ÛÛ’ !Ù…Ø±Ø­Ù„Û 1 Ú©Ù„Ú© کریں "Edit with thrive architect" لنک میں ایڈمن صÙØ­Û ÙÛØ±Ø³ØªÙ…Ø±Ø­Ù„Û 2 "Settings" آیکون پر دائیں ورٹک مینو پر Ú©Ù„Ú© Ú©Ø±ÛŒÚºÙ…Ø±Ø­Ù„Û 3 "مزید ترتیبات" => "CSS میں سیکشن Â»Ù…Ø±Ø­Ù„Û 4 اس بات Ú©Ùˆ یقینی بنائیں Ú©Û "CSS سے نکالنے Ú©Û’ لئے Ù†Ûیں چیک کیا گیا ÛÛ’Ù…Ø±Ø­Ù„Û 5 "Save Work" Ú©Û’ بٹن پر Ú©Ù„Ú© کریںسٹائل تمام Ùارم ایک Ú©Ù„Ú© میں عالمی سطح پرسٹائل Ûر Ø´Ú©Ù„ Ú©Û’ ساتھ کسی بھی سٹائل ڈیزائن انÙرادی طور پرسٹائل سکرپٹ تمام شکلوں Ú©Û’ لئے غیر Ùعال Ûےاس Ø´Ú©Ù„ Ú©Û’ لئے سٹائل سکرپٹ غیر Ùعال Ûےاس Ùارم Ú©Û’ لئے سٹائل سکرپٹ Ú©ÛŒ اجازتنمونے کا انتخاب Ù†Ûیں کیا گیا Ûےسٹائل Ú©ÛŒ ÙÛرستسٹائل سکرپٹ پیش نظرسٹائل سٹائل سٹائلسٹائل میں شامل کیا جائے گا Tag کےسٹائل میں شامل کیا جائے گا Tag کےکامیابی Ú©Û’Ú©ÛŒ حمایت & KBٹیبلٹ ویڈیوزمتن کا رنگاس سٹائل Ú©Û’ نظام Ú©Ùˆ عالمی سطح پر تمام شکلوں Ú©Û’ لئے ممکن کیا گیا ÛÛ’. اگر آپ Ø±Ø§Ø¨Ø·Û Ùارم Ú©Û’ لئے آپ Ú©Û’ موضوع Ú©ÛŒ سٹائل کا استعمال کرنا چاÛتے Ûیں تو 7 Ú©Ù„Ú© کریں "غائب" بٹن.اس طرح Ú©Û’ طور پر اس طرح Ú©Û’ طور پر % Ú©Û’ s عالمی سطح پر، آپ اسے Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ Ú©Û’ ساتھ سٹائل کر سکتے Ûیں.اس طرح Ú©Û’ طور پر اس طرح Ú©Û’ طور پر % Ú©Û’ s , آپ اسے Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ Ú©Û’ ساتھ سٹائل کر سکتے Ûیں.ÛŒÛ Ùارم Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ Ú©Û’ ساتھ سٹائل کیا جاتا ÛÛ’ØŒ آپ اسے غیر Ùعال کر سکتے Ûیں اور عالمی ترتیبات کا استعمال کرسکتے Ûیں.ÛŒÛ Ùارم کسی بھی سٹائل ڈیزائن Ú©Û’ ساتھ سٹائل Ù†Ûیں ÛÛ’ØŒ آپ اس Ùارم Ú©Û’ لئے Ù…ÙˆØ¬ÙˆØ¯Û ÚˆÛŒØ²Ø§Ø¦Ù† Ú©Ùˆ Ùعال کر سکتے Ûیں یا "تمام Ùارم Ú©Û’ لئے استعمال کریں" پر Ú©Ù„Ú© کرکے عالمی سٹائل ڈیزائن Ú©Ùˆ ترتیب دے سکتے Ûیں.ÛŒÛ Ù†Ø¸Ø§Ù… موجود Ù†Ûیں Ûےٹوبیاس کانڈٹویٹرنگغیر معمولیپرو Ú©Û’ لئے اپ گریڈ کریںتصویر اپ لوڈ کریںورٹیکا طویلWOW سٹائل Ø±Ø§Ø¨Ø·Û Ùارم 7خوش آمدیدوسیعجی Ûاںآپ Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ Ú©ÛŒ ترتیبات Ú©Û’ ساتھ نئے سٹائل ڈیزائن بن سکتے Ûیں. اگر آپ Ù…Ù†Ø¯Ø±Ø¬Û Ø°ÛŒÙ„ میں سÙید سٹائل Schem Unchek Checkbox بنانا چاÛتے Ûیں.آپ Ú©Ùˆ حذ٠نÛیں کر سکتےآپ اس صÙØ­Û’ Ú©ÛŒ قسم پر اس ترتیب کا استعمال Ù†Ûیں کرسکتے Ûیںآپ Ú©Û’ پاس کوئی Ø±Ø§Ø¨Ø·Û Ùارم Ù†Ûیں ÛÛ’ 7 اشیاءآپ Ú©Ùˆ Ø±Ø§Ø¨Ø·Û Ùارم 7 Ú©Û’ لئے کسی بھی سٹائل ڈیزائن کا استعمال Ù†Ûیں کرتے Ûیں. Ú©Ù„Ú© کریں "تمام Ùارم Ú©Û’ لئے استعمال کریں" Ù…ÙˆØ¬ÙˆØ¯Û Ù†Ø¸Ø§Ù… Ú©Ùˆ عالمی سطح پر استعمال کرنے Ú©Û’ لئے.حذ٠کریںتمام اقسام Ú©Û’ لئے دستیاب↑ انگریزی ویکیپیڈیا Ú©Û’ مشارکین۔ //Saleswonder.BizHttps: //Saleswonder.Biz/Blog/4Free-Contact-Form-7-Cf7-Formular-Und-Klick-Tipp-Einfach-Verbinden/languages/cf7-styler-ur.po000064400000121151146725417150011512 0ustar00msgid "" msgstr "" "Language: ur\n" "POT-Creation-Date: 2023-04-15 15:26+0000\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "PO-Revision-Date: 2023-04-15 16:01+0000\n" "X-Generator: Loco https://localise.biz/\n" "Project-Id-Version: WOW Style Contact Form 7\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: Tobias support@saleswonder.biz\n" "Language-Team: Urdu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Loco-Version: 2.6.4; wp-6.1.2-alpha-55489" #: admin/class-cf7-customizer-admin.php:463 msgid "- disable style scheme -" msgstr "- غیر Ùعال سٹائل ڈیزائن -" #: includes/lib/Cf7_Template.php:68 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:463 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:517 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:672 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:789 msgid "- select -" msgstr "منتخب کریں -" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 msgid "14-days Trial" msgstr "14 دن Ú©ÛŒ سماعت" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:231 #, php-format msgid "" "%s used for all forms globally, click \"Use for all forms\" " "if you want to use current Scheme." msgstr "" "%s عالمی سطح پر تمام Ùارم Ú©Û’ لئے استعمال کیا جاتا ÛÛ’ØŒ اگر " "آپ Ù…ÙˆØ¬ÙˆØ¯Û Ù†Ø¸Ø§Ù… کا استعمال کرنا چاÛتے Ûیں تو \"تمام Ùارم Ú©Û’ لئے استعمال " "کریں\" پر Ú©Ù„Ú© کریں." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:242 msgid "Activate style for all forms*" msgstr "تمام شکلوں Ú©Û’ لئے سٹائل Ùعال کریں *" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1292 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1329 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1396 msgid "Activate style for current form" msgstr "Ù…ÙˆØ¬ÙˆØ¯Û Ø´Ú©Ù„ Ú©Û’ لئے سٹائل Ùعال کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:318 msgid "" "As an alternative you can disable clean out the styles like on Thrive " "architect:" msgstr "" "ایک متبادل Ú©Û’ طور پر آپ Ú©Ùˆ اس طرح Ú©Û’ سٹائل Ú©Ùˆ صا٠کرنے Ú©ÛŒ اجازت Ù†Ûیں دے سکتے " "Ûیں جیسا Ú©Û Ùریو آرکیٹیکٹ:" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:532 msgid "Background Color" msgstr "پس منظر کا رنگ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:560 msgid "Background Image" msgstr "تصویر Ú©Û’ پس منظر" #: admin/partials/cf7-customizer-admin-tab-required-plugin.php:9 msgid "" "Before using WOW Style Contact Form 7, you need to install and activate " "Contact Form 7 plugin." msgstr "" "Wow سٹائل Ø±Ø§Ø¨Ø·Û Ùارم 7 کا استعمال کرنے سے Ù¾ÛÙ„Û’ØŒ آپ Ú©Ùˆ انسٹال اور Ùعال کرنے " "Ú©ÛŒ ضرورت ÛÛ’ Ø±Ø§Ø¨Ø·Û Ùارم 7 پلگ ان." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:853 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1076 msgid "BG Color" msgstr "بی سی رنگ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:859 msgid "BG Opacity" msgstr "بی جے Ù¾ÛŒ Ú©Û’ متنازعÛ" #: includes/lib/Cf7_Template.php:43 msgid "Blur radius" msgstr "بلیو ریڈیو" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:943 msgid "Border" msgstr "سرحدیں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:807 msgid "Border Color" msgstr "سرحد کا رنگ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:802 msgid "Border Radius" msgstr "سرحد راجستÛ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:786 msgid "Border Type" msgstr "سرحدی اقسام" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:764 msgid "Border Width" msgstr "سرحد Ú©ÛŒ وسیع" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1102 msgid "Button Border" msgstr "بٹن Ú©ÛŒ سرحد" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1041 msgid "Buttons" msgstr "بٹنیں" #: includes/lib/Cf7_Required_Plugin.php:13 msgid "By Takayuki Miyoshi" msgstr "Ú©ÛŒ طر٠سے Takayuki Miyoshi" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:414 msgid "Cancel" msgstr "منسوخ" #: cf7-styler.php:129 #, php-format msgid "" "CF7 Customizer requires Contact Form 7 plugin to be installed and active. " "You can download %s." msgstr "" "Cf7 Customizer Ø±Ø§Ø¨Ø·Û Ùارم 7 پلگ ان Ú©Ùˆ انسٹال اور Ùعال کرنے Ú©ÛŒ ضرورت ÛÛ’. آپ " "Ú©Ùˆ % S ڈاؤن لوڈ کر سکتے Ûیں." #: admin/class-cf7-customizer-admin-ajax.php:487 msgid "CF7 Form is not selected" msgstr "Cf7 Ùارم منتخب Ù†Ûیں کیا گیا ÛÛ’" #: public/class-cf7-customizer-public.php:342 #: public/class-cf7-customizer-public.php:371 #: admin/class-cf7-customizer-admin.php:94 #: admin/class-cf7-customizer-admin.php:95 #: admin/class-cf7-customizer-admin.php:115 #: admin/class-cf7-customizer-admin.php:116 #: admin/class-cf7-customizer-admin.php:430 msgid "CF7 Styler" msgstr "Cf7 سٹائلر" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:986 msgid "Checkboxes & Radiobuttons" msgstr "چیک باکس اور ریڈیو بٹن" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:378 msgid "Clean Styles" msgstr "صا٠سٹائل" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1144 msgid "Clear" msgstr "واضح ÛÛ’" #: public/class-cf7-customizer-public.php:360 msgid "Close" msgstr "قریب ÛÛ’" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:973 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1116 msgid "Color" msgstr "رنگیں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1187 msgid "Contact form 7 list" msgstr "ÙÛرست نمبر 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:675 msgid "Contain" msgstr "شامل کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:410 msgid "Copy current style scheme settings" msgstr "Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ سکرپٹ Ú©ÛŒ ترتیبات کاپی کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:674 msgid "Cover" msgstr "کوریج" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:413 msgid "Create" msgstr "تخلیق" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:293 msgid "Create multiple style schemes" msgstr "کثیر سٹائل سکرپٹ بنائیں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:370 msgid "Create new style scheme!" msgstr "ایک نئے سٹائل ڈیزائن بنائیں!" #: admin/partials/cf7-customizer-admin-preview-mode.php:6 msgid "Current Style" msgstr "Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1381 #, php-format msgid "" "Currently %s form is " "styled with %s. As " "in free version you can style only one form at a time and if you activate " "style for current form, style will be removed from other form." msgstr "" "ÙÛŒ الحال % Ú©Û’ s Ø´Ú©Ù„ Ú©Û’ " "ساتھ اسٹائل کیا جاتا ÛÛ’ % " "Ú©Û’ s → جیسا Ú©Û Ù…Ùت ورژن میں آپ صر٠ایک Ùارم Ú©Ùˆ ایک بار میں سٹائل کر " "سکتے Ûیں اور اگر آپ Ù…ÙˆØ¬ÙˆØ¯Û Ùارم Ú©Û’ لئے سٹائل Ú©Ùˆ Ùعال کرتے Ûیں تو سٹائل Ú©Ùˆ " "دوسرے Ùارم سے Ûٹا دیا جائے گا." #: admin/class-cf7-customizer-admin.php:481 #, php-format msgid "" "Currently %s form is styled with %s. As in " "free version you can style only one form at a time and if you activate style " "for current form, style will be removed from other form." msgstr "" "ÙÛŒ الحال % Ú©Û’ s Ø´Ú©Ù„ Ú©Û’ ساتھ اسٹائل کیا جاتا ÛÛ’ % Ú©Û’ " "s → جیسا Ú©Û Ù…Ùت ورژن میں آپ صر٠ایک Ùارم Ú©Ùˆ ایک بار میں سٹائل کر " "سکتے Ûیں اور اگر آپ Ù…ÙˆØ¬ÙˆØ¯Û Ùارم Ú©Û’ لئے سٹائل Ú©Ùˆ Ùعال کرتے Ûیں تو سٹائل Ú©Ùˆ " "دوسرے Ùارم سے Ûٹا دیا جائے گا." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1134 msgid "Custom CSS" msgstr "CSS Ú©Û’ مترادÙات" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1136 msgid "Custom CSS Code" msgstr "CSS Ú©ÙˆÚˆ کا استعمال کریں" #: includes/lib/Cf7_Template.php:80 msgid "Dashed" msgstr "ڈھونڈنا" #: admin/class-cf7-customizer-admin-ajax.php:66 #: admin/class-cf7-customizer-admin-ajax.php:237 #: includes/lib/Cf7_Style_Scheme.php:7 msgid "Default Scheme" msgstr "ÚˆÙالٹ سسٹم" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:580 msgid "Delete Image" msgstr "تصویر Ú©Ùˆ Ûٹا دیں" #: admin/class-cf7-customizer-admin-ajax.php:286 msgid "deleted" msgstr "حذ٠کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1168 msgid "Desktop View" msgstr "ڈیسک ٹاپ دیکھیں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:258 msgid "Disable style for all forms" msgstr "تمام شکلوں Ú©Û’ لئے غیر Ùعال سٹائل" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1296 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1333 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1400 msgid "Disable style for current form" msgstr "Ù…ÙˆØ¬ÙˆØ¯Û Ø´Ú©Ù„ Ú©Û’ لئے غیر Ùعال سٹائل" #: admin/partials/cf7-customizer-admin-display.php:41 msgid "" "Do you like to get styler premium version for free? Then Enter your WP2LEADS pro " "license or get a license here!" msgstr "" "کیا آپ Ù…Ùت Ú©Û’ لئے Styler پریمیوم ورژن حاصل کرنا چاÛتے Ûیں؟ اور پھر آپ Ú©Û’ Wp2Leads پرو " "لائسنس میں داخل کریں یا لائسنس حاصل کریں ÛŒÛاں ÛŒÛاں " "ÛÛ’ !" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:184 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:303 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Do you want to save changes before leaving page?" msgstr "کیا آپ صÙحات Ú©Ùˆ Ú†Ú¾ÙˆÚ‘Ù†Û’ سے Ù¾ÛÙ„Û’ تبدیلیوں Ú©Ùˆ محÙوظ کرنا چاÛتے Ûیں؟" #: includes/lib/Cf7_Template.php:79 msgid "Dotted" msgstr "ڈوٹنگ" #: includes/lib/Cf7_Template.php:81 msgid "Double" msgstr "دوÛرا" #: admin/partials/cf7-customizer-admin-preview-mode.php:32 msgid "Duplicate form in second column" msgstr "دوسری ستون میں دوگنا Ùارم" #: admin/class-cf7-customizer-admin-ajax.php:396 msgid "enabled for all forms" msgstr "تمام اقسام Ú©Û’ لئے دستیاب" #: public/class-cf7-customizer-public.php:471 #: admin/class-cf7-customizer-admin-ajax.php:133 #: admin/class-cf7-customizer-admin-ajax.php:230 #: admin/class-cf7-customizer-admin-ajax.php:237 #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:434 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 #: admin/class-cf7-customizer-admin-ajax.php:487 #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "Error" msgstr "غلطی" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:149 msgid "Exit Full Screen" msgstr "مکمل اسکرین سے باÛر نکلنا" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:461 msgid "Font Family" msgstr "Ùینٹ خاندان" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:455 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:834 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1090 msgid "Font Size" msgstr "Ùونٹ سائز" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:514 msgid "Font Style" msgstr "Ùونٹ سٹائل" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:509 msgid "Font Weight" msgstr "وزن کا Ú†Ù…Ú†" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:530 msgid "Form BG Image & Colors" msgstr "Ø´Ú©Ù„ BG تصویر اور رنگ" #: admin/partials/cf7-customizer-admin-tabs.php:16 msgid "Form Customizing" msgstr "Ø´Ú©Ù„ Ú©ÛŒ تصدیق" #: admin/class-cf7-customizer-admin-ajax.php:415 #: admin/class-cf7-customizer-admin-ajax.php:443 #: admin/class-cf7-customizer-admin-ajax.php:469 msgid "Form is not selected" msgstr "Ùورم منتخب Ù†Ûیں کیا گیا" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:689 msgid "Form Padding, Margin & Border" msgstr "Ùارم پڈنگ، مارجن اور سرحد" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:446 msgid "Form Text" msgstr "Ùارم متن" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:148 msgid "Full Screen" msgstr "پورے اسکرین" #: includes/lib/Cf7_Template.php:82 msgid "Groove" msgstr "زراعت" #: includes/lib/Cf7_Template.php:31 msgid "Horizontal Length" msgstr "اÙÙ‚ÛŒ لمبائی" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1081 msgid "Hover BG Color" msgstr "Hover BG رنگ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1121 msgid "Hover Color" msgstr "Ûاؤس رنگ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1069 msgid "Hover Text Color" msgstr "Hover متن کا رنگ" #. Description of the plugin msgid "" "How to turn your contact form7 form into a converting and easy to use and " "pro styled contact form, \"survey\" lead generator or an eye catching form" msgstr "" "آپ Ú©Û’ رابطے Ùارم 7 Ú©Ùˆ تبدیل کرنے Ú©Û’ لئے کس طرح ایک تبدیل کرنے اور استعمال " "کرنے Ú©Û’ لئے آسان اور پرو سٹائل رابطے Ùارم، \"سائن اپ\" پاؤڈر جنریٹر یا ایک " "آنکھ Ù¾Ú©Ú‘Ù†Û’ Ùارم" #. Author URI of the plugin msgid "https://saleswonder.biz" msgstr "↑ انگریزی ویکیپیڈیا Ú©Û’ مشارکین۔ //Saleswonder.Biz" #. URI of the plugin msgid "" "https://saleswonder.biz/blog/4free-contact-form-7-cf7-formular-und-klick-" "tipp-einfach-verbinden/" msgstr "" "Https: //Saleswonder.Biz/Blog/4Free-Contact-Form-7-Cf7-Formular-Und-Klick-" "Tipp-Einfach-Verbinden/" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:352 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:360 msgid "I'm happy with this! Save" msgstr "میں اس سے خوش ÛÙˆÚº! بچاؤ" #: admin/partials/cf7-customizer-admin-display.php:31 msgid "" "If you are using page builders, like Thrive Architect, OptimizePress etc., " "please check our Knowledge Base page for fixing possible issues" msgstr "" "اگر آپ صÙحات Ú©ÛŒ تعمیر کرنے والے استعمال کر رÛÛ’ Ûیں، جیسے Ùریم آرکیٹیکٹ، " "Optimizepress وغیرÛØŒ Ø¨Ø±Ø§Û Ù…Ûربانی Ûماری چیک کریں علم Ú©ÛŒ بنیاد پر صÙØ­Û " "Ù…Ù…Ú©Ù†Û Ù…Ø³Ø§Ø¦Ù„ Ú©Ùˆ حل کرنے Ú©Û’ لئے" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:275 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." ") and in premium version. You can not do it on archives pages (blog, " "products list etc) in this case you need to use global settings." msgstr "" "اگر آپ Ú©Û’ اندر اندر سٹائل ڈیزائن لوڈ کرنے Ú©ÛŒ ضرورت ÛÛ’ صر٠" "Ú©Ú†Ú¾ صÙحات پر ٹیگ کریں، آپ \"Cf7 Styler\" بٹن کا استعمال کرتے Ûوئے frontend " "پر کر سکتے Ûیں. ÛŒÛ Ø®ØµÙˆØµÛŒØª صر٠ایک پوسٹ قسم Ú©Û’ لئے دستیاب ÛÛ’ (صÙحات، پوسٹس، " "مصنوعات وغیرÛ) اس Ú©Û’ علاوÛØŒ پرمیوم ورژن میں. آپ اس آرکائیو صÙحات پر Ù†Ûیں کر " "سکتے Ûیں (بلاگ، مصنوعات Ú©ÛŒ ÙÛرست وغیرÛ) اس صورت میں آپ Ú©Ùˆ عالمی ترتیبات کا " "استعمال کرنے Ú©ÛŒ ضرورت ÛÛ’." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:314 msgid "" "If you need to load style scheme inside <body> tag only " "on some pages, you can do it on frontend using \"CF7 Styler\" button. This " "function is only available for single post types (pages, posts, products etc." "). You can not do it on archives pages (blog, products list etc) in this " "case you need to use global settings." msgstr "" "اگر آپ Ú©Û’ اندر اندر سٹائل ڈیزائن لوڈ کرنے Ú©ÛŒ ضرورت ÛÛ’ صر٠" "Ú©Ú†Ú¾ صÙحات پر ٹیگ کریں، آپ \"Cf7 Styler\" بٹن کا استعمال کرتے Ûوئے frontend " "پر کر سکتے Ûیں. ÛŒÛ Ø®ØµÙˆØµÛŒØª صر٠ایک پوسٹ قسم (صÙحات، پوسٹس، مصنوعات وغیرÛ) Ú©Û’ " "لئے دستیاب ÛÛ’. آپ اس آرکائیو صÙحات پر Ù†Ûیں کر سکتے Ûیں (بلاگ، مصنوعات Ú©ÛŒ " "ÙÛرست وغیرÛ) اس صورت میں آپ Ú©Ùˆ عالمی ترتیبات کا استعمال کرنے Ú©ÛŒ ضرورت ÛÛ’." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:547 msgid "" "Image background settings available in live mode only for Professional " "version. You can test it in preview mode \"current style\", but it will not " "be saved." msgstr "" "تصویر Ú©Û’ پس منظر Ú©ÛŒ ترتیبات ØµØ±Ù Ù¾ÛŒØ´Û ÙˆØ±Ø§Ù†Û ÙˆØ±Ú˜Ù† Ú©Û’ لئے لائیو موڈ میں دستیاب " "Ûیں. آپ اسے \"ابھی Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„\" موڈ میں ٹیسٹ کر سکتے Ûیں، لیکن ÛŒÛ Ù…Ø­Ùوظ " "Ù†Ûیں کیا جائے گا." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:663 msgid "Image Opacity" msgstr "تصویر Ú©Û’ مترادÙات Opacity" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:586 msgid "Image Position" msgstr "تصویر Ú©ÛŒ پوزیشن" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:670 msgid "Image Size" msgstr "تصویر Ú©ÛŒ سائز" #: includes/lib/Cf7_Template.php:77 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:521 msgid "Inherit" msgstr "میراث" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:820 msgid "Input Fields" msgstr "Ø¯Ø§Ø®Ù„Û Ú©Û’ میدان" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:402 msgid "Input style scheme title" msgstr "انٹرویو سٹائل سکرپٹ" #: includes/lib/Cf7_Template.php:70 includes/lib/Cf7_Template.php:84 msgid "Inset" msgstr "انسٹا" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:519 msgid "Italic" msgstr "ایتالیائی" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:497 msgid "Labels Color" msgstr "ٹیگ Ú©Û’ رنگ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:502 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1032 msgid "Labels Font Size" msgstr "ٹیگ کیا گیا ÛÛ’ Font Size" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:492 msgid "Labels Settings" msgstr "Labels ترتیبات" #: admin/partials/cf7-customizer-admin-tabs.php:18 msgid "License" msgstr "لائسنس" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:839 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1095 msgid "Line Height" msgstr "لائن Ú©ÛŒ اونچائی" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:480 msgid "Links Color" msgstr "بائیں رنگ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:485 msgid "Links Hover Color" msgstr "Ûاؤس Ûاؤس رنگ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:476 msgid "Links Settings" msgstr "Ú†Ù¾ رÛÙ†Û’ کا نظام" #: admin/partials/cf7-customizer-admin-preview-mode.php:7 #: admin/partials/cf7-customizer-admin-preview-mode.php:19 msgid "Live" msgstr "لائیو" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:265 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:299 msgid "Load styles in <body> tag" msgstr "پرنٹ سٹائل میں Tag Ú©Û’" #: public/class-cf7-customizer-public.php:348 msgid "Load styles inside <body> tag on this page" msgstr "انٹرویو سٹائل Ø¯Ø§Ø®Ù„Û Tag اس صÙØ­Û’ پر" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1009 msgid "Make checkbox item one per line" msgstr "چیک باکس اشیاء Ú©Ùˆ ایک لائن پر بنائیں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1045 msgid "Make full width?" msgstr "مکمل طور پر پھیلاؤ ÛÛ’ØŸ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:822 msgid "Make input fields full width?" msgstr "انٹرویو Ùیلڈ مکمل وسیع بنائیں؟" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1019 msgid "Make radiobutton item one per line" msgstr "Radiobutton اشیاء Ú©Ùˆ ایک لائن پر بنائیں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:733 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:912 msgid "Margin" msgstr "مارکیٹ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1170 msgid "Mobile View" msgstr "موبائل دیکھیں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:828 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1015 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1025 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1051 msgid "NO" msgstr "Ù†Ûیں Ù†Ûیں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1450 msgid "No Contact Form 7 items for preview" msgstr "کوئی Ø±Ø§Ø¨Ø·Û Ùارم 7 اشیاء Ú©Û’ لئے پیش نظارÛ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1387 msgid "" "No form is styled with style scheme, click \"Activate style for current " "form\" button to apply current scheme for this form." msgstr "" "کوئی Ùارم اسٹائل ڈیزائن Ú©Û’ ساتھ سٹائل Ù†Ûیں ÛÛ’ØŒ اس Ùارم Ú©Û’ لئے Ù…ÙˆØ¬ÙˆØ¯Û ÚˆÛŒØ²Ø§Ø¦Ù† " "Ú©Ùˆ لاگو کرنے Ú©Û’ لئے \"آج Ú©Û’ Ùارم Ú©Û’ لئے سٹائل Ùعال کریں\" بٹن پر Ú©Ù„Ú© کریں." #: admin/class-cf7-customizer-admin-ajax.php:517 msgid "No plugin selected to install" msgstr "کوئی پلگ ان منتخب Ù†Ûیں کیا گیا انسٹال کرنے Ú©Û’ لئے" #: admin/class-cf7-customizer-admin-ajax.php:230 msgid "No style scheme selected" msgstr "کوئی Ù†Ù…ÙˆÙ†Û Ù…Ù†ØªØ®Ø¨ Ù†Ûیں کیا گیا" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:518 msgid "Normal" msgstr "معمولی" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:520 msgid "Oblique" msgstr "بلیک" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:995 msgid "" "One per line styles for checkboxes and radiobuttons in live mode only for " "Professional version. You can test it in preview mode \"current style\", but " "it will not be saved." msgstr "" "چیک باکس اور ریڈیو بٹونز Ú©Û’ لئے ایک لائن سٹائل لائیو موڈ میں ØµØ±Ù Ù¾ÛŒØ´Û ÙˆØ± " "ÙˆØ±Ø§Ù†Û ÙˆØ±Ú˜Ù† Ú©Û’ لئے. آپ اسے \"ابھی Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„\" موڈ میں ٹیسٹ کر سکتے Ûیں، " "لیکن ÛŒÛ Ù…Ø­Ùوظ Ù†Ûیں کیا جائے گا." #: includes/lib/Cf7_Template.php:61 msgid "Opacity" msgstr "ناخوشگوار" #: public/class-cf7-customizer-public.php:375 #: public/class-cf7-customizer-public.php:389 #: admin/class-cf7-customizer-admin.php:488 msgid "Open styler" msgstr "کھولیں سٹائل" #: admin/class-cf7-customizer-admin.php:527 msgid "Opt-in to see account" msgstr "اکاؤنٹ دیکھنے Ú©Û’ لئے opt-in" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:673 msgid "Original size" msgstr "اصل سائز" #: includes/lib/Cf7_Template.php:69 msgid "Outline" msgstr "آؤٹ لائن" #: includes/lib/Cf7_Template.php:85 msgid "Outset" msgstr "باÛر نکلنا" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:702 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:881 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1055 msgid "Padding" msgstr "Ù¾ÚˆÙ†Ú¯" #: admin/class-cf7-customizer-admin-ajax.php:133 msgid "Please input style scheme title" msgstr "Ø¨Ø±Ø§Û Ù…Ûربانی داخل کریں سٹائل سکرپٹ عنوان" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1140 msgid "Preview" msgstr "پیشگوئی" #: admin/partials/cf7-customizer-admin-preview-mode.php:2 msgid "Preview mode" msgstr "پیشگوئی کا طریقÛ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1343 msgid "Preview Unstyled" msgstr "غیر معمولی پیش نظر" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:968 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1110 msgid "Radius" msgstr "ریڈیو" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:678 msgid "Repeat both" msgstr "دو بار تکرار کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:677 msgid "Repeat horizontal" msgstr "اÙÙ‚ÛŒ طور پر تکرار کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:676 msgid "Repeat vertical" msgstr "ورٹیکاٹ Ú©ÛŒ تکرار" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:383 msgid "Reset to default" msgstr "Ø¯ÙˆØ¨Ø§Ø±Û ÚˆØ§Ø¤Ù† لوڈ کریں default" #: includes/lib/Cf7_Template.php:83 msgid "Ridge" msgstr "ریڈنگ" #: public/class-cf7-customizer-public.php:354 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:361 msgid "Save" msgstr "بچاؤ" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 msgid "Saved" msgstr "بچاؤ" #: admin/partials/cf7-customizer-admin-preview-mode.php:17 msgid "Second column view" msgstr "دوسری سٹائل کا منظر" #: admin/class-cf7-customizer-admin.php:459 msgid "Select style scheme for this form" msgstr "اس Ùارم Ú©Û’ لئے سٹائل سکرپٹ کا انتخاب کریں" #: admin/partials/cf7-customizer-admin-tabs.php:17 msgid "Settings" msgstr "ترتیبات" #: admin/class-cf7-customizer-admin-ajax.php:210 msgid "Settings saved as " msgstr "ترتیبات Ú©Ùˆ محÙوظ کریں جیسے" #: includes/lib/Cf7_Template.php:27 msgid "Shadow" msgstr "Ø³Ø§ÛŒÛ ÛÛ’" #: includes/lib/Cf7_Template.php:56 msgid "Shadow Color" msgstr "Ø³Ø§ÛŒÛ Ú©Ø§ رنگ" #: includes/lib/Cf7_Template.php:66 msgid "Shadow Position" msgstr "Ø³Ø§ÛŒÛ Ú©ÛŒ پوزیشن" #: includes/lib/Cf7_Template.php:78 msgid "Solid" msgstr "مضبوطی" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:271 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:310 msgid "" "Some themes or page builders (fe. Thrive Architect, OptimizePress etc.) " "could remove inline styles inside <head> tag. Loading " "style scheme within <body> tag will fix this issue and " "show your forms styled." msgstr "" "Ú©Ú†Ú¾ موضوعات یا صÙØ­Û Ø¨Ù†Ø§Ù†Û’ والے (Fe. ٹریو آرکیٹیکٹ، Optimizepress ÙˆØºÛŒØ±Û " "انٹرویو سٹائل Ú©Ùˆ داخل کر سکتے Ûیں ٹیگ کریں لوڈنگ سٹائل Ú©Û’ " "نظام Ú©Û’ اندر اندر ٹیگ اس مسئلے Ú©Ùˆ درست کرے گا اور آپ Ú©Û’ " "Ùارم سٹائل دکھائیں Ú¯Û’." #: admin/partials/cf7-customizer-admin-preview-mode.php:5 msgid "Split mode" msgstr "تقسیم کا طریقÛ" #: admin/partials/cf7-customizer-admin-preview-mode.php:12 msgid "Split view" msgstr "تقسیم نظر" #: includes/lib/Cf7_Template.php:48 msgid "Spread radius" msgstr "راجکماری" #: admin/partials/cf7-customizer-admin-tutorial.php:49 msgid "Start styling" msgstr "شروع کرنے Ú©Û’ لئے سٹائل" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:337 msgid "Start with creating Default Style Scheme" msgstr "ÚˆÛŒÙالٹ سٹائل سکرپٹ Ú©ÛŒ تخلیق سے شروع کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1413 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1454 msgid "" "Start with creating your first Contact " "Form 7" msgstr "" "آپ Ú©ÛŒ تخلیق Ú©Û’ ساتھ شروع سب سے Ù¾ÛÙ„Û’ " "Ø±Ø§Ø¨Ø·Û Ù†Ù…Ø¨Ø± 7 " #: admin/partials/cf7-customizer-admin-display.php:50 msgid "" "Start your 14-day free trial with all Professional functions here!" msgstr "" "تمام Ù¾ÛŒØ´Û ÙˆØ±Ø§Ù†Û Ø®ØµÙˆØµÛŒØ§Øª Ú©Û’ ساتھ آپ Ú©Û’ 14 دن Ù…Ùت ٹیسٹ شروع کریں ÛŒÛاں ÛŒÛاں ÛÛ’ !" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:320 msgid "Step 1. Click \"Edit with Thrive architect\" link in admin page list" msgstr "" "Ù…Ø±Ø­Ù„Û 1 Ú©Ù„Ú© کریں \"Edit with thrive architect\" لنک میں ایڈمن صÙØ­Û ÙÛرست" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:322 msgid "Step 2. Click \"Settings\" icon on right vertical menu" msgstr "Ù…Ø±Ø­Ù„Û 2 \"Settings\" آیکون پر دائیں ورٹک مینو پر Ú©Ù„Ú© کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:324 msgid "Step 3. \"Advanced settings\" => \"CSS in the <head> section\"" msgstr "Ù…Ø±Ø­Ù„Û 3 \"مزید ترتیبات\" => \"CSS میں سیکشن »" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:326 msgid "" "Step 4. Make sure that \"Do not strip CSS from <head>\" is checked" msgstr "" "Ù…Ø±Ø­Ù„Û 4 اس بات Ú©Ùˆ یقینی بنائیں Ú©Û \"CSS سے نکالنے Ú©Û’ لئے Ù†Ûیں چیک کیا " "گیا ÛÛ’" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:328 msgid "Step 5. Click \"SAVE WORK\" button" msgstr "Ù…Ø±Ø­Ù„Û 5 \"Save Work\" Ú©Û’ بٹن پر Ú©Ù„Ú© کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:290 msgid "Style all forms in one click globally" msgstr "سٹائل تمام Ùارم ایک Ú©Ù„Ú© میں عالمی سطح پر" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:296 msgid "Style each form with any style scheme individually" msgstr "سٹائل Ûر Ø´Ú©Ù„ Ú©Û’ ساتھ کسی بھی سٹائل ڈیزائن انÙرادی طور پر" #: admin/class-cf7-customizer-admin-ajax.php:405 msgid "Style scheme disabled for all forms" msgstr "سٹائل سکرپٹ تمام شکلوں Ú©Û’ لئے غیر Ùعال ÛÛ’" #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Style scheme disabled for this form" msgstr "اس Ø´Ú©Ù„ Ú©Û’ لئے سٹائل سکرپٹ غیر Ùعال ÛÛ’" #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 msgid "Style scheme enabled for this form" msgstr "اس Ùارم Ú©Û’ لئے سٹائل سکرپٹ Ú©ÛŒ اجازت" #: admin/class-cf7-customizer-admin-ajax.php:377 #: admin/class-cf7-customizer-admin-ajax.php:434 msgid "Style scheme is not selected" msgstr "نمونے کا انتخاب Ù†Ûیں کیا گیا ÛÛ’" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:180 msgid "Style schemes list" msgstr "سٹائل Ú©ÛŒ ÙÛرست" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1164 msgid "Style schemes preview" msgstr "سٹائل سکرپٹ پیش نظر" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:146 msgid "Style schemes settings" msgstr "سٹائل سٹائل سٹائل" #: admin/class-cf7-customizer-admin-ajax.php:298 msgid "Style will be loaded in tag" msgstr "سٹائل میں شامل کیا جائے گا Tag Ú©Û’" #: admin/class-cf7-customizer-admin-ajax.php:301 msgid "Style will be loaded in tag" msgstr "سٹائل میں شامل کیا جائے گا Tag Ú©Û’" #: public/class-cf7-customizer-public.php:483 #: admin/class-cf7-customizer-admin-ajax.php:119 #: admin/class-cf7-customizer-admin-ajax.php:210 #: admin/class-cf7-customizer-admin-ajax.php:286 #: admin/class-cf7-customizer-admin-ajax.php:304 #: admin/class-cf7-customizer-admin-ajax.php:386 #: admin/class-cf7-customizer-admin-ajax.php:396 #: admin/class-cf7-customizer-admin-ajax.php:405 #: admin/class-cf7-customizer-admin-ajax.php:423 #: admin/class-cf7-customizer-admin-ajax.php:459 #: admin/class-cf7-customizer-admin-ajax.php:477 msgid "Success" msgstr "کامیابی Ú©Û’" #: admin/class-cf7-customizer-admin.php:105 #: admin/class-cf7-customizer-admin.php:106 #: admin/class-cf7-customizer-admin.php:124 #: admin/class-cf7-customizer-admin.php:125 msgid "Support & KB" msgstr "Ú©ÛŒ حمایت & KB" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1169 msgid "Tablet View" msgstr "ٹیبلٹ ویڈیوز" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:450 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:848 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1064 msgid "Text Color" msgstr "متن کا رنگ" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1315 #, php-format msgid "" "This form is styled with %s globally, you can style it with " "current Style scheme." msgstr "" "اس طرح Ú©Û’ طور پر اس طرح Ú©Û’ طور پر % Ú©Û’ s عالمی سطح پر، آپ " "اسے Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ Ú©Û’ ساتھ سٹائل کر سکتے Ûیں." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1311 #, php-format msgid "" "This form is styled with %s, you can style it with current " "Style scheme." msgstr "" "اس طرح Ú©Û’ طور پر اس طرح Ú©Û’ طور پر % Ú©Û’ s , آپ اسے Ù…ÙˆØ¬ÙˆØ¯Û " "سٹائل Ú©Û’ ساتھ سٹائل کر سکتے Ûیں." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1307 msgid "" "This form is styled with current Style Scheme, you can disable it and use " "global settings." msgstr "" "ÛŒÛ Ùارم Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ Ú©Û’ ساتھ سٹائل کیا جاتا ÛÛ’ØŒ آپ اسے غیر Ùعال کر سکتے Ûیں " "اور عالمی ترتیبات کا استعمال کرسکتے Ûیں." #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1319 msgid "" "This form not styled with any Style scheme, you can enable current Scheme " "for this form or set up global Style Scheme by clicking \"Use for all " "forms\" below scheme title." msgstr "" "ÛŒÛ Ùارم کسی بھی سٹائل ڈیزائن Ú©Û’ ساتھ سٹائل Ù†Ûیں ÛÛ’ØŒ آپ اس Ùارم Ú©Û’ لئے Ù…ÙˆØ¬ÙˆØ¯Û " "ڈیزائن Ú©Ùˆ Ùعال کر سکتے Ûیں یا \"تمام Ùارم Ú©Û’ لئے استعمال کریں\" پر Ú©Ù„Ú© کرکے " "عالمی سٹائل ڈیزائن Ú©Ùˆ ترتیب دے سکتے Ûیں." #: admin/class-cf7-customizer-admin-ajax.php:386 msgid "This scheme is not existed" msgstr "ÛŒÛ Ù†Ø¸Ø§Ù… موجود Ù†Ûیں ÛÛ’" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:251 msgid "" "This Style Scheme enabled globally for all forms. If you want to use your " "theme's style for Contact Form 7 click \"Disable\" button." msgstr "" "اس سٹائل Ú©Û’ نظام Ú©Ùˆ عالمی سطح پر تمام شکلوں Ú©Û’ لئے ممکن کیا گیا ÛÛ’. اگر آپ " "Ø±Ø§Ø¨Ø·Û Ùارم Ú©Û’ لئے آپ Ú©Û’ موضوع Ú©ÛŒ سٹائل کا استعمال کرنا چاÛتے Ûیں تو 7 Ú©Ù„Ú© " "کریں \"غائب\" بٹن." #. Author of the plugin msgid "Tobias Conrad" msgstr "ٹوبیاس کانڈ" #: admin/partials/cf7-customizer-admin-tutorial.php:36 msgid "Tutorial" msgstr "ٹویٹرنگ" #: admin/partials/cf7-customizer-admin-preview-mode.php:8 #: admin/partials/cf7-customizer-admin-preview-mode.php:26 msgid "Unstyled" msgstr "غیر معمولی" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:302 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:551 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:999 msgid "Upgrade to Pro" msgstr "پرو Ú©Û’ لئے اپ گریڈ کریں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:576 msgid "Upload Image" msgstr "تصویر اپ لوڈ کریں" #: includes/lib/Cf7_Template.php:36 msgid "Vertical Length" msgstr "ورٹیکا طویل" #: admin/partials/cf7-customizer-admin-tutorial.php:34 msgid "Welcome" msgstr "خوش آمدید" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1105 msgid "Width" msgstr "وسیع" #. Name of the plugin #: cf7-styler.php:138 admin/partials/cf7-customizer-admin-display.php:22 msgid "WOW Style Contact Form 7" msgstr "WOW سٹائل Ø±Ø§Ø¨Ø·Û Ùارم 7" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:825 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1012 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1022 #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1048 msgid "YES" msgstr "جی Ûاں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:405 msgid "" "You can create new style scheme with current scheme settings. If you want to " "create blank style schem unchek checkbox below." msgstr "" "آپ Ù…ÙˆØ¬ÙˆØ¯Û Ø³Ù¹Ø§Ø¦Ù„ Ú©ÛŒ ترتیبات Ú©Û’ ساتھ نئے سٹائل ڈیزائن بن سکتے Ûیں. اگر آپ " "Ù…Ù†Ø¯Ø±Ø¬Û Ø°ÛŒÙ„ میں سÙید سٹائل Schem Unchek Checkbox بنانا چاÛتے Ûیں." #: admin/class-cf7-customizer-admin-ajax.php:237 msgid "You can not delete" msgstr "آپ Ú©Ùˆ حذ٠نÛیں کر سکتے" #: public/class-cf7-customizer-public.php:471 msgid "You can not use this settings on this page type" msgstr "آپ اس صÙØ­Û’ Ú©ÛŒ قسم پر اس ترتیب کا استعمال Ù†Ûیں کرسکتے Ûیں" #: admin/partials/cf7-customizer-admin-tab-form-customize.php:1411 msgid "You do not have any Contact Form 7 items" msgstr "آپ Ú©Û’ پاس کوئی Ø±Ø§Ø¨Ø·Û Ùارم Ù†Ûیں ÛÛ’ 7 اشیاء" #. No scheme enabled #: admin/partials/cf7-customizer-admin-tab-form-customize.php:233 msgid "" "You do not use any of Style Schemes for Contact Form 7. Click \"Use for all " "forms\" to use current Scheme globally." msgstr "" "آپ Ú©Ùˆ Ø±Ø§Ø¨Ø·Û Ùارم 7 Ú©Û’ لئے کسی بھی سٹائل ڈیزائن کا استعمال Ù†Ûیں کرتے Ûیں. Ú©Ù„Ú© " "کریں \"تمام Ùارم Ú©Û’ لئے استعمال کریں\" Ù…ÙˆØ¬ÙˆØ¯Û Ù†Ø¸Ø§Ù… Ú©Ùˆ عالمی سطح پر استعمال " "کرنے Ú©Û’ لئے." changelog.txt000064400000027752146725417150007265 0ustar00== Changelog == = 1.5.0 + 1.5.1 released 2023.04.15 = * Fix: Avoid fatal error when activate the plugin twice When upgrade free to Pro free gets deactivated. * Fix: Freemius SDK update fixes one error * Added/updated: Languages total: IT (Italian), VI (Vietnamese) HI (Hindi) ES-MX Spanish (Mexico) UR (Urdu) RU (Russian) PT-BR Portuguese (Brazil), DE German PO Polish ES Spanish (Spain) FRFrench (France) JA Japanese VI Vietnamese Thank you for your trust and great support by buying the Pro version = 1.4.9 released 2023.03.22 = = All update please = = FINAL FREEMIUS SDK UPDATE = * Fix: Fatal error: Uncaught Error: Call to undefined method Freemius_Api_WordPress::RemoteRequest() For details see: https://github.com/Freemius/wordpress-sdk/releases/tag/2.5.5 Background: Freemius handling opt-ins, licenses, analytics, affiliation, ... = 1.4.7 + 1.4.8 released 2023.03.17 = = Freemius SDK update = * Updated Freemius: for better handling of opt-in, license, analytics, affiliation, ... * Fix: Freemius activate the premium version when "Sorry, you are not allowed to access this page." shown. * improving connection * Stopp connection test on plugin activation * Create Affiliation inside the plugin is working again * Please join and earn % on new customer including renewals Successful, nicely styled and sustainable 2023 = 1.4.6 released 2023.02.12 = * Updated: Freemius SDK Benefits: Premium plugin user see now the changelog and other tabs from WP.org when upgrading. That avoid upgrading without seeing the changes ,-) * If you have issue activating your license because you do not the the account menu item. Please go to the WP main plugins menu search for "WOW styler" and click opt-in and confirm Then you see your account and if the mail address of account and bought license match also your license after click "sync" = 1.4.5 released 2023.01.28 = * Updated: Freemius SDK for nice free trial and license handling Please do not use CF7 5.7.0 which added space to your form. Please directly update to 5.7.1+ latest 5.7.3 https://contactform7.com/category/releases/ = 1.4.4 released 2022.09.18 = * Fixed: Access to style the form, if you fresh installed the plugin Thank you Christopher for telling me about the bug * Added: Knowledge base articles: Two columns forms, placeholder color, use theme style, ... Start and improve your forms by using the New Handbook & Knowledge Base articles! Please on the page select "T" or "NT" user to see the articles. = 1.4.3 released 2022.09.11 = * Added: Knowledge base & chat/ticket support inside the plugin * Added: Four knowledge base articles Start and improve your forms by using the New Handbook & Knowledge Base articles! Please on the page select "T" or "NT" user to see the articles. = 1.4.2 released 2022.02.24 = * Security fix: in one of our used libraries all update please! * More easy license and trial handling. Benefits: Trial for free is always the best start to have multiple forms each styled different with nice light background images ect. = 1.4.1 released 2021.03.09 = * Compatible with the latest CF7 and WP Version * Updated Freemius SDK which handles trial, paid versions and opt-in to exclusive email tutorials = 1.4.0 released 2020.12.04 = * updated to the latest freemius SDK for more security, privacy and usability * added menu item 'Opt-in to see account' if admin skip opt-in previously * feel free to request more features = 1.3.13 released 2019.08.25 = * Checked and WP 5.5 compatible * Thank you all very much for 1000 active installations * To thank you please handover your cf7 style needs and we will look what we can do ;-) = 1.3.12 released 2019.07.27 = * updated the tutorial page inside the plugin:
  • Tutorial content:
  • Simple style
  • Complex style
  • Style headings
  • Add image to form
  • Create 2 columns
Your benefits you can do more with your forms. = 1.3.11 released 2019.07.21 = * Contact form 7 style headings with the WOW Styler please watch the tutorial video and use the CSS code, both provided inside the tutorials page in the plugin = 1.3.10 released 2019.05.28 = * New and short videos and images inside the plugin in the tutorial section Your benefits easy and fast start = 1.3.9 released 2019.04.18 = * First step to more functionality * Updated all translations = 1.3.8 released 2019.04.07 = * Hand translated french, spanish and polish translation replace the machine translation. Thank you Marek from translation service http://www.lexpertise.eu/. For each translation he got an one site lifetime version in exchange. * This deal i do with every hand translated main language which is sent to support@saleswonder.biz. Easy translation with free "loco" translation plugin. * Roadmap: We will add a lot more styling features. Your benefit would be that you can style any part of the form. * We where busy developing the "Better reviews for WooCommerce", we developed for ourself and now released new version for all. https://wordpress.org/plugins/more-better-reviews-for-woocommerce/ = 1.3.7.2 released 2019.02.06 = * Added translations (by Yandex): Portuguese (Brazil), Polish, Spanish (Spain), French (France), Japanese, Russian * Already translated by humans in English (US) and German (all kinds) Benefits of the translations: You feel more home, can work faster and can use this plugin if you do not unterstand english. * You have a better, additional translation? Great ;-) Use https://wordpress.org/plugins/loco-translate/ to generate a .po and .mo file and share files via support@saleswonder.biz = 1.3.7.1 released 2019.01.18 = * Added: Buttons to the tutorial and welcome page Benefits: Faster access to the styler = 1.3.7 released 2019.01.17 = * Added: 3 Animated gifs, to the wp.org screenshots section and to the tutorial page inside the plugin Benefit: Match the form to your style, add background image, get buttons aligned in seconds * Added: New shorter intro video Benefit: Get faster how the plugin works * Updated: Plugin name Benefit: One name allover "WOW Style Contact Form 7" for easy search and handling = 1.3.6 released 2019.01.10 = * 2 Fixes and 1 small known issue * Known Pro version issue: When you add a background and label color to a scheme and activate scheme for all forms, your individual styled forms are styled with the colors too. Workaround: Click "Disable style for all forms" and Activate style one by one per form, until fixed ;-), sorry. * Fixed: Change permalink handling to show form if permalink not set up Benefit: In every permalink setting now the styles previews the form (Thank you Vlad, Brian) * Fixed: Link above each form in frontend Benefit: With more than one form on a page or post you can now click on edit button above each form, for instant editing (Thank you Vlad) = 1.3.5 released 2019.01.07 = * Known Bug: Permalink Settings When "Common Settings" set to "Plain" like "http://domain.com/?p=123" Results in an 404 in the styler form preview Workaround: Please choose a different setting to "Plain" Issue sent to developer Bug will be fixed. * Minimum PHP memory 64 M better 128 M Example: When using a lot of memory consuming plugins and you activate styler you could run out of memory. This is not only happen with CF7 style plugin but also common with other plugins. Task to check memory consumption is on the developers task list. Benefits of a higher PHP Memory: When install and activate plugins you not run into white site. * Welcome and Tutorial video updated now you see the latest styler version in action Benefits: See how to style your forms in minutes into an eye catching form with a higher conversion rate. * Updated screenshots Benefits: You see better how to add style in Contact Form 7 with beautiful backgrounds by looking at the beautiful examples. = 1.3.4 released 2019.12.28 = I am really sorry the admin bar was not shown. I got aware of it by using the plugin myself. Now tested and working ;-) * Fix: Show admin bar on frontend Your benefit: Have your frontend admin bar, to access backend easily, back So if you running into trouble please contact us and we will solve issue. Also feature requests are welcome. = 1.3.2 - 1.3.3 released 2019.12.19 = * Split view also in free version Your benefit: Always see style changes instantly Your benefit: Always see live form style * Show duplicated form in second column Your benefit: Better comparison of design view and live/unstyled view * Reduced menu height on the right side Your benefit: More space for styling = 1.3.1 released 2019.12.17 = * Fix: Make switch to scroll or fix inside split mode = 1.3 released 2019.12.17 = * Added: Split view Benefit: See live results when styling or saving style. Best for usability. = 1.2.6 - 1.2.7 released 2019.12.03 = * Tip: Opt-in with freemius to get access to extrem long trial period version. Your benefit is you can test everything for free without entering any payment infos. * Tutorial and welcome page with quick start & quick style video Your benefit is an easy start with the styler, i had fun doing this video. * Fix an issue when showed wrong style scheme on page loading Your benefit is an more intuitive style flow * Fix an font family issue seen on Twenty Twenty theme Now fonts from styler overwrite theme fonts in form = 1.1.9 - 1.2.5 released 2019.11.15 = * Improved german translation by Melanie and Tobias * Added: border style settings * Added: label font weight and font style * Added: Style mode current/live/unstyled dropdown * Added: link from frontend to styler Benefit: You open a form click on "Open Styler" and edit the style * Added: CF7 editor added dropdown to choose style * Added: Added clear, preview button to custom CSS Code Benefit: Where your create your form you can choose style scheme too. * Moved: some functions to premium Benefit: You get a CF7 Styler that is supported and working continuously * Moved: some settings together to reduce clicking * Fixed: Cf7_Quiet_Skin declaration in WP 5.3 * Fixed: Custom CSS-Code area * Fixed: Scrolling issue = 1.1.3 - 1.1.8 released 2019.11.09 = * Stunning Background image settings like Background Color behind picture, Picture Opacity, Image Size like cover, contain, repeat vertical, repeat horizontal, repeat both Image position * Added setting to load styles in body-tag instead of head-tag (Lifetime Premium or WP2LEADS Pro active) Case: Themes or page builder plugins can stripe out CSS from head-tag and leave your form unstyled. Benefit: 1) Activate this option per page (directly on page near the form) or globally for all forms to get your styles back 2) Tested Themes and page builder compatibility: Thrive Architect, Optimize Press, Divi Theme, Elementor * Added German translation (Thank you, Melanie and Tobias) * Improved saving buttons usability, by conditionally grey out some buttons Benefit: You see intuitively what are your next options * Disable freemius if wp2leads is pro Case: We sell via freemius and we allow to use the premium version for free for all WP2LEADS Pro license holder Benefit: freemius will not be shown to you, when you are a WP2LEADS Pro license holder * Show sticky message instead of popup alert Benefit: You do not have to confirm saving ect. * Removed knowledge base link and added all infos to plugin * Updated Message with link if CF7 plugin got deactivated on plugins page = 1.1.1 - 1.1.2 released 2019.11.06 = After a lot of testing we are proud to release our first cf7 styler version on wp.org * Added knowledge base link message * stay fullscreen after delete color scheme * Sanitise values * Fixed Quiet_Skin error * added Padding to default style scheme * uncheck unstyle by default * fix mobile and tab view height = 1.1.0 released 2019.11.04 = * Install Contact Form 7 (CF7) if not yet installed, because it is a required plugin. * Padding for form preview * uncheck unstyle by default * fix mobile and tab view height * Sanitize values * Changed slug and title = 1.0 released 2019.11.01 =freemius/LICENSE.txt000064400000104504146725417150010226 0ustar00 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read .freemius/assets/img/plugin-icon.png000064400000064247146725417150013424 0ustar00‰PNG  IHDR\r¨fiCCPkCGColorSpaceGenericRGB8U]hU>»sg#$ÎSl4…t¨? % “V4¡´ºÝÝ6n–I6Ú"èdöîΘÉÎ83»ý¡OEP|1ê›Ä¿·€ (õÛ>´/• %ÚÔ (>´øƒP苦ë™;3™iº±Þeî|óïž{î¹gï蹪X–‘š®-2âs‡ˆ=+„‡ ¡WQ+]©L6O wµ[ßCÂ{_ÙÕÝþŸ­·F qb³æ¨ ˆð§UËvzú‘?êZöbè·1@Ä/z¸ác×Ãs>~ifä,âÓˆUSjˆ—ÌÅøF û1°Ö_ Mjëªèå¢b›uÝ ±pïaþŸmÁh…ómçϙŸ>„ïa\û+5%çáQÄKª’ŸFüâkm}¶àÛ–›‘?ÜÞš¯¦ïD\¬Ûª¾Ÿ¤­µŠ!~ç„6ó,â-ˆÏ7çÊSÁØ«ª“ÅœÁvÄ·5Zòò;À‰º[šñÇrûmSžòçåê5šË{yDüú¼yHö}rŸ9íé|èó„–-ü¥—”ƒăˆ¡FAöçâþ±ÜJjåI.’£[/ã]m¦èÏK 7ÔKëúR ÿD³‹r€¯Y«QŒOÚ-¹êëùQÅÎ|Ÿ|…6«¾ ³ (˜0‡½ MXd(@ßØh©ƒ2­Š_¡fçÀ<ò:´™ÍÁ¾Â”þÈÈ_ƒù¸Î´*d‡>‚²üŽ¬Óeñ«…\c?~,7?& ÙƒÏ^2Iö‘q2"yŠ@ÿ«g Ÿ|U\ ï\eXIfMM*(‡i>  µ„µà¶iTXtXML:com.adobe.xmp 1 2 2 1 256 256 gó¡@IDATxí½ ¼eGUï_}{NÏÝI§;CÇ Cd€˜*þŸ/h@DEPžÀCEDåñTx€üÿŸâ*ƒ2©Ágðý}„üæˆ1t ;CgNw'îôÜ÷_ßUû·Ï:u÷9÷Ü{Ͻ÷œîªû9wU­ZkUÕÚk­ö>û„PRÑ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@Ñ@ÑÀ i`Πuèpéσl}èþ-aÿþýaÞ¼yᘧ¬ K–._]®Éáb0Îbl³pî¸ãŽÑk¯»2<úО¶Ö¬\ŽY8æÍ]cøåË—‡Õ«W—Ѧ¥Rè§Jè§6{%çÿ¯knm¤Þ¿dQxZ8&ì[¾0œ°huØ°oY8âš{ÂÜÇvý‘Ç,4¨ qâ‰'ZyåÊ•aIä9ö¨µåššFÊ¿^4PŒ¥-õ‘æ _øÂèï®ü×Z"?ogrny¹¬· qÑÜõaÙ—o ¬H¬ H «V­ +V¬ e›aê)ÿ* ”0æð¾ýg£·î¼»nµÉáUÙ­šnõÒ±Gg«ˆýß»7¬ºW[  H°Í˜;wn[(«SÝañ¯€¼ÌüwÇ_Ž;ã7u©›³çô½Ð*@°Õ`Á6Ã'­$Ž:rƒ¡×¬‰‡”K—–m†WÒ!/`/"à…7üIÝb/ŽZÇÌDéá øºE@Ãy„VV–mZ®tØ€ƒvŒŽÌ]:#zàð¥w}¸¶É:'¦ÂÛ~É8uùºú°’³’îfW€`›áWG¯^fJïô£¤f ̈á77=ØX=집nܸqô~ªøTX‚ú%yý”•o3.[V|áuÛ ¿«Á%ABÏD±dA_õßÖp)˜JÈ áºë®½ë®»2lŠ·=ciøøæ+jaýt6 ™Èž.¹ :¬üöûoë߆sÜSž¢a\ïfä«‹6‚ 6lguV±ûJWE•"vlß:z͵ׇúüçÃÚóß݃)MœäK{î ¾iâŒ}äøÁÑ…§>¼²û+*ïeÒÓÃym =o÷ê°jÅâ6\/…›þ2<ï¼óÂ9g?³ü\»à2àNÎ$Ä©›RßÉ©#É°S)ýŸ,Ÿ-½<å»9ßx¼óxtÝÚ ãñ7µO·k‚܉êlÁ›ß [Ð9„ž‰ðOVR¯g"ù“•ÃþÐT ñä_ž}ÏGvMÈ0':aH$o¤2tðãÏÛËìN “LÚœˆÓilãñŒçèô¹2¤'AäjläIÝ‚¨ôð»~âŠõw€®SÓa§ú~†‚ßÑðw2ô.VÃæÕ#/™q5°häqÛ·Œ¨EÎ –|Mû~Ê2XAÍh*‹‡²7XÉ4yŤ™Ðó¦šT'žZNì‡úL»äóO'‡ö´jÙ{F9LLg$ôIuÞéÕWdx¼Æ¿ûàŠÈ—%dÑ'Ñ ?¨¾½>½L¾—‘úÑí!lŠÄ_‡áiWu£‚ ±où–ð¯¼ß*Ž¼caà¶ï ßq( ºŽŽ!#íó”1ø¸ %kN(#ÊÙd\žWtð /c„¯ÎG9$õƒº9¡µô/4rr9³¯#ïåBNråˆy_qÆØzí¨ðåŽâÛEŽ—ëëàÍûdòª@¡1‹‡:<ÂY¾rV§^4‰«ºN—^Øtë”}ß$C°)¨®´ Ä"á/uZàá¯SN9e`WÚ­©N#+ø)iÀ®ò”ËÔHrútYÌAÔF,â‘éåªJA퀇ŽäÛÎðѱ|Yy >& þ£ìå/Ç/xúMòôБ,ˆTŽ«>‹W4* ÂGÞ œä«=Ñ‘M=u €à;%Nõ½àÿöæßYµË™{¡Ÿ šfXë2b Œ˜.ȘeÄê–9}¤5‚Á8A|‚jGe „6•7<}ªœÕ;£§«ÖñjLÔñ^Éç%ÛäU,ÇTû«>H.8ÉA†wà&š\‡ð‹GíIuR?‚ÀG¼:|cnz–¡S;³‰/`6µÛ–aæ†,õÆ,-urTä¨^Ñ0<ÉÒP-ˆ0VExñ#Sý¢NtÔËÀ‘Pr%Oíj ‚’ É­ä!C8òÐQömˆ×êcû*K†øÒSM“MiªA`þö=á¶Ý[šD®wdd2H0>—pâ‘qS/\N£²‡^&|â÷2Ìð+ã÷¼¢'Ç€¶–ûÒ”ü¸ÔoÉZÛÙXå@8¯ú­„ÊÁ8$•léIãð<~Ì¢G–ÑÄvÕ'ƒ:e’xlüÕÕ?«GF¥Ê&Ç9¼úF]/iªA —6f‹¦§y C”ÁA"ck34Œ¬rx œÐ‰LFíŒQuÐ+Éàåj‹öeÈê‹Œ^ñIŽú¢r^ßÆû”'AxOE§Y[2é>ГO'ú ÕK?±^2 —¡ÑÁû>Z9 DàÄS÷¥jÃóŠú úg0Ò*‰Çhª¶„S?plµ%œø½#û¾ZÜøÄjCr€½8øxAÂË#ò¢£ÂËÖ7+:'ž…r Né2‡è¬7b¶w9„—xl…Ž:ÍœâÊ^ ^¦Ïwã_õ@>’ ´ 4F?ƒÁËo¼üD·ƒ¼üg¬%¸+.ƒv¨¡Èʹ謜KNã„@@Hê3P}?“ö&“&&ÓÆLñ”à4Ýæ4Õ2Q† ™HNˆð;ƒžJ¨®Æ!Gï¢íÜ?žyÖ=ã‘•úÖÀõ×…ea{lµåxm9~~}—|÷ûaë¾{ë^>mñÉ–ðøt¶@Á;tMØ%ãƒÈkçŸÞÑ…vªJ¨®ÆaûÃh02 ŒGp.ZéCoÐõl òûï~¸vC¨ò?ˆ¯?ºÆûÌê §ÖÅñ‚?Å>è©€®_Fö@^H@\3Ît¸Xõˆ'éÀ°SW}`h£q  ßPôgèr:ièüáˆÒŸ±ûc¡NF´kß’ÃQ=C5f]/¿àšæ×r"ƒê´*˜ˆŒA£-À]›é«ÛDºÝ„ÓÛ'â©'¹ø ÇU²ƒ¢…#ìÿS²å¾»f> “÷eñL6Ýú“Œaxˆ¾–-@uÅÌ ªÛDr~pZBúÕÁ=Vÿ¤®u¢›ïYm=ѵò³¿Voꪂ¹Ê“ÝΆáÆ\@uå5Ëc4,e0>é ÷^ùáKÇëéáÌyóÃM»î«ÁŽwÚ¨ZÏ4­†á†S€»¨2 F"'°<Žœ9>´5Må¤Â /¹4%œše“aæNîÛM“ Éj‚Þ|Û6Æl,ªú¾H®ÆAÉ÷Iy]<ÀZn¥ÃIW1‰G2<ù^SÓX‘Iû6Þ(HP2yèguhÝÛ7¼»Õwì}ê1‘g$Ða î Ée°µaF'·”; ŽPád¼âir5%ÊâS^Ž—;¡ç‘œ^ @´ÞIÀi¬ªW;8{^Ÿ÷IõâA¶_xÙÐHWðùqKï&Ï ÉßKÊÇ*ž¤Óئ Öª6ˆÈÔ4ëK‡ƒG¯æw?•3€êa2J æpM8­wò>™“eúןpâÍ˽LŸïÆãùÇË#SçùxÆãL=ÁadîÒ¡0¢ª+Œ±Ù Û–º‚#1 ›IœCˆÎh*§1VÿÄ+ùÐÈÊCîHyðžGrŒÞõ§© NÉú_-‰åÔùö)k @åÁ+ù~ g´•îšVÐI–Úóco’ÙÄ3Ù±K–úIyºÒ°<ÀøKȬ@†Ì œ7 ò¢¯žÀ?à…3YUYôr“‡£U„¼œÅðÕå’<#O’ÜTjýG&ý‘<õ£‰§¦É‚“¤ù¾ 2 , .’ãi|{»áÜøE” k2c—<ëcÕOá/¹’a&ñ™È¢OùxšÄA ]§öM^£OâÉûïû.ϧ¼—éóÝxÄÛ Df~Mzá›, ?2,©º+…ãÀ2\4Æ£:‘«î¤µûª¯ †pãæöoåNtÞ³ç‹}†aûeþÖwöÔ³´ÃwHŽ<ó„G¬ê‰°Ü^´a3° Ò•Õ’‚—3ŸtžF^­||l™ÈCIjY´íÇ€LõSãÔõS¹ŸpXž`Ìí–ÑO- ±,‡ß ª²L_~ÝÚGÃÚÅéM0-'Iƒ—!R ?ó[?Z¹øí?ÒÝ~ÌFý>ÿÙ ÃI+ÓóõwoY”޴ʇbÉ^9£p³ŸÜùdÛ ¯~ÉiïÆ{ׄ/}uí˜.±äˆpõmkÓV(ÒÙ’ºÚ"!ž‡±6»;}s í:ºkH×èûd“Î šÁ0=Äø§} 0,Ë!›%tÀgËã: ïxÕ»^j¿À²Ÿ„óøÊçub1<8›éî;›¬RAÊô;ÈûõoàúðæWÝbÝ% |âkgXpÓ÷í©½Íò?mÔtM}U'8™.ãø/cX^¢>O{PCƒ1ˆ|I‹áÈP|^cá¾ÿo~úâèÝÄ%D+(¹œR/ŸóhØ>z¤DÌ(¤m’¶äÕGò$fKÒ¦{G‡î}nøÒ­Ï´«ê8“›ã»*-±g;¸év,ý׸€$]G+Pf Ó†åE z ÒDY+ÙÒ1–1’ á*ZV¶ô¬Ê¹±IÞg®:%Ê9©Íe¨¢ñ°Mfµ*¡¾ç›?Å¡â¸Lf»Òazˆ¾—_ÁX–ãi+ÃT†eyóË9‘¡¯ÆJŽøE£2PIm«,˜Ë~¢ùõþ7nyüxºÉò}öyxR<Ú„—!:Ú$ù":Ѩì¡×…Ïwã!œåIcÌëÇ+û;rü¦å?r†éú[ZÈ’fA¿€D†´T¤Bµ¬¬p’!ï¢ eñ)/ÃÇx•·:·=¡ÜkB¾wd* x|.Ou5¬œ^éI<­±& m2FèxzÐy-ú´*‘kÝûʘ÷2U%½zùÂAÃŽ^¿¨¾çßË›ºÍþjw˜` ÙÕj3–Êp1RoxrX½áÉyedÔJ«ÕtY:Ѹ½*ó@CáªÀaå*ˆ‰_r½åd0<]Ÿj&z ®“h=ÎÓé§Àº½ÈÓwšý¡–CogFnª±A†2fúÈlCY8A34Œ¶2b£© O4‚ÈÁðd|6û¬’dQ´@Ñ “:ÍÎF‘Oê‡ÕeŽåéò<}¢}9H^¯²9¼×C5Vñõ"£MÈr:1~×oÉ׋׃Ɉ²HâQŸ çeº¼äzÚÃ=_V•xCÒl#ãÀp¨—É©ÅcŽX-ý…œžÙû6 F’ ßÔx©Qß=uŽk—pâÓrÝË” * $Ñ9¥K/C´ªórÔ†hTD¾‚4Ýdˆ§_gní—°’S€S´ c$ÉÈóÀ _Cå›n۷ËàÄ ™ƒòmÀKÞ~aúêr´äœrFïHiI'¢ó8ñP§mp¢£¬o‚“®È{Ýzù¹ h»%d溇™MãÉeé/ǪåÜ•Õ2]ìªÒìïö½_òߘûøÿ97üã5ëìk³¢ ~¢FìÛ®¼úÇ8¬Ÿ4”ï”ê‡Æ„CK5N9—+œx){çöy_Éô<Ê÷;9z§ÀàeNÕù‡í! ÆÞ¾©ôÚ8LòzLÃÆH0DqíQ2fœ‚–6YNwЙ<§É¥>%ŸW_T×åÜ^^N‡ÌN²ØL6-YÎS“ÕË€ó_síõá”û=Ì»õËaõ¢-cA³Xe¸\VŒ‹„}ëÖ“-ŸÿãK3<7O¡Õ,šÓÎfYÎM½3ȱ­ÿ±ïVO ÀÙ#­á#dL|Ä/º¦1å|¢‘s«/« `[ªöE'¹*åÜÚ€C†Rê€S٠˴ׇüƒl6çöÎß O/¼œÌ¸yü•oÿéÛrÈÐ7æ¼Cå²gû 3ô'½ð#Ítê+Ðœ<:=ɺ ~8ºÕgÁP =õ¢“óQïå@Ó䀒ãÛG†ñ;ðû”—}d‚S>Éo›ç™j~X~ Äó°» pãõ7‡³Ÿ|WXðDúfœW† TÐ/t’7R¾úËJ€ó€;ï î<Áî`bâ„oBjú6 9f¼ @?-UwÔ_áqrR'T]¯"¤ŸzÜÎi…³¶"g/,µoA![µˆ¦îŒË¨?B©MõAø©Âa|€16€™ÿ¦o 6ógοu÷sXÛ¯Ç_—‘£ o(M¯©f% %?ô,”IšÁÈ#‡á…šÞ€%[F -)7ZpÐB×Gh’¯>h¶¤MRŽW9Õ¶þ'™éÉEë§s|Q‰W¼ïK7ݨ_6þ,8Õò«àÕ&§ŠT¦kÇçû þ©Þ”œa‚‡Eó?ÿþ76^ÎpX-aÍ€+cFýd6Æäñ2¦Ü˜Õ˜—'P|rnÕÉØ&öƒ²d¨.çñò$ÇCñóy¼úC~¼äÇ ­d"Ãœ-âry9|Ò£96ˆè¤ùØ|Yí@J2>çØy}¢Ûá=œÊþŸ`ìí›*¯C$ÇwŒ²ìïäü~˜6k3ÓVN‡1Éñj 2láe|”…C¦òjËËĸ¡ñIüÔI&y%«w—NôÔ+/èyÈKŽÉ®ä[*yðåI<^&Žë4µ^¢,å¡‘LÓ§“ïy¨ÓX=¯ñ»±ú6ÉK&²|Ÿr9_¿ËÃö"ÿÌü v~7œÿÐÖxÇ…še´0È0 Àa`6{UÁ¢‰œxá!‰NxªÑâD6ŽË9Ú••ÕðÊ_ä!i|äÅC¾×„LÚ—.áC&²&#¯×v=ÝïŽÆùŽïS/ùC6lܸqtÙãW†57¼s\=pàÓL3ÔhÀ$s"œ,. ˆ³ËÀ ÿY ªxäPâ P¼ÐØGr3^sMåD¹Cª /[Î&ÙÔ ':_ÎÒËôyÏc2c¿š’Æ T>§C–—':úâǘóNåC2àüëç]æ|û'}-g#È(½Ñ’Ï\#z)9=uõÌ]9¾hä^9^¦Ïwãñüã呉, ^]œ6—ãûâëÔ/A꼞Ä^z-u詟阣VõSÜŒÉ:䀜Áw?:a%Êyd< ^hÀÉ‘0,ñxZ£i0¶Ü)›ñFè“ –~(/c†®ÉˆEg2+yÂIö˜r r?ŸÏyåû"ÙJ?’M2‘eŸ†Ù]<È–|ãwºÚR߀ zÔÕü‘·dLÛ‹@4ÞC*àü'íùX˜ŒóK!ãAŒ c’Ñå†ež¶xäPfÜ•µ'•=ô2}¾ç/L9N>žn¼¾/MtÒuê«—¿Õ9}‰G]å}—e‚â?/Óç»ñˆw*KÆ°ÁC"pØwÕUW™óóhït'Œ ãëdTMŽ!žÜ(½‹¦©ÿ^¦Ïwãi’Ó ‡ÌÜÑ:Ñz¼ï‹Çû¼ôNýõãF†Õ H °ÎLàß°ýˆÚÐ?€ó?tÿ{ÀgÞý“´¥ÈÈc”rrknȶÄt÷ Ïê½ñ3»)//‰>x‡PÞúàÚž\¸N‰>iëó!3ÇIŽÆ¢²‡¾/à;éM²ý%Gã3"Ãéßdº²äˆ—²ïŸÏ{]û~æ25Ùç†õÆ<Ô+¾ÔÃ=þuw½iJÏõ£%9e kFAÁè²™Ë1yxÂË`s^ɆÎË7ºÊÈó:s¶ª}É÷r„*oý©.½p‚žW²©C/”óÏ¢‘ÇktÆeó¤6¼,áЉɎŽ®zé_rèwž|;’•_CO“ó÷£<¬Ï0ö¡ Ìü|£ï¹»ßföNå¢æFæÒË5ƒeÆÄè#ôÉ ¸ªO½p¢“‘æ¼*{ùž‡zï¢S;¢UYò€úXœ9âEk™êŸÚí(p×g÷Áu^<ˆ€Vº”cRŸ×™^b_DC}ÝVPŒ)þ]†¯ ^¿àH’©28ÕSšìÀ°ýˆÆ Ê-€žîÃù§ò>¯å1$.8Œcá5aÔñ& ×\xc¸× b)pŠxÊâ{íwù©59¹ ×ByšÁåôjÖ;8×Jô5¬xtÁs-ó4Ù-ÀkçŸÞ‘ ’òPí÷¯¿þúðÒ]ÿ¥ï*Æ(̸¢h†0C©öÞ2´sN îÚÖ÷öWG. ·ÑËùÄsû ^´úQ»¶îpýt %LA _4ö^ïàø\–dÓçÎí{ÔìÐÀÁ{ž´G|ÃüìÙFb 8¸c»û»ç•`f(nö×òó‰{Õ?ý¡Ÿò¨Úè´¬DÖC¬–žmŒU>¨Ïç2šx{Á!³Óxºñû¾t££Nmè Tíå|MïU”‡®«t®ö½³êðOr¥#шWõ’¡2P<×KþÜ¥7…wì~8œ8² žß3†å¤}ïƒtÄ@€£·}"ì¿=|tO˜¿|~Ø¿7~aeé¼t,×ç   %cÌÅ…sXøD›ßgö¼¢æÉËôùn<¹Œnedâ88¥ïS7ê|_z¡U@ŸGŽÒžÑ•±®õ²ú¼=•õ[83IÐê£>­ïëçÎN™1« Aõe"Жû4¿8:ÿ!”ÆZã nÑÜp`AÜ›ïmÍü¬ö®8ª/½å@f<)´Ô‡DeSòC)‘§NõœgE@™$êTïgL“áúR±×@< |^rkB—A¦õ§!92Ë"ÓÆR'¯ïV6'«t ¼§—~Ìá£|Ú‚NãWè­O•\áüxëúJoðC§D$ òªë™õo\vu¸dÅ-F6Y‚Ýx†©n(À|sþhÀ ’C .}ܶ!ˆÙJ2ÆGʆðÞPÉ{:©¦ ’‹ É¡ òðWóW}€†¤6ʧšô_üçé¬ýè,m^öü>ïå7ñØ_9©œ²“ƒjÌÈ’<ñP—ËQ_¤W•»ÁüYÿ¯ç/TKÌ6§ŽF ¯—)§>—)ÉŸ ê=ÙJÊÓ/ͪÂA“óƒS=ur`á¨'åeÃÅà“úÛ Ä꿜՘ݿ|ÜTA‹|µM?„³úX&5õÁðUpÌóê ø^’N÷{¡vš–Å ðHö톟Àèêèn æ,_0錹˜f`oÀMN#Ç7'« >y£öxdËÙäjOF®²çS¾­ÏnàyL>N傃ø»AõËúûÙ-© ‰~©={CÛž–6<uèSɧ–ëÆ+:ñx½˜l×¾—%>A–ûÿ<ï«vkO¸ñà°o †"4]BžØ"ì]´:¯žÖ2†é-74s’ÌhÅãA8u6/ ô2}¾ç/L¸|<Ýx}_ºÑQ§6l–vúa 8²Ú÷N-™àò~® DÐ!Ç`¤¥NrsyZîŸèùöw|ÈÕÖÀÂCpló„ã“´Rà°pÉ‚'+‚^·û‘0®’&ûá“04ãSæÅ$$_'z/Oyòñ@Ϙ4¯ 9†j¨À@ ¤‹‹¦ÙØž?ž(íqõ€94$PÌ‹[‡ý.t:#à.£Ù†¼·= ˆÔt[?eeñŸfdadâ¥^8Ñ©Wà Mñ×Y.V¨ìy4‹©“Su\r}[Ê›#Ut>߉'o_r:AdJ‡¾ßèÁÓF£~ª±SO’<µ!žôb’X_µm´6ã§3ʺˆzáÉß ï<åcáÄ9½MðŠiàÀ"žØ2žïáø!¾˜ƒ½?)? ¤<7:=δÀPî]欘ÓñiB £ÅÀì‡$yù3Ö>l¿ ¼y×¢°vñîT¢|õmkí—‚õ4!òÏ}ÖÀ«[C蜉±Žmãêïì³¾£o×ϧ³NØ^uÎ'Â+Ÿó—C¿|÷ãšl~¬'+iù˜Ñqæ|ö'°ÜŸ³ ƒ2t£q•À] íÝæÌî(Ú·=IÞeÍ.i&lhkæðôü$ø;~ö[Õ–ýÎ wŽžl³š‚Ëg~ësm4¥Ð_ l¾uUxÓ#g~±ÙnZáÚ^rúÃÿó²¿ Ü ûÞ½_šŠM«}~ÓÀýŠ€ú´RH”âÓ!‚‡ˆì| {~À?ÎürØ|ö@¢‚ù#–Œ}ŒpsS/isc„·¤þkà±ñ1ñ˜Ø(q½˜õ?ù³¿þøÕo5tq~ig^bgËËzöùîÂj¹·Zî+´†¿Þ鸴EØ_=.À™ÁœÈÖq†psrî|¯‰¬´"H|ʃrçØ/#lߺ;R,‡¬-h¢ü› ìI?ÏåÏ,Þñ’ß ¯9ûºi™õýJ"ÝL MËà¦IèÀ¯8Ð#À@œÄ÷pn’9y $9¹ 8m Èû;Zœ¿þþpÁI׶ÍÐ*ùYŸ¼¶šíE'賑Vª/pú4`/«/8ùºpù¯¿$¼þ¢¿³Æ¦cÖ÷2}~úF×ÉÃsPüáÀ¶Ä¯N÷qî ÒžrúÞ@‚!– 8â³óÃÍ#Œ%{ }á[ÃU'Þó­7‡÷œašféÎvÀ¯ phöHÞÑ áþ-Y‹£¦;}a)LH Än /|þæpþÒ¿j9þ¶SÓ:—{úÜÖœP ‡.ñP€Ö ß:Øã–ûxœ›;@œ¿vvw'@+€Ö"9>x’äÿȺ›Â‹6¼9|òΆ÷^ñæüÔkÆ·|b!kK}-ùó`°sç £ÑrxëíO5ܼƒå¦ˆ>ý;ù‡2Ik~#üõ_óWÝæù:<Ì£@ ا¾ ›˜¡,ÕÙ·3Ós;ÄA,'æ{z9;3¿=4TÑÁ« ã{ÎyÉoŽÙl¼wMÛùr0ZR~ÛÏð^Xa ñŸx)sÆ`N_øÜt«Ò; Ü;'r”ràÅ£vz 6Ш]øÔ†ÏK®Ú¶¶\_<¾)ïÛ@‰6…çžþ{_öÙpIJo‡}ìóI~˜/í“BÆÿ?ðwü’÷lZò·V¢õAB8‚ŽÎLOªƒFÄq‡2+hxzPÿüÑW…[ÞpqøO½LbÚ ãÇñd "’Ѫì!´rV øÁçÉãpÊ8tí¸Õ#ÅðÉ9;ÉõÈ ù¾äüyÙªmýªú-ùr\Oß-/>Oƒ|ÚWXyéžþü°­}¹ï}ž`@Ê¡ÇÁá÷o¨—G3:yœT[Ú;¶§Õ­Cp~{= (ÇW`€gÑœøô`OôEm[À¨fQèä´ÈS¼çñíK4¤¼œ°é¿d"KýGü¾/ÂyÈ=ýÏýü/† žquËñåÔž°×¼_%HŽ`Ãþõß|XCô„IbE@¢œ¶ &'ÇÖì½hÅ'˜³[ˆ±2*Ð?wáÝáãç¾.üùÅo°ï`è ÔËQÍá+7ÎQáç#®óÐ2ãWŽŸ·ƒ¼C)u½§Ï²_ö5áz¡é Àa½ßßa8Î:;Q >ÝçOŽîgmÛTo‚Fut™: œ’dR†O+ ef{A\Àmß»Öê.:ö{á³?þŠð+Ïþóz9®ÙѼR/ŽÊGu´éórdë‹»$šE 0ú€#QVÎø];Âù¨M }ª`dã?ëg%ß$ã¯Æ Z%|Jêeɨë\ .‡,÷ÿðÒ„O¼þ•áÔ£7¥Y?^çÐË'6Måa_ Å €C:söxáÓ,ÎíÀdhÜ$é€Õv>ŸT'z•%ËÓjÕNtä¡]¾`3Y;<¤üg.|é’ÚÓ„rL#¨þÉ™äÞá!‘Ó˜FG³™¾r$òžÆ —#^ê郒h¬¾rnúaýÌœPý€·Í© ¬:ª>iu •<ßõßd"C4dÕWòòýÝÏÿFý­½}[6¤=Á NPu§:àa”†"ðÖ_ï¨ùõaÀ’ý@uPÇï(¥Ù›¯<Òa´ M:“¾¦2á¡nמeaá†9Õꃶ Ããá'üßaΉ‹Â®mŸ ›6¼3œwdX°÷NHBú²Š p[öKÃÛ®ýßöx«+b?ù„_Ñ4Ñ&ÎÕ  W\³2ÕNO4?3ðNnN<ÿ]ñú !~_³¸p´+^ÕùaõÕÊ࿼äZ_ÜaÆœm ç& ÊÑSmËÑåÔàåØ‚¢¯ÎÓ‚ùá™âý CRf•À‰=BIÛ9;Û^eÑÁŸÎZ+söH`°jCañÂ'ÂÜ9é‡J$KuöMûâù»Ã3z[øîâ_'?{GõØpzdUÏ®«ýé€O¸o"Êå¼ 8"É;3eÑy¼z¼=£kÅQ­$×hÜ€åþ»ÎýhX¾á¦ÀRß–û‘¼'ÌäþçAÂËV9ÍäZ ® ç}vί¾öÚ4÷¨"=¨ãîxþŸ¤`7æÕ Ÿ¾`3x¬ç< å¤­:962l–ç⻤Àâá˜UAE_;µB­•Ã»>ö|eixò¢WÖÒõý1`œ\A¨¼º©™^¼x&òëHÇ-ú^xËÿõ¥´Ï×rŸEŽfxwZ¦{Éá€ÔqÐLô8¡fmèpZñJ4$á B $Ü„·µºH¯,cöW`@ŽV ’,ÉgK0]€½8Ψ¥¼Ú7|u@ût-ó¡‘3[]uß_'øÚß‹F²xr‡`yÜ™¹ßcÎït“ÏÖáYGÝ^ñ‚¹á„%Z²·v iæm_H^SprBYA>ÕK†‡MuÂyy87rº}‰“+Ø@ëÛ¤ p$ñxîk­Ìó“=øïzeÛ“€Z½£Òfs?‹[ªÐH &x8äã‰HÝÓ¯DÄßjØßÀÜúñámùí¾)¼üìé rLû}'Ç÷òUîÔÎÁó_^õ®—†[6ϧ­ûc&<ì³,´žTx×æø 3¸ÛLÕù¹f^e –ûþwF·îlvxd0ûÃë‚Ÿ5KI8¦ÇáÐ$ñ¤RëN¯2Ê ö*«%}LNÁ¡€1ªiF°¼ç6àxI:‚€V'¯jͨÔÙwâãÂÓ1£k¶žˆãBë·ôQeòJÐùÔÔÖ݆?øÁÇ·o©ÞzØkŸ-~ÍêÚ«ƒÇYEçgqêD¯%>8%ÍöâT=åóîï_Îy,¼æYŸo¸ø{aåª+l–ãü8ê4ÏÐc[N§•ìƒÓK–àµ1N¾— à€Ä^röâð“§oËvß™¾$äöß3é¨ôi&ÚãÇQü» iw¶‚ñ¬ÙæÎÝÖ,~(¼õÇ¿Ôþ‚:SOAB¿ ïÃRÝœ¹~Šǯ¼`ƒA (xi¼ó€¦ ñ‚7œ»)¼àicP¯ g®¤»Zv vZ~Ou§]dh_?™3dˆ_Ëåÿïú»þvµ[Æõ{5pÜܯ™ã/ˆoJzÅÓ¾~ñ¹7ÛʆQõömižÏøVÑaùOÝt‚ªíé%LBÃÝ‚‡€;¶·ö¸Mâ_pÊÃá—l}Ü ß=­[Úîe¶ç=‚|YH&‡S 8¼©xÁã„ß¹úâðå‡ÞvLwVtߧoJìÕý–@{ù&ZÕI«æoËFn³ü³V_Þô¼o†cV§~Ø×´«ØÈêÅF£~¯?æ°i[ FàíýÕí¤‰ ÂNA Û À7¡ÕÀ¦ïз×K =´2úü«1\½¬<ÓSÖ® oˆ?yæñq¾›†[|ÞØi·K|äôêüzC1<$½ éÊø‹CŸ¾ïmvPè—ý:èó¸ÄÙþ??ä£våü{š¹×á‹â­½·¾à›–ç7ý¬ÇÏõ=Þj¾ñ¶ Îc h¡/©ýº/"''äßóžÑ¯^y¥=( ½®D/øsÏÛb· u^xÝ-ïgxûuâøFÓ²¾i9Ÿoh»WW?´GÂáÆKÚø«.´mÁžQ^y'q·ÇÏ—û'ž¾Ôõ45ë7õQuy0˜1ÖA_élŽÓyÑx·ª­@Y4(g"(‚À?ÿÓ?Õ,“ `[ð¾ŸÚÖÅŸ‹êÕyáƒV·ìä„*S¯Ä^œ_.–SXz}ðG²€MrêÃÌêŧž>Ïk5Àmÿø· ÚΠíåŒà)ó¾^ò±ÜцŒß¯n¿æ€™Ä  q–Ÿ©^AÀz3õ%L]‡Á©uE‡„¼Ès:‚„Úó³#uÚÿkÕ º&‡ÏG¯³?2%Oí_uÏéá#×½0l|üçê§øÔ¶‡º§Ïr×þ5áì£.ï¾øzÛçïzriXxð±1Ë{Íì^ŽòMuÂå`ÆWêä4Áú¤X=-Ø@—ü!álÝT £;­ÌñÝÌšïý{Q³¶Ÿ¼ùŒð‰›Þd?y®-üäIë~Å ·öÞûüØù ˆ|O/'6âì_SpA™àt(2ØJ‘¯ß¿¹ý}S‘¯VMyƒÕl-Ø´×GžŸá)Ëл9·fhèI~ÑËŒŸ¸zÿ¿çˆ5añ;ÂÛ¿x~Û¶àøy߬—ûº§Ô¦1€ö.ZìÞÚxHPE½C5”л]öDù—ÿígFÿ×UéEš=1ô@Äjà·.¾-œ¹æ`Gcö³ÖdY]QÉaTz™åµÏ§O–v·ßó׬ßÉ7nÚÞý›ÂÃ;Ö†Å󶄧¯ºÖîéóJs9¾P Š‹‡MuÂõ Æ„áÞ_€t¿´ÐÇôØ÷?0úºw|c܇&Ó$«7¼|CXºwÓ¬ž LǬŸëÃîjüÃõLJâ÷)tOú~@}@¡êò`Øv;¢! t{@õu+º?xiùü=á3¿z—-ÝûÝ»oÜqtøOá7q;}K'ñÒ^'ãÝ9ge½t‡GådÜé'ÊÀ“€Ìö$ùHȵƒ¸Å÷úSNdØŠÁÕlxŠGxùY3=ÐCÿXÆSÏJDŸW~LÌì$p:K¡ìW/Ð$=êUjév&xèR]ë+ѹŽ‘×ö€¦`ÓPÖ7É+qK>«ŽSŸô};Ìò¶ïK?ûÅûXº÷;ñ˜ñ]¾&üÑnŸ¥½lzñ‡^è!(ç.ŒÏ`¸|Xn/}¬”åPÔ#S2ì™ysž¸äÖýýlïLj×NŒ#;g6¼ˆ;È  úS§J†§È£z~SÁ–í±=~[AÚÓ‘EÞ:BôJŒ7mA„={—ÚdÇ~˜ÜX/~ñܺKÙ¬‚M ‘å„–£ËÙ…'àøz‰yDïqâ= à@韗|èÕûOúMGb5ðŽ<ÉV‚8<KÊ™Õ&œÍ äµ¼ÚqœcC§„ƒZ î!óN!IDATÀÁõ©* /B£,‚ƒœ˜¶4#§Y;0j9Çm?œ•>“ 'ËSSpjO+Œ’½µ®1PAÛrö&˜ÓP–S“W*«i¢ t`  ´bé}áý—l™¶ @;ß}dCøÀç÷‡{wεYÕà ª? X+MŽÍ €¼ œÛ}VÌfÛêÁžzéìRò']¡Ï8µÍÐÕr‡§-úc³q Ìîuª[ø䛽“'Z«‚ßõ-áÆnaÖ¾é Íøð€#I/Vpÿ<4&” à´Ôßì@€|¨|ãï/¹Ã¶¼;°Ÿ‰íVoùÛ5ácŸnâe´@í圚ÙÞ'ἑ{§÷´ÎãèÞÙqdŸª:-µÍÁ+G'¯ „ƒ(HF˾¢ƒ&9p‚FD9ukG-Go­Œ¾Ã?èIZ!X*Zé™"ù#'¥™¿ª·•€òMP«Õ4X ä«)l 8ñÕuâ|»õBú âWv>öú­/ õ;ø¦¯¸vW½SÈÙqò´ßo­!ÃÖJÀËRž•‚[-àH–„‹Ðfÿjæ·FÄÑO>ædU€79ñÔ–û´/Çn’—êSª=uÖ§6)ð,~4žÎâÄ>ÉÉ;Ah}妽=çЩ.às\Õí€ÝêèÆ ¦¡¼C‘q÷é×mšÖ àWÜ)è”X (ád~K`«„j¹/š¾Aǯ¹õÁ pÀø!(ð±Yß xú4«Kž®m( æyÊ  à”<¸£}; €ôŽ®²¢ÕáŸwh­ Ó‹Kpú¦€ ´‡`ŠÀ €„{cúÔ«o· 0Ý×…;oüÜYv§€¶|tÒͪã2óêÓ©o{WÕ“óšƒË¡£°Úɽ`9:+ò•“×_ñÓ¿:`x™™^“óF9 ©©N8 ‰vql¯§´ IgЈVžü\¥ñ\`dë“°µ’œ¾„Ò×QöA€2é0?Š®”öŽ~ÆÓq‹Pm òX2gÜ2Äh5c-Û6ÀŒ=:^môr0A ª ÷ã娠˜¡-ùš¼>©¶™Ž:ñUtiön׫ƗËIŽÝ¾4Nc×*^9x-§ê'ß H¦mRÒ+&xÓùJj#ézìY‹Ésngj„Y›ÎML¥V øåy2ýá°è0~XÍ™¥kxÈã„Â¥rrìTŸfÚ¦ ßÞ°"ò¶VMä‘!§S¡Ñ<‰í@Û­B9®Õ6ü‹mÕgTCc{çO ÀÉunàõ¢¯Á°ü1¥¡2ŒI £Q °ýv¬û™gÞ.}Å3D2mP· ù¢ÒÏ}øÄðÍÛ“M[ƒrh ¯YÞåq~›ñ…ó<ÓÖ±$XÁElí¬ñ:q熾)@§YZÊvvW ’®5׸…KÏZhBh»U(çÅÙqPH½ÇaK²'AÑ© ¿O 7¤ù¡ÜGWžÛŒ-ÎZ$îüÂÉ_Ÿ‘  ~ 8$üÄÆø~ò,ÙŒÈ×i'äðÀ<£Ç_î×툶F´gZŽ¨[…QV•ä€*kö§¬:áÈÁMŸ=#+ë³Ñâ؉6=,¤ÕÍŠ†<ÉÚPç%jÛú>ÎúéÖoëðOÁ~e=g±(¾Ìd6Ó°>„Î>ðõÕ‰& h&ÏÔ?9øÜÕ•ÑW3ð„—ç•£Êa%_³ÃËy}prhÓI¼F’—hÓêZðzÆ‚kÙ¢Ow˜ý±  O²%0ÇÇa•ü2]yA–ø|T`'¼ê‡:- îHpv-u±Y"b¤–QÅ Y%p|X ¼ö% ?K-Âi‚ÿrýbû†¡V \}i®rìZVåÌrpmÌé¨ëc  Mò6“G‡Õµ2Öl+xœè¹¶º~È#QÇXØ6‘W=2Ïàü6ìA²D;º}Wy0®Rü™NNÒž_³¼h)‹–<‰ à?ª.Q åÿ¡4+ƒ ž‹o3‡îÇÇ‹Ä,Âçâu7‡·\zt'1Ó‚ç…¦~5pݦ¸¬­ÎÌ!§Òªfï< 3ÖY°Œ±·µ¥@—à5\–4[ã„äõLyÑÈ9 )ã”@Öë:@£.¾Ü(µ¿×—:ʼL…Ä”DT0°» úf!Î‡Ô æuÐké_Áù«âO¤‰NuÐ iŠ C’ÑI×fàUAF ÃÎ u6‚€ú©³îØÁ—X“ÈÐþèȶÔopèZ|Eo+õA°&j-é5ÓË!!Ïo"äl‚¯]r>]?ñ©(Ç'ϵT €VŽSSVp <©iE(² Û ý"Ê`^]œñ÷m‹?Ó®™éÊ! iqúÿÉÓÅN3Ù™zãëf3 €#€°’P}È3û¬QO™‘Õrêa÷þeÙÊ!*(ÑRÞp ð Ãz04À º'a4úÈÀct2(ʤ–!¦UFÆJ€[„é|»PêAçÿZ |sszn ¦tŽª[{õa_$’Nl¬ŽÖø)ÇѨ.B韷Où‘.ÔëCÊSO¾åüÉyÁ)IÿÉ)ÓFu‚ `ôÑËS=³°±2†XïÇarÁÅÑ“' ¦Rý_ºáó"° RÕQ/’OåîúV@c J~’Ó¾P fwÑ‚—}—@íx¨óÁ6¾(øþ€dìV¡T@P¨ÕA€Á‚¡^ÿò\LÐ ÔÝ À8øè*—Ãoò›ÙNþ¢;·U«°¬Ñ©ÍA#d¬c_ü­dTP©Ï‹• "½ùzáħ:á[×! äØõˆ×(O¨"ÒÆPUJrÈK^í°ÕµæZ¦ú´Q@!&Yí6ÂvD@öÎp¢•ëS~f~%åÑ9•E7dÐpp{®½VÆ ƒ—±e µQURF[9‚f¦ÑÞ÷S›ì·fóL@}Ój ?Ðøì@0Ž«Ö Œrr aöã!OL¥ú¿wBŸ¯ b=LTï!y>ºðÉAs”ÕoAÑ$9½¯ $+µ•‚†œ¸{´ý ejíz»ìÑñE¤õ¬®Ù]†”Œ|üŠ Ø xÂܽáw^¼1üø3wÍêÁ ÆÚt6 -3 Œ¸meS»zæÂür~LPc]râ´rP•œ^ŽÃ(ó©©N89@!yð«Z‘\¶oGô’Eák5­žür~Íøä¡¥L;Z-|4¾€”ñi™ïï0ãS'¨±‹¡C”†&˜‘WFƒ~ýò‹ç …¼QÜt›ñ;]'‚À/ÿØz hfïWvû+:9c3' QâøÕŒ/h3쬠Ñ5¬¤3ÑÙø¢=Í®r@éÂdÇ‚¿ªôNߢO³¶h<¿Ú­h€ BOYÎ ” ήƒAèDK—Ý!ð¡_œ½ô´C”øàß  ýÊhUnƒ8ÃÒ²ÝwZ˜é‹të²Vþ«ÆõsÕx5û š3uÐu|D 4Z`iŸÕ™EµÚHN•–ú °8P’—f]áqÜÜyU†žÄ¸ýÄ Uouquã“êUGûàß‘ÎpR9íùqrÊr~}›ÞÔïÔgå¶ ¨€œßž¨Æâɇ!ŸF> ==xë{G÷ÞùÙú‚` \L%.¸Œœ³VƒßDá'7=Óžãç\@ôNTF¿éyvÛ—/ˆo"“³Õ{ûlüÜCǨÑ_ ¢Ñy9 u3¼ú'}¢Ûñô-`~-­ñÎ<¨Øoàü< 0ä·ÿ¤Ñ4e¨4„ÐÏ}í>N¢ÕD•g%pªg„?ýÂÃ}mj¢ÂXþ?ë¨ÛËÏ «Vn1ö“Wñ\œëœ“Êá8¼Âåty{MuÂá£q·€c'Gi ¤ºÖžù¹Óø6EïÛ÷Ž¯Úõ4’Yo_4“GȨ‚GªO?é¿ø˜åC&›ºtw µ$ZJ¾ŸàmõèHØæ,o—âÄŸY_A@0‰ªÿCZ_úhZÆXêYMÎÚ/õ{yn&åÑápéY: à ,Ñû´ï¿`ÃÃfô)øEïŒi_lŽYÈ`Í!Ý^ßôUuJŽ)œ7úŠÄ`r"T‚ÇãR>áƒ#*`ˆÇCñ{ª§”÷I2…Æ]¼9¬mbÊ÷ôÐ?Ie+Tÿ’,iÏÏgÜàK‘cûòÕÀP˜f{3ôí•óË9µ¬õŽÛ~ 'Wòòª¶Ø,{ãÉჟNŽž;|¿¬ãÇe¾ÍŽ§†ë¿w¸æ«û[‚nI+‡³NŠ´ r,ñÉAUö°©N8œ¨“óSG0­—Ù”½êò²ð3 Ñ•±Ój`¦;4ÅöúÄRwˆØ~ @0űeײߟÏ8¾òØYáãWìž–Ù^M½à”‡Ã+^07¬[•08¶&8þ¿ß}Ä„û@@YÎ]„³¯ gŸ¾a×ä¸Ýœµ©N¸™  b/,ûó™áÈ“TNÚMÿU'\¾=`ö÷Ï Øj Ï?òiCw` W›æþLX³ïKaaüÍ:3ú范âüÛùç.°_’±ôâüoýáèðƒ½–dÞð•{ž®¸vW >?`…Âç÷7hãm/oɞ͂:ðN¨|L¿9íu:ñ‡ß=î–ìÔ?RÈñE“Ú1ñŸ—Oß;Ûj@ŒCú.À’å ÃâcÒ©¶éÔ/Çû¡dÍLÚ§M¾Iø§¿Øÿ· ÉùíÛ€±ºµÇªƒŸ)ÿäe·÷eåÁ–áoÿýôúÜ€WtaìšÍQ ùTn-µ-ó*Óþ]Ž#(š$'ݾ—;‡rJ8üþCd Šž²œY:Ú@ŽOû8~Ϋ~€×G¼Ô©Þÿ )2Iœ Ø €³€‘îÛ/c°­+:`£;>²Ù¶ºË/ñôôǯöõÖ@žŸ@«O,:9¼ñSó/ÿœÊ­Bÿàå{Ç<à³gþªðÿ¼-ð{¤©´Ñ4¬´¨ö·qŸë$9ëpÎó7Õ 'çËÏà§.9[ç»¾Ñ ×©,¼‡8ýto ¸Ó2ÿ9_#s—´OI‚½8ö¨µsøpè7-I¯Y^Æ:­ :t„G‡?öêGìëÄyXˆý¸OÿéÅ{ÃÔÏ¥Ó9?ßÀñûíü´ì¯_ŸNüy`‡­Žì:‹ä·b¢³ ÷gU €¨JŽÉ¶&­,ôŒËw%µ¡² x}reú!ˆÓ“´Ô§/Ÿ„óí‰Fí¨N3>P}9òˆ¸2‹9ŽqÛIŸ:çGíñÚ ü¢Û8QuÁî­N;ýôžŸôw ž²vmxùÙiÛÁ/"“žëÃë?¾¦žù§ó²ð+Ç7Åt|’0=ˆÓúž€œ0G«¤–ý‚Ö?ÔX0GâÉÄ*pP/Zœ‡Ã¡ü²9™QK÷´jHKu/SrtË™:Þ+˜h´½IÁÄ;¶Ú mµd "sW<ð³÷Ägx˜‰ÊˆÿØÑŠfB(¬;= ýkëÖî/5jÌXÁt´*Њ@«ÚêÔHû¦Ëžn¹ùæžgkV¼„SyÉå°7û ÑiˆùJÂÓõÂ/zä°’ág¹ÐµœU³+tù’ž:ÑIŽ`Sp8&mäòà¥.9agÙjÃÓ 'þ¼ìÛ¤m‚ÁÇ¡œWò%KpÎê%–]xÎÕCåGê?pè:¾ýš·Œ.ØúµziÇ ür”rSÒ6ÂHA®rpxm̃AÃ}òæ3ìKD p¬nŽ¨=8´rŠ_ýÌ™aû(âÖé”…ß1ØôL€ïC§>5õÅÆêÛdGü»w,©2œ´Éó’NàÉ{š'—Ÿ–Ì»'=Ÿë8¡‡vdë“6ûDFV/®ñÔï_~\¹ÿÞºMdÚA^„ûFV…ùã«Ð•ô žüŒõøç×°‡.¨ã‚{®9o —[sù:;±W;Á÷ÿöqáyëÓc½ÐüÛÝkÂ×/¿³¼É¡y°GiÝ‘cêîy4í‹=/A`¼s úsÁGJ´Á}Ûo±å®Gæ¸ñÊž×ç=_§<ô¾®‰¿S½§j~ؾñ×m¼Cº nPêþçgÿzôãþûŽNÇ{¿pÙeõµ¸îºëFÿý_þ{8yþMáÁø’Þc㛺õ¤å‹Ó­©TJÿ·ïJ3(üƒ^—å+uŸ¼Ì’?t4P.ð ]K‚Àg?óÿÚm¼ÉçþÈ|ßkêkíKÖ^¹-þlKÛÛph9úª•É¹!9fÉÒ°'T‘Àñ<¶s³•Ä;‘@pö9ç„?ýЇê~9±%{ˆh \ܼÌìïxÛÛÚV[·l ?ØtgÛuøúç~b”íÀ“Äì}wø¾¿’wôeánCï +ž˜lHÜI  &®¾öÚ¶¾5ˆ/¨!ÖÀPÜbý¶uý9ÏyÎœ÷}àã¾züǧÓå#ÖìKeñðçÖ§_¾`sósO é¾:‡g:@ƒnÅÒûl•pÒñ'†õÇ…ðCÇíçl˜.9}“}µ^ýs§?|Ï{úŒ…~—4y ”è>yÝMš“•ÀûÞýîz;ϲÛ.»`ôˆãâ#«ñ-4zEÙšn_AÓTÏ©t«M·óXhEpëi+¡3Ý)ÐAaÞ?õ¥Àá×@YÌÂ5d%ð{1°ÇnzªoÅÝ\ÿR”Q7í%ñö$N­{×éÁ•ôô }g ®¸·M0€Ž`Áí0èH”Yœ_"Šày§§w¸«ÀJ€DßX\zÉ%e`9ôþ•À€]Ó›/ÿ½ÑÓÖýEàÇ&w=47,}¬í)¹N3 VÉÐgJÀKè{å `4>*«ý9ñ±d0ˆ£óݾ:„#SÖ™@½-ˆ«Ÿ,8Ä ²¯z%uû"ßüx^p̾4³£1p&Àv༳Ï-ƒ^£Ã›/[€»vg®Øæ¯i=ÞÛ©{:У޾½W=3O¹åàé…¹ Pˆ$[Ä °pÁŽŽÛן¸ÞèŸzÒÉ£¬¬Pþ ­Ê!à^:¾ß ß«×—g€~†·™?ö½×o®¥¯²¶_n¿’@ lÄ °?¾¬Ão ðà· u0¿MÈ]Î~íí¿^ùÓ¿ÒÞÄ% ´ÊÀËc_pŠ35û9:ÝlÛËWK}¿ÿ×lî‡4~dvº;€l}Ÿ ÿRQþß’L ”0€×…0÷ÁøË4Uß&ãÄù°&#ãØ_LÂcȬî~ })‰ÕI€¼_”@€F†#•0€×I[€é^þ3ôñ²coz›Ž‚|úvbS0 ^ÉËQ¸G% ε¨{b[€X‰«€ñt¼-€„NU†ÂÙ?¿Ã6Ôžåw~ôûÅΤ˜ƒå ØQwôú3nÿ5Ζç<èCÐ+¹ôº­NPò9GHyûÞµñöa-Ɇyñ þäK-ˬ~•ÞD ° ÈgiÍÜ(hªËz¯ä~ȘØ&¸Hâ墼·oåª+ÂÈé[Š½™Vç_¹ ƒs-{²ï‹gŒöÃ9½ð~ËC¶—IÒæ‚õ›­éâüþ N¾€Á¹{B 2w2VJ¾n2Ï HN'*WuàÈ%aþªÛ¾m§†…ç}[è\|)ϲÊ…™å ÐKó¼ }ñƒ_i ýtrú0QGoê7ÆtàØtËpþ²[Ê’¿II†+`À.H·î4 ô;ÐþDƒÁÁÕGÔÝæ{ e¹_«cà3% ü%jïàtœ ´·Jã›íã2tû®°kϲ°ê’o[jRä€ãÊEð ÔÔ=Þ´aÏÿšðLÝ$k<œý¶^ü ¬ƒ¦[}¼\”¾½§ÿRXùô·ûO^_.à€_ nÝ{ìû]tï§&õ@O7¹·óøí»;·½8œþ£ï.vÒMaC\W.ì_<ßuýf"¸NÏ0›“¸G¿tA|̸ròý§¼2,YókÅL;‡×¿rÑÑë½óöO´ñ[õXqðCô:—a                                                                                                      ’þ?KüXíIEND®B`‚freemius/assets/img/index.php000064400000000127146725417150012275 0ustar00o;o‰2›Í 2"Ñò#!@† ™2dÈ!C&€ 2dÈ C†L2dÈ!@† ™2dÈ!C&€ 2dÈ C†L2dÈ!@† ™2d°Xù££#‡Ãqtxˆßx~¹\®àôôôäÄívÿõ×_ÿzÿ ΋øøøD¥‰‰‰IIIø þ%?[™lr YßÙÙÙÛݵ{?B¾ƒ½Îµß­ö!%%E­NÏÈHMM•)!@lY­[[[;^@­‹ðCÏÎÎö¼8ÿ›˜˜˜´´´ /²³³“ÕjùÕ‹(y, w¡ßX_ßÜÜ´Z­Ðñ ~B¸I­V£Ñà—L™tܛ͆Gd6™vwwC蓃ùùyùù° ²›$ h¹‡¦_]Y1™LÇÇÇ!}/¦AƒÂÂÂÜÜ\DòË• ¶­­•ÕÕkkGGGavk :®¸¤$33S~Ñ2þ—˵¼¼¼¸°°¿¿ö7«V«KJKËÊÊ@ ùÕG:ÑBî×ÖÖÎÎÎ"êÆáÁ TVUeddȈD/ßøãÇôôôööv„«@ ¾¡!//O&@Dàôôtiiivf†ÍT¦THNN¾}û¶F«• ΢¿°°0m0„_€K III¿üúkzzºL€psx SS²”_‹ÔÔÔG+•J™á¸ãã²Ã,ŠŠŠnß¹# T±»»;<}6©Òp Àááá·oß6Ö×eé ……÷îÝ ƒQÈÀd2}•¢å/âââbcc/9n·ûÄÛ+*UI mmmÚœ™Òàôôtttta~ž¹g¥R©Ôju²çW²ÒÛÒž˜èéqç¢2AO+ý?p8žFãý}ü†Á¤VuuuSssèF¡JÄ»_z{wvv‘xøÄiÞ§¦¦ ဠÂζ6›mww*€…ÛÏÊΆ)HJJ’ 666úûú¤u{ ô™YY&Û ¸4"ð4ðµ)ommIë8Áº×Ö–‚îPè`fff|lL*go:777///'7—¤8LÁºÅb4™ÌÒõpB#´´¶VVVÊPç!Þ]YYÿG#l-,,ÔiµZ–ý]èXƒÕ••µµ5IŽËËËoܼB!AÈÀívÃé‡ó#òÏ…¾/+/‡Ê­Žr( ¼Ù•åe“É$²µÔæäÜ¿?TÎŒCƒŸ?}s0‰R©,-õtΪT*E(nqÁ1]#uJÊãÇC",@î?õôŠóãRSSkjku:]8 A€S43=-šô?yò„ýù\¬`gg§çãGq´—F£èÃçQ„/ŒFã´Á`³ÙÄI<~ò$--M&Oà=Aúy š ™™™õ á-úa±X&ÆÇE8E‰‹‹{øðaVv¶L€ ±µµÏGhéOIIilj*((PDVWV&ôz§À½r111°YYY2‚€Õj…îô¤Ê Z¿²²2’Gg"6˜Ÿ›ÓONž©hð¨=~ÌfK ‹@ ö¾»[PÝ_VVÅ/FóáððptdQ² xÂd5spØí]]]ÂE½jµúöíÛÙ,÷—°¾¾><4d·Û#*&f‹Ý]] /«S]] ·'ì'ð|Îñ±±¹¹9®¯T*ûýw¦Î"€Ëå‚î· 3žV•œÜvï^¦t¡ØÆƆ6Dæ®mnl 8N!. ðôÙ3xD2þ…¿þú«§§G ®®¢ââ›7oJøÐæ燆†4MëŒçÅ}@688¸¶º*ÄÅ¡>zÄÈ9#+\XX ~Yx;·nÝ*.)‘Ö²u¼|é+Mƒ†ø»¡±1$âo¼‘‘áa! ­‹‹‹ïÞ»'àoÀéăÂíyðàä™ÜÚ%¯:>>¾®¾¾¢¢‚ýj‹¾/_„˜«×ÜÒ‚L&€'ù𩧇zÅbNNN5‰û{{oÞ¼¹òîRRRZZ[Ù?~†íúòåË&í:\ÃGKI¬¾ö÷S—þÊÊJx™,T䎌Œø»»ýý}0ÿó§Ov¶×Òà1>zô¨¬¼œzÔ×ß×'P¨ð<‚þ~ê)ØVÄš,œïšL¦õëÂzX`˜ˆÑÑQJžøKIt4B©––ºO¯þKo¯´ÍR`|llËj¥ûžàö°àY*¼UkŽ_9;3ƒ@yqaåa¦UÕÕˆ\éÆ-ˆ18>¥p#ÀÆúúÌÌ Å ÆÄÄÀíÑétŒˆËÜì¬#˜SU¨ÃÁÁÁ·,³.**zðË/tOæça*#‹°zp~èJÿ¯²sÒttt495Åã=uPïß÷1àûC^^‚Wº‡*ßDkxb‚_¿~¥èúãe<~ò„©sVÏ”RŸþÇÚÚëW¯ôz=›£N³³³al)Ú÷oß"…pûŒ?~ÐÕýL•›ã—––ÈäÔää«ŽŽU)¦`\ GF¸|eyyyFFÉÏJKK{òôéýû÷yïk‚èOz‹«ÅÉ-ú­Ñ\ÊùòÃÂü¼påOBÀl6““‰‹ƒ̦ó3??¿Ï!¼áûrA¡N×þâEcc#o{ƒ w¨»»[´ã ä© §Ó¹¸¸b€Á¥ðøêë•J%ƒÒ||Ìñ½P<·†è×ÖÕ!0(&ȵoY­o;;¿ ˆP\˜˜ˆ`€ü:K‹‹ùo‚`Û Â‹¨’“+Xݺ éç²…73++ØØ—  îÞ»÷Ûo¿‘xVKKK3ÓÓBWWVV¦¤¤^&kUçMpÌ FcC›“www9ÐܼyS¸výþÇwîÞåm$OÜî±±±×¯_ :”Ñ?'Ðb6 ±ú›¾„Á= ß5’žžNëD:Fý{»ûŠP¶TRRòâÏ?kjky+ ‡ÝÞûùsÏÇTNl®DAAù~$°Tˆ5éô €x…ÜªÒ ©Ãh4ry ðûE»…ØØئ¦¦/^¬ú[__ï|ófdxX-«ð ^Be³Ù¨é¥O€eâÐlŽŒå>ì Ò/rͶgö/¿ì ‚Y›››ëxùr~~žz ^¨†x-•ÙdB0@÷³Q&8J¾d Mõ?;3Ãe©èÏ5Ï¢A«ÕzŠ«oÞ$)®‚5 îo¿Öýýýã£#º9\ÊX!îh†cskïÑÑÑ·ao7$Íë)®®¨@`@²ñÀÇz{{)º0©©©äÖétRœF“ðÈÃßêš6ÕÿøØ—ç^RZšÉÀ”.8`­7nü§½äÝd4¾~õjœlÊ]#`±XÞ91,Ž°?†›é¶——qqqqM,…ï)))?þõ×_IŠ«§ †ŽŽ„väÎ7^.áÉ&ìðÁÁÛí¦uŠG“?ˆ–——³™ûåVöÓÐØèë÷e yùù0Í--$ÅÕ]ïÞª^¼\ò“A›÷3à“P‰†©I>™ì<ų@ŽÉŽÇÕ•./ÑKEEïŸrxx¸/تH^uu5’è|{{»»«ëk?É$çRâô€¯õòFe§w,­GlµZ SÈùùùL­Pö~?Çao¼c_<º‰ñq_ç \ö‡ CÃ:ݺ}!òÈð0ïF™ÕÕU£ÑX[[‹hGYžJ¥B4ìsåùbOÞ2"õäädB—š0§K»ÌÔ …WTT”|žÁ%\‹÷ÝÝçâõöƒÞèì+‘žžþôÙ³¶û÷y«›ÓÓS½^ø˜_΃ÜÎïþ“ %ŸLF2ÄÇdz6æVáÁÆefwll,ù˜»»»oßþ|n(ΆÄ£ðˆêø¨s:ûûúÞ¿lb/š°Fú\_ 8!ô;èÀa·NãÀû`0üãRÖg Øä†Éd‚?}åC;kW D¿¾¾4ÐÌ]ßvvŽ3÷ /šd$žÂ{Lqž’&Ë©<Ê b¥Å`éÛæÆ—E£ªªª ®<;3ó¥·×ß©‚ÈM൵µ=#+®Æ½@(¹'ÁuÄc½Ï7 À#é¼¥C€M2  ajÅ‹"˜ŽÇ¼ü|î— “äÏÿ·ß¿sç4.Ü׬ììýý}xäë µZ-ïb¿À…á¡ÛÛÛ¼S¢”@V7ba­ïE,.,pœÏʺŽ¾¾¾…ùùkäI¢ñGx%¥¥žâêšš ÜÑBÎH@s¬©ÆÏ"¬w¼x@úyÓ¥@8²„+þ òó™’~ÄU‡½q—W8 ===\|*BÕHÏavss{{{>·—¢R©.®'t8!Âœ~ÐÅ&ÉK•„£— lr+~ÖsëxüûÑsXk…«}ü𣌗”>$«ÕFã’õæèग़ýK ÅøEÃ@Øþ ‚©±?0â×z)AÅ?ÑÞwwsÏXóž}BÇGG\¶Tdfeý\à [ÇåH‘aÕ॓`hBÒ€¼O‚.F¸u<þ¿ÜÜ …€(twuÕm¨¦´f‚ccc×Ú@˜î?¹;Ü5Jøê.…àq.FJ’øãï„Ks¯<ÁOÙ÷×'àKö›¤K¦1QЧåRúš—ŸŸà?eÄåtŒp¿íÞO‚wvvl) ÛH¶Àù!o—¦î—°¸°pih.51>Þûùs°ç”P«ÒŽBÂ'äâÀî[Â_ë$aÀ‰—þê8¨–tÒb¸2ÿ'--ànWâk?8àáp8`Fø¬CýK›žŸ›ãâ°_¹III±±~e ÿ OŒÄ…†uýyèŒw­JJ€}² vÔÿáá¡[Ç£?˜M&òŠ@i<„ÉÉÉë?¤ZÍ¥òî1„;°£Ÿ‘‘AB€Ã«àcÇÓIRík'+a'œKžÆ?z¦¼‘,)ÆFG¹bpoj9>>ÜUœF6:Éß÷”(1È,@:°Ùl+â.(÷ s \ÆB£¦Ž 5 ÓÏ! tÇÃY"våÀÙUKñðãŽG UG%G.›Iá÷[¶ˆ+È¥¦¦’Ä6¶tÕôUƒÁ­Ñð¨16Fãµ_g0g u oçç ‡PÎÝቹ\®n‘ N¨;%ßþ`Çc€ãAá¾2 e¿¸¸èÙþëöð|ðËä ˜¹Ä¾ˆS©lú¸²PTI6 äÚ³öÀ)Q"…2<;ýh¾œœœÿùßÿ­¨¨ÿPëkÿ¥Q„x…Ý]]ƒß¿~Ù‹%؜Ĥ^ÏÅÕæä$ÑÈÏ‚o?WŽŠû:à‡ˆ1ˆôœ‹¬{UBèx„з޸£yãæMÏ‘åq$0›Í…:8¼9ëæ&ÇrCÜÔÞÞ÷­øâ Œaq ïE·3))éb²‹0óË¥Ú á¼¯+ÕY¬ ä»6« ìx¼¸Ó ŽïãÇFãØè(õÕ ƒ«y^ËqN'w rÉ”ët:º!ÄQ«Õž‹#©àv~zå¡‘ D2¿ Ú ©2-þva-6!àÌÍÎr´oâX68å\IÃH!@€ŽÇäääêêjÂëgk4Žoݾ-í\·ÀZ¾ôörIü«’“ÅÕA8U„Ÿ0œçˆÀÚ@Ï€óã/]ÐÒÒBåD³⩬ è$Õ‡ÝϘJ¾Ý]]‹KÅMõÂ!!,Âç)Q¢÷D’És8îÖ_³_NNN>ÕµÄx&Í--ÿio—jßÇ¥° ß¾}êéá8 %+++Eô> ’š~®ÚùPu¢d|ŒXÙ+Bèxô 4&_à| jµúׇ¡wGGF„[}w%fggONNÀjH¼Ålþñã÷ 9.IUXÞ)TDüˆK'‰fõÖ×× Þ°Z­oÞ”WT444ðhö ŒÜÜÜœöö¹¹¹©ÉIÂM>AaÑ ßÚHÃœJAßPC"ˆäüâÔ îµ b~n®ãåËùùy*«g/UUU/þü³¼¼œñ ¢_@Õä.ˆ$å$nˆÃá "¡Ê§‘ãVhèá¡!X!ŠŸ![7oÝúãùsÖ&_DQq±$±;¡mŒ#«©!ºá²zfZÛî#--{9;â?ööö QüŒOòäéÓ°0ýøŽª•Š„EeDßLXÐ/Z7zKk«Ùlæv›ŒF„p]êêêbi×,ææåÍÎÌ fÑù a•+!Ý"  $$ÙP‰ ˆìÄx¥ÓÓÓËKKÔƒ˜˜˜Úº:ÅlìÆÔhµŽd aZ»ˆ=VˆAyLდ600Ðõîá2Ú«Õ‡Ry÷Þ½ß~ÿ]Ú Á`£´<$ô„ M4Ȫ wk…¨¨(„¡üò0ÛÛÛÝ]]_ûû0Y~pàîÝ»RWÃ%“°9IAþ9N‘‹@IÜ6|Z½^ÿúÕ«µµ5êŸ-66ïÅ‹þc AõôQüœ’’òðÑ£_>¤õ™ i{ãöC*%'´)É£Ä#à2ŸŒ:àÁ¢~Y‹ÅSÀqêN°ÈË˃)hni!Ì|Chri{ã­5ˆê@cbÈ+ØI ÷”ÐHBŸ,ÄàPznvÁ‚ÅÕàmuu5ƒ²²2Þ))-e¤0›°˜p¿{Aþõˆ€––f ½íìÜÜØ ~ñÄÄÄ[·oÿñü9úÍt/l`Ÿ, N¥u“çÚ¶¶Äì–º”C¨¯¯TÃ}øðáË—/Nªž ÇOŸ=k»Ÿ{*ú’Ù¦p~K¨T•Ó Y9ü„u‚Q„¨ª®zWŸñÇW¯^M³ˆ[§Óµ¿xÑÐÐÀÅ”ÁõggœãîÎaîXE£‚• G ä„H r÷ªoŸ sÑvƒë¸!úuõõ ÷ýˆ3ì-ËO–“©ÔðÑ9"l&²X,ÔãEîÈÉɧöðððÛ·o]ïÞÙ(®†º×Ö`À£ŽÔç¹Ùß!#­": luEȸ!@°ÈÍ”fcqÒ|6[WW×·¯_©7ÄAªü­ÐKR©Äöv-.íàTJµRtÞ:ùÃå2°[8À…«ªªó'®¬¬À#2LMQ¬‡Ÿ›ów 'О Þ°§þÈ‹ hŸ†°z1¨ùMB ¶®Nä‘8ˆ‰'&&^¿z…{'¿šgï“ŸmïðR…¯- *""ì°S©T´†8Q³ûyùù$߃(a(ì‹Åÿ¹N§³ïË—ïßž MêõWf“…ÞsÁäõ/ôª¸é€¸±hqaAÚSVV–&‘¦ÜÜÜ|ÛÙ948EÎãÛAž?O/??_Âmœù?Ïò¨v–Ð…°X,⊿¤,¥0ç!,„¸ãåËÙÙÙ`½ÁÑÑÑ+Óh0kbö—qëø˜°7Eq†E4EéÉ'ó‚€%^-)Žœø³‘/¹‚£##oÞX8FÓ슋‹™Úà¤ðŽj%LyÃÿ¡ÐÓÌý‘—˜/--I +¼S$—’ýýýO==Ÿ?}²_W\ÇåoïÔ¤F«eJú=§þÄ“'³¨¶qÒ$€F£!Ÿ'D¿yPjBàÏ0›ÍoÞ¼A2‡¿ä¯§„Á•ÆV«•0ýÿ‡nF‹&`˜ÈÛ§ i_’„3Ò®Tðq‹ ?{GGGS~ö>eegKëË] “ÉDªž4º”?‹9¡õ‡½½=‹tµqž'ÂÞóãããÁÁÁ·—ò'W.öì¹`£ãñ"l6Ûq’ƒúxmÊȤ±`GZ#àkbi°ØÝÝ}ÿþ}__Ÿ/W¶³³ã/g Õž‹kƒuÂ+(“’¨Ö¦_UV^·•ä ›››0Rµí Q©F?ÖÖÌ&Suuµ¿F¢øøxIö\èJ> 3G€˜ž~X ac“z½T¯jUÒª$.8==…ëﯕTòaoW‚¼Ö 7¥ @‘oN‡¿Hn1yÀl6‹¿¶–"Ôj5;Y¬s€«ä Gàý QÎ-ˆª€D~‘‰ñq‘›\.W€}’!RöRŸx‰TŒjŽ0.± €â1Œÿö÷÷çææÄ|Oý}}WPtd2ÕaGT`1›‰§G² ´WJ(g±¦¦†ü"ˆø‡ñÀÀ·oë¬Ç 111Eì¥>aT©œlêˆÓëb  °üDÉívÃá=ÁóYYY içœúžcr,/-‘wü(•Jáªt…"€g?nu5ùu­‚Ó× ì¹ø‘ò°·»KeµTEe¥€ŸV¸K—””P©Dÿþý»p{4 úþ©BeeeŒ¤>ñ1b½iÔö‚Ûj!Çà)€»ú‰ ÂëØív(é&ÿóøèåeÒ>ðLRRSââ⮬c9ó⯳¿qŠNNÀù““óÿœ°´P4ì {óé~ß³¥ÒõOqŽ·ØªªªÈwËÍÌÌd’ »£Ñø}`@¸{‡hµÚÜÜ\*cøn/ðINOccbÒ32ØiøŠúÛÛÛFÎ*•JèI^ÂF ²ªÊ_Á:wxr”_¿>þœÖ>Ãõõõþ¾>áÎ’““qã_^œìÌu •V5—]Ú‚;Ž0T ŒÇÐЕ´±±Ñûù³p7MM!!¬B`fzšÊÚ(ØOÚÙ' b-%7nue…|´ Õjýüé“pQ5"¶êšš(öjªÅÙd¢5ãŒd§-CPxÏçi¨ ’ÔêàÝ|êéNú¡±ªª«#VúÇ¥ÑTªiX!ÐÜÜLE, »½½½üÆ©C9A÷ º‘)//ÁB|Ñ\8?TKˆŠhÅð" 3+‹V‚¯ýýÁƯËKK`Ž {¹£££s™9x´\…wq‰huâž .¤uVo±X‚Êßë'&„~¦™™´’T!‡¥ÅEZ;Ï“Õj%¥¹Ÿl@©TRÌjÍÏÏÏÎÌ\ûen·»÷ógãtÁÎi”ø/Å:††1?¼¨ççZzM=cccÇÊîïí½{û–|L€°Z­Ëô¶~èt:‘k:Ä. ¹yë­¾¸4ü0ïÞ½³÷¡rDbbbú?;;;óôê!âï°›jµº–^uÇÙÙÙ—ÞÞŸ»cáïÅ\ÁÍࡱ¿¿çL1²B”(þ]HPBX[[KqºËéééçOŸl6ÛùߌŽŽÂ;ŸØ%ý0­†©)Š§éÙÙÙ’œKSC{çî]ŠÝˆt?¼ï;€äÓ'@$Y€½ÝÝI½žbNÞ£ EÿÌ@¥Rµ´¶R¼ Ïôöö.H±d &&&IÄÌäÒo0èVRUKw|.YEII ÝÍ%à€IŠI* oíg„”?lmmMQõ|ÞfΔÔT©îHÊ6¢ÖÖÖ4–vWÉ@`˜L&¸—tÏSSSu’n/–’à1ØÊ,Â>äYÀº¸H}Ë7\ÿʪ*i§Ä¤¦¾¡!Ôý‡ðŽ€ONN SSÔGvûÆ&H®þ$^Ž§PPPpàtÎH‘º¡¥RÉÎvêpâÕЫr»ˆÒ²²Té\V ðîÎËÏw8F‰BXÒ8|€ÍÍÍÅ…!ZçòòòrØØ\Ï„êB(¬+*:>>ö7ñXŽ€EÆéé)D_ ×‘žžÎÎêb&G099¹¬¼üØåÚ§TU+€7ìvûÜì¬nÏàKø2Ÿî <éšššÐê%ŽŽhh«$€·³²²¢Ÿ˜Húëêë™ ™X!@LL T) PuBúÃæ ¶wltÔd4 Ô9×P_ÏZÖ›¡U"))) ¤¿¡±1TJ‹ÃÃÿq»Ý z½žÊ,·«]íØØú††ffx±H¨R_^ hlj „: ìÍfóððð†£áá(°³Y.ÅÖ2)x>™˜˜; Â\$B„tÔf³ŽŒx&˜ Ù8ÝWÉÔöev  ð¦D}¿A4ÜÔÜ̲ÀgKdϦsÁîÎÎÄøøÌô´p>ÏEχYéW0’ýW¢ !¶Ò7O×ÇýÄ„h{bÂÞÿÙÙÙA˜»'J®ÆœYχ](¼)Qh&_.|&õúööW‡P ¦Õj…è‹öakëêØOj³HØM(×ýýýsON¤ajJ´w®` ”åZÀx"ÀÝØØà7NwhTSSu¾ŒVqN§ó¼éÎw> º$î@€Î²k{vvG}}>È?:##£²²2&D ý”ÑÑÑp„¶··/ \EEE’RÉÈ&÷´ôtÀàêÀ¿ß²Z·¶¶é9¹¹¥¥¥!t8È.MU*|·Û}þ7žÚéÂÂ$•Šî4~`j ÖÉÉ ôý6´ýö¶˜Ã`.o§¬¬LËFgÛl63ûᎎŽ®,H„w4m0H›‚‚Ÿ–šæ¸*þŽ:(xûþþB¥½½óxI* NƒÓŠAL@áí¾2W =·0?q”1* ñ^¿Ê‹¤¤$!|¸õ‡ÃéðZ@r3øw2 %……Þ®ð$‘œ¿7m±X–hìâ¤Î¥R™xÿ\ˆAw¹\ðý\°q.×Láá!þĈÄ_DAAA¡è=#ˆÀîîn€(”¢ajŠÍ“²+'Dóøûï*Hö©¾M©!q/p{ øSC!Ú€@@Ó ¨UØöo$œ‘™Y^^ó€£BBnàò^›ÏC†/fdX°Ò²2ŠÓ]ep"k…¾ŒâÀn—™™ éƒQN¡G)Ñ+}Ó±ÑQ’e’2®|ªeåå @˜ÝWÈ ´Iô‚K¯* ECc£g¹|__¨”LëȨ¨¼¼¼‚°B±#$;¨]TxaÛ6›^¯—…˜7Ò32JJJÂxë}Th%O # ê[æç笭ÉÒ’’’Š‹‹A€0·o¡E€kS¢þŒ8¬ÁÈÈHÈ ’ÊÛÔeeeEÂÌ÷¨KŸÛív~.^'˜ƒø˜ÁÞFkY¨Óegg‡îÉnøÑ-"Þ5 ëøØ`0ëJ…½ÃSPP™•9¢ª·¶¶/;°²¼,~¿kHMM…è§Eê–鶴 ØÜܤRÿãë4™L‘–0…¦×jµ­–å¾6™~ár¹|k!iÅÖ¶­-<ŠHð‹TÉɹ¹¹ˆqÙ»$ ¶··N'Ýk lY­‹%TÊKƒ p5 ¼üpšæÑ8==…¤ T"ï°ÛmÛÛ›âSqqqÙ ô}䬲ŒÞ~@aSû¸wwvr„–w¤V«¡ìÓÓҔ´§… B»º¯r)èø¥¹yy0{»»6›M艂ü””äéQNMMV«Ã©`S¶¡¿3Øív;½]¹>$É…o©BJŠÚÛŽ ' ÚSdðÁ†¤ž:‚ütOãîá!ØVÀ( ‘TMò"Q©ôý&„6‰È.€HOO§˜ Z…DE%x¡¸°õÞír¹ON`(ðËåÅ þxrrzò7~6ÐßÐèò蘘¸ØXø0qÞ>ú/Ãx«L"@JÎJ3‚8¯øÊâÅ>¤ð±Ÿœë¹ðíØ“_§Œ%€âŸ{ò•¡8ß±'CF$@qaÇž ‘HÅ…{2dD"Âx„ ™œŒ€œ•¹ˆð.'M…·ÏUN‰Êˆ\ÀJ Áu=2dPƒ\,#¢  S¢2"œÞ%]rJTF¤@!§DeD8䔨Œˆ&€Â[%ió.eȸp‡ÑÑrJTFä@áž"§De\‰ÿ`¼µÏ=Ü› —IEND®B`‚freemius/assets/js/nojquery.ba-postmessage.js000064400000011135146725417150015441 0ustar00/*! * jQuery postMessage - v0.5 - 9/11/2009 * http://benalman.com/projects/jquery-postmessage-plugin/ * * Copyright (c) 2009 "Cowboy" Ben Alman * Dual licensed under the MIT and GPL licenses. * http://benalman.com/about/license/ * * Non-jQuery fork by Jeff Lee * * This fork consists of the following changes: * 1. Basic code cleanup and restructuring, for legibility. * 2. The `postMessage` and `receiveMessage` functions can be bound arbitrarily, * in terms of both function names and object scope. Scope is specified by * the the "this" context of NoJQueryPostMessageMixin(); * 3. I've removed the check for Opera 9.64, which used `$.browser`. There were * at least three different GitHub users requesting the removal of this * "Opera sniff" on the original project's Issues page, so I figured this * would be a relatively safe change. * 4. `postMessage` no longer uses `$.param` to serialize messages that are not * strings. I actually prefer this structure anyway. `receiveMessage` does * not implement a corresponding deserialization step, and as such it seems * cleaner and more symmetric to leave both data serialization and * deserialization to the client. * 5. The use of `$.isFunction` is replaced by a functionally-identical check. * 6. The `$:nomunge` YUI option is no longer necessary. */ function NoJQueryPostMessageMixin(postBinding, receiveBinding) { var setMessageCallback, unsetMessageCallback, currentMsgCallback, intervalId, lastHash, cacheBust = 1; if (window.postMessage) { if (window.addEventListener) { setMessageCallback = function(callback) { window.addEventListener('message', callback, false); } unsetMessageCallback = function(callback) { window.removeEventListener('message', callback, false); } } else { setMessageCallback = function(callback) { window.attachEvent('onmessage', callback); } unsetMessageCallback = function(callback) { window.detachEvent('onmessage', callback); } } this[postBinding] = function(message, targetUrl, target) { if (!targetUrl) { return; } // The browser supports window.postMessage, so call it with a targetOrigin // set appropriately, based on the targetUrl parameter. target.postMessage( message, targetUrl.replace( /([^:]+:\/\/[^\/]+).*/, '$1' ) ); } // Since the browser supports window.postMessage, the callback will be // bound to the actual event associated with window.postMessage. this[receiveBinding] = function(callback, sourceOrigin, delay) { // Unbind an existing callback if it exists. if (currentMsgCallback) { unsetMessageCallback(currentMsgCallback); currentMsgCallback = null; } if (!callback) { return false; } // Bind the callback. A reference to the callback is stored for ease of // unbinding. currentMsgCallback = setMessageCallback(function(e) { switch(Object.prototype.toString.call(sourceOrigin)) { case '[object String]': if (sourceOrigin !== e.origin) { return false; } break; case '[object Function]': if (sourceOrigin(e.origin)) { return false; } break; } callback(e); }); }; } else { this[postBinding] = function(message, targetUrl, target) { if (!targetUrl) { return; } // The browser does not support window.postMessage, so set the location // of the target to targetUrl#message. A bit ugly, but it works! A cache // bust parameter is added to ensure that repeat messages trigger the // callback. target.location = targetUrl.replace( /#.*$/, '' ) + '#' + (+new Date) + (cacheBust++) + '&' + message; } // Since the browser sucks, a polling loop will be started, and the // callback will be called whenever the location.hash changes. this[receiveBinding] = function(callback, sourceOrigin, delay) { if (intervalId) { clearInterval(intervalId); intervalId = null; } if (callback) { delay = typeof sourceOrigin === 'number' ? sourceOrigin : typeof delay === 'number' ? delay : 100; intervalId = setInterval(function(){ var hash = document.location.hash, re = /^#?\d+&/; if ( hash !== lastHash && re.test( hash ) ) { lastHash = hash; callback({ data: hash.replace( re, '' ) }); } }, delay ); } }; } return this; }freemius/assets/js/index.php000064400000000127146725417150012135 0ustar00 0) { $window.on('scroll', function () { for (var i = 0; i < iframes.length; i++) { FS.PostMessage.postScroll(iframes[i]); } }); } }, init_child : function () { this.init(_parent_subdomain); _is_child = true; // Post height of a child right after window is loaded. $(window).bind('load', function () { FS.PostMessage.postHeight(); // Post message that window was loaded. FS.PostMessage.post('loaded'); }); }, hasParent : function () { return _hasParent; }, postHeight : function (diff, wrapper) { diff = diff || 0; wrapper = wrapper || '#wrap_section'; this.post('height', { height: diff + $(wrapper).outerHeight(true) }); }, postScroll : function (iframe) { this.post('scroll', { top: $window.scrollTop(), height: ($window.height() - parseFloat($html.css('paddingTop')) - parseFloat($html.css('marginTop'))) }, iframe); }, post : function (type, data, iframe) { console.debug('PostMessage.post', type); if (iframe) { // Post to iframe. _postman.postMessage(JSON.stringify({ type: type, data: data }), iframe.src, iframe.contentWindow); } else { // Post to parent. _postman.postMessage(JSON.stringify({ type: type, data: data }), _parent_url, window.parent); } }, receive: function (type, callback) { console.debug('PostMessage.receive', type); if (undef === _callbacks[type]) _callbacks[type] = []; _callbacks[type].push(callback); }, receiveOnce: function (type, callback) { if (this.is_set(type)) return; this.receive(type, callback); }, // Check if any callbacks assigned to a specified message type. is_set: function (type) { return (undef != _callbacks[type]); }, parent_url: function () { return _parent_url; }, parent_subdomain: function () { return _parent_subdomain; } }; }(); })(jQuery);freemius/assets/js/nojquery.ba-postmessage.min.js000064400000002453146725417150016226 0ustar00/* * nojquery-postmessage by Jeff Lee * a non-jQuery fork of: * * jQuery postMessage - v0.5 - 9/11/2009 * http://benalman.com/projects/jquery-postmessage-plugin/ * * Copyright (c) 2009 "Cowboy" Ben Alman * Dual licensed under the MIT and GPL licenses. * http://benalman.com/about/license/ */ function NoJQueryPostMessageMixin(g,a){var b,h,e,d,f,c=1;if(window.postMessage){if(window.addEventListener){b=function(i){window.addEventListener("message",i,false)};h=function(i){window.removeEventListener("message",i,false)}}else{b=function(i){window.attachEvent("onmessage",i)};h=function(i){window.detachEvent("onmessage",i)}}this[g]=function(i,k,j){if(!k){return}j.postMessage(i,k.replace(/([^:]+:\/\/[^\/]+).*/,"$1"))};this[a]=function(k,j,i){if(e){h(e);e=null}if(!k){return false}e=b(function(l){switch(Object.prototype.toString.call(j)){case"[object String]":if(j!==l.origin){return false}break;case"[object Function]":if(j(l.origin)){return false}break}k(l)})}}else{this[g]=function(i,k,j){if(!k){return}j.location=k.replace(/#.*$/,"")+"#"+(+new Date)+(c++)+"&"+i};this[a]=function(k,j,i){if(d){clearInterval(d);d=null}if(k){i=typeof j==="number"?j:typeof i==="number"?i:100;d=setInterval(function(){var m=document.location.hash,l=/^#?\d+&/;if(m!==f&&l.test(m)){f=m;k({data:m.replace(l,"")})}},i)}}}return this};freemius/assets/css/index.php000064400000000127146725417150012311 0ustar00table.widefat{border:none !important}#fs_sites .fs-scrollable-table .fs-main-column{width:100%}#fs_sites .fs-scrollable-table .fs-site-details td:first-of-type{text-align:right;color:gray;width:1px}#fs_sites .fs-scrollable-table .fs-site-details td:last-of-type{text-align:right}#fs_sites .fs-scrollable-table .fs-install-details table tr td{width:1px;white-space:nowrap}#fs_sites .fs-scrollable-table .fs-install-details table tr td:last-of-type{width:auto}#fs_addons h3{border:none;margin-bottom:0;padding:4px 5px}#fs_addons td{vertical-align:middle}#fs_addons thead{white-space:nowrap}#fs_addons td:first-child,#fs_addons th:first-child{text-align:left;font-weight:bold}#fs_addons td:last-child,#fs_addons th:last-child{text-align:right}#fs_addons th{font-weight:bold}#fs_billing_address{width:100%}#fs_billing_address tr td{width:50%;padding:5px}#fs_billing_address tr:first-of-type td{padding-top:0}#fs_billing_address span{font-weight:bold}#fs_billing_address input,#fs_billing_address select{display:block;width:100%;margin-top:5px}#fs_billing_address input::-moz-placeholder,#fs_billing_address select::-moz-placeholder{color:transparent;opacity:1}#fs_billing_address input:-ms-input-placeholder,#fs_billing_address select:-ms-input-placeholder{color:transparent}#fs_billing_address input::-webkit-input-placeholder,#fs_billing_address select::-webkit-input-placeholder{color:transparent}#fs_billing_address input.fs-read-mode,#fs_billing_address select.fs-read-mode{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode td span{display:none}#fs_billing_address.fs-read-mode input,#fs_billing_address.fs-read-mode select{border-color:transparent;color:#777;border-bottom:1px dashed #ccc;padding-left:0;background:none}#fs_billing_address.fs-read-mode input::-moz-placeholder,#fs_billing_address.fs-read-mode select::-moz-placeholder{color:#ccc;opacity:1}#fs_billing_address.fs-read-mode input:-ms-input-placeholder,#fs_billing_address.fs-read-mode select:-ms-input-placeholder{color:#ccc}#fs_billing_address.fs-read-mode input::-webkit-input-placeholder,#fs_billing_address.fs-read-mode select::-webkit-input-placeholder{color:#ccc}#fs_billing_address button{display:block;width:100%}@media screen and (max-width: 639px){#fs_account .fs-header-actions{position:static;padding:0 15px 12px 15px;margin:0 0 12px 0}#fs_account .fs-header-actions li{float:none;display:inline-block}#fs_account #fs_account_details{display:block}#fs_account #fs_account_details tbody,#fs_account #fs_account_details tr,#fs_account #fs_account_details td,#fs_account #fs_account_details th{display:block}#fs_account #fs_account_details tr td:first-child{text-align:left}#fs_account #fs_account_details tr td:nth-child(2){padding:0 12px}#fs_account #fs_account_details tr td:nth-child(2) code{margin:0;padding:0}#fs_account #fs_account_details tr td:nth-child(2) label{margin-left:0}#fs_account #fs_account_details tr td:nth-child(3){text-align:left}#fs_account #fs_account_details tr.fs-field-plan td:nth-child(2) .button-group{float:none;margin:12px 0}} freemius/assets/css/admin/common.css000064400000013735146725417150013574 0ustar00.fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:#fff;text-transform:uppercase;padding:5px 10px;-moz-border-radius:3px 0 0 3px;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;font-weight:bold;border-right:0;-moz-box-shadow:0 2px 1px -1px rgba(0,0,0,.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,.3);box-shadow:0 2px 1px -1px rgba(0,0,0,.3)}.theme-browser .theme .fs-premium-theme-badge-container{position:absolute;right:0;top:0}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge{position:relative;top:0;margin-top:10px;text-align:center}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-premium-theme-badge{font-size:1.1em}.theme-browser .theme .fs-premium-theme-badge-container .fs-badge.fs-beta-theme-badge{background:#00a0d2}.fs-switch{position:relative;display:inline-block;color:#ccc;text-shadow:0 1px 1px rgba(255,255,255,.8);height:18px;padding:6px 6px 5px 6px;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);background:#ececec;box-shadow:0 0 4px rgba(0,0,0,.1),inset 0 1px 3px 0 rgba(0,0,0,.1);cursor:pointer}.fs-switch span{display:inline-block;width:35px;text-transform:uppercase}.fs-switch .fs-toggle{position:absolute;top:1px;width:37px;height:25px;border:1px solid #ccc;border:1px solid rgba(0,0,0,.3);border-radius:4px;background:#fff;background-color:#fff;background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #ececec), color-stop(1, #fff));background-image:-webkit-linear-gradient(top, #ececec, #fff);background-image:-moz-linear-gradient(top, #ececec, #fff);background-image:-ms-linear-gradient(top, #ececec, #fff);background-image:-o-linear-gradient(top, #ececec, #fff);background-image:linear-gradient(top, bottom, #ececec, #fff);box-shadow:inset 0 1px 0 0 rgba(255,255,255,.5);z-index:999;-moz-transition:.4s cubic-bezier(0.54, 1.6, 0.5, 1);-o-transition:.4s cubic-bezier(0.54, 1.6, 0.5, 1);-ms-transition:.4s cubic-bezier(0.54, 1.6, 0.5, 1);-webkit-transition:.4s cubic-bezier(0.54, 1.6, 0.5, 1);transition:.4s cubic-bezier(0.54, 1.6, 0.5, 1)}.fs-switch.fs-off .fs-toggle{left:2%}.fs-switch.fs-on .fs-toggle{left:54%}.fs-switch.fs-round{top:8px;padding:4px 25px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round .fs-toggle{top:0;width:24px;height:24px;-moz-border-radius:24px;-webkit-border-radius:24px;border-radius:24px}.fs-switch.fs-round.fs-off .fs-toggle{left:-1px}.fs-switch.fs-round.fs-on{background:#0085ba}.fs-switch.fs-round.fs-on .fs-toggle{left:25px}.fs-switch.fs-small.fs-round{padding:1px 19px}.fs-switch.fs-small.fs-round .fs-toggle{top:0;width:18px;height:18px;-moz-border-radius:18px;-webkit-border-radius:18px;border-radius:18px}.fs-switch.fs-small.fs-round.fs-on .fs-toggle{left:19px}body.fs-loading,body.fs-loading *{cursor:wait !important}#fs_frame{line-height:0;font-size:0}.fs-full-size-wrapper{margin:40px 0 -65px -20px}@media(max-width: 600px){.fs-full-size-wrapper{margin:0 0 -65px -10px}}.fs-notice{position:relative}.fs-notice.fs-has-title{margin-bottom:30px !important}.fs-notice.success{color:green}.fs-notice.promotion{border-color:#00a0d2 !important;background-color:#f2fcff !important}.fs-notice .fs-notice-body{margin:.5em 0;padding:2px}.fs-notice .fs-close{cursor:pointer;color:#aaa;float:right}.fs-notice .fs-close:hover{color:#666}.fs-notice .fs-close>*{margin-top:7px;display:inline-block}.fs-notice label.fs-plugin-title{background:rgba(0,0,0,.3);color:#fff;padding:2px 10px;position:absolute;top:100%;bottom:auto;right:auto;-moz-border-radius:0 0 3px 3px;-webkit-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;left:10px;font-size:12px;font-weight:bold;cursor:auto}div.fs-notice.updated,div.fs-notice.success,div.fs-notice.promotion{display:block !important}#fs_connect .fs-error ol,#fs_connect .fs-error .fs-api-request-error-show-details-link,#fs_connect .fs-error .fs-api-request-error-details,.fs-modal .notice-error ol,.fs-modal .notice-error .fs-api-request-error-show-details-link,.fs-modal .notice-error .fs-api-request-error-details,.fs-notice.error ol,.fs-notice.error .fs-api-request-error-show-details-link,.fs-notice.error .fs-api-request-error-details{text-align:left}#fs_connect .fs-error ol,.fs-modal .notice-error ol,.fs-notice.error ol{list-style-type:disc}#fs_connect .fs-error .fs-api-request-error-show-details-link,.fs-modal .notice-error .fs-api-request-error-show-details-link,.fs-notice.error .fs-api-request-error-show-details-link{text-decoration:none;color:#2271b1;box-shadow:none}#fs_connect .fs-error .fs-api-request-error-details,.fs-modal .notice-error .fs-api-request-error-details,.fs-notice.error .fs-api-request-error-details{border:1px solid #ccc;padding:5px;overflow:auto;max-height:150px}.rtl .fs-notice .fs-close{float:left}.fs-secure-notice{position:fixed;top:32px;left:160px;right:0;background:#ebfdeb;padding:10px 20px;color:green;z-index:9999;-moz-box-shadow:0 2px 2px rgba(6,113,6,.3);-webkit-box-shadow:0 2px 2px rgba(6,113,6,.3);box-shadow:0 2px 2px rgba(6,113,6,.3);opacity:.95;filter:alpha(opacity=95)}.fs-secure-notice:hover{opacity:1;filter:alpha(opacity=100)}.fs-secure-notice a.fs-security-proof{color:green;text-decoration:none}@media screen and (max-width: 960px){.fs-secure-notice{left:36px}}@media screen and (max-width: 600px){.fs-secure-notice{display:none}}@media screen and (max-width: 1250px){#fs_promo_tab{display:none}}@media screen and (max-width: 782px){.fs-secure-notice{left:0;top:46px;text-align:center}}span.fs-submenu-item.fs-sub:before{content:"↳";padding:0 5px}.rtl span.fs-submenu-item.fs-sub:before{content:"↲"}.fs-submenu-item.pricing.upgrade-mode{color:#adff2f}.fs-submenu-item.pricing.trial-mode{color:#83e2ff}#adminmenu .update-plugins.fs-trial{background-color:#00b9eb}.fs-ajax-spinner{border:0;width:20px;height:20px;margin-right:5px;vertical-align:sub;display:inline-block;background:url("/wp-admin/images/wpspin_light-2x.gif");background-size:contain;margin-bottom:-2px}.wrap.fs-section h2{text-align:left}.plugins p.fs-upgrade-notice{border:0;background-color:#d54e21;padding:10px;color:#f9f9f9;margin-top:10px} freemius/assets/css/admin/optout.css000064400000010054146725417150013625 0ustar00.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .dashicons{float:none !important}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity .3s ease-in-out;-o-transition:opacity .3s ease-in-out;-ms-transition:opacity .3s ease-in-out;-webkit-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;position:absolute;background:rgba(0,0,0,.8);color:#fff !important;font-family:"arial",serif;font-size:12px;padding:10px;z-index:999999;bottom:100%;margin-bottom:5px;left:-17px;right:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(0,0,0,.2);line-height:1.3em;font-weight:bold;text-align:left;text-transform:none !important}.rtl .fs-tooltip-trigger .fs-tooltip{text-align:right;left:auto;right:-17px}.fs-tooltip-trigger .fs-tooltip::after{content:" ";display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:rgba(0,0,0,.8) transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl .fs-tooltip-trigger .fs-tooltip::after{right:21px;left:auto}.fs-tooltip-trigger:hover .fs-tooltip{visibility:visible;opacity:1}.fs-permissions .fs-permission.fs-disabled{color:#aaa}.fs-permissions .fs-permission.fs-disabled .fs-permission-description span{color:#aaa}.fs-permissions .fs-permission .fs-switch-feedback{position:absolute;right:15px;top:52px}.fs-permissions ul{height:0;overflow:hidden;margin:0}.fs-permissions ul li{padding:17px 15px;margin:0;position:relative}.fs-permissions ul li>i.dashicons{float:left;font-size:30px;width:30px;height:30px;padding:5px}.fs-permissions ul li .fs-switch{float:right}.fs-permissions ul li .fs-permission-description{margin-left:55px}.fs-permissions ul li .fs-permission-description span{font-size:14px;font-weight:500;color:#23282d}.fs-permissions ul li .fs-permission-description .fs-tooltip{font-size:13px;font-weight:bold}.fs-permissions ul li .fs-permission-description .fs-tooltip-trigger .dashicons{margin:-1px 2px 0 2px}.fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}.fs-permissions.fs-open{background:#fff}.fs-permissions.fs-open ul{overflow:initial;height:auto;margin:20px 0 10px 0}.fs-permissions .fs-switch-feedback .fs-ajax-spinner{margin-right:10px}.fs-permissions .fs-switch-feedback.success{color:#71ae00}.rtl .fs-permissions .fs-switch-feedback{right:auto;left:15px}.rtl .fs-permissions .fs-switch-feedback .fs-ajax-spinner{margin-left:10px;margin-right:0}.rtl .fs-permissions ul li .fs-permission-description{margin-right:55px;margin-left:0}.rtl .fs-permissions ul li .fs-switch{float:left}.rtl .fs-permissions ul li i.dashicons{float:right}.fs-modal-opt-out .fs-modal-footer .fs-opt-out-button{line-height:30px;margin-right:10px}.fs-modal-opt-out .fs-permissions{margin-top:0 !important}.fs-modal-opt-out .fs-permissions .fs-permissions-section--header .fs-group-opt-out-button{float:right;line-height:1.1em}.fs-modal-opt-out .fs-permissions .fs-permissions-section--header .fs-switch-feedback{float:right;line-height:1.1em;margin-right:10px}.fs-modal-opt-out .fs-permissions .fs-permissions-section--header .fs-switch-feedback .fs-ajax-spinner{margin:-2px 0 0}.fs-modal-opt-out .fs-permissions .fs-permissions-section--header-title{font-size:1.1em;font-weight:600;text-transform:uppercase;display:block;line-height:1.1em;margin:.5em 0}.fs-modal-opt-out .fs-permissions .fs-permissions-section--desc{margin-top:0}.fs-modal-opt-out .fs-permissions hr{border:0;border-top:#eee solid 1px;margin:25px 0 20px 0}.fs-modal-opt-out .fs-permissions ul{border:1px solid #c3c4c7;border-radius:3px;margin:10px 0 0 0;box-shadow:0 1px 1px rgba(0,0,0,.04)}.fs-modal-opt-out .fs-permissions ul li{border-bottom:1px solid #d7dde1;border-left:4px solid #72aee6}.rtl .fs-modal-opt-out .fs-permissions ul li{border-left:none;border-right:4px solid #72aee6}.fs-modal-opt-out .fs-permissions ul li.fs-disabled{border-left-color:rgba(114,174,230,0)}.fs-modal-opt-out .fs-permissions ul li:last-child{border-bottom:none} freemius/assets/css/admin/index.php000064400000000127146725417150013401 0ustar00.fs-trigger{font-size:.9em;text-decoration:none;text-align:center;display:block}#fs_connect .fs-permissions>.fs-trigger .fs-arrow::after{content:"→";width:20px;display:inline-block}#fs_connect .fs-permissions.fs-open>.fs-trigger .fs-arrow::after{content:"↓" !important}#fs_connect .fs-permissions ul li{padding-left:0;padding-right:0}@media screen and (max-width: 483px){#fs_connect .fs-permissions ul{height:auto;margin:20px}}#fs_connect .fs-freemium-licensing{padding:8px;background:#777;color:#fff}#fs_connect .fs-freemium-licensing p{text-align:center;display:block;margin:0;padding:0}#fs_connect .fs-freemium-licensing a{color:inherit;text-decoration:underline}#fs_connect .fs-header{padding:0;line-height:0;height:0;position:relative}#fs_connect .fs-header .fs-site-icon,#fs_connect .fs-header .fs-connect-logo{position:absolute;top:-8px;border-radius:50%}#fs_connect .fs-header .fs-site-icon{left:152px}#fs_connect .fs-header .fs-connect-logo{right:152px}#fs_connect .fs-header .fs-site-icon,#fs_connect .fs-header img,#fs_connect .fs-header object{width:50px;height:50px;border-radius:50%}#fs_connect .fs-header .fs-plugin-icon{position:absolute;overflow:hidden;top:-23px;left:50%;margin-left:-44px;border-radius:50%;z-index:1}#fs_connect .fs-header .fs-plugin-icon,#fs_connect .fs-header .fs-plugin-icon img{width:80px;height:80px}#fs_connect .fs-header .dashicons-wordpress-alt{font-size:40px;background:#01749a;color:#fff;width:40px;height:40px;padding:5px;border-radius:50%}#fs_connect .fs-header .dashicons-plus{position:absolute;top:50%;font-size:30px;margin-top:-10px;color:#bbb}#fs_connect .fs-header .dashicons-plus.fs-first{left:28%}#fs_connect .fs-header .dashicons-plus.fs-second{left:65%}#fs_connect .fs-header .fs-plugin-icon,#fs_connect .fs-header .fs-connect-logo,#fs_connect .fs-header .fs-site-icon{border:1px solid #efefef;padding:3px;background:#fff}#fs_connect .fs-terms{text-align:center;font-size:.85em;padding:10px 5px}#fs_connect .fs-terms,#fs_connect .fs-terms a{color:#999}#fs_connect .fs-terms a{text-decoration:none}.fs-multisite-options-container{margin-top:20px;border:1px solid #ccc;padding:5px}.fs-multisite-options-container a{text-decoration:none}.fs-multisite-options-container a:focus{box-shadow:none}.fs-multisite-options-container a.selected{font-weight:bold}.fs-multisite-options-container.fs-apply-on-all-sites{border:0 none;padding:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options{border-spacing:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options td:not(:first-child){display:none}.fs-multisite-options-container .fs-sites-list-container{display:none;overflow:auto}.fs-multisite-options-container .fs-sites-list-container table td{border-top:1px solid #ccc;padding:4px 2px}#fs_marketing_optin{display:none;margin-top:10px;border:1px solid #ccc;padding:10px;line-height:1.5em}#fs_marketing_optin .fs-message{display:block;margin-bottom:5px;font-size:1.05em;font-weight:600}#fs_marketing_optin.error{border:1px solid #d3135a;background:#fee}#fs_marketing_optin.error .fs-message{color:#d3135a}#fs_marketing_optin .fs-input-container{margin-top:5px}#fs_marketing_optin .fs-input-container label{margin-top:5px;display:block}#fs_marketing_optin .fs-input-container label input{float:left;margin:1px 0 0 0}#fs_marketing_optin .fs-input-container label:first-child{display:block;margin-bottom:2px}#fs_marketing_optin .fs-input-label{display:block;margin-left:20px}#fs_marketing_optin .fs-input-label .underlined{text-decoration:underline}.rtl #fs_marketing_optin .fs-input-container label input{float:right}.rtl #fs_marketing_optin .fs-input-label{margin-left:0;margin-right:20px}.rtl #fs_connect{border-radius:3px}.rtl #fs_connect .fs-actions{padding:10px 20px;background:#c0c7ca}.rtl #fs_connect .fs-actions .button .dashicons{font-size:37px;margin-left:-8px;margin-right:12px}.rtl #fs_connect .fs-actions .button.button-primary:after{content:" »"}.rtl #fs_connect .fs-actions .button.button-primary.fs-loading:after{content:""}.rtl #fs_connect .fs-actions .button.button-secondary{float:left}.rtl #fs_connect .fs-header .fs-site-icon{right:20px;left:auto}.rtl #fs_connect .fs-header .fs-connect-logo{right:auto;left:20px}.rtl #fs_connect .fs-permissions>.fs-trigger .fs-arrow::after{content:"â†"}#fs_theme_connect_wrapper{position:fixed;top:0;height:100%;width:100%;z-index:99990;background:rgba(0,0,0,.75);text-align:center;overflow-y:auto}#fs_theme_connect_wrapper:before{content:"";display:inline-block;vertical-align:middle;height:100%}#fs_theme_connect_wrapper>button.close{color:#fff;cursor:pointer;height:40px;width:40px;position:absolute;right:0;border:0;background-color:transparent;top:32px}#fs_theme_connect_wrapper #fs_connect{top:0;text-align:left;display:inline-block;vertical-align:middle;margin-top:0;margin-bottom:20px}#fs_theme_connect_wrapper #fs_connect .fs-terms,#fs_theme_connect_wrapper #fs_connect .fs-terms a{color:#c5c5c5}.wp-pointer-content #fs_connect{margin:0;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.fs-opt-in-pointer .wp-pointer-content{padding:0}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow{border-bottom-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-top .wp-pointer-arrow-inner{border-bottom-color:#fafafa}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow{border-top-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-bottom .wp-pointer-arrow-inner{border-top-color:#fafafa}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow{border-right-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-left .wp-pointer-arrow-inner{border-right-color:#fafafa}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow{border-left-color:#dfdfdf}.fs-opt-in-pointer.wp-pointer-right .wp-pointer-arrow-inner{border-left-color:#fafafa}#license_issues_link{display:block;text-align:center;font-size:.9em;margin-top:10px}.fs-tooltip-trigger{position:relative}.fs-tooltip-trigger:not(a){cursor:help}.fs-tooltip-trigger .dashicons{float:none !important}.fs-tooltip-trigger .fs-tooltip{opacity:0;visibility:hidden;-moz-transition:opacity .3s ease-in-out;-o-transition:opacity .3s ease-in-out;-ms-transition:opacity .3s ease-in-out;-webkit-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;position:absolute;background:rgba(0,0,0,.8);color:#fff !important;font-family:"arial",serif;font-size:12px;padding:10px;z-index:999999;bottom:100%;margin-bottom:5px;left:-17px;right:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(0,0,0,.2);line-height:1.3em;font-weight:bold;text-align:left;text-transform:none !important}.rtl .fs-tooltip-trigger .fs-tooltip{text-align:right;left:auto;right:-17px}.fs-tooltip-trigger .fs-tooltip::after{content:" ";display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:rgba(0,0,0,.8) transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl .fs-tooltip-trigger .fs-tooltip::after{right:21px;left:auto}.fs-tooltip-trigger:hover .fs-tooltip{visibility:visible;opacity:1}.fs-permissions .fs-permission.fs-disabled{color:#aaa}.fs-permissions .fs-permission.fs-disabled .fs-permission-description span{color:#aaa}.fs-permissions .fs-permission .fs-switch-feedback{position:absolute;right:15px;top:52px}.fs-permissions ul{height:0;overflow:hidden;margin:0}.fs-permissions ul li{padding:17px 15px;margin:0;position:relative}.fs-permissions ul li>i.dashicons{float:left;font-size:30px;width:30px;height:30px;padding:5px}.fs-permissions ul li .fs-switch{float:right}.fs-permissions ul li .fs-permission-description{margin-left:55px}.fs-permissions ul li .fs-permission-description span{font-size:14px;font-weight:500;color:#23282d}.fs-permissions ul li .fs-permission-description .fs-tooltip{font-size:13px;font-weight:bold}.fs-permissions ul li .fs-permission-description .fs-tooltip-trigger .dashicons{margin:-1px 2px 0 2px}.fs-permissions ul li .fs-permission-description p{margin:2px 0 0 0}.fs-permissions.fs-open{background:#fff}.fs-permissions.fs-open ul{overflow:initial;height:auto;margin:20px 0 10px 0}.fs-permissions .fs-switch-feedback .fs-ajax-spinner{margin-right:10px}.fs-permissions .fs-switch-feedback.success{color:#71ae00}.rtl .fs-permissions .fs-switch-feedback{right:auto;left:15px}.rtl .fs-permissions .fs-switch-feedback .fs-ajax-spinner{margin-left:10px;margin-right:0}.rtl .fs-permissions ul li .fs-permission-description{margin-right:55px;margin-left:0}.rtl .fs-permissions ul li .fs-switch{float:left}.rtl .fs-permissions ul li i.dashicons{float:right} freemius/assets/css/admin/checkout.css000064400000000123146725417150014074 0ustar00@media screen and (max-width: 782px){#wpbody-content{padding-bottom:0 !important}} freemius/assets/css/admin/add-ons.css000064400000027766146725417150013642 0ustar00.fs-badge{position:absolute;top:10px;right:0;background:#71ae00;color:#fff;text-transform:uppercase;padding:5px 10px;-moz-border-radius:3px 0 0 3px;-webkit-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;font-weight:bold;border-right:0;-moz-box-shadow:0 2px 1px -1px rgba(0,0,0,.3);-webkit-box-shadow:0 2px 1px -1px rgba(0,0,0,.3);box-shadow:0 2px 1px -1px rgba(0,0,0,.3)}#fs_addons .fs-cards-list{list-style:none}#fs_addons .fs-cards-list .fs-card{float:left;height:152px;width:310px;padding:0;margin:0 0 30px 30px;font-size:14px;list-style:none;border:1px solid #ddd;cursor:pointer;position:relative}#fs_addons .fs-cards-list .fs-card .fs-overlay{position:absolute;left:0;right:0;bottom:0;top:0;z-index:9}#fs_addons .fs-cards-list .fs-card .fs-inner{background-color:#fff;overflow:hidden;height:100%;position:relative}#fs_addons .fs-cards-list .fs-card .fs-inner>ul{-moz-transition:all,.15s;-o-transition:all,.15s;-ms-transition:all,.15s;-webkit-transition:all,.15s;transition:all,.15s;left:0;right:0;top:0;position:absolute}#fs_addons .fs-cards-list .fs-card .fs-inner>ul>li{list-style:none;line-height:18px;padding:0 15px;width:100%;display:block;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-card-banner{padding:0;margin:0;line-height:0;display:block;height:100px;background-repeat:repeat-x;background-size:100% 100%;-moz-transition:all,.15s;-o-transition:all,.15s;-ms-transition:all,.15s;-webkit-transition:all,.15s;transition:all,.15s}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-card-banner .fs-badge.fs-installed-addon-badge{font-size:1.02em;line-height:1.3em}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-title{margin:10px 0 0 0;height:18px;overflow:hidden;color:#000;white-space:nowrap;text-overflow:ellipsis;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-offer{font-size:.9em}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-description{background-color:#f9f9f9;padding:10px 15px 100px 15px;border-top:1px solid #eee;margin:0 0 10px 0;color:#777}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-tag{position:absolute;top:10px;right:0px;background:#adff2f;display:block;padding:2px 10px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,.3);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.3);box-shadow:1px 1px 1px rgba(0,0,0,.3);text-transform:uppercase;font-size:.9em;font-weight:bold}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-cta .button,#fs_addons .fs-cards-list .fs-card .fs-inner .fs-cta .button-group{position:absolute;top:112px;right:10px}@media screen and (min-width: 960px){#fs_addons .fs-cards-list .fs-card:hover .fs-overlay{border:2px solid #29abe1;margin-left:-1px;margin-top:-1px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner ul{top:-100px}#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-title,#fs_addons .fs-cards-list .fs-card:hover .fs-inner .fs-offer{color:#29abe1}}#TB_window,#TB_window iframe{width:821px !important}#plugin-information .fyi{width:266px !important}#plugin-information #section-holder{margin-right:299px;clear:none}#plugin-information #section-description h2,#plugin-information #section-description h3,#plugin-information #section-description p,#plugin-information #section-description b,#plugin-information #section-description i,#plugin-information #section-description blockquote,#plugin-information #section-description li,#plugin-information #section-description ul,#plugin-information #section-description ol{clear:none}#plugin-information #section-description iframe{max-width:100%}#plugin-information #section-description .fs-selling-points{padding-bottom:10px;border-bottom:1px solid #ddd}#plugin-information #section-description .fs-selling-points ul{margin:0}#plugin-information #section-description .fs-selling-points ul li{padding:0;list-style:none outside none}#plugin-information #section-description .fs-selling-points ul li i.dashicons{color:#71ae00;font-size:3em;vertical-align:middle;line-height:30px;float:left;margin:0 0 0 -15px}#plugin-information #section-description .fs-selling-points ul li h3{margin:1em 30px !important}#plugin-information #section-description .fs-screenshots:after{content:"";display:table;clear:both}#plugin-information #section-description .fs-screenshots ul{list-style:none;margin:0}#plugin-information #section-description .fs-screenshots ul li{width:225px;height:225px;float:left;margin-bottom:20px;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}#plugin-information #section-description .fs-screenshots ul li a{display:block;width:100%;height:100%;border:1px solid;-moz-box-shadow:1px 1px 1px rgba(0,0,0,.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(0,0,0,.2);background-size:cover}#plugin-information #section-description .fs-screenshots ul li.odd{margin-right:20px}#plugin-information .plugin-information-pricing{margin:-16px;border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan h3{margin-top:0;padding:20px;font-size:16px}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper{border-bottom:1px solid #ddd}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab{cursor:pointer;position:relative;padding:0 10px;font-size:.9em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab label{text-transform:uppercase;color:green;background:#adff2f;position:absolute;left:-1px;right:-1px;bottom:100%;border:1px solid #006400;padding:2px;text-align:center;font-size:.9em;line-height:1em}#plugin-information .plugin-information-pricing .fs-plan .nav-tab-wrapper .nav-tab.nav-tab-active{cursor:default;background:#fffeec;border-bottom-color:#fffeec}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle h3{background:#fffeec;margin:0;padding-bottom:0;color:#0073aa}#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .nav-tab-wrapper,#plugin-information .plugin-information-pricing .fs-plan.fs-single-cycle .fs-billing-frequency{display:none}#plugin-information .plugin-information-pricing .fs-plan .fs-pricing-body{background:#fffeec;padding:20px}#plugin-information .plugin-information-pricing .fs-plan .button{width:100%;text-align:center;font-weight:bold;text-transform:uppercase;font-size:1.1em}#plugin-information .plugin-information-pricing .fs-plan label{white-space:nowrap}#plugin-information .plugin-information-pricing .fs-plan var{font-style:normal}#plugin-information .plugin-information-pricing .fs-plan .fs-billing-frequency,#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-align:center;display:block;font-weight:bold;margin-bottom:10px;text-transform:uppercase;background:#f3f3f3;padding:2px;border:1px solid #ccc}#plugin-information .plugin-information-pricing .fs-plan .fs-annual-discount{text-transform:none;color:green;background:#adff2f}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms{font-size:.9em}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms i{float:left;margin:0 0 0 -15px}#plugin-information .plugin-information-pricing .fs-plan ul.fs-trial-terms li{margin:10px 0 0 0}#plugin-information #section-features .fs-features{margin:-20px -26px}#plugin-information #section-features table{width:100%;border-spacing:0;border-collapse:separate}#plugin-information #section-features table thead th{padding:10px 0}#plugin-information #section-features table thead .fs-price{color:#71ae00;font-weight:normal;display:block;text-align:center}#plugin-information #section-features table tbody td{border-top:1px solid #ccc;padding:10px 0;text-align:center;width:100px;color:#71ae00}#plugin-information #section-features table tbody td:first-child{text-align:left;width:auto;color:inherit;padding-left:26px}#plugin-information #section-features table tbody tr.fs-odd td{background:#fefefe}#plugin-information #section-features .dashicons-yes{width:30px;height:30px;font-size:30px}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .button-group .button,#plugin-information .fs-dropdown .button-group .button{position:relative;width:auto;top:0;right:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .button-group .button:focus,#plugin-information .fs-dropdown .button-group .button:focus{z-index:10}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .button-group .fs-dropdown-arrow,#plugin-information .fs-dropdown .button-group .fs-dropdown-arrow{border-top:6px solid #fff;border-right:4px solid transparent;border-left:4px solid transparent;top:12px;position:relative}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active:not(.up) .button:not(.fs-dropdown-arrow-button),#plugin-information .fs-dropdown.active:not(.up) .button:not(.fs-dropdown-arrow-button){border-bottom-left-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active:not(.up) .fs-dropdown-arrow-button,#plugin-information .fs-dropdown.active:not(.up) .fs-dropdown-arrow-button{border-bottom-right-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active.up .button:not(.fs-dropdown-arrow-button),#plugin-information .fs-dropdown.active.up .button:not(.fs-dropdown-arrow-button){border-top-left-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.active.up .fs-dropdown-arrow-button,#plugin-information .fs-dropdown.active.up .fs-dropdown-arrow-button{border-top-right-radius:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list,#plugin-information .fs-dropdown .fs-dropdown-list{position:absolute;right:-1px;top:100%;margin-left:auto;padding:3px 0;border:1px solid #bfbfbf;background-color:#fff;z-index:1;width:230px;text-align:left;-moz-box-shadow:0px 2px 4px -1px rgba(0,0,0,.2),0px 4px 5px 0px rgba(0,0,0,.14),0px 1px 10px 0px rgba(0,0,0,.12);-webkit-box-shadow:0px 2px 4px -1px rgba(0,0,0,.2),0px 4px 5px 0px rgba(0,0,0,.14),0px 1px 10px 0px rgba(0,0,0,.12);box-shadow:0px 2px 4px -1px rgba(0,0,0,.2),0px 4px 5px 0px rgba(0,0,0,.14),0px 1px 10px 0px rgba(0,0,0,.12)}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li,#plugin-information .fs-dropdown .fs-dropdown-list li{margin:0}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li a,#plugin-information .fs-dropdown .fs-dropdown-list li a{display:block;padding:5px 10px;text-decoration:none;text-shadow:none}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li:hover,#plugin-information .fs-dropdown .fs-dropdown-list li:hover{background-color:#0074a3;color:#fff}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown .fs-dropdown-list li:hover a,#plugin-information .fs-dropdown .fs-dropdown-list li:hover a{color:#fff}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown:not(.up) .fs-dropdown-list,#plugin-information .fs-dropdown:not(.up) .fs-dropdown-list{-moz-border-radius:3px 0 3px 3px;-webkit-border-radius:3px 0 3px 3px;border-radius:3px 0 3px 3px}#fs_addons .fs-cards-list .fs-card .fs-inner .fs-dropdown.up .fs-dropdown-list,#plugin-information .fs-dropdown.up .fs-dropdown-list{-moz-border-radius:3px 3px 0 3px;-webkit-border-radius:3px 3px 0 3px;border-radius:3px 3px 0 3px}#plugin-information .fs-dropdown .button-group{width:100%}#plugin-information .fs-dropdown .button-group .button{float:none;font-size:14px;font-weight:normal;text-transform:none}#plugin-information .fs-dropdown .fs-dropdown-list{margin-top:1px}#plugin-information .fs-dropdown.up .fs-dropdown-list{top:auto;bottom:100%;margin-bottom:2px}#plugin-information.wp-core-ui .fs-pricing-body .fs-dropdown .button-group{text-align:center;display:table}#plugin-information.wp-core-ui .fs-pricing-body .fs-dropdown .button-group .button{display:table-cell}#plugin-information.wp-core-ui .fs-pricing-body .fs-dropdown .button-group .button:not(.fs-dropdown-arrow-button){left:1px;width:100%}#plugin-information-footer>.button,#plugin-information-footer .fs-dropdown{position:relative;top:3px}#plugin-information-footer>.button.left,#plugin-information-footer .fs-dropdown.left{float:left}#plugin-information-footer>.right,#plugin-information-footer .fs-dropdown{float:right}@media screen and (max-width: 961px){#fs_addons .fs-cards-list .fs-card{height:265px}} freemius/assets/css/admin/affiliation.css000064400000004235146725417150014564 0ustar00#fs_affiliation_content_wrapper #messages{margin-top:25px}#fs_affiliation_content_wrapper h3{font-size:24px;padding:0;margin-left:0}#fs_affiliation_content_wrapper ul li{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;list-style-type:none}#fs_affiliation_content_wrapper ul li:before{content:"✓";margin-right:10px;font-weight:bold}#fs_affiliation_content_wrapper p:not(.description),#fs_affiliation_content_wrapper li,#fs_affiliation_content_wrapper label{font-size:16px !important;line-height:26px !important}#fs_affiliation_content_wrapper .button{margin-top:20px;margin-bottom:7px;line-height:35px;height:40px;font-size:16px}#fs_affiliation_content_wrapper .button#cancel_button{margin-right:5px}#fs_affiliation_content_wrapper form .input-container{margin-bottom:15px}#fs_affiliation_content_wrapper form .input-container .input-label{font-weight:bold;display:block;width:100%}#fs_affiliation_content_wrapper form .input-container.input-container-text label,#fs_affiliation_content_wrapper form .input-container.input-container-text input,#fs_affiliation_content_wrapper form .input-container.input-container-text textarea{display:block}#fs_affiliation_content_wrapper form .input-container #add_domain,#fs_affiliation_content_wrapper form .input-container .remove-domain{text-decoration:none;display:inline-block;margin-top:3px}#fs_affiliation_content_wrapper form .input-container #add_domain:focus,#fs_affiliation_content_wrapper form .input-container .remove-domain:focus{box-shadow:none}#fs_affiliation_content_wrapper form .input-container #add_domain.disabled,#fs_affiliation_content_wrapper form .input-container .remove-domain.disabled{color:#aaa;cursor:default}#fs_affiliation_content_wrapper form #extra_domains_container .description{margin-top:0;position:relative;top:-4px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container{margin-bottom:15px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container .domain{display:inline-block;margin-right:5px}#fs_affiliation_content_wrapper form #extra_domains_container .extra-domain-input-container .domain:last-of-type{margin-bottom:0} freemius/assets/css/admin/clone-resolution.css000064400000003262146725417150015577 0ustar00.fs-notice[data-id^=clone_resolution_options_notice]{padding:0;color:inherit !important}.fs-notice[data-id^=clone_resolution_options_notice] .fs-notice-body{padding:0;margin-bottom:0}.fs-notice[data-id^=clone_resolution_options_notice] .fs-notice-header{padding:5px 10px}.fs-notice[data-id^=clone_resolution_options_notice] ol{margin-top:0;margin-bottom:0}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-options-container{display:flex;flex-direction:row;padding:0 10px 10px}@media(max-width: 750px){.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-options-container{flex-direction:column}}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-option{border:1px solid #ccc;padding:10px 10px 15px 10px;flex:auto;margin:5px}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-option:first-child{margin-left:0}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-option:last-child{margin-right:0}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-resolution-option strong{font-size:1.2em;padding:2px;line-height:1.5em}.fs-notice[data-id^=clone_resolution_options_notice] a{text-decoration:none}.fs-notice[data-id^=clone_resolution_options_notice] .button{margin-right:10px}.rtl .fs-notice[data-id^=clone_resolution_options_notice] .button{margin-right:0;margin-left:10px}.fs-notice[data-id^=clone_resolution_options_notice] .fs-clone-documentation-container{padding:0 10px 15px}.fs-notice[data-id=temporary_duplicate_notice] #fs_clone_resolution_error_message{border:1px solid #d3135a;background:#fee;color:#d3135a;padding:10px}.fs-notice[data-id=temporary_duplicate_notice] ol{margin-top:0} freemius/assets/css/admin/dialog-boxes.css000064400000033543146725417150014660 0ustar00.fs-modal{position:fixed;overflow:auto;height:100%;width:100%;top:0;z-index:100000;display:none;background:rgba(0,0,0,.6)}@media(min-width: 961px){.fs-modal{padding-left:160px}.rtl .fs-modal{padding-left:0;padding-right:160px}}.fs-modal .dashicons{vertical-align:middle}.fs-modal .fs-modal-dialog{background:transparent;position:absolute;left:50%;margin-left:-298px;padding-bottom:30px;top:-100%;z-index:100001;width:596px}@media(max-width: 650px){.fs-modal .fs-modal-dialog{margin-left:-50%;box-sizing:border-box;padding-left:10px;padding-right:10px;width:100%}.fs-modal .fs-modal-dialog .fs-modal-panel>h3>strong{font-size:1.3em}}.fs-modal.active{display:block}.fs-modal.active:before{display:block}.fs-modal.active .fs-modal-dialog{top:10%}.fs-modal.fs-success .fs-modal-header{border-bottom-color:#46b450}.fs-modal.fs-success .fs-modal-body{background-color:#f7fff7}.fs-modal.fs-warn .fs-modal-header{border-bottom-color:#ffb900}.fs-modal.fs-warn .fs-modal-body{background-color:#fff8e5}.fs-modal.fs-error .fs-modal-header{border-bottom-color:#dc3232}.fs-modal.fs-error .fs-modal-body{background-color:#ffeaea}.fs-modal .fs-modal-body,.fs-modal .fs-modal-footer{border:0;background:#fefefe;padding:20px}.fs-modal .fs-modal-header{border-bottom:#eee solid 1px;background:#fbfbfb;padding:15px 20px;position:relative;margin-bottom:-10px}.fs-modal .fs-modal-header h4{margin:0;padding:0;text-transform:uppercase;font-size:1.2em;font-weight:bold;color:#cacaca;text-shadow:1px 1px 1px #fff;letter-spacing:.6px;-webkit-font-smoothing:antialiased}.fs-modal .fs-modal-header .fs-close{position:absolute;right:10px;top:12px;cursor:pointer;color:#bbb;-moz-border-radius:20px;-webkit-border-radius:20px;border-radius:20px;padding:3px;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.fs-modal .fs-modal-header .fs-close:hover{color:#fff;background:#aaa}.fs-modal .fs-modal-header .fs-close .dashicons,.fs-modal .fs-modal-header .fs-close:hover .dashicons{text-decoration:none}.fs-modal .fs-modal-body{border-bottom:0}.fs-modal .fs-modal-body p{font-size:14px}.fs-modal .fs-modal-body h2{font-size:20px;line-height:1.5em}.fs-modal .fs-modal-body>div{margin-top:10px}.fs-modal .fs-modal-body>div h2{font-weight:bold;font-size:20px;margin-top:0}.fs-modal .fs-modal-footer{border-top:#eee solid 1px;text-align:right}.fs-modal .fs-modal-footer>.button{margin:0 7px}.fs-modal .fs-modal-footer>.button:last-of-type{margin:0}.fs-modal .fs-modal-panel>.notice.inline{margin:0;display:none}.fs-modal .fs-modal-panel:not(.active){display:none}.rtl .fs-modal .fs-modal-header .fs-close{right:auto;left:20px}.rtl .fs-modal .fs-modal-footer{text-align:left}body.has-fs-modal{overflow:hidden}.fs-modal.fs-modal-deactivation-feedback .reason-input,.fs-modal.fs-modal-deactivation-feedback .internal-message{margin:3px 0 3px 22px}.fs-modal.fs-modal-deactivation-feedback .reason-input input,.fs-modal.fs-modal-deactivation-feedback .reason-input textarea,.fs-modal.fs-modal-deactivation-feedback .internal-message input,.fs-modal.fs-modal-deactivation-feedback .internal-message textarea{width:100%}.fs-modal.fs-modal-deactivation-feedback li.reason.has-internal-message .internal-message{border:1px solid #ccc;padding:7px;display:none}@media(max-width: 650px){.fs-modal.fs-modal-deactivation-feedback li.reason li.reason{margin-bottom:10px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .reason-input,.fs-modal.fs-modal-deactivation-feedback li.reason li.reason .internal-message{margin-left:29px}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label{display:table}.fs-modal.fs-modal-deactivation-feedback li.reason li.reason label>span{display:table-cell;font-size:1.3em}}.fs-modal.fs-modal-deactivation-feedback .anonymous-feedback-label,.fs-modal.fs-modal-deactivation-feedback .feedback-from-snooze-label{float:left;line-height:30px}.rtl .fs-modal.fs-modal-deactivation-feedback .anonymous-feedback-label,.rtl .fs-modal.fs-modal-deactivation-feedback .feedback-from-snooze-label{float:right}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel{margin-top:0 !important}.fs-modal.fs-modal-deactivation-feedback .fs-modal-panel h3{margin-top:0;line-height:1.5em}#the-list .deactivate>.fs-slug{display:none}.fs-modal.fs-modal-subscription-cancellation .fs-price-increase-warning{color:red;font-weight:bold;padding:0 25px;margin-bottom:0}.fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label input{float:left;top:5px;position:relative}.rtl .fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label input{float:right}.fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label span{display:block;margin-left:24px}.rtl .fs-modal.fs-modal-subscription-cancellation ul.subscription-actions label span{margin-left:0;margin-right:24px}.fs-modal.fs-modal-license-activation .fs-modal-body input.fs-license-key{width:100%}.fs-license-options-container table,.fs-license-options-container table select,.fs-license-options-container table .fs-available-license-key{width:100%}.fs-license-options-container table td:first-child{width:1%}.fs-license-options-container table .fs-other-license-key-container label{position:relative;top:6px;float:left;margin-right:5px}.fs-license-options-container table .fs-other-license-key-container div{overflow:hidden;width:auto;height:30px;display:block;top:2px;position:relative}.fs-license-options-container table .fs-other-license-key-container div input{margin:0}.fs-sites-list-container td{cursor:pointer}.fs-modal.fs-modal-user-change .fs-modal-body input#fs_other_email_address{width:100%}.fs-user-change-options-container table{width:100%;border-collapse:collapse}.fs-user-change-options-container table tr{display:block;margin-bottom:2px}.fs-user-change-options-container table .fs-email-address-container td{display:inline-block}.fs-user-change-options-container table .fs-email-address-container input[type=radio]{margin-bottom:0;margin-top:0}.fs-user-change-options-container table .fs-other-email-address-container{width:100%}.fs-user-change-options-container table .fs-other-email-address-container>div{display:table;width:100%}.fs-user-change-options-container table .fs-other-email-address-container>div label,.fs-user-change-options-container table .fs-other-email-address-container>div>div{display:table-cell}.fs-user-change-options-container table .fs-other-email-address-container>div label{width:1%;padding-left:3px;padding-right:3px}.fs-user-change-options-container table .fs-other-email-address-container>div>div{width:auto}.fs-user-change-options-container table .fs-other-email-address-container>div>div input{width:100%}.fs-modal.fs-modal-developer-license-debug-mode .fs-modal-body input.fs-license-or-user-key{width:100%}.fs-multisite-options-container{margin-top:20px;border:1px solid #ccc;padding:5px}.fs-multisite-options-container a{text-decoration:none}.fs-multisite-options-container a:focus{box-shadow:none}.fs-multisite-options-container a.selected{font-weight:bold}.fs-multisite-options-container.fs-apply-on-all-sites{border:0 none;padding:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options{border-spacing:0}.fs-multisite-options-container.fs-apply-on-all-sites .fs-all-sites-options td:not(:first-child){display:none}.fs-multisite-options-container .fs-sites-list-container{display:none;overflow:auto}.fs-multisite-options-container .fs-sites-list-container table td{border-top:1px solid #ccc;padding:4px 2px}.fs-modal.fs-modal-license-key-resend .email-address-container{overflow:hidden;padding-right:2px}.fs-modal.fs-modal-license-key-resend.fs-freemium input.email-address{width:300px}.fs-modal.fs-modal-license-key-resend.fs-freemium label{display:block;margin-bottom:10px}.fs-modal.fs-modal-license-key-resend.fs-premium input.email-address{width:100%}.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{float:right;margin-left:7px}@media(max-width: 650px){.fs-modal.fs-modal-license-key-resend.fs-premium .button-container{margin-top:2px}}.rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .input-container>.email-address-container{padding-left:2px;padding-right:0}.rtl .fs-modal.fs-modal-license-key-resend .fs-modal-body .button-container{float:left;margin-right:7px;margin-left:0}a.show-license-resend-modal{margin-top:4px;display:inline-block}.fs-modal.fs-modal-email-address-update .fs-modal-body input[type=text]{width:100%}.fs-modal.fs-modal-email-address-update p{margin-bottom:0}.fs-modal.fs-modal-email-address-update ul{margin:1em .5em}.fs-modal.fs-modal-email-address-update ul li label span{float:left;margin-top:0}.fs-modal.fs-modal-email-address-update ul li label span:last-child{display:block;float:none;margin-left:20px}.fs-ajax-loader{position:relative;width:170px;height:20px;margin:auto}.fs-ajax-loader .fs-ajax-loader-bar{position:absolute;top:0;background-color:#0074a3;width:20px;height:20px;-webkit-animation-name:bounce_ajaxLoader;-moz-animation-name:bounce_ajaxLoader;-ms-animation-name:bounce_ajaxLoader;-o-animation-name:bounce_ajaxLoader;animation-name:bounce_ajaxLoader;-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-ms-animation-duration:1.5s;-o-animation-duration:1.5s;animation-duration:1.5s;animation-iteration-count:infinite;-o-animation-iteration-count:infinite;-ms-animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;-webkit-animation-direction:normal;-moz-animation-direction:normal;-ms-animation-direction:normal;-o-animation-direction:normal;animation-direction:normal;-moz-transform:.3;-o-transform:.3;-ms-transform:.3;-webkit-transform:.3;transform:.3}.fs-ajax-loader .fs-ajax-loader-bar-1{left:0px;animation-delay:0.6s;-o-animation-delay:0.6s;-ms-animation-delay:0.6s;-webkit-animation-delay:0.6s;-moz-animation-delay:0.6s}.fs-ajax-loader .fs-ajax-loader-bar-2{left:19px;animation-delay:0.75s;-o-animation-delay:0.75s;-ms-animation-delay:0.75s;-webkit-animation-delay:0.75s;-moz-animation-delay:0.75s}.fs-ajax-loader .fs-ajax-loader-bar-3{left:38px;animation-delay:0.9s;-o-animation-delay:0.9s;-ms-animation-delay:0.9s;-webkit-animation-delay:0.9s;-moz-animation-delay:0.9s}.fs-ajax-loader .fs-ajax-loader-bar-4{left:57px;animation-delay:1.05s;-o-animation-delay:1.05s;-ms-animation-delay:1.05s;-webkit-animation-delay:1.05s;-moz-animation-delay:1.05s}.fs-ajax-loader .fs-ajax-loader-bar-5{left:76px;animation-delay:1.2s;-o-animation-delay:1.2s;-ms-animation-delay:1.2s;-webkit-animation-delay:1.2s;-moz-animation-delay:1.2s}.fs-ajax-loader .fs-ajax-loader-bar-6{left:95px;animation-delay:1.35s;-o-animation-delay:1.35s;-ms-animation-delay:1.35s;-webkit-animation-delay:1.35s;-moz-animation-delay:1.35s}.fs-ajax-loader .fs-ajax-loader-bar-7{left:114px;animation-delay:1.5s;-o-animation-delay:1.5s;-ms-animation-delay:1.5s;-webkit-animation-delay:1.5s;-moz-animation-delay:1.5s}.fs-ajax-loader .fs-ajax-loader-bar-8{left:133px;animation-delay:1.65s;-o-animation-delay:1.65s;-ms-animation-delay:1.65s;-webkit-animation-delay:1.65s;-moz-animation-delay:1.65s}@-moz-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-ms-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-o-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@-webkit-keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}@keyframes bounce_ajaxLoader{0%{-moz-transform:scale(1);-o-transform:scale(1);-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1);background-color:#0074a3}100%{-moz-transform:scale(0.3);-o-transform:scale(0.3);-ms-transform:scale(0.3);-webkit-transform:scale(0.3);transform:scale(0.3);background-color:#fff}}.fs-modal-auto-install #request-filesystem-credentials-form h2,.fs-modal-auto-install #request-filesystem-credentials-form .request-filesystem-credentials-action-buttons{display:none}.fs-modal-auto-install #request-filesystem-credentials-form input[type=password],.fs-modal-auto-install #request-filesystem-credentials-form input[type=email],.fs-modal-auto-install #request-filesystem-credentials-form input[type=text]{-webkit-appearance:none;padding:10px 10px 5px 10px;width:300px;max-width:100%}.fs-modal-auto-install #request-filesystem-credentials-form>div,.fs-modal-auto-install #request-filesystem-credentials-form label,.fs-modal-auto-install #request-filesystem-credentials-form fieldset{width:300px;max-width:100%;margin:0 auto;display:block}.button-primary.warn{box-shadow:0 1px 0 #d2593c;text-shadow:0 -1px 1px #d2593c,1px 0 1px #d2593c,0 1px 1px #d2593c,-1px 0 1px #d2593c;background:#f56a48;border-color:#ec6544 #d2593c #d2593c}.button-primary.warn:hover{background:#fd6d4a;border-color:#d2593c}.button-primary.warn:focus{box-shadow:0 1px 0 #dd6041,0 0 2px 1px #e4a796}.button-primary.warn:active{background:#dd6041;border-color:#d2593c;box-shadow:inset 0 2px 0 #d2593c}.button-primary.warn.disabled{color:#f5b3a1 !important;background:#e76444 !important;border-color:#d85e40 !important;text-shadow:0 -1px 0 rgba(0,0,0,.1) !important} freemius/assets/css/admin/debug.css000064400000002053146725417150013361 0ustar00label.fs-tag,span.fs-tag{background:#ffba00;color:#fff;display:inline-block;border-radius:3px;padding:5px;font-size:11px;line-height:11px;vertical-align:baseline}label.fs-tag.fs-warn,span.fs-tag.fs-warn{background:#ffba00}label.fs-tag.fs-info,span.fs-tag.fs-info{background:#00a0d2}label.fs-tag.fs-success,span.fs-tag.fs-success{background:#46b450}label.fs-tag.fs-error,span.fs-tag.fs-error{background:#dc3232}.fs-switch-label{font-size:20px;line-height:31px;margin:0 5px}#fs_log_book table{font-family:Consolas,Monaco,monospace;font-size:12px}#fs_log_book table th{color:#ccc}#fs_log_book table tr{background:#232525}#fs_log_book table tr.alternate{background:#2b2b2b}#fs_log_book table tr td.fs-col--logger{color:#5a7435}#fs_log_book table tr td.fs-col--type{color:#ffc861}#fs_log_book table tr td.fs-col--function{color:#a7b7b1;font-weight:bold}#fs_log_book table tr td.fs-col--message,#fs_log_book table tr td.fs-col--message a{color:#9a73ac !important}#fs_log_book table tr td.fs-col--file{color:#d07922}#fs_log_book table tr td.fs-col--timestamp{color:#6596be} freemius/assets/css/admin/gdpr-optin-notice.css000064400000000473146725417150015641 0ustar00.fs-notice[data-id^=gdpr_optin_actions] .underlined{text-decoration:underline}.fs-notice[data-id^=gdpr_optin_actions] ul .button,.fs-notice[data-id^=gdpr_optin_actions] ul .action-description{vertical-align:middle}.fs-notice[data-id^=gdpr_optin_actions] ul .action-description{display:inline-block;margin-left:3px} freemius/assets/css/customizer.css000064400000006022146725417150013407 0ustar00#fs_customizer_upsell .fs-customizer-plan{padding:10px 20px 20px 20px;border-radius:3px;background:#fff}#fs_customizer_upsell .fs-customizer-plan h2{position:relative;margin:0;line-height:2em;text-transform:uppercase}#fs_customizer_upsell .fs-customizer-plan h2 .button-link{top:-2px}#fs_customizer_upsell .fs-feature{position:relative}#fs_customizer_upsell .dashicons-yes{color:#0085ba;font-size:2em;vertical-align:bottom;margin-left:-7px;margin-right:10px}.rtl #fs_customizer_upsell .dashicons-yes{margin-left:10px;margin-right:-7px}#fs_customizer_upsell .dashicons-editor-help{color:#bbb;cursor:help}#fs_customizer_upsell .dashicons-editor-help .fs-feature-desc{opacity:0;visibility:hidden;-moz-transition:opacity .3s ease-in-out;-o-transition:opacity .3s ease-in-out;-ms-transition:opacity .3s ease-in-out;-webkit-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;position:absolute;background:#000;color:#fff;font-family:"arial",serif;font-size:12px;padding:10px;z-index:999999;bottom:100%;margin-bottom:5px;left:0;right:0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-moz-box-shadow:1px 1px 1px rgba(0,0,0,.2);-webkit-box-shadow:1px 1px 1px rgba(0,0,0,.2);box-shadow:1px 1px 1px rgba(0,0,0,.2);line-height:1.3em;font-weight:bold;text-align:left}.rtl #fs_customizer_upsell .dashicons-editor-help .fs-feature-desc{text-align:right}#fs_customizer_upsell .dashicons-editor-help .fs-feature-desc::after{content:" ";display:block;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:#000 transparent transparent transparent;position:absolute;top:100%;left:21px}.rtl #fs_customizer_upsell .dashicons-editor-help .fs-feature-desc::after{right:21px;left:auto}#fs_customizer_upsell .dashicons-editor-help:hover .fs-feature-desc{visibility:visible;opacity:1}#fs_customizer_upsell .button-primary{display:block;text-align:center;margin-top:10px}#fs_customizer_support{display:block !important}#fs_customizer_support .button{float:right}#fs_customizer_support .button-group{width:100%;display:block;margin-top:10px}#fs_customizer_support .button-group .button{float:none;width:50%;text-align:center}#customize-theme-controls #accordion-section-freemius_upsell{border-top:1px solid #0085ba !important;border-bottom:1px solid #0085ba !important}#customize-theme-controls #accordion-section-freemius_upsell h3.accordion-section-title{color:#fff;background-color:#0085ba;border-left:4px solid #0085ba;transition:.15s background-color ease-in-out,.15s border-color ease-in-out;outline:none;border-bottom:none !important}#customize-theme-controls #accordion-section-freemius_upsell h3.accordion-section-title:hover{background-color:#008ec2;border-left-color:#0073aa}#customize-theme-controls #accordion-section-freemius_upsell h3.accordion-section-title:after{color:#fff}#customize-theme-controls #accordion-section-freemius_upsell .rtl h3.accordion-section-title{border-left:none;border-right:4px solid #0085ba}#customize-theme-controls #accordion-section-freemius_upsell .rtl h3.accordion-section-title:hover{border-right-color:#0073aa} freemius/assets/index.php000064400000000127146725417150011521 0ustar00is_features_enabled() ) { return 0; } if ( $this->is_unlimited() ) { return 999; } return ( $this->quota - $this->activated - ( $this->is_free_localhost ? 0 : $this->activated_local ) ); } /** * Check if single site license. * * @author Vova Feldman (@svovaf) * @since 1.1.8.1 * * @return bool */ function is_single_site() { return ( is_numeric( $this->quota ) && 1 == $this->quota ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @return bool */ function is_expired() { return ! $this->is_lifetime() && ( strtotime( $this->expiration ) < WP_FS__SCRIPT_START_TIME ); } /** * Check if license is not expired. * * @author Vova Feldman (@svovaf) * @since 1.2.1 * * @return bool */ function is_valid() { return ! $this->is_expired(); } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return bool */ function is_lifetime() { return is_null( $this->expiration ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.0 * * @return bool */ function is_unlimited() { return is_null( $this->quota ); } /** * Check if license is fully utilized. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param bool|null $is_localhost * * @return bool */ function is_utilized( $is_localhost = null ) { if ( is_null( $is_localhost ) ) { $is_localhost = WP_FS__IS_LOCALHOST_FOR_SERVER; } if ( $this->is_unlimited() ) { return false; } return ! ( $this->is_free_localhost && $is_localhost ) && ( $this->quota <= $this->activated + ( $this->is_free_localhost ? 0 : $this->activated_local ) ); } /** * Check if license can be activated. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param bool|null $is_localhost * * @return bool */ function can_activate( $is_localhost = null ) { return ! $this->is_utilized( $is_localhost ) && $this->is_features_enabled(); } /** * Check if license can be activated on a given number of production and localhost sites. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $production_count * @param int $localhost_count * * @return bool */ function can_activate_bulk( $production_count, $localhost_count ) { if ( $this->is_unlimited() ) { return true; } /** * For simplicity, the logic will work as following: when given X sites to activate the license on, if it's * possible to activate on ALL of them, do the activation. If it's not possible to activate on ALL of them, * do NOT activate on any of them. */ return ( $this->quota >= $this->activated + $production_count + ( $this->is_free_localhost ? 0 : $this->activated_local + $localhost_count ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1 * * @return bool */ function is_active() { return ( ! $this->is_cancelled ); } /** * Check if license's plan features are enabled. * * - Either if plan not expired * - If expired, based on the configuration to block features or not. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return bool */ function is_features_enabled() { return $this->is_active() && ( ! $this->is_block_features || ! $this->is_expired() ); } /** * Subscription considered to be new without any payments * if the license expires in less than 24 hours * from the license creation. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_first_payment_pending() { return ( WP_FS__TIME_24_HOURS_IN_SEC >= strtotime( $this->expiration ) - strtotime( $this->created ) ); } /** * @return int */ function total_activations() { return ( $this->activated + $this->activated_local ); } /** * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @return string */ function get_html_escaped_masked_secret_key() { return self::mask_secret_key_for_html( $this->secret_key ); } /** * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @param string $secret_key * * @return string */ static function mask_secret_key_for_html( $secret_key ) { return ( // Initial 6 chars - sk_ABC htmlspecialchars( substr( $secret_key, 0, 6 ) ) . // Masking str_pad( '', ( strlen( $secret_key ) - 9 ) * 6, '•' ) . // Last 3 chars. htmlspecialchars( substr( $secret_key, - 3 ) ) ); } } freemius/includes/entities/class-fs-plugin-plan.php000064400000005305146725417150016504 0ustar00name = strtolower( $plan->name ); } } static function get_type() { return 'plan'; } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_free() { return ( 'free' === $this->name ); } /** * Checks if this plan supports "Technical Support". * * @author Leo Fajardo (leorw) * @since 1.2.0 * * @return bool */ function has_technical_support() { return ( ! empty( $this->support_email ) || ! empty( $this->support_skype ) || ! empty( $this->support_phone ) || ! empty( $this->is_success_manager ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function has_trial() { return ! $this->is_free() && is_numeric( $this->trial_period ) && ( $this->trial_period > 0 ); } }freemius/includes/entities/class-fs-plugin-tag.php000064400000002451146725417150016324 0ustar00release_mode ); } }freemius/includes/entities/class-fs-plugin-info.php000064400000001332146725417150016501 0ustar00first ) ? $this->first : '' ) ) . ' ' . ucfirst( trim( is_string( $this->last ) ? $this->last : '' ) ) ); } function is_verified() { return ( isset( $this->is_verified ) && true === $this->is_verified ); } /** * @author Leo Fajardo (@leorw) * @since 2.4.2 * * @return bool */ function is_beta() { // Return `false` since this is just for backward compatibility. return false; } static function get_type() { return 'user'; } }freemius/includes/entities/index.php000064400000000127146725417150013651 0ustar00status ); } /** * @author Leo Fajardo * * @return bool */ function is_pending() { return ( 'pending' === $this->status ); } /** * @author Leo Fajardo * * @return bool */ function is_suspended() { return ( 'suspended' === $this->status ); } /** * @author Leo Fajardo * * @return bool */ function is_rejected() { return ( 'rejected' === $this->status ); } /** * @author Leo Fajardo * * @return bool */ function is_blocked() { return ( 'blocked' === $this->status ); } }freemius/includes/entities/class-fs-plugin.php000064400000007566146725417150015567 0ustar00is_premium = false; $this->is_live = true; if ( empty( $this->premium_slug ) && ! empty( $plugin->slug ) ) { $this->premium_slug = "{$this->slug}-premium"; } if ( empty( $this->premium_suffix ) ) { $this->premium_suffix = '(Premium)'; } if ( isset( $plugin->info ) && is_object( $plugin->info ) ) { $this->info = new FS_Plugin_Info( $plugin->info ); } } /** * Check if plugin is an add-on (has parent). * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return bool */ function is_addon() { return isset( $this->parent_plugin_id ) && is_numeric( $this->parent_plugin_id ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.3 * * @return bool */ function has_affiliate_program() { return ( ! empty( $this->affiliate_moderation ) ); } static function get_type() { return 'plugin'; } }freemius/includes/entities/class-fs-entity.php000064400000006066146725417150015577 0ustar00 $def_value ) { $this->{$key} = isset( $entity->{$key} ) ? $entity->{$key} : $def_value; } } static function get_type() { return 'type'; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param FS_Entity $entity1 * @param FS_Entity $entity2 * * @return bool */ static function equals( $entity1, $entity2 ) { if ( is_null( $entity1 ) && is_null( $entity2 ) ) { return true; } else if ( is_object( $entity1 ) && is_object( $entity2 ) ) { return ( $entity1->id == $entity2->id ); } else if ( is_object( $entity1 ) ) { return is_null( $entity1->id ); } else { return is_null( $entity2->id ); } } private $_is_updated = false; /** * Update object property. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string|array[string]mixed $key * @param string|bool $val * * @return bool */ function update( $key, $val = false ) { if ( ! is_array( $key ) ) { $key = array( $key => $val ); } $is_updated = false; foreach ( $key as $k => $v ) { if ( $this->{$k} === $v ) { continue; } if ( ( is_string( $this->{$k} ) && is_numeric( $v ) || ( is_numeric( $this->{$k} ) && is_string( $v ) ) ) && $this->{$k} == $v ) { continue; } // Update value. $this->{$k} = $v; $is_updated = true; } $this->_is_updated = $is_updated; return $is_updated; } /** * Checks if entity was updated. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_updated() { return $this->_is_updated; } /** * @param $id * * @author Vova Feldman (@svovaf) * @since 1.1.2 * * @return bool */ static function is_valid_id($id){ return is_numeric($id); } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @return string */ public static function get_class_name() { return get_called_class(); } }freemius/includes/entities/class-fs-pricing.php000064400000005704146725417150015714 0ustar00monthly_price ) && $this->monthly_price > 0 ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @return bool */ function has_annual() { return ( is_numeric( $this->annual_price ) && $this->annual_price > 0 ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @return bool */ function has_lifetime() { return ( is_numeric( $this->lifetime_price ) && $this->lifetime_price > 0 ); } /** * Check if unlimited licenses pricing. * * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @return bool */ function is_unlimited() { return is_null( $this->licenses ); } /** * Check if pricing has more than one billing cycle. * * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @return bool */ function is_multi_cycle() { $cycles = 0; if ( $this->has_monthly() ) { $cycles ++; } if ( $this->has_annual() ) { $cycles ++; } if ( $this->has_lifetime() ) { $cycles ++; } return $cycles > 1; } /** * Get annual over monthly discount. * * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @return int */ function annual_discount_percentage() { return floor( $this->annual_savings() / ( $this->monthly_price * 12 * ( $this->is_unlimited() ? 1 : $this->licenses ) ) * 100 ); } /** * Get annual over monthly savings. * * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @return float */ function annual_savings() { return ( $this->monthly_price * 12 - $this->annual_price ) * ( $this->is_unlimited() ? 1 : $this->licenses ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @return bool */ function is_usd() { return ( 'usd' === $this->currency ); } }freemius/includes/entities/class-fs-affiliate-terms.php000064400000010326146725417150017331 0ustar00commission_type ) ? ( '$' . $this->commission ) : ( $this->commission . '%' ); } /** * @author Leo Fajardo (@leorw) * * @return bool */ function has_lifetime_commission() { return ( 0 !== $this->future_payments_days ); } /** * @author Leo Fajardo (@leorw) * * @return bool */ function is_session_cookie() { return ( 0 == $this->cookie_days ); } /** * @author Leo Fajardo (@leorw) * * @return bool */ function has_renewals_commission() { return ( is_null( $this->commission_renewals_days ) || $this->commission_renewals_days > 0 ); } }freemius/includes/entities/class-fs-subscription.php000064400000006540146725417150017004 0ustar00is_canceled() ) { return false; } return ( ! empty( $this->next_payment ) && strtotime( $this->next_payment ) > WP_FS__SCRIPT_START_TIME ); } /** * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @return bool */ function is_canceled() { return ! is_null( $this->canceled_at ); } /** * Subscription considered to be new without any payments * if the next payment should be made within less than 24 hours * from the subscription creation. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_first_payment_pending() { return ( WP_FS__TIME_24_HOURS_IN_SEC >= strtotime( $this->next_payment ) - strtotime( $this->created ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7 */ function has_trial() { return ! is_null( $this->trial_ends ); } }freemius/includes/entities/class-fs-payment.php000064400000007704146725417150015740 0ustar00bound_payment_id ) && 0 > $this->gross ); } /** * Checks if the payment was migrated from another platform. * * @author Vova Feldman (@svovaf) * @since 2.0.2 * * @return bool */ function is_migrated() { return ( 0 != $this->source ); } /** * Returns the gross in this format: * `{symbol}{amount | 2 decimal digits} {currency | uppercase}` * * Examples: £9.99 GBP, -£9.99 GBP. * * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @return string */ function formatted_gross() { return ( ( $this->gross < 0 ? '-' : '' ) . $this->get_symbol() . number_format( abs( $this->gross ), 2, '.', ',' ) . ' ' . strtoupper( $this->currency ) ); } /** * A map between supported currencies with their symbols. * * @var array */ static $CURRENCY_2_SYMBOL; /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @return string */ private function get_symbol() { if ( ! isset( self::$CURRENCY_2_SYMBOL ) ) { // Lazy load. self::$CURRENCY_2_SYMBOL = array( self::CURRENCY_USD => '$', self::CURRENCY_GBP => '£', self::CURRENCY_EUR => '€', ); } return self::$CURRENCY_2_SYMBOL[ $this->currency ]; } }freemius/includes/entities/class-fs-site.php000064400000016402146725417150015222 0ustar00plan_id = $site->plan_id; } if ( ! is_bool( $this->is_disconnected ) ) { $this->is_disconnected = false; } } static function get_type() { return 'install'; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $url * * @return bool */ static function is_localhost_by_address( $url ) { if ( false !== strpos( $url, '127.0.0.1' ) || false !== strpos( $url, 'localhost' ) ) { return true; } if ( ! fs_starts_with( $url, 'http' ) ) { $url = 'http://' . $url; } $url_parts = parse_url( $url ); $subdomain = $url_parts['host']; return ( // Starts with. fs_starts_with( $subdomain, 'local.' ) || fs_starts_with( $subdomain, 'dev.' ) || fs_starts_with( $subdomain, 'test.' ) || fs_starts_with( $subdomain, 'stage.' ) || fs_starts_with( $subdomain, 'staging.' ) || // Ends with. fs_ends_with( $subdomain, '.dev' ) || fs_ends_with( $subdomain, '.test' ) || fs_ends_with( $subdomain, '.staging' ) || fs_ends_with( $subdomain, '.local' ) || fs_ends_with( $subdomain, '.example' ) || fs_ends_with( $subdomain, '.invalid' ) || // GoDaddy test/dev. fs_ends_with( $subdomain, '.myftpupload.com' ) || // ngrok tunneling. fs_ends_with( $subdomain, '.ngrok.io' ) || // wpsandbox. fs_ends_with( $subdomain, '.wpsandbox.pro' ) || // SiteGround staging. fs_starts_with( $subdomain, 'staging' ) || // WPEngine staging. fs_ends_with( $subdomain, '.staging.wpengine.com' ) || fs_ends_with( $subdomain, '.dev.wpengine.com' ) || fs_ends_with( $subdomain, '.wpengine.com' ) || // Pantheon ( fs_ends_with( $subdomain, 'pantheonsite.io' ) && ( fs_starts_with( $subdomain, 'test-' ) || fs_starts_with( $subdomain, 'dev-' ) ) ) || // Cloudways fs_ends_with( $subdomain, '.cloudwaysapps.com' ) || // Kinsta ( ( fs_starts_with( $subdomain, 'staging-' ) || fs_starts_with( $subdomain, 'env-' ) ) && ( fs_ends_with( $subdomain, '.kinsta.com' ) || fs_ends_with( $subdomain, '.kinsta.cloud' ) ) ) || // DesktopServer fs_ends_with( $subdomain, '.dev.cc' ) || // Pressable fs_ends_with( $subdomain, '.mystagingwebsite.com' ) || // WPMU DEV ( fs_ends_with( $subdomain, '.tempurl.host' ) || fs_ends_with( $subdomain, '.wpmudev.host' ) ) || // Vendasta ( fs_ends_with( $subdomain, '.websitepro-staging.com' ) || fs_ends_with( $subdomain, '.websitepro.hosting' ) ) || // InstaWP fs_ends_with( $subdomain, '.instawp.xyz' ) ); } function is_localhost() { return ( WP_FS__IS_LOCALHOST_FOR_SERVER || self::is_localhost_by_address( $this->url ) ); } /** * Check if site in trial. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_trial() { return is_numeric( $this->trial_plan_id ) && ( strtotime( $this->trial_ends ) > WP_FS__SCRIPT_START_TIME ); } /** * Check if user already utilized the trial with the current install. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_trial_utilized() { return is_numeric( $this->trial_plan_id ); } /** * @author Edgar Melkonyan * * @return bool */ function is_beta() { return ( isset( $this->is_beta ) && true === $this->is_beta ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.1 * * @param string $site_url * * @return bool */ function is_clone( $site_url ) { $clone_install_url = trailingslashit( fs_strip_url_protocol( $this->url ) ); return ( $clone_install_url !== $site_url ); } }freemius/includes/class-freemius-abstract.php000064400000027761146725417150015456 0ustar00is_registered() && $fs->is_tracking_allowed()` * * @since 1.0.1 * * @param bool $ignore_anonymous_state Since 2.5.1 * * @return bool */ abstract function is_registered( $ignore_anonymous_state = false ); /** * Check if the user skipped connecting the account with Freemius. * * @since 1.0.7 * * @return bool */ abstract function is_anonymous(); /** * Check if the user currently in activation mode. * * @since 1.0.7 * * @return bool */ abstract function is_activation_mode(); #endregion #---------------------------------------------------------------------------------- #region Module Type #---------------------------------------------------------------------------------- /** * Checks if the plugin's type is "plugin". The other type is "theme". * * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return bool */ abstract function is_plugin(); /** * Checks if the module type is "theme". The other type is "plugin". * * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return bool */ function is_theme() { return ( ! $this->is_plugin() ); } #endregion #---------------------------------------------------------------------------------- #region Permissions #---------------------------------------------------------------------------------- /** * Check if plugin must be WordPress.org compliant. * * @since 1.0.7 * * @return bool */ abstract function is_org_repo_compliant(); /** * Check if plugin is allowed to install executable files. * * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @return bool */ function is_allowed_to_install() { return ( $this->is_premium() || ! $this->is_org_repo_compliant() ); } #endregion /** * Check if user in trial or in free plan (not paying). * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @return bool */ function is_not_paying() { return ( $this->is_trial() || $this->is_free_plan() ); } /** * Check if the user has an activated and valid paid license on current plugin's install. * * @since 1.0.9 * * @return bool */ abstract function is_paying(); /** * Check if the user is paying or in trial. * * @since 1.0.9 * * @return bool */ function is_paying_or_trial() { return ( $this->is_paying() || $this->is_trial() ); } /** * Check if user in a trial or have feature enabled license. * * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @return bool */ abstract function can_use_premium_code(); #---------------------------------------------------------------------------------- #region Premium Only #---------------------------------------------------------------------------------- /** * All logic wrapped in methods with "__premium_only()" suffix will be only * included in the premium code. * * Example: * if ( freemius()->is__premium_only() ) { * ... * } */ /** * Returns true when running premium plugin code. * * @since 1.0.9 * * @return bool */ function is__premium_only() { return $this->is_premium(); } /** * Check if the user has an activated and valid paid license on current plugin's install. * * @since 1.0.9 * * @return bool * */ function is_paying__premium_only() { return ( $this->is__premium_only() && $this->is_paying() ); } /** * All code wrapped in this statement will be only included in the premium code. * * @since 1.0.9 * * @param string $plan Plan name. * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. * * @return bool */ function is_plan__premium_only( $plan, $exact = false ) { return ( $this->is_premium() && $this->is_plan( $plan, $exact ) ); } /** * Check if plan matches active license' plan or active trial license' plan. * * All code wrapped in this statement will be only included in the premium code. * * @since 1.0.9 * * @param string $plan Plan name. * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. * * @return bool */ function is_plan_or_trial__premium_only( $plan, $exact = false ) { return ( $this->is_premium() && $this->is_plan_or_trial( $plan, $exact ) ); } /** * Check if the user is paying or in trial. * * All code wrapped in this statement will be only included in the premium code. * * @since 1.0.9 * * @return bool */ function is_paying_or_trial__premium_only() { return $this->is_premium() && $this->is_paying_or_trial(); } /** * Check if the user has an activated and valid paid license on current plugin's install. * * @since 1.0.4 * * @return bool * * @deprecated Method name is confusing since it's not clear from the name the code will be removed. * @using Alias to is_paying__premium_only() */ function is_paying__fs__() { return $this->is_paying__premium_only(); } /** * Check if user in a trial or have feature enabled license. * * All code wrapped in this statement will be only included in the premium code. * * @author Vova Feldman (@svovaf) * @since 1.1.9 * * @return bool */ function can_use_premium_code__premium_only() { return $this->is_premium() && $this->can_use_premium_code(); } #endregion #---------------------------------------------------------------------------------- #region Trial #---------------------------------------------------------------------------------- /** * Check if the user in a trial. * * @since 1.0.3 * * @return bool */ abstract function is_trial(); /** * Check if trial already utilized. * * @since 1.0.9 * * @return bool */ abstract function is_trial_utilized(); #endregion #---------------------------------------------------------------------------------- #region Plans #---------------------------------------------------------------------------------- /** * Check if the user is on the free plan of the product. * * @since 1.0.4 * * @return bool */ abstract function is_free_plan(); /** * @since 1.0.2 * * @param string $plan Plan name. * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. * * @return bool */ abstract function is_plan( $plan, $exact = false ); /** * Check if plan based on trial. If not in trial mode, should return false. * * @since 1.0.9 * * @param string $plan Plan name. * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. * * @return bool */ abstract function is_trial_plan( $plan, $exact = false ); /** * Check if plan matches active license' plan or active trial license' plan. * * @since 1.0.9 * * @param string $plan Plan name. * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. * * @return bool */ function is_plan_or_trial( $plan, $exact = false ) { return $this->is_plan( $plan, $exact ) || $this->is_trial_plan( $plan, $exact ); } /** * Check if plugin has any paid plans. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return bool */ abstract function has_paid_plan(); /** * Check if plugin has any free plan, or is it premium only. * * Note: If no plans configured, assume plugin is free. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return bool */ abstract function has_free_plan(); /** * Check if plugin is premium only (no free plans). * * NOTE: is__premium_only() is very different method, don't get confused. * * @author Vova Feldman (@svovaf) * @since 1.1.9 * * @return bool */ abstract function is_only_premium(); /** * Check if module has a premium code version. * * Serviceware module might be freemium without any * premium code version, where the paid features * are all part of the service. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @return bool */ abstract function has_premium_version(); /** * Check if module has any release on Freemius, * or all plugin's code is on WordPress.org (Serviceware). * * @return bool */ function has_release_on_freemius() { return ! $this->is_org_repo_compliant() || $this->has_premium_version(); } /** * Checks if it's a freemium plugin. * * @author Vova Feldman (@svovaf) * @since 1.1.9 * * @return bool */ function is_freemium() { return $this->has_paid_plan() && $this->has_free_plan(); } /** * Check if module has only one plan. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @return bool */ abstract function is_single_plan(); #endregion /** * Check if running payments in sandbox mode. * * @since 1.0.4 * * @return bool */ abstract function is_payments_sandbox(); /** * Check if running test vs. live plugin. * * @since 1.0.5 * * @return bool */ abstract function is_live(); /** * Check if running premium plugin code. * * @since 1.0.5 * * @return bool */ abstract function is_premium(); /** * Get upgrade URL. * * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @param string $period Billing cycle. * * @return string */ abstract function get_upgrade_url( $period = WP_FS__PERIOD_ANNUALLY ); /** * Check if Freemius was first added in a plugin update. * * @author Vova Feldman (@svovaf) * @since 1.1.5 * * @return bool */ function is_plugin_update() { return ! $this->is_plugin_new_install(); } /** * Check if Freemius was part of the plugin when the user installed it first. * * @author Vova Feldman (@svovaf) * @since 1.1.5 * * @return bool */ abstract function is_plugin_new_install(); #---------------------------------------------------------------------------------- #region Marketing #---------------------------------------------------------------------------------- /** * Check if current user purchased any other plugins before. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ abstract function has_purchased_before(); /** * Check if current user classified as an agency. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ abstract function is_agency(); /** * Check if current user classified as a developer. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ abstract function is_developer(); /** * Check if current user classified as a business. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ abstract function is_business(); #endregion }freemius/includes/class-fs-api.php000064400000053676146725417150013221 0ustar00get_option( 'api_clock_diff', 0 ); Freemius_Api_WordPress::SetClockDiff( self::$_clock_diff ); if ( self::$_options->get_option( 'api_force_http', false ) ) { Freemius_Api_WordPress::SetHttp(); } } /** * @param string $slug * @param string $scope 'app', 'developer', 'user' or 'install'. * @param number $id Element's id. * @param string $public_key Public key. * @param bool|string $secret_key Element's secret key. * @param bool $is_sandbox * @param null|string $sdk_version * @param null|string $url */ private function __construct( $slug, $scope, $id, $public_key, $secret_key, $is_sandbox, $sdk_version, $url ) { $this->_api = new Freemius_Api_WordPress( $scope, $id, $public_key, $secret_key, $is_sandbox ); $this->_slug = $slug; $this->_sdk_version = $sdk_version; $this->_url = $url; $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $slug . '_api', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); } /** * Find clock diff between server and API server, and store the diff locally. * * @param bool|int $diff * * @return bool|int False if clock diff didn't change, otherwise returns the clock diff in seconds. */ private function _sync_clock_diff( $diff = false ) { $this->_logger->entrance(); // Sync clock and store. $new_clock_diff = ( false === $diff ) ? Freemius_Api_WordPress::FindClockDiff() : $diff; if ( $new_clock_diff === self::$_clock_diff ) { return false; } self::$_clock_diff = $new_clock_diff; // Update API clock's diff. Freemius_Api_WordPress::SetClockDiff( self::$_clock_diff ); // Store new clock diff in storage. self::$_options->set_option( 'api_clock_diff', self::$_clock_diff, true ); return $new_clock_diff; } /** * Override API call to enable retry with servers' clock auto sync method. * * @param string $path * @param string $method * @param array $params * @param bool $in_retry Is in retry or first call attempt. * * @return array|mixed|string|void */ private function _call( $path, $method = 'GET', $params = array(), $in_retry = false ) { $this->_logger->entrance( $method . ':' . $path ); $force_http = ( ! $in_retry && self::$_options->get_option( 'api_force_http', false ) ); if ( self::is_temporary_down() ) { $result = $this->get_temporary_unavailable_error(); } else { /** * @since 2.3.0 Include the SDK version with all API requests that going through the API manager. IMPORTANT: Only pass the SDK version if the caller didn't include it yet. */ if ( ! empty( $this->_sdk_version ) ) { if ( false === strpos( $path, 'sdk_version=' ) && ! isset( $params['sdk_version'] ) ) { // Always add the sdk_version param in the querystring. DO NOT INCLUDE IT IN THE BODY PARAMS, OTHERWISE, IT MAY LEAD TO AN UNEXPECTED PARAMS PARSING IN CASES WHERE THE $params IS A REGULAR NON-ASSOCIATIVE ARRAY. $path = add_query_arg( 'sdk_version', $this->_sdk_version, $path ); } } /** * @since 2.5.0 Include the site's URL, if available, in all API requests that are going through the API manager. */ if ( ! empty( $this->_url ) ) { if ( false === strpos( $path, 'url=' ) && ! isset( $params['url'] ) ) { $path = add_query_arg( 'url', $this->_url, $path ); } } $result = $this->_api->Api( $path, $method, $params ); if ( ! $in_retry && null !== $result && isset( $result->error ) && isset( $result->error->code ) ) { $retry = false; if ( 'request_expired' === $result->error->code ) { $diff = isset( $result->error->timestamp ) ? ( time() - strtotime( $result->error->timestamp ) ) : false; // Try to sync clock diff. if ( false !== $this->_sync_clock_diff( $diff ) ) { // Retry call with new synced clock. $retry = true; } } else if ( Freemius_Api_WordPress::IsHttps() && FS_Api::is_ssl_error_response( $result ) ) { $force_http = true; $retry = true; } if ( $retry ) { if ( $force_http ) { $this->toggle_force_http( true ); } $result = $this->_call( $path, $method, $params, true ); } } } if ( self::is_api_error( $result ) ) { if ( $this->_logger->is_on() ) { // Log API errors. $this->_logger->api_error( $result ); } if ( $force_http ) { $this->toggle_force_http( false ); } } return $result; } /** * Override API call to wrap it in servers' clock sync method. * * @param string $path * @param string $method * @param array $params * * @return array|mixed|string|void * @throws Freemius_Exception */ function call( $path, $method = 'GET', $params = array() ) { return $this->_call( $path, $method, $params ); } /** * Get API request URL signed via query string. * * @param string $path * * @return string */ function get_signed_url( $path ) { return $this->_api->GetSignedUrl( $path ); } /** * @param string $path * @param bool $flush * @param int $expiration (optional) Time until expiration in seconds from now, defaults to 24 hours * * @return stdClass|mixed */ function get( $path = '/', $flush = false, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) { $this->_logger->entrance( $path ); $cache_key = $this->get_cache_key( $path ); // Always flush during development. if ( WP_FS__DEV_MODE || $this->_api->IsSandbox() ) { $flush = true; } $cached_result = self::$_cache->get( $cache_key ); if ( $flush || ! self::$_cache->has_valid( $cache_key, $expiration ) ) { $result = $this->call( $path ); if ( ! is_object( $result ) || isset( $result->error ) ) { // Api returned an error. if ( is_object( $cached_result ) && ! isset( $cached_result->error ) ) { // If there was an error during a newer data fetch, // fallback to older data version. $result = $cached_result; if ( $this->_logger->is_on() ) { $this->_logger->warn( 'Fallback to cached API result: ' . var_export( $cached_result, true ) ); } } else { if ( is_object( $result ) && isset( $result->error->http ) && 404 == $result->error->http ) { /** * If the response code is 404, cache the result for half of the `$expiration`. * * @author Leo Fajardo (@leorw) * @since 2.2.4 */ $expiration /= 2; } else { // If no older data version and the response code is not 404, return result without // caching the error. return $result; } } } self::$_cache->set( $cache_key, $result, $expiration ); $cached_result = $result; } else { $this->_logger->log( 'Using cached API result.' ); } return $cached_result; } /** * @todo Remove this method after migrating Freemius::safe_remote_post() to FS_Api::call(). * * @author Leo Fajardo (@leorw) * @since 2.5.4 * * @param string $url * @param array $remote_args * * @return array|WP_Error The response array or a WP_Error on failure. */ static function remote_request( $url, $remote_args ) { if ( ! class_exists( 'Freemius_Api_WordPress' ) ) { require_once WP_FS__DIR_SDK . '/FreemiusWordPress.php'; } if ( method_exists( 'Freemius_Api_WordPress', 'RemoteRequest' ) ) { return Freemius_Api_WordPress::RemoteRequest( $url, $remote_args ); } // The following is for backward compatibility when a modified PHP SDK version is in use and the `Freemius_Api_WordPress:RemoteRequest()` method doesn't exist. $response = wp_remote_request( $url, $remote_args ); if ( is_array( $response ) && ( empty( $response['headers'] ) || empty( $response['headers']['x-api-server'] ) ) ) { // API is considered blocked if the response doesn't include the `x-api-server` header. When there's no error but this header doesn't exist, the response is usually not in the expected form (e.g., cannot be JSON-decoded). $response = new WP_Error( 'api_blocked', htmlentities( $response['body'] ) ); } return $response; } /** * Check if there's a cached version of the API request. * * @author Vova Feldman (@svovaf) * @since 1.2.1 * * @param string $path * @param string $method * @param array $params * * @return bool */ function is_cached( $path, $method = 'GET', $params = array() ) { $cache_key = $this->get_cache_key( $path, $method, $params ); return self::$_cache->has_valid( $cache_key ); } /** * Invalidate a cached version of the API request. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param string $path * @param string $method * @param array $params */ function purge_cache( $path, $method = 'GET', $params = array() ) { $this->_logger->entrance( "{$method}:{$path}" ); $cache_key = $this->get_cache_key( $path, $method, $params ); self::$_cache->purge( $cache_key ); } /** * Invalidate a cached version of the API request. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $path * @param int $expiration * @param string $method * @param array $params */ function update_cache_expiration( $path, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $method = 'GET', $params = array() ) { $this->_logger->entrance( "{$method}:{$path}:{$expiration}" ); $cache_key = $this->get_cache_key( $path, $method, $params ); self::$_cache->update_expiration( $cache_key, $expiration ); } /** * @param string $path * @param string $method * @param array $params * * @return string * @throws \Freemius_Exception */ private function get_cache_key( $path, $method = 'GET', $params = array() ) { $canonized = $this->_api->CanonizePath( $path ); // $exploded = explode('/', $canonized); // return $method . '_' . array_pop($exploded) . '_' . md5($canonized . json_encode($params)); return strtolower( $method . ':' . $canonized ) . ( ! empty( $params ) ? '#' . md5( json_encode( $params ) ) : '' ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.4 * * @param bool $is_http */ private function toggle_force_http( $is_http ) { self::$_options->set_option( 'api_force_http', $is_http, true ); if ( $is_http ) { Freemius_Api_WordPress::SetHttp(); } else if ( method_exists( 'Freemius_Api_WordPress', 'SetHttps' ) ) { Freemius_Api_WordPress::SetHttps(); } } /** * @author Leo Fajardo (@leorw) * @since 2.5.4 * * @param mixed $response * * @return bool */ static function is_blocked( $response ) { return ( self::is_api_error_object( $response, true ) && isset( $response->error->code ) && 'api_blocked' === $response->error->code ); } /** * Check if API is temporary down. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @return bool */ static function is_temporary_down() { self::_init(); $test = self::$_cache->get_valid( 'ping_test', null ); return ( false === $test ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @return object */ private function get_temporary_unavailable_error() { return (object) array( 'error' => (object) array( 'type' => 'TemporaryUnavailable', 'message' => 'API is temporary unavailable, please retry in ' . ( self::$_cache->get_record_expiration( 'ping_test' ) - WP_FS__SCRIPT_START_TIME ) . ' sec.', 'code' => 'temporary_unavailable', 'http' => 503 ) ); } /** * Check if based on the API result we should try * to re-run the same request with HTTP instead of HTTPS. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param $result * * @return bool */ private static function should_try_with_http( $result ) { if ( ! Freemius_Api_WordPress::IsHttps() ) { return false; } return ( ! is_object( $result ) || ! isset( $result->error ) || ! isset( $result->error->code ) || ! in_array( $result->error->code, array( 'curl_missing', 'cloudflare_ddos_protection', 'maintenance_mode', 'squid_cache_block', 'too_many_requests', ) ) ); } function get_url( $path = '' ) { return Freemius_Api_WordPress::GetUrl( $path, $this->_api->IsSandbox() ); } /** * Clear API cache. * * @author Vova Feldman (@svovaf) * @since 1.0.9 */ static function clear_cache() { self::_init(); self::$_cache = FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME ); self::$_cache->clear(); } /** * @author Leo Fajardo (@leorw) * @since 2.5.4 */ static function clear_force_http_flag() { self::$_options->unset_option( 'api_force_http' ); } #---------------------------------------------------------------------------------- #region Error Handling #---------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $result * * @return bool Is API result contains an error. */ static function is_api_error( $result ) { return ( is_object( $result ) && isset( $result->error ) ) || is_string( $result ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param mixed $result * @param bool $ignore_message * * @return bool Is API result contains an error. */ static function is_api_error_object( $result, $ignore_message = false ) { return ( is_object( $result ) && isset( $result->error ) && ( $ignore_message || isset( $result->error->message ) ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.4 * * @param WP_Error|object|string $response * * @return bool */ static function is_ssl_error_response( $response ) { $http_error = null; if ( $response instanceof WP_Error ) { if ( isset( $response->errors ) && isset( $response->errors['http_request_failed'] ) ) { $http_error = strtolower( $response->errors['http_request_failed'][0] ); } } else if ( self::is_api_error_object( $response ) && ! empty( $response->error->message ) ) { $http_error = $response->error->message; } return ( ! empty( $http_error ) && ( false !== strpos( $http_error, 'curl error 35' ) || ( false === strpos( $http_error, '' ) && false !== strpos( $http_error, 'ssl' ) ) ) ); } /** * Checks if given API result is a non-empty and not an error object. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $result * @param string|null $required_property Optional property we want to verify that is set. * * @return bool */ static function is_api_result_object( $result, $required_property = null ) { return ( is_object( $result ) && ! isset( $result->error ) && ( empty( $required_property ) || isset( $result->{$required_property} ) ) ); } /** * Checks if given API result is a non-empty entity object with non-empty ID. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $result * * @return bool */ static function is_api_result_entity( $result ) { return self::is_api_result_object( $result, 'id' ) && FS_Entity::is_valid_id( $result->id ); } /** * Get API result error code. If failed to get code, returns an empty string. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param mixed $result * * @return string */ static function get_error_code( $result ) { if ( is_object( $result ) && isset( $result->error ) && is_object( $result->error ) && ! empty( $result->error->code ) ) { return $result->error->code; } return ''; } #endregion }freemius/includes/class-freemius.php000064400003676244146725417150013666 0ustar00store_id_slug_type_path_map( $module_id, $slug ); } $this->_module_id = $module_id; $this->_slug = $this->get_slug(); $this->_module_type = $this->get_module_type(); $this->_blog_id = is_multisite() ? get_current_blog_id() : null; $this->_storage = FS_Storage::instance( $this->_module_type, $this->_slug ); $this->_cache = FS_Cache_Manager::get_manager( WP_FS___OPTION_PREFIX . "cache_{$module_id}" ); $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $this->get_unique_affix(), WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); $this->_plugin_main_file_path = $this->_find_caller_plugin_file( $is_init, $main_file ); $this->_plugin_dir_path = plugin_dir_path( $this->_plugin_main_file_path ); $this->_plugin_basename = $this->get_plugin_basename(); $this->_free_plugin_basename = str_replace( '-premium/', '/', $this->_plugin_basename ); $this->_is_multisite_integrated = ( defined( "WP_FS__PRODUCT_{$module_id}_MULTISITE" ) && ( true === constant( "WP_FS__PRODUCT_{$module_id}_MULTISITE" ) ) ); $this->_is_network_active = ( is_multisite() && $this->_is_multisite_integrated && // Themes are always network activated, but the ACTUAL activation is per site. $this->is_plugin() && ( is_plugin_active_for_network( $this->_plugin_basename ) || // Plugin network level activation or uninstall. ( fs_is_network_admin() && is_plugin_inactive( $this->_plugin_basename ) ) ) ); $this->_storage->set_network_active( $this->_is_network_active, $this->is_delegated_connection() ); if ( ! isset( $this->_storage->is_network_activated ) ) { $this->_storage->is_network_activated = $this->_is_network_active; } if ( $this->_storage->is_network_activated != $this->_is_network_active ) { // Update last activation level. $this->_storage->is_network_activated = $this->_is_network_active; $this->maybe_adjust_storage(); } #region Migration if ( is_multisite() ) { /** * If the install_timestamp exists on the site level but doesn't exist on the * network level storage, it means that we need to process the storage with migration. * * The code in this `if` scope will only be executed once and only for the first site that will execute it because once we migrate the storage data, install_timestamp will be already set in the network level storage. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ if ( false === $this->_storage->get( 'install_timestamp', false, true ) && false !== $this->_storage->get( 'install_timestamp', false, false ) ) { // Initiate storage migration. $this->_storage->migrate_to_network(); // Migrate module cache to network level storage. $this->_cache->migrate_to_network(); } } #endregion $base_name_split = explode( '/', $this->_plugin_basename ); $this->_plugin_dir_name = $base_name_split[0]; if ( $this->_logger->is_on() ) { $this->_logger->info( 'plugin_main_file_path = ' . $this->_plugin_main_file_path ); $this->_logger->info( 'plugin_dir_path = ' . $this->_plugin_dir_path ); $this->_logger->info( 'plugin_basename = ' . $this->_plugin_basename ); $this->_logger->info( 'free_plugin_basename = ' . $this->_free_plugin_basename ); $this->_logger->info( 'plugin_dir_name = ' . $this->_plugin_dir_name ); } // Remember link between file to slug. $this->store_file_slug_map(); // Store plugin's initial install timestamp. if ( ! isset( $this->_storage->install_timestamp ) ) { $this->_storage->install_timestamp = WP_FS__SCRIPT_START_TIME; } if ( ! is_object( $this->_plugin ) ) { $this->_plugin = FS_Plugin_Manager::instance( $this->_module_id )->get(); } $this->_admin_notices = FS_Admin_Notices::instance( $this->_slug . ( $this->is_theme() ? ':theme' : '' ), /** * Ensure that the admin notice will always have a title by using the stored plugin title if available and * retrieving the title via the "get_plugin_name" method if there is no stored plugin title available. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ ( is_object( $this->_plugin ) && isset( $this->_plugin->title ) ? $this->_plugin->title : $this->get_plugin_name() ), $this->get_unique_affix() ); if ( 'true' === fs_request_get( 'fs_clear_api_cache' ) || fs_request_is_action( 'restart_freemius' ) ) { FS_Api::clear_cache(); $this->_cache->clear(); } $this->register_constructor_hooks(); /** * Starting from version 2.0.0, `FS_Site` entities no longer have the `plan` property and have `plan_id` * instead. This should be called before calling `_load_account()`, otherwise, `$this->_site` will not be * loaded in `_load_account` for versions of SDK starting from 2.0.0. * * @author Leo Fajardo (@leorw) */ self::migrate_install_plan_to_plan_id( $this->_storage ); $this->_load_account(); $this->_version_updates_handler(); } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 */ private function maybe_adjust_storage() { $install_timestamp = null; $prev_is_premium = null; $options_to_update = array(); $is_network_admin = fs_is_network_admin(); $network_install_timestamp = $this->_storage->get( 'install_timestamp', null, true ); if ( ! $is_network_admin ) { if ( is_null( $network_install_timestamp ) ) { // Plugin was not network-activated before. return; } if ( is_null( $this->_storage->get( 'install_timestamp', null, false ) ) ) { // Set the `install_timestamp` only if it's not yet set. $install_timestamp = $network_install_timestamp; } $prev_is_premium = $this->_storage->get( 'prev_is_premium', null, true ); } else { $current_wp_user = self::_get_current_wp_user(); $current_fs_user = self::_get_user_by_email( $current_wp_user->user_email ); $network_user_info = array(); $skips_count = 0; $sites = self::get_sites(); $sites_count = count( $sites ); $blog_id_2_install_map = array(); $is_first_non_ignored_blog = true; foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $blog_install_timestamp = $this->_storage->get( 'install_timestamp', null, $blog_id ); if ( is_null( $blog_install_timestamp ) ) { // Plugin has not been installed on this blog. continue; } $is_earlier_install = ( ! is_null( $install_timestamp ) && $blog_install_timestamp < $install_timestamp ); $install = $this->get_install_by_blog_id( $blog_id ); $update_network_user_info = false; if ( ! is_object( $install ) ) { if ( ! $this->_storage->get( 'is_anonymous', false, $blog_id ) ) { // The opt-in decision (whether to skip or opt in) is yet to be made. continue; } $skips_count ++; } else { $blog_id_2_install_map[ $blog_id ] = $install; if ( empty( $network_user_info ) ) { // Set the network user info for the 1st time. Choose any user information whether or not it is for the current WP user. $update_network_user_info = true; } if ( ! $update_network_user_info && is_object( $current_fs_user ) && $network_user_info['user_id'] != $current_fs_user->id && $install->user_id == $current_fs_user->id ) { // If an install that is owned by the current WP user is found, use its user information instead. $update_network_user_info = true; } if ( ! $update_network_user_info && $is_earlier_install && ( ! is_object( $current_fs_user ) || $current_fs_user->id == $install->user_id ) ) { // Update to the earliest install info if there's no install found so far that is owned by the current WP user; OR only if the found install is owned by the current WP user. $update_network_user_info = true; } } if ( $update_network_user_info ) { $network_user_info = array( 'user_id' => $install->user_id, 'blog_id' => $blog_id ); } $site_prev_is_premium = $this->_storage->get( 'prev_is_premium', null, $blog_id ); if ( $is_first_non_ignored_blog ) { $prev_is_premium = $site_prev_is_premium; if ( is_null( $network_install_timestamp ) ) { $install_timestamp = $blog_install_timestamp; } $is_first_non_ignored_blog = false; continue; } if ( ! is_null( $prev_is_premium ) && $prev_is_premium !== $site_prev_is_premium ) { // If a different `$site_prev_is_premium` value is found, do not include the option in the collection of options to update. $prev_is_premium = null; } if ( $is_earlier_install ) { // If an earlier install timestamp is found. $install_timestamp = $blog_install_timestamp; } } $installs_count = count( $blog_id_2_install_map ); if ( $sites_count === ( $installs_count + $skips_count ) ) { if ( ! empty( $network_user_info ) ) { $options_to_update['network_user_id'] = $network_user_info['user_id']; $options_to_update['network_install_blog_id'] = $network_user_info['blog_id']; foreach ( $blog_id_2_install_map as $blog_id => $install ) { if ( $install->user_id == $network_user_info['user_id'] ) { continue; } $this->_storage->store( 'is_delegated_connection', true, $blog_id ); } } if ( $sites_count === $skips_count ) { /** * Assume network-level skipping as the intended action if all actions identified were only * skipping of the connection (i.e., no opt-ins and delegated connections so far). */ $options_to_update['is_anonymous_ms'] = true; } else if ( $sites_count === $installs_count ) { /** * Assume network-level opt-in as the intended action if all actions identified were only opt-ins * (i.e., no delegation and skipping of the connections so far). */ $options_to_update['is_network_connected'] = true; } } } if ( ! is_null( $install_timestamp ) ) { $options_to_update['install_timestamp'] = $install_timestamp; } if ( ! is_null( $prev_is_premium ) ) { $options_to_update['prev_is_premium'] = $prev_is_premium; } if ( ! empty( $options_to_update ) ) { $this->adjust_storage( $options_to_update, $is_network_admin ); } } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param array $options * @param bool $is_network_admin */ private function adjust_storage( $options, $is_network_admin ) { foreach ( $options as $name => $value ) { $this->_storage->store( $name, $value, $is_network_admin ? true : null ); } } /** * Checks whether this module has a settings menu. * * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return bool */ function has_settings_menu() { return ( $this->_is_network_active && fs_is_network_admin() ) ? $this->_menu->has_network_menu() : $this->_menu->has_menu(); } /** * If `true` the opt-in should be shown as a modal dialog box on the themes.php page. WordPress.org themes guidelines prohibit from redirecting the user from the themes.php page after activating a theme. * * @author Vova Feldman (@svovaf) * @since 2.4.5 * * @return bool */ function show_opt_in_on_themes_page() { if ( ! $this->is_free_wp_org_theme() ) { return false; } if ( ! $this->has_settings_menu() ) { return true; } return $this->show_settings_with_tabs(); } /** * If `true` the opt-in should be shown on the product's main setting page. * * @author Vova Feldman (@svovaf) * @since 2.4.5 * * @return bool * * @uses show_opt_in_on_themes_page(); */ function show_opt_in_on_setting_page() { return ! $this->show_opt_in_on_themes_page(); } /** * If `true` the settings should be shown using tabs. * * @author Vova Feldman (@svovaf) * @since 2.4.5 * * @return bool */ function show_settings_with_tabs() { return ( self::NAVIGATION_TABS === $this->_navigation ); } /** * Check if the context module is free wp.org theme. * * This method is helpful because: * 1. wp.org themes are limited to a single submenu item, * and sub-submenu items are most likely not allowed (never verified). * 2. wp.org themes are not allowed to redirect the user * after the theme activation, therefore, the agreed UX * is showing the opt-in as a modal dialog box after * activation (approved by @otto42, @emiluzelac, @greenshady, @grapplerulrich). * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool */ function is_free_wp_org_theme() { return ( $this->is_theme() && $this->is_org_repo_compliant() && ! $this->is_premium() ); } /** * Checks whether this a submenu item is visible. * * @author Vova Feldman (@svovaf) * @since 1.2.2.6 * @since 1.2.2.7 Even if the menu item was specified to be hidden, when it is the context page, then show the submenu item so the user will have the right context page. * * @param string $slug * @param bool $is_tabs_visibility_check This is used to decide if the associated tab should be shown or hidden. * * @return bool */ function is_submenu_item_visible( $slug, $is_tabs_visibility_check = false ) { if ( $this->is_admin_page( $slug ) ) { /** * It is the current context page, so show the submenu item * so the user will have the right context page, even if it * was set to hidden. */ return true; } if ( ! $this->has_settings_menu() ) { // No menu settings at all. return false; } if ( ! $is_tabs_visibility_check && $this->is_org_repo_compliant() && $this->show_settings_with_tabs() ) { /** * wp.org themes are limited to a single submenu item, and * sub-submenu items are most likely not allowed (never verified). */ return false; } return $this->_menu->is_submenu_item_visible( $slug ); } /** * Check if a Freemius page should be accessible via the UI. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @param string $slug * * @return bool */ function is_page_visible( $slug ) { if ( $this->is_admin_page( $slug ) ) { return true; } return $this->_menu->is_submenu_item_visible( $slug, true, true ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 */ private function _version_updates_handler() { if ( ! isset( $this->_storage->sdk_version ) || $this->_storage->sdk_version != $this->version ) { // Freemius version upgrade mode. $this->_storage->sdk_last_version = $this->_storage->sdk_version; $this->_storage->sdk_version = $this->version; if ( empty( $this->_storage->sdk_last_version ) || version_compare( $this->_storage->sdk_last_version, $this->version, '<' ) ) { $this->_storage->sdk_upgrade_mode = true; $this->_storage->sdk_downgrade_mode = false; } else { $this->_storage->sdk_downgrade_mode = true; $this->_storage->sdk_upgrade_mode = false; } $this->do_action( 'sdk_version_update', $this->_storage->sdk_last_version, $this->version ); } $plugin_version = $this->get_plugin_version(); if ( ! isset( $this->_storage->plugin_version ) || $this->_storage->plugin_version != $plugin_version ) { // Plugin version upgrade mode. $this->_storage->plugin_last_version = $this->_storage->plugin_version; $this->_storage->plugin_version = $plugin_version; if ( empty( $this->_storage->plugin_last_version ) || version_compare( $this->_storage->plugin_last_version, $plugin_version, '<' ) ) { $this->_storage->plugin_upgrade_mode = true; $this->_storage->plugin_downgrade_mode = false; } else { $this->_storage->plugin_downgrade_mode = true; $this->_storage->plugin_upgrade_mode = false; } if ( ! empty( $this->_storage->plugin_last_version ) ) { // Different version of the plugin was installed before, therefore it's an update. $this->_storage->is_plugin_new_install = false; } $this->do_action( 'plugin_version_update', $this->_storage->plugin_last_version, $plugin_version ); } } #-------------------------------------------------------------------------------- #region Data Migration on SDK Update #-------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 1.1.5 * * @param string $sdk_prev_version * @param string $sdk_version */ function _sdk_version_update( $sdk_prev_version, $sdk_version ) { if ( empty( $sdk_prev_version ) ) { return; } if ( version_compare( $sdk_prev_version, '2.5.1', '<' ) && version_compare( $sdk_version, '2.5.1', '>=' ) ) { if ( $this->is_registered( true ) ) { /** * Migrate to new permissions layer. */ require_once WP_FS__DIR_INCLUDES . '/supplements/fs-migration-2.5.1.php'; $install_by_blog_id = is_multisite() ? $this->get_blog_install_map() : array( 0 => $this->_site ); fs_migrate_251( $this, $install_by_blog_id ); } } } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param \FS_Storage $storage * @param bool|int|null $blog_id */ private static function migrate_install_plan_to_plan_id( FS_Storage $storage, $blog_id = null ) { if ( empty( $storage->sdk_version ) ) { // New installation of the plugin, no need to upgrade. return; } if ( ! version_compare( $storage->sdk_version, '2.0.0', '<' ) ) { // Previous version is >= 2.0.0, so no need to migrate. return; } // Alias. $module_type = $storage->get_module_type(); $module_slug = $storage->get_module_slug(); $installs = self::get_all_sites( $module_type, $blog_id ); $install = isset( $installs[ $module_slug ] ) ? $installs[ $module_slug ] : null; if ( ! is_object( $install ) ) { return; } if ( isset( $install->plan ) && is_object( $install->plan ) ) { if ( isset( $install->plan->id ) && ! empty( $install->plan->id ) ) { $install->plan_id = self::_decrypt( $install->plan->id ); } unset( $install->plan ); $installs[ $module_slug ] = clone $install; self::set_account_option_by_module( $module_type, 'sites', $installs, true, $blog_id ); } } /** * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @param string $plugin_prev_version * @param string $plugin_version */ function _after_version_update( $plugin_prev_version, $plugin_version ) { if ( $this->is_theme() ) { // Expire the cache of the previous tabs since the theme may // have setting updates. $this->_cache->expire( 'tabs' ); $this->_cache->expire( 'tabs_stylesheets' ); } } /** * A special migration logic for the $_accounts, executed for all the plugins in the system: * - Moves some data to the network level storage. * - If the plugin's connection was skipped for all sites, set the plugin as if it was network skipped. * - If the plugin's connection was ignored for all sites, don't do anything in terms of the network connection. * - If the plugin was connected to all sites by the same super-admin, set the plugin as if was network opted-in for all sites. * - If there's at least one site that was connected by a super-admin, find the "main super-admin" (the one that installed the majority of the plugin installs) and set the plugin as if was network activated with the main super-admin, set all the sites that were skipped or opted-in with a different user to delegated mode. Then, prompt the currently logged super-admin to choose what to do with the ignored sites. * - If there are any sites in the network which the connection decision was not yet taken for, set this plugin into network activation mode so a super-admin can choose what to do with the rest of the sites. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ private static function migrate_accounts_to_network() { $sites = self::get_sites(); $sites_count = count( $sites ); $connection_status = array(); $plugin_slugs = array(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); self::$_accounts->migrate_to_network( $blog_id ); /** * Build a list of all Freemius powered plugins slugs. */ $id_slug_type_path_map = self::$_accounts->get_option( 'id_slug_type_path_map', array(), $blog_id ); foreach ( $id_slug_type_path_map as $module_id => $data ) { if ( WP_FS__MODULE_TYPE_PLUGIN === $data['type'] ) { $plugin_slugs[ $data['slug'] ] = true; } } $installs = self::get_account_option( 'sites', WP_FS__MODULE_TYPE_PLUGIN, $blog_id ); if ( is_array( $installs ) ) { foreach ( $installs as $slug => $install ) { if ( ! isset( $connection_status[ $slug ] ) ) { $connection_status[ $slug ] = array(); } if ( is_object( $install ) && FS_Site::is_valid_id( $install->id ) && FS_User::is_valid_id( $install->user_id ) ) { $connection_status[ $slug ][ $blog_id ] = $install->user_id; } } } } foreach ( $plugin_slugs as $slug => $true ) { if ( ! isset( $connection_status[ $slug ] ) ) { $connection_status[ $slug ] = array(); } foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); if ( isset( $connection_status[ $slug ][ $blog_id ] ) ) { continue; } $storage = FS_Storage::instance( WP_FS__MODULE_TYPE_PLUGIN, $slug ); $is_anonymous = $storage->get( 'is_anonymous', null, $blog_id ); if ( ! is_null( $is_anonymous ) ) { // Since 1.1.3 is_anonymous is an array. if ( is_array( $is_anonymous ) && isset( $is_anonymous['is'] ) ) { $is_anonymous = $is_anonymous['is']; } if ( is_bool( $is_anonymous ) && true === $is_anonymous ) { $connection_status[ $slug ][ $blog_id ] = 'skipped'; } } if ( ! isset( $connection_status[ $slug ][ $blog_id ] ) ) { $connection_status[ $slug ][ $blog_id ] = 'ignored'; } } } $super_admins = array(); foreach ( $connection_status as $slug => $blogs_status ) { $skips = 0; $ignores = 0; $connections = 0; $opted_in_users = array(); $opted_in_super_admins = array(); $storage = FS_Storage::instance( WP_FS__MODULE_TYPE_PLUGIN, $slug ); foreach ( $blogs_status as $blog_id => $status_or_user_id ) { if ( 'skipped' === $status_or_user_id ) { $skips ++; } else if ( 'ignored' === $status_or_user_id ) { $ignores ++; } else if ( FS_User::is_valid_id( $status_or_user_id ) ) { $connections ++; if ( ! isset( $opted_in_users[ $status_or_user_id ] ) ) { $opted_in_users[ $status_or_user_id ] = array(); } $opted_in_users[ $status_or_user_id ][] = $blog_id; if ( isset( $super_admins[ $status_or_user_id ] ) || self::is_super_admin( $status_or_user_id ) ) { // Cache super-admin data. $super_admins[ $status_or_user_id ] = true; // Remember opted-in super-admins for the plugin. $opted_in_super_admins[ $status_or_user_id ] = true; } } } $main_super_admin_user_id = null; $all_migrated = false; if ( $sites_count == $skips ) { // All sites were skipped -> network skip by copying the anonymous mode from any of the sites. $storage->is_anonymous_ms = $storage->is_anonymous; $all_migrated = true; } else if ( $sites_count == $ignores ) { // Don't do anything, still in activation mode. $all_migrated = true; } else if ( 0 < count( $opted_in_super_admins ) ) { // Find the super-admin with the majority of installs. $max_installs_by_super_admin = 0; foreach ( $opted_in_super_admins as $user_id => $true ) { $installs_count = count( $opted_in_users[ $user_id ] ); if ( $installs_count > $max_installs_by_super_admin ) { $max_installs_by_super_admin = $installs_count; $main_super_admin_user_id = $user_id; } } if ( $sites_count == $connections && 1 == count( $opted_in_super_admins ) ) { // Super-admin opted-in for all sites in the network. $storage->is_network_connected = true; $all_migrated = true; } // Store network user. $storage->network_user_id = $main_super_admin_user_id; $storage->network_install_blog_id = ( $sites_count == $connections ) ? // Since all sites are opted-in, associating with the main site. get_current_blog_id() : // Associating with the 1st found opted-in site. $opted_in_users[ $main_super_admin_user_id ][0]; /** * Make sure we migrate the plan ID of the network install, otherwise, if after the migration * the 1st page that will be loaded is the network level WP Admin and $storage->network_install_blog_id * is different than the main site of the network, the $this->_site will not be set since the plan_id * will be empty. */ $storage->migrate_to_network(); self::migrate_install_plan_to_plan_id( $storage, $storage->network_install_blog_id ); } else { // At least one opt-in. All the opt-in were created by a non-super-admin. if ( 0 == $ignores ) { // All sites were opted-in or skipped, all by non-super-admin. So delegate all. $storage->store( 'is_delegated_connection', true, true ); $all_migrated = true; } } if ( ! $all_migrated ) { /** * Delegate all sites that were: * 1) Opted-in by a user that is NOT the main-super-admin. * 2) Skipped and non of the sites was opted-in by a super-admin. If any site was opted-in by a super-admin, there will be a main-super-admin, and we consider the skip as if it was done by that user. */ foreach ( $blogs_status as $blog_id => $status_or_user_id ) { if ( $status_or_user_id == $main_super_admin_user_id ) { continue; } if ( FS_User::is_valid_id( $status_or_user_id ) || ( 'skipped' === $status_or_user_id && is_null( $main_super_admin_user_id ) ) ) { $storage->store( 'is_delegated_connection', true, $blog_id ); } } } if ( ( $connections + $skips > 0 ) ) { if ( $ignores > 0 ) { /** * If admin already opted-in or skipped in any of the network sites, and also * have sites which the connection decision was not yet taken, set this plugin * into network activation mode so the super-admin can choose what to do with * the rest of the sites. */ self::set_network_upgrade_mode( $storage ); } } } } /** * Set a module into network upgrade mode. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_Storage $storage * * @return bool */ private static function set_network_upgrade_mode( FS_Storage $storage ) { return $storage->is_network_activation = true; } /** * Will return true after upgrading to the SDK with the network level integration, * when the super-admin involvement is required regarding the rest of the sites. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return bool */ function is_network_upgrade_mode() { return $this->_storage->get( 'is_network_activation' ); } /** * Clear flag after the upgrade mode completion. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return bool True if network activation was on and now completed. */ private function network_upgrade_mode_completed() { if ( fs_is_network_admin() && $this->is_network_upgrade_mode() ) { $this->_storage->remove( 'is_network_activation' ); return true; } return false; } #endregion /** * This action is connected to the 'plugins_loaded' hook and helps to determine * if this is a new plugin installation or a plugin update. * * There are 3 different use-cases: * 1) New plugin installation right with Freemius: * 1.1 _activate_plugin_event_hook() will be executed first * 1.2 Since $this->_storage->is_plugin_new_install is not set, * and $this->_storage->plugin_last_version is not set, * $this->_storage->is_plugin_new_install will be set to TRUE. * 1.3 When _plugins_loaded() will be executed, $this->_storage->is_plugin_new_install will * be already set to TRUE. * * 2) Plugin update, didn't have Freemius before, and now have the SDK: * 2.1 _activate_plugin_event_hook() will not be executed, because * the activation hook do NOT fires on updates since WP 3.1. * 2.2 When _plugins_loaded() will be executed, $this->_storage->is_plugin_new_install will * be empty, therefore, it will be set to FALSE. * * 3) Plugin update, had Freemius in prev version as well: * 3.1 _version_updates_handler() will be executed 1st, since FS was installed * before, $this->_storage->plugin_last_version will NOT be empty, * therefore, $this->_storage->is_plugin_new_install will be set to FALSE. * 3.2 When _plugins_loaded() will be executed, $this->_storage->is_plugin_new_install is * already set, therefore, it will not be modified. * * Use-case #3 is backward compatible, #3.1 will be executed since 1.0.9. * * NOTE: * The only fallback of this mechanism is if an admin updates a plugin based on use-case #2, * and then, the next immediate PageView is the plugin's main settings page, it will not * show the opt-in right away. The reason it will happen is because Freemius execution * will be turned off till the plugin is fully loaded at least once * (till $this->_storage->was_plugin_loaded is TRUE). * * @author Vova Feldman (@svovaf) * @since 1.1.9 * */ function _plugins_loaded() { // Update flag that plugin was loaded with Freemius at least once. $this->_storage->was_plugin_loaded = true; /** * Bug fix - only set to false when it's a plugin, due to the * execution sequence of the theme hooks and our methods, if * this will be set for themes, Freemius will always assume * it's a theme update. * * @author Vova Feldman (@svovaf) * @since 1.2.2.2 */ if ( $this->is_plugin() && ! isset( $this->_storage->is_plugin_new_install ) ) { $this->_storage->is_plugin_new_install = ( ! is_plugin_active( $this->_plugin_basename ) && empty( $this->_storage->plugin_last_version ) ); } } /** * Opens the support forum subemenu item in a new browser page. * * @author Vova Feldman (@svovaf) * @since 2.1.4 */ static function _open_support_forum_in_new_page() { ?> _logger->entrance(); if ( is_admin() ) { add_action( 'admin_init', array( &$this, '_hook_action_links_and_register_account_hooks' ) ); if ( $this->is_plugin() ) { if ( self::is_plugin_install_page() && true !== fs_request_get_bool( 'fs_allow_updater_and_dialog' ) ) { /** * Unless the `fs_allow_updater_and_dialog` URL param exists and its value is `true`, make * Freemius-related updates unavailable on the "Add Plugins" admin page (/plugin-install.php) * so that they won't interfere with the .org plugins' functionalities on that page (e.g. * updating of a .org plugin). */ add_filter( 'site_transient_update_plugins', array( 'Freemius', '_remove_fs_updates_from_plugin_install_page' ), 10, 2 ); } else if ( self::is_plugins_page() || self::is_updates_page() ) { /** * On the "Plugins" and "Updates" admin pages, if there are premium or non–org-compliant plugins, modify their details dialog URLs (add a Freemius-specific param) so that the SDK can determine if the plugin information dialog should show information from Freemius. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ add_action( 'admin_footer', array( 'Freemius', '_prepend_fs_allow_updater_and_dialog_flag_url_param' ) ); } $plugin_dir = dirname( $this->_plugin_dir_path ) . '/'; /** * @since 1.2.2 * * Hook to both free and premium version activations to support * auto deactivation on the other version activation. */ register_activation_hook( $plugin_dir . $this->_free_plugin_basename, array( &$this, '_activate_plugin_event_hook' ) ); register_activation_hook( $plugin_dir . $this->premium_plugin_basename(), array( &$this, '_activate_plugin_event_hook' ) ); } else { add_action( 'after_switch_theme', array( &$this, '_activate_theme_event_hook' ), 10, 2 ); add_action( 'admin_footer', array( &$this, '_style_premium_theme' ) ); } /** * Part of the mechanism to identify new plugin install vs. plugin update. * * @author Vova Feldman (@svovaf) * @since 1.1.9 */ if ( empty( $this->_storage->was_plugin_loaded ) ) { /** * During the plugin activation (not theme), 'plugins_loaded' will be already executed * when the logic gets here since the activation logic first add the activate plugins, * then triggers 'plugins_loaded', and only then include the code of the plugin that * is activated. Which means that _plugins_loaded() will NOT be executed during the * plugin activation, and that IS intentional. * * @author Vova Feldman (@svovaf) */ if ( $this->is_plugin() && $this->is_activation_mode( false ) && 0 == did_action( 'plugins_loaded' ) ) { add_action( 'plugins_loaded', array( &$this, '_plugins_loaded' ) ); } else { // If was activated before, then it was already loaded before. $this->_plugins_loaded(); } } if ( ! self::is_ajax() ) { if ( ! $this->is_addon() ) { add_action( 'init', array( &$this, '_add_default_submenu_items' ), WP_FS__LOWEST_PRIORITY ); } } if ( $this->_storage->handle_gdpr_admin_notice ) { add_action( 'init', array( &$this, '_maybe_show_gdpr_admin_notice' ) ); } add_action( 'init', array( &$this, '_maybe_add_gdpr_optin_ajax_handler') ); add_action( 'init', array( &$this, '_maybe_add_pricing_ajax_handler' ) ); } if ( $this->is_plugin() ) { if ( version_compare( $GLOBALS['wp_version'], '5.1', '<' ) ) { add_action( 'wpmu_new_blog', array( $this, '_after_new_blog_callback' ), 10, 6 ); } else { add_action( 'wp_initialize_site', array( $this, '_after_wp_initialize_site_callback' ), 11, 2 ); } register_deactivation_hook( $this->_plugin_main_file_path, array( &$this, '_deactivate_plugin_hook' ) ); } if ( is_multisite() ) { add_action( 'deactivate_blog', array( &$this, '_after_site_deactivated_callback' ) ); add_action( 'archive_blog', array( &$this, '_after_site_deactivated_callback' ) ); add_action( 'make_spam_blog', array( &$this, '_after_site_deactivated_callback' ) ); if ( version_compare( $GLOBALS['wp_version'], '5.1', '<' ) ) { add_action( 'deleted_blog', array( $this, '_after_site_deleted_callback' ), 10, 2 ); } else { add_action( 'wp_delete_site', array( $this, '_after_wpsite_deleted_callback' ) ); } add_action( 'activate_blog', array( &$this, '_after_site_reactivated_callback' ) ); add_action( 'unarchive_blog', array( &$this, '_after_site_reactivated_callback' ) ); add_action( 'make_ham_blog', array( &$this, '_after_site_reactivated_callback' ) ); } if ( $this->is_theme() && self::is_customizer() && $this->apply_filters( 'show_customizer_upsell', true ) ) { // Register customizer upsell. add_action( 'customize_register', array( &$this, '_customizer_register' ) ); } add_action( 'admin_init', array( &$this, '_redirect_on_clicked_menu_link' ), WP_FS__LOWEST_PRIORITY ); if ( $this->is_theme() && ! $this->is_migration() ) { add_action( 'admin_init', array( &$this, '_add_tracking_links' ) ); } add_action( 'admin_init', array( &$this, '_add_license_activation' ) ); add_action( 'admin_init', array( &$this, '_add_premium_version_upgrade_selection' ) ); add_action( 'admin_init', array( &$this, '_add_beta_mode_update_handler' ) ); add_action( 'admin_init', array( &$this, '_add_user_change_option' ) ); add_action( 'admin_init', array( &$this, '_add_email_address_update_option' ) ); $this->add_ajax_action( 'update_billing', array( &$this, '_update_billing_ajax_action' ) ); $this->add_ajax_action( 'start_trial', array( &$this, '_start_trial_ajax_action' ) ); $this->add_ajax_action( 'set_data_debug_mode', array( &$this, '_set_data_debug_mode' ) ); $this->add_ajax_action( 'toggle_whitelabel_mode', array( &$this, '_toggle_whitelabel_mode_ajax_handler' ) ); if ( $this->_is_network_active && fs_is_network_admin() ) { $this->add_ajax_action( 'network_activate', array( &$this, '_network_activate_ajax_action' ) ); } $this->add_ajax_action( 'install_premium_version', array( &$this, '_install_premium_version_ajax_action' ) ); $this->add_ajax_action( 'submit_affiliate_application', array( &$this, '_submit_affiliate_application' ) ); $this->add_action( 'after_plans_sync', array( &$this, '_check_for_trial_plans' ) ); $this->add_action( 'sdk_version_update', array( &$this, '_sdk_version_update' ), WP_FS__DEFAULT_PRIORITY, 2 ); $this->add_action( 'plugin_version_update', array( &$this, '_after_version_update' ), WP_FS__DEFAULT_PRIORITY, 2 ); $this->add_filter( 'after_code_type_change', array( &$this, '_after_code_type_change' ) ); add_action( 'admin_init', array( &$this, '_add_trial_notice' ) ); add_action( 'admin_init', array( &$this, '_add_affiliate_program_notice' ) ); add_action( 'admin_enqueue_scripts', array( &$this, '_enqueue_common_css' ) ); /** * Handle request to reset anonymous mode for `get_reconnect_url()` or reset the pending activation mode. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 */ if ( ( fs_request_is_action( 'reset_anonymous_mode' ) || fs_request_is_action( 'reset_pending_activation_mode' ) ) && $this->get_unique_affix() === fs_request_get( 'fs_unique_affix' ) ) { add_action( 'admin_init', array( &$this, 'connect_again' ) ); } } /** * Register the required hooks right after the settings parse is completed. * * @author Vova Feldman (@svovaf) * @since 2.3.1 */ private function register_after_settings_parse_hooks() { if ( is_admin() && $this->is_theme() && $this->is_premium() && ! $this->has_active_valid_license() ) { $this->add_ajax_action( 'delete_theme_update_data', array( &$this, '_delete_theme_update_data_action' ) ); } if ( $this->show_settings_with_tabs() ) { /** * Include the required hooks to capture the theme settings' page tabs * and cache them. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 */ if ( ! $this->_cache->has_valid( 'tabs' ) ) { add_action( 'admin_footer', array( &$this, '_tabs_capture' ) ); // Add license activation AJAX callback. $this->add_ajax_action( 'store_tabs', array( &$this, '_store_tabs_ajax_action' ) ); add_action( 'admin_enqueue_scripts', array( &$this, '_store_tabs_styles' ), 9999999 ); } add_action( 'admin_footer', array( &$this, '_add_freemius_tabs' ), /** * The tabs JS code must be executed after the tabs capture logic (_tabs_capture()). * That's why the priority is 11 while the tabs capture logic is added * with priority 10. * * @author Vova Feldman (@svovaf) */ 11 ); } if ( ! self::is_ajax() ) { if ( ! $this->is_addon() || $this->is_only_premium() ) { add_action( ( $this->_is_network_active && fs_is_network_admin() ? 'network_' : '' ) . 'admin_menu', array( &$this, '_prepare_admin_menu' ), WP_FS__LOWEST_PRIORITY ); } } } /** * Makes Freemius-related updates unavailable on the "Add Plugins" admin page (/plugin-install.php) so that * they won't interfere with the .org plugins' functionalities on that page (e.g. updating of a .org plugin). * * @author Leo Fajardo (@leorw) * @since 2.2.3 * * @param object $updates * @param string|null $transient * * @return object */ static function _remove_fs_updates_from_plugin_install_page( $updates, $transient = null ) { if ( is_object( $updates ) && isset( $updates->response ) ) { foreach ( $updates->response as $file => $plugin ) { if ( isset( $plugin->package ) && false !== strpos( $plugin->package, 'api.freemius' ) ) { unset( $updates->response[ $file ] ); } } } return $updates; } /** * Prepends the `fs_allow_updater_and_dialog` param to the plugin information URLs to tell the SDK to handle * the information that is shown on the plugin details dialog that is shown when the relevant link is clicked. * * @author Leo Fajardo (@leorw) * @since 2.2.3 * * @return string */ static function _prepend_fs_allow_updater_and_dialog_flag_url_param() { $slug_basename_map = array(); foreach ( self::$_instances as $instance ) { if ( ! $instance->is_plugin() ) { continue; } $slug_basename_map[ $instance->get_slug() ] = $instance->premium_plugin_basename(); } ?> is_beta() ) { $has_any_beta_version = true; break; } } if ( $has_any_beta_version ) { fs_enqueue_local_style( 'fs_plugins', '/admin/plugins.css' ); } } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 */ static function _maybe_add_beta_label_to_plugins_and_handle_confirmation() { $beta_data = array(); foreach ( self::$_instances as $instance ) { if ( ! $instance->is_premium() ) { continue; } /** * If there's an available beta version update, a confirmation message will be shown when the * "Update now" link on the "Plugins" or "Themes" page is clicked. */ $has_beta_update = $instance->has_beta_update(); $is_beta = ( // The "Beta" label is added separately for themes. $instance->is_plugin() && $instance->is_beta() ); if ( ! $is_beta && ! $has_beta_update ) { continue; } $beta_data[ $instance->get_plugin_basename() ] = array( 'is_installed_version_beta' => $is_beta ); if ( ! $has_beta_update ) { continue; } $beta_data[ $instance->get_plugin_basename() ]['beta_version_update_confirmation_message'] = sprintf( '%s %s', sprintf( fs_esc_attr_inline( 'An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.', 'beta-version-update-caution', $instance->get_slug() ), $instance->get_plugin_title() ), fs_esc_attr_inline( 'Would you like to proceed with the update?', 'update-confirmation', $instance->get_slug() ) ); } if ( empty( $beta_data ) ) { return; } ?> _free_plugin_basename ] ); unset( $uninstallable_plugins[ $this->premium_plugin_basename() ] ); update_option( 'uninstall_plugins', $uninstallable_plugins ); } /** * @since 1.2.0 Invalidate module's main file cache, otherwise, FS_Plugin_Updater will not fetch updates. * * @param bool $store_prev_path */ private function clear_module_main_file_cache( $store_prev_path = true ) { if ( ! isset( $this->_storage->plugin_main_file ) || empty( $this->_storage->plugin_main_file->path ) ) { return; } if ( ! $store_prev_path ) { /** * Storing the previous path is not needed when clearing the cache after an SDK version update since * the main purpose of the cache clearing in that event is to correct a wrong plugin main file path * which causes data mix-up between plugins (e.g. titles and versions of an add-on and its parent plugin). * * @author Leo Fajardo (@leorw) * @since 2.2.1 */ unset( $this->_storage->plugin_main_file->path ); } else { $plugin_main_file = clone $this->_storage->plugin_main_file; // Store cached path (2nd layer cache). $plugin_main_file->prev_path = $plugin_main_file->path; // Clear cached path. unset( $plugin_main_file->path ); $this->_storage->plugin_main_file = $plugin_main_file; } /** * Clear global cached path. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ $id_slug_type_path_map = self::$_accounts->get_option( 'id_slug_type_path_map' ); unset( $id_slug_type_path_map[ $this->_module_id ]['path'] ); self::$_accounts->set_option( 'id_slug_type_path_map', $id_slug_type_path_map, true ); } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 */ function _hook_action_links_and_register_account_hooks() { if ( $this->is_migration() ) { return; } if ( ( self::is_plugins_page() && $this->is_plugin() ) || ( self::is_themes_page() && $this->is_theme() ) || fs_request_is_action_secure( $this->get_unique_affix() . '_reconnect' ) ) { $this->_add_tracking_links(); } if ( self::is_plugins_page() && $this->is_plugin() ) { $this->hook_plugin_action_links(); } $this->_register_account_hooks(); } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 */ private function _register_account_hooks() { if ( ! is_admin() ) { return; } /** * Always show the deactivation feedback form since we added * automatic free version deactivation upon premium code activation. * * @since 1.2.1.6 */ $this->add_ajax_action( 'submit_uninstall_reason', array( &$this, '_submit_uninstall_reason_action' ) ); $this->add_ajax_action( 'cancel_subscription_or_trial', array( &$this, 'cancel_subscription_or_trial_ajax_action' ) ); if ( ! $this->is_addon() || $this->is_parent_plugin_installed() ) { if ( ( $this->is_plugin() && self::is_plugins_page() ) || ( $this->is_theme() && self::is_themes_page() ) ) { add_action( 'admin_footer', array( &$this, '_add_deactivation_feedback_dialog_box' ) ); } } } /** * Leverage backtrace to find caller plugin file path. * * @param bool $is_init Is initiation sequence. * @param string $main_file Since 2.5.0 expects the module's main file path to potentially purge the cached path. * * @return string * @since 1.0.6 * * @author Vova Feldman (@svovaf) */ private function _find_caller_plugin_file( $is_init = false, $main_file = '' ) { // Try to load the cached value of the file path. if ( isset( $this->_storage->plugin_main_file ) ) { $plugin_main_file = $this->_storage->plugin_main_file; if ( ! empty( $plugin_main_file->path ) ) { $absolute_path = $this->get_absolute_path( $plugin_main_file->path ); if ( file_exists( $absolute_path ) ) { if ( $is_init && $absolute_path !== $this->get_absolute_path( $main_file ) ) { // Update cached path if not matching the actual path. $plugin_main_file->path = $main_file; $this->_storage->plugin_main_file = $plugin_main_file; } return $absolute_path; } } } /** * @since 1.2.1 * * `clear_module_main_file_cache()` is clearing the plugin's cached path on * deactivation. Therefore, if any plugin/theme was initiating `Freemius` * with that plugin's slug, it was overriding the empty plugin path with a wrong path. * * So, we've added a special mechanism with a 2nd layer of cache that uses `prev_path` * when the class instantiator isn't the module. */ if ( ! $is_init ) { // Fetch prev path cache. if ( isset( $this->_storage->plugin_main_file ) && ! empty( $this->_storage->plugin_main_file->prev_path ) ) { $absolute_path = $this->get_absolute_path( $this->_storage->plugin_main_file->prev_path ); if ( file_exists( $absolute_path ) ) { return $absolute_path; } } wp_die( $this->get_text_inline( 'Freemius SDK couldn\'t find the plugin\'s main file. Please contact sdk@freemius.com with the current error.', 'failed-finding-main-path' ) . " Module: {$this->_slug}; SDK: " . WP_FS__SDK_VERSION . ";", $this->get_text_inline( 'Error', 'error' ), array( 'back_link' => true ) ); } /** * @since 1.2.1 * * Only the original instantiator that calls dynamic_init can modify the module's path. */ // Find caller module. $this->_storage->plugin_main_file = (object) array( 'path' => $main_file, ); return $this->get_absolute_path( $main_file ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.3 * * @param string $path * * @return string */ private function get_relative_path( $path ) { $module_root_dir = $this->get_module_root_dir_path(); if ( 0 === strpos( $path, $module_root_dir ) ) { $path = substr( $path, strlen( $module_root_dir ) ); } return $path; } /** * @author Leo Fajardo (@leorw) * @since 1.2.3 * * @param string $path * @param string|bool $module_type * * @return string */ private function get_absolute_path( $path, $module_type = false ) { $module_root_dir = $this->get_module_root_dir_path( $module_type ); if ( 0 !== strpos( $path, $module_root_dir ) ) { $path = fs_normalize_path( $module_root_dir . $path ); } return $path; } /** * @author Leo Fajardo (@leorw) * @since 1.2.3 * * @param string|bool $module_type * * @return string */ private function get_module_root_dir_path( $module_type = false ) { $is_plugin = empty( $module_type ) ? $this->is_plugin() : ( WP_FS__MODULE_TYPE_PLUGIN === $module_type ); return fs_normalize_path( trailingslashit( $is_plugin ? WP_PLUGIN_DIR : get_theme_root( get_stylesheet() ) ) ); } /** * @author Leo Fajardo (@leorw) * * @param number $module_id * @param string $slug * * @return string Since 2.5.0 return the module's main file path. * * @since 1.2.2 */ private function store_id_slug_type_path_map( $module_id, $slug ) { $id_slug_type_path_map = self::$_accounts->get_option( 'id_slug_type_path_map', array() ); $store_option = false; if ( ! isset( $id_slug_type_path_map[ $module_id ] ) ) { $id_slug_type_path_map[ $module_id ] = array( 'slug' => $slug ); $store_option = true; } else if ( isset( $id_slug_type_path_map[ $module_id ]['slug'] ) && $slug !== $id_slug_type_path_map[ $module_id ]['slug'] ) { $id_slug_type_path_map[ $module_id ]['slug'] = $slug; $store_option = true; } $find_caller = empty( $id_slug_type_path_map[ $module_id ]['path'] ); if ( ! $find_caller ) { /** * This verification is for cases when suddenly the same module * is installed but with a different folder name. * * @author Vova Feldman (@svovaf) * @since 1.2.3 */ $find_caller = ! file_exists( $this->get_absolute_path( $id_slug_type_path_map[ $module_id ]['path'], $id_slug_type_path_map[ $module_id ]['type'] ) ); } foreach ( $id_slug_type_path_map as $id => $data ) { if ( empty( $id ) ) { // Remove maps with empty module ID. unset( $id_slug_type_path_map[ $id ] ); $store_option = true; continue; } /** * If the module's main file path is identical to the main file path of another module then it means that the cached path of the current module or the other one with the same path is wrong, and therefore, we need to recalculate those paths. * * @author Vova Feldman (@svovaf) * @since 2.5.0 */ if ( ! $find_caller ) { if ( $id == $module_id ) { continue; } if ( isset( $data['path'] ) && $data['path'] === $id_slug_type_path_map[ $module_id ]['path'] ) { $find_caller = true; } } } if ( $find_caller ) { $caller_main_file_and_type = $this->get_caller_main_file_and_type( $module_id ); $id_slug_type_path_map[ $module_id ]['type'] = $caller_main_file_and_type->module_type; $id_slug_type_path_map[ $module_id ]['path'] = $caller_main_file_and_type->path; $store_option = true; } if ( $store_option ) { self::$_accounts->set_option( 'id_slug_type_path_map', $id_slug_type_path_map, true ); } return $id_slug_type_path_map[ $module_id ]['path']; } /** * Identifies the caller type: plugin or theme. * * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @author Vova Feldman (@svovaf) * @since 1.2.2.3 Find the earliest module in the call stack that calls to the SDK. This fix is for cases when * add-ons are relying on loading the SDK from the parent module, and also allows themes including the * SDK an internal file instead of directly from functions.php. * @since 1.2.1.7 Knows how to handle cases when an add-on includes the parent module logic. * * @param number $module_id @since 2.5.0 */ private function get_caller_main_file_and_type( $module_id ) { self::require_plugin_essentials(); $all_plugins = fs_get_plugins( true ); $all_plugins_paths = array(); // Get active plugin's main files real full names (might be symlinks). foreach ( $all_plugins as $relative_path => $data ) { if ( false === strpos( fs_normalize_path( $relative_path ), '/' ) ) { /** * Ignore plugins that don't have a folder (e.g. Hello Dolly) since they * can't really include the SDK. * * @author Vova Feldman * @since 1.2.1.7 */ continue; } $all_plugins_paths[] = fs_normalize_path( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) ); } $caller_file_candidate = false; $caller_map = array(); $module_type = WP_FS__MODULE_TYPE_PLUGIN; $themes_dir = fs_normalize_path( get_theme_root( get_stylesheet() ) ); $plugin_dir_to_skip = false; for ( $i = 1, $bt = debug_backtrace(), $len = count( $bt ); $i < $len; $i ++ ) { if ( empty( $bt[ $i ]['file'] ) ) { continue; } if ( $i > 1 && ! empty( $bt[ $i - 1 ]['file'] ) && $bt[ $i ]['file'] === $bt[ $i - 1 ]['file'] ) { // If file same as the prev file in the stack, skip it. continue; } if ( ! empty( $bt[ $i ]['function'] ) && in_array( $bt[ $i ]['function'], array( 'do_action', 'apply_filter', // The string split is stupid, but otherwise, theme check // throws info notices. 'requir' . 'e_once', 'requir' . 'e', 'includ' . 'e_once', 'includ' . 'e', 'install_and_activate_plugin', 'try_activate_plugin', 'activate_plugin' ) ) ) { if ( 'activate_plugin' === $bt[ $i ]['function'] ) { /** * Store the directory of the activator plugin so that any other file that starts with it * cannot be mistakenly chosen as a candidate caller file. * * @author Leo Fajardo * * @since 2.3.0 */ $caller_file_path = fs_normalize_path( $bt[ $i ]['file'] ); foreach ( $all_plugins_paths as $plugin_path ) { $plugin_dir = fs_normalize_path( dirname( $plugin_path ) . '/' ); if ( false !== strpos( $caller_file_path, $plugin_dir ) ) { $plugin_dir_to_skip = $plugin_dir; break; } } } // Ignore call stack hooks and files inclusion. continue; } $caller_file_path = fs_normalize_path( $bt[ $i ]['file'] ); if ( ! empty( $plugin_dir_to_skip ) ) { /** * Skip if it's an activator plugin file to avoid mistakenly choosing it as a candidate caller file. * * @author Leo Fajardo * * @since 2.3.0 */ if ( 0 === strpos( $caller_file_path, $plugin_dir_to_skip ) ) { continue; } } if ( 'functions.php' === basename( $caller_file_path ) ) { /** * 1. Assumes that theme's starting execution file is functions.php. * 2. This complex logic fixes symlink issues (e.g. with Vargant). * * @author Vova Feldman (@svovaf) * @since 1.2.2.5 */ if ( $caller_file_path == fs_normalize_path( realpath( trailingslashit( $themes_dir ) . basename( dirname( $caller_file_path ) ) . '/' . basename( $caller_file_path ) ) ) ) { $module_type = WP_FS__MODULE_TYPE_THEME; /** * Relative path of the theme, e.g.: * `my-theme/functions.php` * * @author Leo Fajardo (@leorw) */ $caller_file_candidate = basename( dirname( $caller_file_path ) ) . '/' . basename( $caller_file_path ); continue; } } $caller_file_hash = md5( $caller_file_path ); if ( ! isset( $caller_map[ $caller_file_hash ] ) ) { foreach ( $all_plugins_paths as $plugin_path ) { if ( empty( $plugin_path ) ) { continue; } if ( false !== strpos( $caller_file_path, fs_normalize_path( dirname( $plugin_path ) . '/' ) ) ) { $caller_map[ $caller_file_hash ] = fs_normalize_path( $plugin_path ); break; } } } if ( isset( $caller_map[ $caller_file_hash ] ) ) { $module_type = WP_FS__MODULE_TYPE_PLUGIN; $caller_file_candidate = plugin_basename( $caller_map[ $caller_file_hash ] ); } } $caller_main_file_and_type = (object) array( 'module_type' => $module_type, 'path' => $caller_file_candidate ); return apply_filters( "fs_{$module_id}_caller_main_file_and_type", $caller_main_file_and_type ); } #---------------------------------------------------------------------------------- #region Deactivation Feedback Form #---------------------------------------------------------------------------------- /** * Displays a confirmation and feedback dialog box when the user clicks on the "Deactivate" link on the plugins * page. * * @author Vova Feldman (@svovaf) * @author Leo Fajardo (@leorw) * * @since 1.1.2 */ function _add_deactivation_feedback_dialog_box() { if ( $this->is_clone() || ( is_object( $this->_site ) && ! $this->is_registered() ) ) { return; } $subscription_cancellation_dialog_box_template_params = $this->apply_filters( 'show_deactivation_subscription_cancellation', true ) ? $this->_get_subscription_cancellation_dialog_box_template_params() : array(); /** * @since 2.3.0 Developers can optionally hide the deactivation feedback form using the 'show_deactivation_feedback_form' filter. */ $show_deactivation_feedback_form = ! self::is_deactivation_snoozed(); if ( $this->has_filter( 'show_deactivation_feedback_form' ) ) { $show_deactivation_feedback_form = $this->apply_filters( 'show_deactivation_feedback_form', true ); } else if ( $this->is_addon() ) { /** * If the add-on's 'show_deactivation_feedback_form' is not set, try to inherit the value from the parent. */ $show_deactivation_feedback_form = $this->get_parent_instance()->apply_filters( 'show_deactivation_feedback_form', true ); } $uninstall_confirmation_message = $this->apply_filters( 'uninstall_confirmation_message', '' ); if ( empty( $subscription_cancellation_dialog_box_template_params ) && ! $show_deactivation_feedback_form && empty( $uninstall_confirmation_message ) ) { return; } $vars = array( 'id' => $this->_module_id ); if ( $show_deactivation_feedback_form ) { /* Check the type of user: * 1. Long-term (long-term) * 2. Non-registered and non-anonymous short-term (non-registered-and-non-anonymous-short-term). * 3. Short-term (short-term) */ $is_long_term_user = true; // Check if the site is at least 2 days old. $time_installed = $this->_storage->install_timestamp; // Difference in seconds. $date_diff = time() - $time_installed; // Convert seconds to days. $date_diff_days = floor( $date_diff / ( 60 * 60 * 24 ) ); if ( $date_diff_days < 2 ) { $is_long_term_user = false; } $is_long_term_user = $this->apply_filters( 'is_long_term_user', $is_long_term_user ); if ( $is_long_term_user ) { $user_type = 'long-term'; } else { if ( ! $this->is_registered() && ! $this->is_anonymous() ) { $user_type = 'non-registered-and-non-anonymous-short-term'; } else { $user_type = 'short-term'; } } $uninstall_reasons = $this->_get_uninstall_reasons( $user_type ); $vars['reasons'] = $uninstall_reasons; } $vars['subscription_cancellation_dialog_box_template_params'] = &$subscription_cancellation_dialog_box_template_params; $vars['show_deactivation_feedback_form'] = $show_deactivation_feedback_form; $vars['uninstall_confirmation_message'] = $uninstall_confirmation_message; /** * Load the HTML template for the deactivation feedback dialog box. * * @todo Deactivation form core functions should be loaded only once! Otherwise, when there are multiple Freemius powered plugins the same code is loaded multiple times. The only thing that should be loaded differently is the various deactivation reasons object based on the state of the plugin. */ fs_require_template( 'forms/deactivation/form.php', $vars ); } /** * @author Leo Fajardo (@leorw) * @since 1.1.2 * * @param string $user_type * * @return array The uninstall reasons for the specified user type. */ function _get_uninstall_reasons( $user_type = 'long-term' ) { $module_type = $this->_module_type; $internal_message_template_var = array( 'id' => $this->_module_id ); $plan = $this->get_plan(); if ( $this->is_registered() && is_object( $plan ) && $plan->has_technical_support() ) { $contact_support_template = fs_get_template( 'forms/deactivation/contact.php', $internal_message_template_var ); } else { $contact_support_template = ''; } $reason_found_better_plugin = array( 'id' => self::REASON_FOUND_A_BETTER_PLUGIN, 'text' => sprintf( $this->get_text_inline( 'I found a better %s', 'reason-found-a-better-plugin' ), $module_type ), 'input_type' => 'textfield', 'input_placeholder' => sprintf( $this->get_text_inline( "What's the %s's name?", 'placeholder-plugin-name' ), $module_type ), ); $reason_temporary_deactivation = array( 'id' => self::REASON_TEMPORARY_DEACTIVATION, 'text' => sprintf( $this->get_text_inline( "It's a temporary %s - I'm troubleshooting an issue", 'reason-temporary-x' ), strtolower( $this->is_plugin() ? $this->get_text_inline( 'Deactivation', 'deactivation' ) : $this->get_text_inline( 'Theme Switch', 'theme-switch' ) ) ), 'input_type' => '', 'input_placeholder' => '' ); $reason_other = array( 'id' => self::REASON_OTHER, 'text' => $this->get_text_inline( 'Other', 'reason-other' ), 'input_type' => 'textfield', 'input_placeholder' => '' ); $long_term_user_reasons = array( array( 'id' => self::REASON_NO_LONGER_NEEDED, 'text' => sprintf( $this->get_text_inline( 'I no longer need the %s', 'reason-no-longer-needed' ), $module_type ), 'input_type' => '', 'input_placeholder' => '' ), $reason_found_better_plugin, array( 'id' => self::REASON_NEEDED_FOR_A_SHORT_PERIOD, 'text' => sprintf( $this->get_text_inline( 'I only needed the %s for a short period', 'reason-needed-for-a-short-period' ), $module_type ), 'input_type' => '', 'input_placeholder' => '' ), array( 'id' => self::REASON_BROKE_MY_SITE, 'text' => sprintf( $this->get_text_inline( 'The %s broke my site', 'reason-broke-my-site' ), $module_type ), 'input_type' => '', 'input_placeholder' => '', 'internal_message' => $contact_support_template ), array( 'id' => self::REASON_SUDDENLY_STOPPED_WORKING, 'text' => sprintf( $this->get_text_inline( 'The %s suddenly stopped working', 'reason-suddenly-stopped-working' ), $module_type ), 'input_type' => '', 'input_placeholder' => '', 'internal_message' => $contact_support_template ) ); if ( $this->is_paying() ) { $long_term_user_reasons[] = array( 'id' => self::REASON_CANT_PAY_ANYMORE, 'text' => $this->get_text_inline( "I can't pay for it anymore", 'reason-cant-pay-anymore' ), 'input_type' => 'textfield', 'input_placeholder' => $this->get_text_inline( 'What price would you feel comfortable paying?', 'placeholder-comfortable-price' ) ); } $reason_dont_share_info = array( 'id' => self::REASON_DONT_LIKE_TO_SHARE_MY_INFORMATION, 'text' => $this->get_text_inline( "I don't like to share my information with you", 'reason-dont-like-to-share-my-information' ), 'input_type' => '', 'input_placeholder' => '' ); /** * If the current user has selected the "don't share data" reason in the deactivation feedback modal, inform the * user by showing additional message that he doesn't have to share data and can just choose to skip the opt-in * (the Skip button is included in the message to show). This message will only be shown if anonymous mode is * enabled and the user's account is currently not in pending activation state (similar to the way the Skip * button in the opt-in form is shown/hidden). */ if ( $this->is_enable_anonymous() && ! $this->is_pending_activation() ) { $reason_dont_share_info['internal_message'] = fs_get_template( 'forms/deactivation/retry-skip.php', $internal_message_template_var ); } $uninstall_reasons = array( 'long-term' => $long_term_user_reasons, 'non-registered-and-non-anonymous-short-term' => array( array( 'id' => self::REASON_DIDNT_WORK, 'text' => sprintf( $this->get_text_inline( "The %s didn't work", 'reason-didnt-work' ), $module_type ), 'input_type' => '', 'input_placeholder' => '' ), $reason_dont_share_info, $reason_found_better_plugin ), 'short-term' => array( array( 'id' => self::REASON_COULDNT_MAKE_IT_WORK, 'text' => $this->get_text_inline( "I couldn't understand how to make it work", 'reason-couldnt-make-it-work' ), 'input_type' => '', 'input_placeholder' => '', 'internal_message' => $contact_support_template ), $reason_found_better_plugin, array( 'id' => self::REASON_GREAT_BUT_NEED_SPECIFIC_FEATURE, 'text' => sprintf( $this->get_text_inline( "The %s is great, but I need specific feature that you don't support", 'reason-great-but-need-specific-feature' ), $module_type ), 'input_type' => 'textarea', 'input_placeholder' => $this->get_text_inline( 'What feature?', 'placeholder-feature' ) ), array( 'id' => self::REASON_NOT_WORKING, 'text' => sprintf( $this->get_text_inline( 'The %s is not working', 'reason-not-working' ), $module_type ), 'input_type' => 'textarea', 'input_placeholder' => $this->get_text_inline( "Kindly share what didn't work so we can fix it for future users...", 'placeholder-share-what-didnt-work' ) ), array( 'id' => self::REASON_NOT_WHAT_I_WAS_LOOKING_FOR, 'text' => $this->get_text_inline( "It's not what I was looking for", 'reason-not-what-i-was-looking-for' ), 'input_type' => 'textarea', 'input_placeholder' => $this->get_text_inline( "What you've been looking for?", 'placeholder-what-youve-been-looking-for' ) ), array( 'id' => self::REASON_DIDNT_WORK_AS_EXPECTED, 'text' => sprintf( $this->get_text_inline( "The %s didn't work as expected", 'reason-didnt-work-as-expected' ), $module_type ), 'input_type' => 'textarea', 'input_placeholder' => $this->get_text_inline( 'What did you expect?', 'placeholder-what-did-you-expect' ) ) ) ); // Randomize the reasons for the current user type. shuffle( $uninstall_reasons[ $user_type ] ); // Keep the following reasons as the last items in the list. $uninstall_reasons[ $user_type ][] = $reason_temporary_deactivation; $uninstall_reasons[ $user_type ][] = $reason_other; $uninstall_reasons = $this->apply_filters( 'uninstall_reasons', $uninstall_reasons ); return $uninstall_reasons[ $user_type ]; } /** * Called after the user has submitted his reason for deactivating the plugin. * * @author Leo Fajardo (@leorw) * @since 1.1.2 */ function _submit_uninstall_reason_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'submit_uninstall_reason' ); $reason_id = fs_request_get( 'reason_id' ); // Check if the given reason ID is an unsigned integer. if ( ! ctype_digit( $reason_id ) ) { exit; } $reason_info = trim( fs_request_get( 'reason_info', '' ) ); if ( ! empty( $reason_info ) ) { $reason_info = substr( $reason_info, 0, 128 ); } $reason = (object) array( 'id' => $reason_id, 'info' => $reason_info, 'is_anonymous' => fs_request_get_bool( 'is_anonymous' ) ); $this->_storage->store( 'uninstall_reason', $reason ); if ( self::REASON_TEMPORARY_DEACTIVATION == $reason->id ) { $snooze_period = fs_request_get( 'snooze_period' ); if ( is_numeric( $snooze_period ) && 0 < $snooze_period ) { self::snooze_deactivation_form( (int) $snooze_period ); } } /** * If the module type is "theme", trigger the uninstall event here (on theme deactivation) since themes do * not support uninstall hook. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ if ( $this->is_theme() ) { if ( $this->is_premium() && ! $this->has_active_valid_license() ) { FS_Plugin_Updater::instance( $this )->delete_update_data(); } $this->_uninstall_plugin_event( false ); $this->remove_sdk_reference(); } // Print '1' for successful operation. echo 1; exit; } #-------------------------------------------------------------------------------- #region Deactivation Feedback Snoozing #-------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 2.4.3 * * @param int $period * * @return bool True if the value was set, false otherwise. */ private static function snooze_deactivation_form( $period ) { return ( 0 < $period && self::reset_deactivation_snoozing( $period ) ); } /** * Check if deactivation feedback form is snoozed. * * @author Vova Feldman (@svovaf) * @since 2.4.3 * * @return bool */ static function is_deactivation_snoozed() { $is_snoozed = ( ! is_multisite() || fs_is_network_admin() ) ? get_transient( 'fs_snooze_period' ) : get_site_transient( 'fs_snooze_period' ); return ( 'true' === $is_snoozed ); } /** * Reset deactivation snoozing. When `$period` is `0` will stop deactivation snoozing by deleting the transients. Otherwise, will set the transients for the selected period. * * @param int $period Period in seconds. * * @author Vova Feldman (@svovaf) * @since 2.4.3 */ private static function reset_deactivation_snoozing( $period = 0 ) { $value = ( 0 === $period ) ? null : 'true'; if ( ! is_multisite() || fs_is_network_admin() ) { return set_transient( 'fs_snooze_period', $value, $period ); } else { return set_site_transient( 'fs_snooze_period', $value, $period ); } } /** * The deactivation snooze expiration UNIX timestamp (in sec). * * @author Vova Feldman (@svovaf) * @since 2.4.3 * * @return int */ static function deactivation_snooze_expires_at() { return ( ! is_multisite() || fs_is_network_admin() ) ? (int) get_option( '_transient_timeout_fs_snooze_period' ) : (int) get_site_option( '_site_transient_timeout_fs_snooze_period' ); } #endregion /** * @author Leo Fajardo (@leorw) * @since 2.1.4 */ function cancel_subscription_or_trial_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'cancel_subscription_or_trial' ); $result = $this->cancel_subscription_or_trial( fs_request_get( 'plugin_id', $this->get_id() ), false ); if ( $this->is_api_error( $result ) ) { $this->shoot_ajax_failure( $result->error->message ); } $this->shoot_ajax_success(); } /** * @author Leo Fajardo (@leorw) * @since 2.1.4 * * @param number $plugin_id * * @return object */ private function cancel_subscription_or_trial( $plugin_id ) { $fs = null; if ( $plugin_id == $this->get_id() ) { $fs = $this; } else if ( $this->is_addon_activated( $plugin_id ) ) { $fs = self::get_instance_by_id( $plugin_id ); } $result = null; if ( ! is_null( $fs ) ) { $result = $fs->is_paid_trial() ? $fs->_cancel_trial() : $fs->_downgrade_site(); } return $result; } /** * @author Leo Fajardo (@leorw) * @since 2.0.2 */ function _delete_theme_update_data_action() { FS_Plugin_Updater::instance( $this )->delete_update_data(); } #endregion #---------------------------------------------------------------------------------- #region Instance #---------------------------------------------------------------------------------- /** * Main singleton instance. * * @author Vova Feldman (@svovaf) * @since 1.0.0 * * @param number $module_id * @param string|bool $slug * @param bool $is_init Is initiation sequence. * * @return Freemius|false */ static function instance( $module_id, $slug = false, $is_init = false ) { if ( empty( $module_id ) ) { return false; } /** * Load the essential static data prior to initiating FS_Plugin_Manager since there's an essential MS network migration logic that needs to be executed prior to the initiation. */ self::_load_required_static(); if ( ! is_numeric( $module_id ) ) { if ( ! $is_init && true === $slug ) { $is_init = true; } $slug = $module_id; $module = FS_Plugin_Manager::instance( $slug )->get(); if ( is_object( $module ) ) { $module_id = $module->id; } } $key = 'm_' . $module_id; if ( ! isset( self::$_instances[ $key ] ) ) { self::$_instances[ $key ] = new Freemius( $module_id, $slug, $is_init ); } return self::$_instances[ $key ]; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param number $addon_id * * @return bool */ private static function has_instance( $addon_id ) { return isset( self::$_instances[ 'm_' . $addon_id ] ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @param string|number $id_or_slug * @param string $module_type * * @return number|false */ private static function get_module_id( $id_or_slug, $module_type = WP_FS__MODULE_TYPE_PLUGIN ) { if ( is_numeric( $id_or_slug ) ) { return $id_or_slug; } foreach ( self::$_instances as $instance ) { // Also check the module type since there can be a plugin and a theme with the same slug. if ( ( $module_type === $instance->get_module_type() ) && ( $id_or_slug === $instance->get_slug() ) ) { return $instance->get_id(); } } return false; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param number $id * * @return false|Freemius */ static function get_instance_by_id( $id ) { return isset ( self::$_instances[ 'm_' . $id ] ) ? self::$_instances[ 'm_' . $id ] : false; } /** * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param string $plugin_file * @param string $module_type * * @return false|Freemius */ static function get_instance_by_file( $plugin_file, $module_type = WP_FS__MODULE_TYPE_PLUGIN ) { $slug = self::find_slug_by_basename( $plugin_file ); return ( false !== $slug ) ? self::instance( self::get_module_id( $slug, $module_type ) ) : false; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return false|Freemius */ function get_parent_instance() { return self::get_instance_by_id( $this->_plugin->parent_plugin_id ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param string|number $id_or_slug * * @return false|Freemius */ function get_addon_instance( $id_or_slug ) { $addon_id = self::get_module_id( $id_or_slug ); return self::instance( $addon_id ); } /** * @return Freemius[] */ static function _get_all_instances() { return self::$_instances; } #endregion ------------------------------------------------------------------ /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return bool */ function is_parent_plugin_installed() { $is_active = self::has_instance( $this->_plugin->parent_plugin_id ); if ( $is_active ) { return true; } /** * Parent module might be a theme. If that's the case, the add-on's FS * instance will be loaded prior to the theme's FS instance, therefore, * we need to check if it's active with a "look ahead". * * @author Vova Feldman * @since 1.2.2.3 */ global $fs_active_plugins; if ( is_object( $fs_active_plugins ) && is_array( $fs_active_plugins->plugins ) ) { $active_theme = wp_get_theme(); foreach ( $fs_active_plugins->plugins as $sdk => $module ) { if ( WP_FS__MODULE_TYPE_THEME === $module->type ) { if ( $module->plugin_path == $active_theme->get_stylesheet() ) { // Parent module is a theme and it's currently active. return true; } } } } return false; } /** * Check if add-on parent plugin in activation mode. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return bool */ function is_parent_in_activation() { $parent_fs = $this->get_parent_instance(); if ( ! is_object( $parent_fs ) ) { return false; } return ( $parent_fs->is_activation_mode() ); } /** * Is plugin in activation mode. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param bool $and_on * * @return bool */ function is_activation_mode( $and_on = true ) { return fs_is_network_admin() ? $this->is_network_activation_mode( $and_on ) : $this->is_site_activation_mode( $and_on ); } /** * Is plugin in activation mode. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param bool $and_on * * @return bool */ function is_site_activation_mode( $and_on = true ) { return ( ( $this->is_on() || ! $and_on ) && ( ( $this->is_premium() && true === $this->_storage->require_license_activation ) || ( ( ! $this->is_registered() || ( $this->is_only_premium() && ! $this->has_features_enabled_license() ) ) && ( ! $this->is_enable_anonymous() || ( ! $this->is_anonymous() && ! $this->is_pending_activation() ) ) ) ) ); } /** * Checks if the SDK in network activation mode. * * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param bool $and_on * * @return bool */ private function is_network_activation_mode( $and_on = true ) { if ( ! $this->_is_network_active ) { // Not network activated. return false; } if ( $this->is_network_upgrade_mode() ) { // Special flag to enforce network activation mode to decide what to do with the sites that are not yet opted-in nor skipped. return true; } if ( ! $this->is_site_activation_mode( $and_on ) ) { // Whether the context is single site or the network, if the plugin is no longer in activation mode then it is not in network activation mode as well. return false; } if ( $this->is_network_delegated_connection() ) { // Super-admin delegated the connection to the site admins -> not activation mode. return false; } if ( $this->is_network_anonymous() && true !== $this->_storage->require_license_activation ) { // Super-admin skipped the connection network wide -> not activation mode. return false; } if ( $this->is_network_registered() ) { // Super-admin connected at least one site -> not activation mode. return false; } return true; } /** * Check if current page is the opt-in/pending-activation page. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @return bool */ function is_activation_page() { if ( $this->_menu->is_activation_page( $this->show_opt_in_on_themes_page() ) ) { return true; } if ( ! $this->is_activation_mode() ) { return false; } // Check if current page is matching the activation page. return $this->is_matching_url( $this->get_activation_url() ); } /** * Check if URL path's are matching and that all querystring * arguments of the $sub_url exist in the $url with the same values. * * WARNING: * 1. This method doesn't check if the sub/domain are matching. * 2. Ignore case sensitivity. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param string $sub_url * @param string $url If argument is not set, check if the sub_url matching the current's page URL. * * @return bool */ private function is_matching_url( $sub_url, $url = '' ) { if ( empty( $url ) ) { $url = $_SERVER['REQUEST_URI']; } $url = strtolower( $url ); $sub_url = strtolower( $sub_url ); if ( parse_url( $sub_url, PHP_URL_PATH ) !== parse_url( $url, PHP_URL_PATH ) ) { // Different path - DO NOT OVERRIDE PAGE. return false; } $url_params = array(); parse_str( parse_url( $url, PHP_URL_QUERY ), $url_params ); $sub_url_params = array(); parse_str( parse_url( $sub_url, PHP_URL_QUERY ), $sub_url_params ); foreach ( $sub_url_params as $key => $val ) { if ( ! isset( $url_params[ $key ] ) || $val != $url_params[ $key ] ) { // Not matching query string - DO NOT OVERRIDE PAGE. return false; } } return true; } /** * Get the basenames of all active plugins for specific blog. Including network activated plugins. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id * * @return string[] */ private static function get_active_plugins_basenames( $blog_id = 0 ) { if ( is_multisite() && $blog_id > 0 ) { $active_basenames = get_blog_option( $blog_id, 'active_plugins' ); } else { $active_basenames = get_option( 'active_plugins' ); } if ( ! is_array( $active_basenames ) ) { $active_basenames = array(); } if ( is_multisite() ) { $network_active_basenames = get_site_option( 'active_sitewide_plugins' ); if ( is_array( $network_active_basenames ) && ! empty( $network_active_basenames ) ) { $active_basenames = array_merge( $active_basenames, array_keys( $network_active_basenames ) ); } } return $active_basenames; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param int $blog_id * * @return array */ static function get_active_plugins_directories_map( $blog_id = 0 ) { $active_basenames = self::get_active_plugins_basenames( $blog_id ); $map = array(); foreach ( $active_basenames as $active_basename ) { $active_basename = fs_normalize_path( $active_basename ); if ( false === strpos( $active_basename, '/' ) ) { continue; } $map[ dirname( $active_basename ) ] = true; } return $map; } /** * Get collection of all active plugins. Including network activated plugins. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param int $blog_id Since 2.0.0 * * @return array[string]array */ private static function get_active_plugins( $blog_id = 0 ) { self::require_plugin_essentials(); $active_plugin = array(); $all_plugins = fs_get_plugins(); $active_plugins_basenames = self::get_active_plugins_basenames( $blog_id ); foreach ( $active_plugins_basenames as $plugin_basename ) { $active_plugin[ $plugin_basename ] = $all_plugins[ $plugin_basename ]; } return $active_plugin; } /** * Get collection of all site active plugins for a specified blog. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id * * @return array[string]array */ private static function get_site_active_plugins( $blog_id = 0 ) { $active_basenames = ( is_multisite() && $blog_id > 0 ) ? get_blog_option( $blog_id, 'active_plugins' ) : get_option( 'active_plugins' ); $active = array(); if ( ! is_array( $active_basenames ) ) { return $active; } foreach ( $active_basenames as $basename ) { $active[ $basename ] = array( 'is_active' => true, 'Version' => '1.0', // Dummy version. 'slug' => self::get_plugin_slug( $basename ), ); } return $active; } /** * Get collection of all plugins with their activation status for a specified blog. * * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @param int $blog_id Since 2.0.0 * * @return array Key is the plugin file path and the value is an array of the plugin data. */ private static function get_all_plugins( $blog_id = 0 ) { self::require_plugin_essentials(); $all_plugins = fs_get_plugins(); $active_plugins_basenames = self::get_active_plugins_basenames( $blog_id ); foreach ( $all_plugins as $basename => &$data ) { // By default set to inactive (next foreach update the active plugins). $data['is_active'] = false; // Enrich with plugin slug. $data['slug'] = self::get_plugin_slug( $basename ); } // Flag active plugins. foreach ( $active_plugins_basenames as $basename ) { if ( isset( $all_plugins[ $basename ] ) ) { $all_plugins[ $basename ]['is_active'] = true; } } return $all_plugins; } /** * Get collection of all plugins and if they are network level activated. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return array Key is the plugin basename and the value is an array of the plugin data. */ private static function get_network_plugins() { self::require_plugin_essentials(); $all_plugins = fs_get_plugins(); $network_active_basenames = is_multisite() ? get_site_option( 'active_sitewide_plugins' ) : array(); foreach ( $all_plugins as $basename => &$data ) { // By default set to inactive (next foreach update the active plugins). $data['is_active'] = false; // Enrich with plugin slug. $data['slug'] = self::get_plugin_slug( $basename ); } // Flag active plugins. foreach ( $network_active_basenames as $basename ) { if ( isset( $all_plugins[ $basename ] ) ) { $all_plugins[ $basename ]['is_active'] = true; } } return $all_plugins; } /** * Cached result of get_site_transient( 'update_plugins' ) * * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @var object */ private static $_plugins_info; /** * Helper function to get specified plugin's slug. * * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @param $basename * * @return string */ private static function get_plugin_slug( $basename ) { if ( ! isset( self::$_plugins_info ) ) { self::$_plugins_info = get_site_transient( 'update_plugins' ); } $slug = ''; if ( is_object( self::$_plugins_info ) ) { if ( isset( self::$_plugins_info->no_update ) && isset( self::$_plugins_info->no_update[ $basename ] ) && ! empty( self::$_plugins_info->no_update[ $basename ]->slug ) ) { $slug = self::$_plugins_info->no_update[ $basename ]->slug; } else if ( isset( self::$_plugins_info->response ) && isset( self::$_plugins_info->response[ $basename ] ) && ! empty( self::$_plugins_info->response[ $basename ]->slug ) ) { $slug = self::$_plugins_info->response[ $basename ]->slug; } } if ( empty( $slug ) ) { // Try to find slug from FS data. $slug = self::find_slug_by_basename( $basename ); } if ( empty( $slug ) ) { // Fallback to plugin's folder name. $slug = dirname( $basename ); } return $slug; } private static $_statics_loaded = false; /** * Load static resources. * * @author Vova Feldman (@svovaf) * @since 1.0.1 */ private static function _load_required_static() { if ( self::$_statics_loaded ) { return; } self::$_static_logger = FS_Logger::get_logger( WP_FS__SLUG, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); self::$_static_logger->entrance(); self::$_accounts = FS_Options::instance( WP_FS__ACCOUNTS_OPTION_NAME, true ); if ( is_multisite() ) { $has_skipped_migration = ( // 'id_slug_type_path_map' - was never stored on older versions, therefore, not exists on the site level. null === self::$_accounts->get_option( 'id_slug_type_path_map', null, false ) && // 'file_slug_map' stored on the site level, so it was running an SDK version before it was integrated with MS-network. null !== self::$_accounts->get_option( 'file_slug_map', null, false ) ); /** * If the file_slug_map exists on the site level but doesn't exist on the * network level storage, it means that we need to process the storage with migration. * * The code in this `if` scope will only be executed once and only for the first site that will execute it because once we migrate the storage data, file_slug_map will be already set in the network level storage. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ if ( ( $has_skipped_migration && true !== self::$_accounts->get_option( 'ms_migration_complete', false, true ) ) || ( null === self::$_accounts->get_option( 'file_slug_map', null, true ) && null !== self::$_accounts->get_option( 'file_slug_map', null, false ) ) ) { self::migrate_options_to_network(); } } self::$_global_admin_notices = FS_Admin_Notices::instance( 'global' ); if ( ! WP_FS__DEMO_MODE ) { add_action( ( fs_is_network_admin() ? 'network_' : '' ) . 'admin_menu', array( 'Freemius', '_add_debug_section' ) ); } add_action( "wp_ajax_fs_toggle_debug_mode", array( 'Freemius', '_toggle_debug_mode' ) ); self::add_ajax_action_static( 'get_debug_log', array( 'Freemius', '_get_debug_log' ) ); self::add_ajax_action_static( 'get_db_option', array( 'Freemius', '_get_db_option' ) ); self::add_ajax_action_static( 'set_db_option', array( 'Freemius', '_set_db_option' ) ); if ( 0 == did_action( 'plugins_loaded' ) ) { add_action( 'plugins_loaded', array( 'Freemius', '_load_textdomain' ), 1 ); } $clone_manager = FS_Clone_Manager::instance(); add_action( 'init', array( $clone_manager, '_init' ) ); add_action( 'admin_footer', array( 'Freemius', '_open_support_forum_in_new_page' ) ); if ( self::is_plugins_page() || self::is_themes_page() ) { add_action( 'admin_print_footer_scripts', array( 'Freemius', '_maybe_add_beta_label_styles' ), 9 ); /** * Specifically use this hook so that the JS event handlers will work properly on the "Themes" * page. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ add_action( 'admin_footer-' . self::get_current_page(), array( 'Freemius', '_maybe_add_beta_label_to_plugins_and_handle_confirmation') ); } self::$_statics_loaded = true; } #-------------------------------------------------------------------------------- #region Clone #-------------------------------------------------------------------------------- /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param bool $only_if_manual_resolution_is_not_hidden * * @return bool */ private function is_unresolved_clone( $only_if_manual_resolution_is_not_hidden = false ) { if ( ! $this->is_clone( $only_if_manual_resolution_is_not_hidden ) ) { return false; } return FS_Clone_Manager::instance()->has_temporary_duplicate_mode_expired(); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param bool $only_if_manual_resolution_is_not_hidden */ function is_clone( $only_if_manual_resolution_is_not_hidden = false ) { if ( ! is_object( $this->_site ) ) { return false; } $blog_id = null; if ( fs_is_network_admin() && FS_Site::is_valid_id( $this->_storage->network_install_blog_id ) ) { // Ensure that we're comparing the network install's URL with the relevant subsite's URL. $blog_id = $this->_storage->network_install_blog_id; } $site_url = Freemius::get_unfiltered_site_url( $blog_id, true, true ); if ( ! $this->_site->is_clone( $site_url ) ) { return false; } return ( ! $only_if_manual_resolution_is_not_hidden || ! FS_Clone_Manager::instance()->should_hide_manual_resolution() ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param int|null $blog_id * @param bool $strip_protocol * @param bool $add_trailing_slash * * @return string */ static function get_unfiltered_site_url( $blog_id = null, $strip_protocol = false, $add_trailing_slash = false ) { global $wp_filter; $site_url_filters = array( 'site_url' => null, 'pre_option_siteurl' => null, 'default_option_siteurl' => null, 'option_siteurl' => null, ); // Detach all URL-related filters to get the actual site's URL (stripped of potential manipulations by multilingual plugins). foreach ( $site_url_filters as $hook_name => $site_url_filter ) { if ( ! empty( $wp_filter[ $hook_name ] ) ) { $site_url_filters[ $hook_name ] = $wp_filter[ $hook_name ]; unset( $wp_filter[ $hook_name ] ); } } $url = get_site_url( $blog_id ); // Re-attach the filters back. foreach ( $site_url_filters as $hook_name => $site_url_filter ) { if ( ! empty( $site_url_filter ) ) { $wp_filter[ $hook_name ] = $site_url_filter; } } if ( $strip_protocol ) { $url = fs_strip_url_protocol( $url ); } if ( $add_trailing_slash ) { $url = trailingslashit( $url ); } return $url; } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param number $site_id */ function fetch_install_by_id( $site_id ) { return $this->get_current_or_network_user_api_scope()->get( "/installs/{$site_id}.json" ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @return string|object|bool */ function _handle_long_term_duplicate() { $this->_logger->entrance(); $this->delete_current_install( false ); $license_key = false; if ( is_object( $this->_license ) && ! $this->_license->is_utilized( ( WP_FS__IS_LOCALHOST_FOR_SERVER || FS_Site::is_localhost_by_address( self::get_unfiltered_site_url() ) ) ) ) { $license_key = $this->_license->secret_key; } return $this->opt_in( false, false, false, $license_key, false, false, false, null, array(), false ); } #endregion /** * @author Leo Fajardo (@leorw) * * @since 2.1.3 */ private static function migrate_options_to_network() { self::migrate_accounts_to_network(); // Migrate API options from site level to network level. $api_network_options = FS_Option_Manager::get_manager( WP_FS__OPTIONS_OPTION_NAME, true, true ); $api_network_options->migrate_to_network(); // Migrate API cache to network level storage. FS_Cache_Manager::get_manager( WP_FS__API_CACHE_OPTION_NAME )->migrate_to_network(); self::$_accounts->set_option( 'ms_migration_complete', true, true ); } #---------------------------------------------------------------------------------- #region Localization #---------------------------------------------------------------------------------- /** * Load framework's text domain. * * @author Vova Feldman (@svovaf) * @since 1.2.1 */ static function _load_textdomain() { if ( ! is_admin() ) { return; } global $fs_active_plugins; // Works both for plugins and themes. load_plugin_textdomain( 'freemius', false, $fs_active_plugins->newest->sdk_path . '/languages/' ); } #endregion #---------------------------------------------------------------------------------- #region Debugging #---------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 1.0.8 */ static function _add_debug_section() { if ( ! is_super_admin() ) { // Add debug page only for super-admins. return; } self::$_static_logger->entrance(); $title = sprintf( '%s [v.%s]', fs_text_inline( 'Freemius Debug' ), WP_FS__SDK_VERSION ); if ( WP_FS__DEV_MODE ) { // Add top-level debug menu item. $hook = FS_Admin_Menu_Manager::add_page( $title, $title, 'manage_options', 'freemius', array( 'Freemius', '_debug_page_render' ) ); } else { // Add hidden debug page. $hook = FS_Admin_Menu_Manager::add_subpage( '', $title, $title, 'manage_options', 'freemius', array( 'Freemius', '_debug_page_render' ) ); } if ( ! empty( $hook ) ) { add_action( "load-$hook", array( 'Freemius', '_debug_page_actions' ) ); } } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.3 */ static function _toggle_debug_mode() { check_admin_referer( 'fs_toggle_debug_mode' ); if ( ! is_super_admin() ) { return; } $is_on = fs_request_get( 'is_on', false, 'post' ); if ( fs_request_is_post() && in_array( $is_on, array( 0, 1 ) ) ) { update_option( 'fs_debug_mode', $is_on ); // Turn on/off storage logging. FS_Logger::_set_storage_logging( ( 1 == $is_on ) ); } exit; } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.6 */ static function _get_debug_log() { check_admin_referer( 'fs_get_debug_log' ); if ( ! is_super_admin() ) { return; } $limit = min( ! empty( $_POST['limit'] ) ? absint( $_POST['limit'] ) : 200, 200 ); $offset = min( ! empty( $_POST['offset'] ) ? absint( $_POST['offset'] ) : 200, 200 ); $logs = FS_Logger::load_db_logs( fs_request_get( 'filters', false, 'post' ), $limit, $offset ); self::shoot_ajax_success( $logs ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.7 */ static function _get_db_option() { check_admin_referer( 'fs_get_db_option' ); $option_name = fs_request_get( 'option_name' ); if ( ! is_super_admin() || ! fs_starts_with( $option_name, 'fs_' ) ) { self::shoot_ajax_failure(); } $value = get_option( $option_name ); $result = array( 'name' => $option_name, ); if ( false !== $value ) { if ( ! is_string( $value ) ) { $value = json_encode( $value ); } $result['value'] = $value; } self::shoot_ajax_success( $result ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.7 */ static function _set_db_option() { check_admin_referer( 'fs_set_db_option' ); $option_name = fs_request_get( 'option_name' ); if ( ! is_super_admin() || ! fs_starts_with( $option_name, 'fs_' ) ) { self::shoot_ajax_failure(); } $option_value = fs_request_get( 'option_value' ); if ( ! empty( $option_value ) ) { update_option( $option_name, $option_value ); } self::shoot_ajax_success(); } /** * @author Vova Feldman (@svovaf) * @since 1.0.8 */ static function _debug_page_actions() { self::_clean_admin_content_section(); if ( fs_request_is_action( 'restart_freemius' ) ) { check_admin_referer( 'restart_freemius' ); if ( ! is_multisite() ) { // Clear accounts data. self::$_accounts->clear( null, true ); } else { $sites = self::get_sites(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); self::$_accounts->clear( $blog_id, true ); } // Clear network level storage. self::$_accounts->clear( true, true ); } // Clear SDK reference cache. delete_option( 'fs_active_plugins' ); } else if ( fs_request_is_action( 'clear_updates_data' ) ) { check_admin_referer( 'clear_updates_data' ); if ( ! is_multisite() ) { set_site_transient( 'update_plugins', null ); set_site_transient( 'update_themes', null ); } else { $current_blog_id = get_current_blog_id(); $sites = self::get_sites(); foreach ( $sites as $site ) { switch_to_blog( self::get_site_blog_id( $site ) ); set_site_transient( 'update_plugins', null ); set_site_transient( 'update_themes', null ); } switch_to_blog( $current_blog_id ); } } else if ( fs_request_is_action( 'reset_deactivation_snoozing' ) ) { check_admin_referer( 'reset_deactivation_snoozing' ); self::reset_deactivation_snoozing(); } else if ( fs_request_is_action( 'simulate_trial' ) ) { check_admin_referer( 'simulate_trial' ); $fs = freemius( fs_request_get( 'module_id' ) ); // Update SDK install to at least 24 hours before. $fs->_storage->install_timestamp = ( time() - WP_FS__TIME_24_HOURS_IN_SEC ); // Unset the trial shown timestamp. unset( $fs->_storage->trial_promotion_shown ); } else if ( fs_request_is_action( 'simulate_network_upgrade' ) ) { check_admin_referer( 'simulate_network_upgrade' ); $fs = freemius( fs_request_get( 'module_id' ) ); self::set_network_upgrade_mode( $fs->_storage ); } else if ( fs_request_is_action( 'delete_install' ) ) { check_admin_referer( 'delete_install' ); self::_delete_site_by_slug( fs_request_get( 'slug' ), fs_request_get( 'module_type' ), true, fs_request_get( 'blog_id', null ) ); } else if ( fs_request_is_action( 'delete_user' ) ) { check_admin_referer( 'delete_user' ); self::delete_user( fs_request_get( 'user_id' ) ); } else if ( fs_request_is_action( 'download_logs' ) ) { check_admin_referer( 'download_logs' ); $download_url = FS_Logger::download_db_logs( fs_request_get( 'filters', false, 'post' ) ); if ( false === $download_url ) { wp_die( 'Oops... there was an error while generating the logs download file. Please try again and if it doesn\'t work contact support@freemius.com.' ); } fs_redirect( $download_url ); } else if ( fs_request_is_action( 'migrate_options_to_network' ) ) { check_admin_referer( 'migrate_options_to_network' ); self::migrate_options_to_network(); } } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @return array */ static function get_all_modules_sites() { self::$_static_logger->entrance(); $sites_by_type = array( WP_FS__MODULE_TYPE_PLUGIN => array(), WP_FS__MODULE_TYPE_THEME => array(), ); $module_types = array_keys( $sites_by_type ); if ( ! is_multisite() ) { foreach ( $module_types as $type ) { $sites_by_type[ $type ] = self::get_all_sites( $type ); foreach ( $sites_by_type[ $type ] as $slug => $install ) { $sites_by_type[ $type ][ $slug ] = array( $install ); } } } else { $sites = self::get_sites(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); foreach ( $module_types as $type ) { $installs = self::get_all_sites( $type, $blog_id ); foreach ( $installs as $slug => $install ) { if ( ! isset( $sites_by_type[ $type ][ $slug ] ) ) { $sites_by_type[ $type ][ $slug ] = array(); } $install->blog_id = $blog_id; $sites_by_type[ $type ][ $slug ][] = $install; } } } } return $sites_by_type; } /** * @author Vova Feldman (@svovaf) * @since 1.0.8 */ static function _debug_page_render() { self::$_static_logger->entrance(); $all_modules_sites = self::get_all_modules_sites(); $licenses_by_module_type = self::get_all_licenses_by_module_type(); $vars = array( 'plugin_sites' => $all_modules_sites[ WP_FS__MODULE_TYPE_PLUGIN ], 'theme_sites' => $all_modules_sites[ WP_FS__MODULE_TYPE_THEME ], 'users' => self::get_all_users(), 'addons' => self::get_all_addons(), 'account_addons' => self::get_all_account_addons(), 'plugin_licenses' => $licenses_by_module_type[ WP_FS__MODULE_TYPE_PLUGIN ], 'theme_licenses' => $licenses_by_module_type[ WP_FS__MODULE_TYPE_THEME ] ); fs_enqueue_local_style( 'fs_debug', '/admin/debug.css' ); fs_require_once_template( 'debug.php', $vars ); } #endregion #---------------------------------------------------------------------------------- #region Connectivity Issues #---------------------------------------------------------------------------------- /** * Check if Freemius should be turned on for the current plugin install. * * Note: * $this->_is_on is updated in has_api_connectivity() * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_on() { self::$_static_logger->entrance(); if ( is_object( $this->_site ) && ! $this->is_registered() ) { return false; } if ( isset( $this->_is_on ) ) { return $this->_is_on; } // If already installed or pending then sure it's on :) if ( $this->is_registered() || $this->is_pending_activation() ) { $this->_is_on = true; return true; } return false; } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @param bool $flush_if_no_connectivity * * @return bool */ private function should_run_connectivity_test( $flush_if_no_connectivity = false ) { if ( ! isset( $this->_storage->connectivity_test ) ) { // Connectivity test was never executed, or cache was cleared. return true; } if ( WP_FS__PING_API_ON_IP_OR_HOST_CHANGES ) { if ( WP_FS__IS_HTTP_REQUEST ) { if ( $_SERVER['HTTP_HOST'] != $this->_storage->connectivity_test['host'] ) { // Domain changed. return true; } if ( WP_FS__REMOTE_ADDR != $this->_storage->connectivity_test['server_ip'] ) { // Server IP changed. return true; } } } if ( $this->_storage->connectivity_test['is_connected'] && $this->_storage->connectivity_test['is_active'] ) { // API connected and Freemius is active - no need to run connectivity check. return false; } if ( $flush_if_no_connectivity ) { /** * If explicitly asked to flush when no connectivity - do it only * if at least 10 sec passed from the last API connectivity test. */ return ( isset( $this->_storage->connectivity_test['timestamp'] ) && ( WP_FS__SCRIPT_START_TIME - $this->_storage->connectivity_test['timestamp'] ) > 10 ); } /** * @since 1.1.7 Don't check for connectivity on plugin downgrade. */ $version = $this->get_plugin_version(); if ( version_compare( $version, $this->_storage->connectivity_test['version'], '>' ) ) { // If it's a plugin version upgrade and Freemius is off or no connectivity, run connectivity test. return true; } return false; } /** * @author Leo Fajardo (@leorw) * @since 2.5.4 * * @param bool $is_update * * @return bool */ private function should_turn_fs_on( $is_update = true ) { if ( empty( $this->_plugin->opt_in_moderation ) || ! is_array( $this->_plugin->opt_in_moderation ) ) { return true; } $optin_config = $this->_plugin->opt_in_moderation; if ( WP_FS__IS_LOCALHOST && ( ! isset( $optin_config['localhost'] ) || false !== $optin_config['localhost'] ) ) { return true; } $optin_config_key = $is_update ? 'updates' : 'new'; if ( ! isset( $optin_config[ $optin_config_key ] ) ) { return true; } $visibility_percentage = $optin_config[ $optin_config_key ]; if ( 0 == $visibility_percentage ) { return false; } if ( ! is_numeric( $visibility_percentage ) ) { return true; } $min = 1; $max = 100; if ( function_exists( 'random_int' ) ) { $random = random_int( $min, $max ); } else { $random = rand( $min, $max ); } return ( $random <= $visibility_percentage ); } /** * Check if there's any connectivity issue to Freemius API. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param bool $flush_if_no_connectivity * * @return bool|null */ function has_api_connectivity( $flush_if_no_connectivity = false ) { $this->_logger->entrance(); if ( isset( $this->_has_api_connection ) && ( $this->_has_api_connection || ! $flush_if_no_connectivity ) ) { return $this->_has_api_connection; } if ( WP_FS__SIMULATE_NO_API_CONNECTIVITY && isset( $this->_storage->connectivity_test ) && true === $this->_storage->connectivity_test['is_connected'] ) { $this->clear_connectivity_info(); } if ( ! $this->should_run_connectivity_test( $flush_if_no_connectivity ) ) { $this->_has_api_connection = $this->_storage->connectivity_test['is_connected']; /** * @since 1.1.6 During dev mode, if there's connectivity - turn Freemius on regardless the configuration. * * @since 1.2.1.5 If the user running the premium version then ignore the 'is_active' flag and turn Freemius on to enable license key activation. */ $this->_is_on = $this->_storage->connectivity_test['is_active'] || $this->is_premium() || ( WP_FS__DEV_MODE && $this->_has_api_connection && ! WP_FS__SIMULATE_FREEMIUS_OFF ); return $this->_has_api_connection; } if ( ! empty( $this->_storage->connectivity_test ) && isset( $this->_storage->connectivity_test['is_active'] ) ) { $is_active = $this->_storage->connectivity_test['is_active']; } else { $is_active = $this->should_turn_fs_on( $this->apply_filters( 'is_plugin_update', $this->is_plugin_update() ) ); $this->store_connectivity_info( (object) array( 'is_active' => $is_active ), null ); } if ( $is_active ) { $this->_is_on = true; } return $this->_has_api_connection; } /** * @author Leo Fajardo (@leorw) * @since 2.5.4 */ private function clear_connectivity_info() { unset( $this->_storage->connectivity_test ); FS_Api::clear_force_http_flag(); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.4 * * @param object $pong * @param bool|null $is_connected */ private function store_connectivity_info( $pong, $is_connected ) { $this->_logger->entrance(); $version = $this->get_plugin_version(); if ( false === $is_connected || WP_FS__SIMULATE_FREEMIUS_OFF ) { $is_active = false; } else { $is_active = ( isset( $pong->is_active ) && true == $pong->is_active ); } $is_active = $this->apply_filters( 'is_on', $is_active, $this->is_plugin_update(), $version ); $this->_storage->connectivity_test = array( 'is_connected' => $is_connected, 'host' => $_SERVER['HTTP_HOST'], 'server_ip' => WP_FS__REMOTE_ADDR, 'is_active' => $is_active, 'timestamp' => WP_FS__SCRIPT_START_TIME, // Last version with connectivity attempt. 'version' => $version, ); $this->_has_api_connection = $is_connected; $this->_is_on = $is_active || ( WP_FS__DEV_MODE && $is_connected && ! WP_FS__SIMULATE_FREEMIUS_OFF ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.4 * * @param bool $is_connected */ private function update_connectivity_info( $is_connected ) { $this->store_connectivity_info( // This is true since we update the connection info only after a successful opt-in or license activation which means that Freemius has already been on even before the process. (object) array( 'is_active' => true ), $is_connected ); } /** * Force turning Freemius on. * * @author Vova Feldman (@svovaf) * @since 1.1.8.1 * * @return bool TRUE if successfully turned on. */ private function turn_on() { $this->_logger->entrance(); if ( $this->is_on() || ! isset( $this->_storage->connectivity_test['is_active'] ) ) { return false; } $updated_connectivity = $this->_storage->connectivity_test; $updated_connectivity['is_active'] = true; $updated_connectivity['timestamp'] = WP_FS__SCRIPT_START_TIME; $this->_storage->connectivity_test = $updated_connectivity; $this->_is_on = true; return true; } /** * Anonymous and unique site identifier (Hash). * * @author Vova Feldman (@svovaf) * @since 1.1.0 * * @param null|int $blog_id Since 2.0.0 * * @return string */ function get_anonymous_id( $blog_id = null ) { $unique_id = self::$_accounts->get_option( 'unique_id', null, $blog_id ); if ( empty( $unique_id ) || ! is_string( $unique_id ) ) { $key = self::get_unfiltered_site_url( $blog_id, true ); $secure_auth = defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : ''; if ( empty( $secure_auth ) || false !== strpos( $secure_auth, ' ' ) || 'put your unique phrase here' === $secure_auth ) { // Protect against default auth key. $secure_auth = md5( microtime() ); } /** * Base the unique identifier on the WP secure authentication key. Which * turns the key into a secret anonymous identifier. This will help us * to avoid duplicate installs generation on the backend upon opt-in. * * @author Vova Feldman (@svovaf) * @since 1.2.3 */ $unique_id = md5( $key . $secure_auth ); self::$_accounts->set_option( 'unique_id', $unique_id, true, $blog_id ); } $this->_logger->departure( $unique_id ); return $unique_id; } /** * Returns anonymous network ID. * * @since 2.4.3 * * @return string */ function get_anonymous_network_id() { return $this->get_anonymous_id( get_network()->site_id ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.4 * * @return \WP_User */ static function _get_current_wp_user() { self::require_pluggable_essentials(); self::wp_cookie_constants(); return wp_get_current_user(); } /** * Define cookie constants which are required by Freemius::_get_current_wp_user() since * it uses wp_get_current_user() which needs the cookie constants set. When a plugin * is network activated the cookie constants are only configured after the network * plugins activation, therefore, if we don't define those constants WP will throw * PHP warnings/notices. * * @author Vova Feldman (@svovaf) * @since 2.1.1 */ private static function wp_cookie_constants() { if ( defined( 'LOGGED_IN_COOKIE' ) && ( defined( 'AUTH_COOKIE' ) || defined( 'SECURE_AUTH_COOKIE' ) ) ) { return; } /** * Used to guarantee unique hash cookies * * @since 1.5.0 */ if ( ! defined( 'COOKIEHASH' ) ) { $siteurl = get_site_option( 'siteurl' ); if ( $siteurl ) { define( 'COOKIEHASH', md5( $siteurl ) ); } else { define( 'COOKIEHASH', '' ); } } if ( ! defined( 'LOGGED_IN_COOKIE' ) ) { define( 'LOGGED_IN_COOKIE', 'wordpress_logged_in_' . COOKIEHASH ); } /** * @since 2.5.0 */ if ( ! defined( 'AUTH_COOKIE' ) ) { define( 'AUTH_COOKIE', 'wordpress_' . COOKIEHASH ); } /** * @since 2.6.0 */ if ( ! defined( 'SECURE_AUTH_COOKIE' ) ) { define( 'SECURE_AUTH_COOKIE', 'wordpress_sec_' . COOKIEHASH ); } } /** * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @return int */ static function get_current_wp_user_id() { $wp_user = self::_get_current_wp_user(); return $wp_user->ID; } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param string $email * * @return bool */ static function is_valid_email( $email ) { if ( false === filter_var( $email, FILTER_VALIDATE_EMAIL ) ) { return false; } $parts = explode( '@', $email ); if ( 2 !== count( $parts ) || empty( $parts[1] ) ) { return false; } $blacklist = array( 'admin.', 'webmaster.', 'localhost.', 'dev.', 'development.', 'test.', 'stage.', 'staging.', ); // Make sure domain is not one of the blacklisted. foreach ( $blacklist as $invalid ) { if ( 0 === strpos( $parts[1], $invalid ) ) { return false; } } // Get the UTF encoded domain name. $domain = idn_to_ascii( $parts[1] ) . '.'; return ( checkdnsrr( $domain, 'MX' ) || checkdnsrr( $domain, 'A' ) ); } #endregion #---------------------------------------------------------------------------------- #region Email #---------------------------------------------------------------------------------- /** * Generates and sends an HTML email with customizable sections. * * @author Leo Fajardo (@leorw) * @since 1.1.2 * * @param string $to_address * @param string $subject * @param array $sections * @param array $headers * * @return bool Whether the email contents were sent successfully. */ private function send_email( $to_address, $subject, $sections = array(), $headers = array() ) { $default_sections = $this->get_email_sections(); // Insert new sections or replace the default email sections. if ( is_array( $sections ) && ! empty( $sections ) ) { foreach ( $sections as $section_id => $custom_section ) { if ( ! isset( $default_sections[ $section_id ] ) ) { // If the section does not exist, add it. $default_sections[ $section_id ] = $custom_section; } else { // If the section already exists, override it. $current_section = $default_sections[ $section_id ]; // Replace the current section's title if a custom section title exists. if ( isset( $custom_section['title'] ) ) { $current_section['title'] = $custom_section['title']; } // Insert new rows under the current section or replace the default rows. if ( isset( $custom_section['rows'] ) && is_array( $custom_section['rows'] ) && ! empty( $custom_section['rows'] ) ) { foreach ( $custom_section['rows'] as $row_id => $row ) { $current_section['rows'][ $row_id ] = $row; } } $default_sections[ $section_id ] = $current_section; } } } $vars = array( 'sections' => $default_sections ); $message = fs_get_template( 'email.php', $vars ); // Set the type of email to HTML. $headers[] = 'Content-type: text/html; charset=UTF-8'; $header_string = implode( "\r\n", $headers ); return wp_mail( $to_address, $subject, $message, $header_string ); } /** * Generates the data for the sections of the email content. * * @author Leo Fajardo (@leorw) * @since 1.1.2 * * @return array */ private function get_email_sections() { // Retrieve the current user's information so that we can get the user's email, first name, and last name below. $current_user = self::_get_current_wp_user(); // Retrieve the cURL version information so that we can get the version number below. $curl_version_information = curl_version(); $active_plugin = self::get_active_plugins(); // Generate the list of active plugins separated by new line. $active_plugin_string = ''; foreach ( $active_plugin as $plugin ) { $active_plugin_string .= sprintf( '%s [v%s]
', $plugin['PluginURI'], $plugin['Name'], $plugin['Version'] ); } $server_ip = WP_FS__REMOTE_ADDR; // Add PHP info for deeper investigation. ob_start(); phpinfo(); $php_info = ob_get_clean(); $api_domain = substr( FS_API__ADDRESS, strpos( FS_API__ADDRESS, ':' ) + 3 ); // Generate the default email sections. $sections = array( 'sdk' => array( 'title' => 'SDK', 'rows' => array( 'fs_version' => array( 'FS Version', $this->version ), 'curl_version' => array( 'cURL Version', $curl_version_information['version'] ) ) ), 'plugin' => array( 'title' => ucfirst( $this->get_module_type() ), 'rows' => array( 'name' => array( 'Name', $this->get_plugin_name() ), 'version' => array( 'Version', $this->get_plugin_version() ) ) ), 'api' => array( 'title' => 'API Subdomain', 'rows' => array( 'dns' => array( 'DNS_CNAME', function_exists( 'dns_get_record' ) ? var_export( dns_get_record( $api_domain, DNS_CNAME ), true ) : 'dns_get_record() disabled/blocked' ), 'ip' => array( 'IP', function_exists( 'gethostbyname' ) ? gethostbyname( $api_domain ) : 'gethostbyname() disabled/blocked' ), ), ), 'site' => array( 'title' => 'Site', 'rows' => array( 'unique_id' => array( 'Unique ID', $this->get_anonymous_id() ), 'address' => array( 'Address', site_url() ), 'host' => array( 'HTTP_HOST', ( ! empty( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : '' ) ), 'hosting' => array( 'Hosting Company' => fs_request_has( 'hosting_company' ) ? fs_request_get( 'hosting_company' ) : 'Unknown', ), 'server_addr' => array( 'SERVER_ADDR', '' . $server_ip . '' ) ) ), 'user' => array( 'title' => 'User', 'rows' => array( 'email' => array( 'Email', $current_user->user_email ), 'first' => array( 'First', $current_user->user_firstname ), 'last' => array( 'Last', $current_user->user_lastname ) ) ), 'plugins' => array( 'title' => 'Plugins', 'rows' => array( 'active_plugins' => array( 'Active Plugins', $active_plugin_string ) ) ), 'php_info' => array( 'title' => 'PHP Info', 'rows' => array( 'info' => array( $php_info ) ), ) ); // Allow the sections to be modified by other code. $sections = $this->apply_filters( 'email_template_sections', $sections ); return $sections; } #endregion #---------------------------------------------------------------------------------- #region Initialization #---------------------------------------------------------------------------------- /** * Init plugin's Freemius instance. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param number $id * @param string $public_key * @param bool $is_live * @param bool $is_premium */ function init( $id, $public_key, $is_live = true, $is_premium = true ) { $this->_logger->entrance(); $this->dynamic_init( array( 'id' => $id, 'public_key' => $public_key, 'is_live' => $is_live, 'is_premium' => $is_premium, ) ); } /** * Dynamic initiator, originally created to support initiation * with parent_id for add-ons. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param array $plugin_info * * @throws Freemius_Exception */ function dynamic_init( array $plugin_info ) { $this->_logger->entrance(); $this->parse_settings( $plugin_info ); $this->register_after_settings_parse_hooks(); /** * If anonymous but there's already a user entity and the user's site is associated with a valid license or trial period, update the anonymous mode accordingly. * * @todo Remove this entire `if` block after several releases as starting from this version, the anonymous mode will already be updated accordingly after a purchase. */ if ( $this->is_anonymous() ) { $is_network_level = ( $this->_is_network_active && fs_is_network_admin() ); if ( ! $is_network_level || FS_Site::is_valid_id( $this->_storage->network_install_blog_id ) ) { if ( $this->is_paying_or_trial() ) { $this->reset_anonymous_mode( $is_network_level ); } } else { $network = get_network(); if ( is_object( $network ) ) { $main_blog_id = $network->site_id; $first_install = $this->get_install_by_blog_id( $main_blog_id ); if ( is_object( $first_install ) ) { $this->_storage->network_install_blog_id = $main_blog_id; $this->_storage->network_user_id = $first_install->user_id; } } } } if ( $this->should_stop_execution() ) { return; } if ( ! $this->is_registered() ) { if ( $this->is_anonymous() ) { // If user skipped, no need to test connectivity. $this->_has_api_connection = true; $this->_is_on = true; } else { if ( false === $this->has_api_connectivity() ) { return; } else { if ( $this->_anonymous_mode ) { // Simulate anonymous mode. $this->_is_anonymous = true; } } } } /** * This should be executed even if Freemius is off for the core module, * otherwise, the add-ons dialog box won't work properly. This is especially * relevant when the developer decided to turn FS off for existing users. * * @author Vova Feldman (@svovaf) */ if ( $this->is_user_in_admin() && 'plugin-information' === fs_request_get( 'tab', false ) && $this->should_use_freemius_updater_and_dialog() && ( ( $this->is_addon() && $this->get_slug() == fs_request_get( 'plugin', false ) ) || ( $this->has_addons() && $this->get_id() == fs_request_get( 'parent_plugin_id', false ) ) ) ) { require_once WP_FS__DIR_INCLUDES . '/fs-plugin-info-dialog.php'; new FS_Plugin_Info_Dialog( $this->is_addon() ? $this->get_parent_instance() : $this ); } // Check if Freemius is on for the current plugin. // This MUST be executed after all the plugin variables has been loaded. if ( ! $this->is_registered() && ! $this->is_on() ) { return; } if ( $this->has_api_connectivity() ) { if ( self::is_cron() ) { $this->hook_callback_to_sync_cron(); } else if ( $this->is_user_in_admin() ) { /** * Schedule daily data sync cron if: * * 1. User opted-in (for tracking). * 2. If skipped, but later upgraded (opted-in via upgrade). * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * */ if ( $this->is_registered() && $this->is_tracking_allowed() ) { $this->maybe_schedule_sync_cron(); } /** * Check if requested for manual blocking background sync. */ if ( fs_request_has( 'background_sync' ) ) { self::require_pluggable_essentials(); self::wp_cookie_constants(); $this->run_manual_sync(); } } } if ( $this->is_registered() ) { FS_Clone_Manager::instance()->maybe_resolve_new_subsite_install_automatically( $this ); $this->hook_callback_to_install_sync(); } if ( $this->is_addon() ) { if ( $this->is_parent_plugin_installed() ) { // Link to parent FS. $this->_parent = self::get_instance_by_id( $this->_plugin->parent_plugin_id ); // Get parent plugin reference. $this->_parent_plugin = $this->_parent->get_plugin(); } } if ( $this->is_user_in_admin() ) { if ( $this->is_registered() && fs_request_has( 'purchase_completed' ) ) { $this->_admin_notices->add_sticky( sprintf( /* translators: %s: License type (e.g. you have a professional license) */ $this->get_text_inline( 'You have purchased a %s license.', 'you-have-x-license' ), fs_request_get( 'purchased_plan' ) ) . sprintf( $this->get_text_inline(" The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box.", 'post-purchase-email-sent-message' ), $this->get_module_label( true ), ( FS_Plugin::is_valid_id( $this->get_bundle_id() ) ? "products' " : '' ), ( FS_Plugin::is_valid_id( $this->get_bundle_id() ) ? 's' : '' ), sprintf( '%s', fs_request_get( 'purchase_email' ) ) ), 'plan_purchased', $this->get_text_x_inline( 'Yee-haw', 'interjection expressing joy or exuberance', 'yee-haw' ) . '!' ); } if ( $this->is_addon() ) { if ( ! $this->is_parent_plugin_installed() ) { $parent_name = $this->get_option( $plugin_info, 'parent_name', null ); if ( isset( $plugin_info['parent'] ) ) { $parent_name = $this->get_option( $plugin_info['parent'], 'name', null ); } $this->_admin_notices->add( ( ! empty( $parent_name ) ? sprintf( $this->get_text_x_inline( '%s cannot run without %s.', 'addonX cannot run without pluginY', 'addon-x-cannot-run-without-y' ), $this->get_plugin_name(), $parent_name ) : sprintf( $this->get_text_x_inline( '%s cannot run without the plugin.', 'addonX cannot run...', 'addon-x-cannot-run-without-parent' ), $this->get_plugin_name() ) ), $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...', 'error' ); return; } else { $is_network_admin = fs_is_network_admin(); if ( ! $this->_parent->is_registered() && $this->is_registered() ) { // If add-on activated and parent not, automatically install parent for the user. $this->activate_parent_account( $this->_parent ); } else if ( $this->_parent->is_registered() && ! $this->is_registered() && /** * If not registered for add-on and the following conditions for the add-on are met, activate add-on account. * * Network active and in network admin - network activate add-on account. * * Network active and not in network admin - activate add-on account for the current blog. * * Not network active and not in network admin - activate add-on account for the current blog. * * If not registered for add-on, not network active, and in network admin, do not handle the add-on activation. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ ( $this->is_network_active() || ! $is_network_admin ) ) { $premium_license = null; if ( ! $this->has_free_plan() && $this->is_bundle_license_auto_activation_enabled() && $this->_parent->is_activated_with_bundle_license() ) { /** * If the add-on has no free plan, try to activate the account only when there's a bundle license. * * @author Leo Fajardo (@leorw) * @since 2.4.0 */ $bundle_license = $this->get_active_parent_license( $this->_parent->_get_license()->secret_key, false ); if ( is_object( $bundle_license ) && ! empty( $bundle_license->products ) && in_array( $this->get_id(), $bundle_license->products ) ) { $premium_license = $bundle_license; } } if ( $this->has_free_plan() || is_object( $premium_license) ) { // If parent plugin activated, automatically install add-on for the user. $this->_activate_addon_account( $this->_parent, ( $this->is_network_active() && $is_network_admin ) ? true : get_current_blog_id(), $premium_license ); } } // @todo This should be only executed on activation. It should be migrated to register_activation_hook() together with other activation related logic. if ( $this->is_premium() ) { // Remove add-on download admin-notice. $this->_parent->_admin_notices->remove_sticky( array( 'addon_plan_upgraded_' . $this->_slug, 'no_addon_license_' . $this->_slug, ) ); } // $this->deactivate_premium_only_addon_without_license(); } } add_action( 'admin_init', array( &$this, '_admin_init_action' ) ); // if ( $this->is_registered() || // $this->is_anonymous() || // $this->is_pending_activation() // ) { // $this->_init_admin(); // } } /** * Should be called outside `$this->is_user_in_admin()` scope * because the updater has some logic that needs to be executed * during AJAX calls. * * Currently, we need to hook to the `http_request_host_is_external` filter. * In the future, there might be additional logic added. * * @author Vova Feldman * @since 1.2.1.6 */ if ( $this->should_use_freemius_updater_and_dialog() && ( $this->is_premium() || /** * If not premium but the premium version is installed, also instantiate the updater so that the * plugin information dialog of the premium version will have the information from the server. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ ( file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $this->premium_plugin_basename() ) ) ) ) && $this->has_release_on_freemius() && ( ! $this->is_unresolved_clone( true ) ) ) { FS_Plugin_Updater::instance( $this ); } $this->do_action( 'initiated' ); if ( $this->_storage->prev_is_premium !== $this->_plugin->is_premium ) { if ( isset( $this->_storage->prev_is_premium ) ) { $this->apply_filters( 'after_code_type_change', // New code type. $this->_plugin->is_premium ); } else { // Set for code type for the first time. $this->_storage->prev_is_premium = $this->_plugin->is_premium; } } if ( ! $this->is_addon() ) { if ( $this->is_registered() ) { // Fix for upgrade from versions < 1.0.9. if ( ! isset( $this->_storage->activation_timestamp ) ) { $this->_storage->activation_timestamp = WP_FS__SCRIPT_START_TIME; } $this->do_action( 'after_init_plugin_registered' ); } else if ( $this->is_anonymous() ) { $this->do_action( 'after_init_plugin_anonymous' ); } else if ( $this->is_pending_activation() ) { $this->do_action( 'after_init_plugin_pending_activations' ); } } else { if ( $this->is_registered() ) { $this->do_action( 'after_init_addon_registered' ); } else if ( $this->is_anonymous() ) { $this->do_action( 'after_init_addon_anonymous' ); } else if ( $this->is_pending_activation() ) { $this->do_action( 'after_init_addon_pending_activations' ); } } } /** * @author Leo Fajardo (@leorw) * @since 2.2.3 * * @return bool */ private function should_use_freemius_updater_and_dialog() { return ( /** * Allow updater and dialog when the `fs_allow_updater_and_dialog` URL query param exists and has `true` * value, or when the current page is not the "Add Plugins" page (/plugin-install.php) and the `action` * URL query param doesn't exist or its value is not `install-plugin` so that there will be no conflicts * with the .org plugins' functionalities (e.g. installation from the "Add Plugins" page and viewing * plugin details from .org). */ ( true === fs_request_get_bool( 'fs_allow_updater_and_dialog' ) ) || ( ! self::is_plugin_install_page() && // Disallow updater and dialog when installing a plugin, otherwise .org "add-on" plugins will be affected. ( 'install-plugin' !== fs_request_get( 'action' ) ) ) ); } /** * @param string[] $permissions * @param bool $is_enabled * @param int|null $blog_id * * @return true|object `true` on success, API error object on failure. */ private function update_site_permissions( array $permissions, $is_enabled, $blog_id = null ) { $this->_logger->entrance(); $params = array( 'permissions' => implode( ',', $permissions ), 'is_enabled' => $is_enabled, ); $current_blog_id = get_current_blog_id(); $is_blog_switched = false; if ( is_numeric( $blog_id ) && $current_blog_id != $blog_id ) { $is_blog_switched = $this->switch_to_blog( $blog_id ); } $result = $this->api_site_call( '/permissions.json', 'put', $params ); if ( $is_blog_switched ) { $this->switch_to_blog( $current_blog_id ); } if ( ! $this->is_api_result_object( $result ) || ! isset( $result->install_id ) ) { $this->_logger->api_error( $result ); return $result; } return true; } /** * @param string[] $permissions * @param bool $is_enabled * @param bool $has_site_delegated_connection * * @return true|object `true` on success, API error object on failure. */ private function update_network_permissions( array $permissions, $is_enabled, &$has_site_delegated_connection ) { $this->_logger->entrance(); $install_id_2_blog_id = array(); $install_by_blog_id = $this->get_blog_install_map(); $has_site_delegated_connection = false; foreach ( $install_by_blog_id as $blog_id => $install ) { if ( $this->is_site_delegated_connection( $blog_id ) ) { // Only update permissions of non-delegated installs. $has_site_delegated_connection = true; continue; } $install_id_2_blog_id[ $install->id ] = $blog_id; } if ( empty( $install_id_2_blog_id ) ) { return true; } $params = array( 'permissions' => implode( ',', $permissions ), 'is_enabled' => $is_enabled, 'install_ids' => implode( ',', array_keys( $install_id_2_blog_id ) ), ); // Send update to FS. $result = $this->get_current_or_network_user_api_scope()->call( "/plugins/{$this->_module_id}/installs/permissions.json", 'put', $params ); if ( ! $this->is_api_result_object( $result, 'installs_metadata' ) ) { $this->_logger->api_error( $result ); return $result; } return true; } /** * @param mixed $result * * @return string */ private function get_api_error_message( $result ) { $error_message = sprintf( $this->get_text_inline( 'There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn\'t work, contact the %s\'s author with the following:', 'unexpected-api-error' ), $this->_module_type ) . ' '; if ( $this->is_api_error( $result ) && isset( $result->error ) ) { $code = empty( $result->error->code ) ? '' : " Code: {$result->error->code}"; $error_message .= "{$result->error->message}{$code}"; } else { $error_message .= var_export( $result, true ); } return $error_message; } /** * @author Vova Feldman (@svovaf) * @since 2.5.1 */ function _toggle_permission_tracking_callback() { $this->_logger->entrance(); $this->check_ajax_referer( 'toggle_permission_tracking' ); if ( ! $this->is_registered( true ) ) { self::shoot_ajax_failure( 'User never opted-in.' ); } $is_enabled = fs_request_get_bool( 'is_enabled' ); $permissions = fs_request_get( 'permissions' ); if ( ! is_string( $permissions ) ) { self::shoot_ajax_failure( 'The permissions param must be a string.' ); } $permissions = explode( ',', $permissions ); $result = $this->toggle_permission_tracking( $permissions, $is_enabled ); if ( true !== $result ) { self::shoot_ajax_failure( $this->get_api_error_message( $result ) ); } self::shoot_ajax_success(); } /** * @param string[] $permissions * @param bool $is_enabled * @param int|null $blog_id * * @return bool|mixed `true` if updated successfully or no update is needed. */ private function toggle_permission_tracking( $permissions, $is_enabled, $blog_id = null ) { if ( ! $this->is_registered( true ) ) { // User never opted-in. return false; } // Check if permissions are already set as needed. if ( FS_Permission_Manager::instance( $this )->are_permissions( $permissions, $is_enabled, $blog_id ) ) { /** * Note: * When running on the network admin, there's no need to iterate through all the installs individually since network opt-in permissions are managed for ALL non-delegated installs through a single option (per permission) on the network-level storage. */ return true; } $api_managed_permissions = array_intersect( $permissions, FS_Permission_Manager::get_api_managed_permission_ids() ); if ( in_array( FS_Permission_Manager::PERMISSION_ESSENTIALS, $permissions ) && ! in_array( FS_Permission_Manager::PERMISSION_SITE, $permissions ) ) { $api_managed_permissions[] = FS_Permission_Manager::PERMISSION_SITE; } if ( ! empty( $api_managed_permissions ) ) { $has_site_delegated_connection = false; if ( ! $is_enabled && ! in_array( FS_Permission_Manager::PERMISSION_EXTENSIONS, $api_managed_permissions ) && false === FS_Permission_Manager::instance( $this )->is_extensions_tracking_allowed( $blog_id ) ) { /** * If we are turning off a permission and the extensions permission is off too, enrich the permissions update request to also turn off extensions tracking, as currently when opting in with extensions tracking disabled the extensions tracking is off but the API isn't aware of it. * * @todo Remove this entire `if` after implementing granular opt-in that also sends the permissions to the API when opting in. */ $api_managed_permissions[] = FS_Permission_Manager::PERMISSION_EXTENSIONS; } if ( is_null( $blog_id ) && fs_is_network_admin() ) { $result = $this->update_network_permissions( $api_managed_permissions, $is_enabled, $has_site_delegated_connection ); } else { $result = $this->update_site_permissions( $api_managed_permissions, $is_enabled, $blog_id ); } if ( true !== $result ) { return $result; } if ( in_array( FS_Permission_Manager::PERMISSION_SITE, $api_managed_permissions ) ) { if ( $is_enabled ) { $this->schedule_sync_cron(); } else { $this->clear_sync_cron( ! $has_site_delegated_connection ); } } if ( in_array( FS_Permission_Manager::PERMISSION_USER, $api_managed_permissions ) ) { $this->toggle_user_permission( $is_enabled, $blog_id ); } } $this->update_tracking_permissions( $permissions, $is_enabled, $blog_id ); return true; } /** * @param bool $is_enabled * @param int|null $blog_id */ private function toggle_user_permission( $is_enabled, $blog_id = null ) { $network_or_blog_ids = is_numeric( $blog_id ) ? $blog_id : fs_is_network_admin(); if ( $is_enabled ) { $this->reset_anonymous_mode( $network_or_blog_ids ); } else { $this->skip_connection( $network_or_blog_ids ); } } /** * Opt-in back into usage tracking. * * Note: This will only work if the user opted-in previously. * * Returns: * 1. FALSE - If the user never opted-in. * 2. TRUE - If successfully opted-in back to usage tracking. * 3. object - API result on failure. * * @author Leo Fajardo (@leorw) * @since 1.2.1.5 * * @bool $is_enabled * * @return bool|object */ private function toggle_site_tracking( $is_enabled, $blog_id = null ) { $this->_logger->entrance(); return $this->toggle_permission_tracking( FS_Permission_Manager::instance( $this )->get_site_tracking_permission_names(), $is_enabled, $blog_id ); } /** * If user opted-in and later disabled usage-tracking, * re-allow tracking for licensing and updates. * * @author Leo Fajardo (@leorw) * @since 1.2.1.5 * * @param bool $is_context_single_site */ private function reconnect_locally( $is_context_single_site = false ) { $this->_logger->entrance(); if ( ! $this->is_registered() ) { return; } if ( ! fs_is_network_admin() || $is_context_single_site ) { if ( $this->is_tracking_prohibited() ) { FS_Permission_Manager::instance( $this )->update_site_tracking( true ); } } else { $installs_map = $this->get_blog_install_map(); foreach ( $installs_map as $blog_id => $install ) { /** * @var FS_Site $install */ if ( ! $this->is_tracking_allowed( $blog_id, $install ) ) { FS_Permission_Manager::instance( $this )->update_site_tracking( true, $blog_id ); } } } } /** * Update permission tracking flags. When updating in a network context, in addition to updating the network-level flags, also update the permissions on the site-level for all non-delegated sites. * * @param string[] $permissions * @param bool $is_enabled * @param int|null $blog_id * * @return array */ private function update_tracking_permissions( $permissions, $is_enabled, $blog_id = null ) { // Alias. $permission_manager = FS_Permission_Manager::instance( $this ); $network_or_blog_ids = is_numeric( $blog_id ) ? $blog_id : fs_is_network_admin(); if ( true === $network_or_blog_ids ) { // Update the permission for all non-delegated sub-sites. $blog_ids = $this->get_non_delegated_blog_ids(); // Add the network-level to the array, to update the permission on the network-level storage. array_unshift( $blog_ids, null ); } else { if ( false === $network_or_blog_ids ) { $network_or_blog_ids = null; } $blog_ids = is_array( $network_or_blog_ids ) ? $network_or_blog_ids : array( $network_or_blog_ids ); } $result = array(); foreach ( $permissions as $permission ) { $permission = trim( $permission ); $is_permission_supported = true; foreach ( $blog_ids as $id ) { $is_permission_supported = $permission_manager->update_permission_tracking_flag( $permission, $is_enabled, $id ); } if ( ! $is_permission_supported ) { $permission = 'no_match'; } $result[ $permission ] = $is_enabled; } return $result; } /** * Parse plugin's settings (as defined by the plugin dev). * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @param array $plugin_info * * @throws \Freemius_Exception */ private function parse_settings( &$plugin_info ) { $this->_logger->entrance(); $id = $this->get_numeric_option( $plugin_info, 'id', false ); $public_key = $this->get_option( $plugin_info, 'public_key', false ); $secret_key = $this->get_option( $plugin_info, 'secret_key', null ); $parent_id = $this->get_numeric_option( $plugin_info, 'parent_id', null ); $parent_name = $this->get_option( $plugin_info, 'parent_name', null ); /** * @author Vova Feldman (@svovaf) * @since 1.1.9 Try to pull secret key from external config. */ if ( is_null( $secret_key ) && defined( "WP_FS__{$this->_slug}_SECRET_KEY" ) ) { $secret_key = constant( "WP_FS__{$this->_slug}_SECRET_KEY" ); } if ( isset( $plugin_info['parent'] ) ) { $parent_id = $this->get_numeric_option( $plugin_info['parent'], 'id', null ); // $parent_slug = $this->get_option( $plugin_info['parent'], 'slug', null ); // $parent_public_key = $this->get_option( $plugin_info['parent'], 'public_key', null ); // $parent_name = $this->get_option( $plugin_info['parent'], 'name', null ); } if ( false === $id ) { throw new Freemius_Exception( array( 'error' => array( 'type' => 'ParameterNotSet', 'message' => 'Plugin id parameter is not set.', 'code' => 'plugin_id_not_set', 'http' => 500, ) ) ); } if ( false === $public_key ) { throw new Freemius_Exception( array( 'error' => array( 'type' => 'ParameterNotSet', 'message' => 'Plugin public_key parameter is not set.', 'code' => 'plugin_public_key_not_set', 'http' => 500, ) ) ); } $plugin = ( $this->_plugin instanceof FS_Plugin ) ? $this->_plugin : new FS_Plugin(); $premium_suffix = $this->get_option( $plugin_info, 'premium_suffix', '(Premium)' ); $plugin->update( array( 'id' => $id, 'type' => $this->get_option( $plugin_info, 'type', $this->_module_type ), 'public_key' => $public_key, 'slug' => $this->_slug, 'premium_slug' => $this->get_option( $plugin_info, 'premium_slug', "{$this->_slug}-premium" ), 'parent_plugin_id' => $parent_id, 'version' => $this->get_plugin_version(), 'title' => $this->get_plugin_name( $premium_suffix ), 'file' => $this->_plugin_basename, 'is_premium' => $this->get_bool_option( $plugin_info, 'is_premium', true ), 'premium_suffix' => $premium_suffix, 'is_live' => $this->get_bool_option( $plugin_info, 'is_live', true ), 'affiliate_moderation' => $this->get_option( $plugin_info, 'has_affiliation' ), 'bundle_id' => $this->get_option( $plugin_info, 'bundle_id', null ), 'bundle_public_key' => $this->get_option( $plugin_info, 'bundle_public_key', null ), 'opt_in_moderation' => $this->get_option( $plugin_info, 'opt_in', null ), ) ); if ( $plugin->is_updated() ) { // Update plugin details. $this->_plugin = FS_Plugin_Manager::instance( $this->_module_id )->store( $plugin ); } // Set the secret key after storing the plugin, we don't want to store the key in the storage. $this->_plugin->secret_key = $secret_key; /** * If the product is network integrated and activated and the current view is in the network level Admin dashboard, if the product's network-level menu located differently from the sub-site level, then use the network menu details (when set). * * @author Vova Feldman * @since 2.4.5 */ if ( $this->is_network_active() && fs_is_network_admin() ) { if ( isset( $plugin_info['menu_network'] ) && is_array( $plugin_info['menu_network'] ) && ! empty( $plugin_info['menu_network'] ) ) { $plugin_info['menu'] = $plugin_info['menu_network']; } } if ( ! isset( $plugin_info['menu'] ) ) { $plugin_info['menu'] = array(); if ( ! empty( $this->_storage->sdk_last_version ) && version_compare( $this->_storage->sdk_last_version, '1.1.2', '<=' ) ) { // Backward compatibility to 1.1.2 $plugin_info['menu']['slug'] = isset( $plugin_info['menu_slug'] ) ? $plugin_info['menu_slug'] : $this->_slug; } } $this->_menu = FS_Admin_Menu_Manager::instance( $this->_module_id, $this->_module_type, $this->get_unique_affix() ); $this->_menu->init( $plugin_info['menu'], $this->is_addon() ); $this->_has_addons = $this->get_bool_option( $plugin_info, 'has_addons', false ); $this->_has_paid_plans = $this->get_bool_option( $plugin_info, 'has_paid_plans', true ); $this->_has_premium_version = $this->get_bool_option( $plugin_info, 'has_premium_version', $this->_has_paid_plans ); $this->_ignore_pending_mode = $this->get_bool_option( $plugin_info, 'ignore_pending_mode', false ); $this->_is_org_compliant = $this->get_bool_option( $plugin_info, 'is_org_compliant', true ); $this->_is_premium_only = $this->get_bool_option( $plugin_info, 'is_premium_only', false ); if ( $this->_is_premium_only ) { // If premium only plugin, disable anonymous mode. $this->_enable_anonymous = false; $this->_anonymous_mode = false; } else { $this->_enable_anonymous = $this->get_bool_option( $plugin_info, 'enable_anonymous', true ); $this->_anonymous_mode = $this->get_bool_option( $plugin_info, 'anonymous_mode', false ); } $this->_permissions = $this->get_option( $plugin_info, 'permissions', array() ); $this->_is_bundle_license_auto_activation_enabled = $this->get_option( $plugin_info, 'bundle_license_auto_activation', false ); if ( ! empty( $plugin_info['trial'] ) ) { $this->_trial_days = $this->get_numeric_option( $plugin_info['trial'], 'days', // Default to 0 - trial without days specification. 0 ); $this->_is_trial_require_payment = $this->get_bool_option( $plugin_info['trial'], 'is_require_payment', false ); } $this->_navigation = $this->get_option( $plugin_info, 'navigation', $this->is_free_wp_org_theme() ? self::NAVIGATION_TABS : self::NAVIGATION_MENU ); } /** * @param string[] $options * @param string $key * @param mixed $default * * @return bool */ private function get_option( &$options, $key, $default = false ) { return ! empty( $options[ $key ] ) ? $options[ $key ] : $default; } private function get_bool_option( &$options, $key, $default = false ) { return isset( $options[ $key ] ) && is_bool( $options[ $key ] ) ? $options[ $key ] : $default; } private function get_numeric_option( &$options, $key, $default = false ) { return isset( $options[ $key ] ) && is_numeric( $options[ $key ] ) ? $options[ $key ] : $default; } /** * Gate keeper. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @return bool */ private function should_stop_execution() { if ( empty( $this->_storage->was_plugin_loaded ) ) { /** * Don't execute Freemius until plugin was fully loaded at least once, * to give the opportunity for the activation hook to run before pinging * the API for connectivity test. This logic is relevant for the * identification of new plugin install vs. plugin update. * * @author Vova Feldman (@svovaf) * @since 1.1.9 */ return true; } if ( $this->is_activation_mode() ) { if ( ! is_admin() ) { /** * If in activation mode, don't execute Freemius outside the admin dashboard. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 */ return true; } if ( ! WP_FS__IS_HTTP_REQUEST ) { /** * If in activation and executed without HTTP context (e.g. CLI, Cronjob), * then don't start Freemius. * * @author Vova Feldman (@svovaf) * @since 1.1.6.3 * * @link https://wordpress.org/support/topic/errors-in-the-freemius-class-when-running-in-wordpress-in-cli */ return true; } if ( self::is_cron() ) { /** * If in activation mode, don't execute Freemius during wp crons * (wp crons have HTTP context - called as HTTP request). * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 */ return true; } if ( self::is_ajax() ) { /** * During activation, if running in AJAX mode, unless there's a sticky * connectivity issue notice, don't run Freemius. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 */ return true; } } return false; } /** * Triggered after code type has changed. * * @author Vova Feldman (@svovaf) * @since 1.1.9.1 */ function _after_code_type_change() { $this->_logger->entrance(); if ( $this->is_theme() ) { // Expire the cache of the previous tabs since the theme may // have setting updates after code type has changed. $this->_cache->expire( 'tabs' ); $this->_cache->expire( 'tabs_stylesheets' ); } if ( $this->is_registered() ) { if ( ! $this->is_addon() ) { add_action( is_admin() ? 'admin_init' : 'init', array( &$this, '_plugin_code_type_changed' ) ); } if ( $this->is_premium() ) { // Purge cached payments after switching to the premium version. // @todo This logic doesn't handle purging the cache for serviceware module upgrade. $this->get_api_user_scope()->purge_cache( "/plugins/{$this->_module_id}/payments.json?include_addons=true" ); } } } /** * Handles plugin's code type change (free <--> premium). * * @author Vova Feldman (@svovaf) * @since 1.0.9 */ function _plugin_code_type_changed() { $this->_logger->entrance(); if ( $this->is_premium() ) { $this->reconnect_locally(); // Activated premium code. $this->do_action( 'after_premium_version_activation' ); // Remove all sticky messages related to download of the premium version. $this->_admin_notices->remove_sticky( array( 'trial_started', 'plan_upgraded', 'plan_changed', 'license_activated', ) ); $notice = ''; if ( ! $this->is_only_premium() ) { $notice = sprintf( $this->get_text_inline( 'Premium %s version was successfully activated.', 'premium-activated-message' ), $this->_module_type ); } $license_notice = $this->get_license_network_activation_notice(); if ( ! empty( $license_notice ) ) { $notice .= ' ' . $license_notice; } if ( ! empty( $notice ) ) { $this->_admin_notices->add_sticky( trim( $notice ), 'premium_activated', $this->get_text_x_inline( 'W00t', 'Used to express elation, enthusiasm, or triumph (especially in electronic communication).', 'woot' ) . '!' ); } } else { // Remove sticky message related to premium code activation. $this->_admin_notices->remove_sticky( 'premium_activated' ); // Activated free code (after had the premium before). $this->do_action( 'after_free_version_reactivation' ); if ( $this->is_paying() && ! $this->is_premium() ) { $this->add_complete_upgrade_instructions_notice( sprintf( /* translators: %s: License type (e.g. you have a professional license) */ $this->get_text_inline( 'You have a %s license.', 'you-have-x-license' ), $this->get_plan_title() ), 'plan_upgraded' ); } } // Schedule code type changes event. $this->schedule_install_sync(); /** * Unregister the uninstall hook for the other version of the plugin (with different code type) to avoid * triggering a fatal error when uninstalling that plugin. For example, after deactivating the "free" version * of a specific plugin, its uninstall hook should be unregistered after the "premium" version has been * activated. If we don't do that, a fatal error will occur when we try to uninstall the "free" version since * the main file of the "free" version will be loaded first before calling the hooked callback. Since the * free and premium versions are almost identical (same class or have same functions), a fatal error like * "Cannot redeclare class MyClass" or "Cannot redeclare my_function()" will occur. */ $this->unregister_uninstall_hook(); $this->clear_module_main_file_cache(); // Update is_premium of latest version. $this->_storage->prev_is_premium = $this->_plugin->is_premium; } #endregion #---------------------------------------------------------------------------------- #region Add-ons #---------------------------------------------------------------------------------- /** * Check if add-on installed and activated on site. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param string|number $id_or_slug * @param bool|null $is_premium Since 1.2.1.7 can check for specified add-on version. * * @return bool */ function is_addon_activated( $id_or_slug, $is_premium = null ) { $this->_logger->entrance(); $addon_id = self::get_module_id( $id_or_slug ); $is_activated = self::has_instance( $addon_id ); if ( ! $is_activated ) { return false; } if ( is_bool( $is_premium ) ) { // Check if the specified code version is activate. $addon = $this->get_addon_instance( $addon_id ); $is_activated = ( $is_premium === $addon->is_premium() ); } return $is_activated; } /** * Check if add-on was connected to install * * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @param string|number $id_or_slug * * @return bool */ function is_addon_connected( $id_or_slug ) { $this->_logger->entrance(); $sites = self::get_all_sites( WP_FS__MODULE_TYPE_PLUGIN ); $addon_id = self::get_module_id( $id_or_slug ); $addon = $this->get_addon( $addon_id ); $slug = $addon->slug; if ( ! isset( $sites[ $slug ] ) ) { return false; } $site = $sites[ $slug ]; $plugin = FS_Plugin_Manager::instance( $addon_id )->get(); if ( $plugin->parent_plugin_id != $this->_plugin->id ) { // The given slug do NOT belong to any of the plugin's add-ons. return false; } return ( is_object( $site ) && is_numeric( $site->id ) && is_numeric( $site->user_id ) && FS_Plugin_Plan::is_valid_id( $site->plan_id ) ); } /** * Determines if add-on installed. * * NOTE: This is a heuristic and only works if the folder/file named as the slug. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param string|number $id_or_slug * * @return bool */ function is_addon_installed( $id_or_slug ) { $this->_logger->entrance(); $addon_id = self::get_module_id( $id_or_slug ); return file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $this->get_addon_basename( $addon_id ) ) ); } /** * Get add-on basename. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param string|number $id_or_slug * * @return string */ function get_addon_basename( $id_or_slug ) { $addon_id = self::get_module_id( $id_or_slug ); if ( $this->is_addon_activated( $addon_id ) ) { return self::instance( $addon_id )->get_plugin_basename(); } $addon = $this->get_addon( $addon_id ); $premium_basename = "{$addon->premium_slug}/{$addon->slug}.php"; if ( file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $premium_basename ) ) ) { return $premium_basename; } $all_plugins = $this->get_all_plugins(); foreach ( $all_plugins as $basename => $data ) { if ( $addon->slug === $data['slug'] || $addon->premium_slug === $data['slug'] ) { return $basename; } } $free_basename = "{$addon->slug}/{$addon->slug}.php"; return $free_basename; } /** * Get installed add-ons instances. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return Freemius[] */ function get_installed_addons() { if ( $this->is_addon() ) { // Add-on cannot have add-ons. return array(); } $installed_addons = array(); foreach ( self::$_instances as $instance ) { if ( $instance->is_addon_of( $this->_plugin->id ) ) { $installed_addons[] = $instance; } } return $installed_addons; } /** * Check if any add-ons of the plugin are installed. * * @author Leo Fajardo (@leorw) * @since 1.1.1 * * @return bool */ function has_installed_addons() { if ( ! $this->has_addons() ) { return false; } foreach ( self::$_instances as $instance ) { if ( $instance->is_addon() && is_object( $instance->_parent_plugin ) ) { if ( $this->_plugin->id == $instance->_parent_plugin->id ) { return true; } } } return false; } /** * Tell Freemius that the current plugin is an add-on. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param number $parent_plugin_id The parent plugin ID */ function init_addon( $parent_plugin_id ) { $this->_plugin->parent_plugin_id = $parent_plugin_id; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return bool */ function is_addon() { return ( isset( $this->_plugin->parent_plugin_id ) && is_numeric( $this->_plugin->parent_plugin_id ) ); } /** * @author Vova Feldman (@svovaf) * @since 2.3.2 * * @param number $parent_product_id * * @return bool */ function is_addon_of( $parent_product_id ) { return ( $this->is_addon() && $parent_product_id == $this->_plugin->parent_plugin_id ); } /** * Deactivate add-on if it's premium only and the user does't have a valid license. * * @param bool $is_after_trial_cancel * * @return bool If add-on was deactivated. */ private function deactivate_premium_only_addon_without_license( $is_after_trial_cancel = false ) { if ( ! $this->has_free_plan() && ! $this->has_features_enabled_license() && ! $this->_has_premium_license() ) { if ( $this->is_registered() ) { // IF wrapper is turned off because activation_timestamp is currently only stored for plugins (not addons). // if (empty($this->_storage->activation_timestamp) || // (WP_FS__SCRIPT_START_TIME - $this->_storage->activation_timestamp) > 30 // ) { /** * @todo When it's first fail, there's no reason to try and re-sync because the licenses were just synced after initial activation. * * Retry syncing the user add-on licenses. */ // Sync licenses. $this->_sync_licenses(); // } // Try to activate premium license. $this->_activate_license( true ); } if ( ! $this->has_free_plan() && ! $this->has_features_enabled_license() && ! $this->_has_premium_license() ) { // @todo Check if deactivate plugins also call the deactivation hook. $this->_parent->_admin_notices->add_sticky( sprintf( ( $is_after_trial_cancel ? $this->_parent->get_text_inline( '%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you\'ll have to purchase a license.', 'addon-trial-cancelled-message' ) : $this->_parent->get_text_inline( '%s is a premium only add-on. You have to purchase a license first before activating the plugin.', 'addon-no-license-message' ) ), '' . $this->_plugin->title . '' ) . ' ' . sprintf( '%s  ➜', $this->_parent->addon_url( $this->_slug ), esc_attr( sprintf( $this->_parent->get_text_inline( 'More information about %s', 'more-information-about-x' ), $this->_plugin->title ) ), $this->_parent->get_text_inline( 'Purchase License', 'purchase-license' ) ), 'no_addon_license_' . $this->_slug, ( $is_after_trial_cancel ? '' : $this->_parent->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...' ), ( $is_after_trial_cancel ? 'success' : 'error' ) ); deactivate_plugins( array( $this->_plugin_basename ), true ); return true; } } return false; } #endregion #---------------------------------------------------------------------------------- #region Sandbox #---------------------------------------------------------------------------------- /** * Set Freemius into sandbox mode for debugging. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param string $secret_key */ function init_sandbox( $secret_key ) { $this->_plugin->secret_key = $secret_key; // Update plugin details. FS_Plugin_Manager::instance( $this->_module_id )->update( $this->_plugin, true ); } /** * Check if running payments in sandbox mode. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @return bool */ function is_payments_sandbox() { return ( ! $this->is_live() ) || isset( $this->_plugin->secret_key ); } #endregion /** * Check if running test vs. live plugin. * * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @return bool */ function is_live() { return $this->_plugin->is_live; } /** * Check if super-admin skipped connection for all sites in the network. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function is_network_anonymous() { if ( ! $this->_is_network_active ) { return false; } $is_anonymous_ms = $this->_storage->get( 'is_anonymous_ms' ); if ( empty( $is_anonymous_ms ) ) { return false; } return $is_anonymous_ms['is']; } /** * Check if super-admin opted-in for all sites in the network. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function is_network_connected() { if ( ! $this->_is_network_active ) { return false; } return $this->_storage->get( 'is_network_connected' ); } /** * Check if the user skipped connecting the account with Freemius. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return bool */ function is_anonymous() { if ( ! isset( $this->_is_anonymous ) ) { if ( $this->is_network_anonymous() ) { $this->_is_anonymous = true; } else if ( fs_is_network_admin() ) { /** * When not-network-anonymous, yet, running in the network admin, consider as anonymous only when ALL non-delegated sites are set to anonymous. */ $non_delegated_sites = $this->get_non_delegated_blog_ids(); foreach ( $non_delegated_sites as $blog_id ) { $is_anonymous = $this->_storage->get( 'is_anonymous', false, $blog_id ); if ( empty( $is_anonymous ) || false === $is_anonymous[ 'is' ] ) { $this->_is_anonymous = false; break; } } if ( false !== $this->_is_anonymous ) { $this->_is_anonymous = true; } } else { if ( ! isset( $this->_storage->is_anonymous ) ) { // Not skipped. $this->_is_anonymous = false; } else if ( is_bool( $this->_storage->is_anonymous ) ) { // For back compatibility, since the variable was boolean before. $this->_is_anonymous = $this->_storage->is_anonymous; // Upgrade stored data format to 1.1.3 format. $this->set_anonymous_mode( $this->_storage->is_anonymous ); } else { // Version 1.1.3 and later. $this->_is_anonymous = $this->_storage->is_anonymous['is']; } } } return $this->_is_anonymous; } /** * Check if the user skipped the connection of a specified site. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id * * @return bool */ function is_anonymous_site( $blog_id = 0 ) { if ( $this->is_network_anonymous() ) { return true; } $is_anonymous = $this->_storage->get( 'is_anonymous', false, $blog_id ); if ( empty( $is_anonymous ) ) { return false; } return $is_anonymous['is']; } /** * Check if user connected his account and install pending email activation. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return bool */ function is_pending_activation() { return $this->_storage->get( 'is_pending_activation', false ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ private function clear_pending_activation_mode() { // Remove the pending activation sticky notice (if it still exists). $this->_admin_notices->remove_sticky( 'activation_pending' ); // Clear the plugin's pending activation mode. unset( $this->_storage->is_pending_activation ); } /** * Check if plugin must be WordPress.org compliant. * * @since 1.0.7 * * @return bool */ function is_org_repo_compliant() { return $this->_is_org_compliant; } #-------------------------------------------------------------------------------- #region WP Cron Common #-------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * * @return object */ private function get_cron_data( $name ) { $this->_logger->entrance( $name ); /** * @var object $cron_data */ return $this->_storage->get( "{$name}_cron", null ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. */ private function clear_cron_data( $name ) { $this->_logger->entrance( $name ); $this->_storage->remove( "{$name}_cron" ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * @param int $cron_blog_id The cron executing blog ID. */ private function set_cron_data( $name, $cron_blog_id = 0 ) { $this->_logger->entrance( $name ); $this->_storage->store( "{$name}_cron", (object) array( 'version' => $this->get_plugin_version(), 'blog_id' => $cron_blog_id, 'sdk_version' => $this->version, 'timestamp' => WP_FS__SCRIPT_START_TIME, 'on' => true, ) ); } /** * Get the cron's executing blog ID. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * * @return int */ private function get_cron_blog_id( $name ) { $this->_logger->entrance( $name ); if ( ! is_multisite() ) { // Not a multisite. return 0; } $cron_data = $this->get_cron_data( $name ); return ( is_object( $cron_data ) && is_numeric( $cron_data->blog_id ) ) ? $cron_data->blog_id : 0; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * * @return bool */ private function is_cron_on( $name ) { $this->_logger->entrance( $name ); /** * @var object $cron_data */ $cron_data = $this->get_cron_data( $name ); return ( ! is_null( $cron_data ) && true === $cron_data->on ); } /** * Unix timestamp for previous cron execution or false if never executed. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * * @return int|false */ private function cron_last_execution( $name ) { $this->_logger->entrance( $name ); return $this->_storage->get( "{$name}_timestamp" ); } /** * Set cron execution time to now. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. */ private function set_cron_execution_timestamp( $name ) { $this->_logger->entrance( $name ); $this->_storage->store( "{$name}_timestamp", time() ); } /** * Sets the keepalive time to now. * * @author Leo Fajardo (@leorw) * @since 2.2.3 * * @param bool|null $use_network_level_storage */ private function set_keepalive_timestamp( $use_network_level_storage = null ) { $this->_logger->entrance(); $this->_storage->store( 'keepalive_timestamp', time(), $use_network_level_storage ); } /** * Check if cron was executed in the last $period of seconds. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * @param int $period In seconds * * @return bool */ private function is_cron_executed( $name, $period = WP_FS__TIME_24_HOURS_IN_SEC ) { $this->_logger->entrance( $name ); $last_execution = $this->cron_last_execution( $name ); if ( ! is_numeric( $last_execution ) ) { return false; } return ( $last_execution > ( WP_FS__SCRIPT_START_TIME - $period ) ); } /** * WP Cron is executed on a site level. When running in a multisite network environment * with the network integration activated, for optimization reasons, we are consolidating * the installs data sync cron to be executed only from a single site. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $except_blog_id Target any except the excluded blog ID. * * @return int */ private function get_cron_target_blog_id( $except_blog_id = 0 ) { if ( ! is_multisite() ) { return 0; } if ( $this->_is_network_active ) { $network_install_blog_id = $this->_storage->network_install_blog_id; if ( is_numeric( $network_install_blog_id ) && $except_blog_id != $network_install_blog_id && self::is_site_active( $network_install_blog_id ) ) { // Try to run cron from the main network blog. $install = $this->get_install_by_blog_id( $network_install_blog_id ); if ( is_object( $install ) && $this->is_tracking_allowed( $network_install_blog_id, $install ) ) { return $network_install_blog_id; } } } // Get first opted-in blog ID with active tracking. $installs = $this->get_blog_install_map(); foreach ( $installs as $blog_id => $install ) { if ( $except_blog_id != $blog_id && self::is_site_active( $blog_id ) && $this->is_tracking_allowed( $blog_id, $install ) ) { return $blog_id; } } return 0; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * @param string $action_tag Callback action tag. * @param bool $is_network_clear If set to TRUE, clear sync cron even if there are installs that are still connected. */ private function clear_cron( $name, $action_tag = '', $is_network_clear = false ) { $this->_logger->entrance( $name ); if ( ! $this->is_cron_on( $name ) ) { return; } $clear_cron = true; if ( ! $is_network_clear && $this->_is_network_active ) { $installs = $this->get_blog_install_map(); foreach ( $installs as $blog_id => $install ) { /** * @var FS_Site $install */ if ( $this->is_tracking_allowed( $blog_id, $install ) ) { $clear_cron = false; break; } } } if ( ! $clear_cron ) { return; } $cron_blog_id = $this->get_cron_blog_id( $name ); $this->clear_cron_data( $name ); if ( 0 < $cron_blog_id ) { switch_to_blog( $cron_blog_id ); } if ( empty( $action_tag ) ) { $action_tag = $name; } wp_clear_scheduled_hook( $this->get_action_tag( $action_tag ) ); if ( 0 < $cron_blog_id ) { restore_current_blog(); } } /** * Unix timestamp for next cron execution or false if not scheduled. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * @param string $action_tag Callback action tag. * * @return int|false */ private function get_next_scheduled_cron( $name, $action_tag = '' ) { $this->_logger->entrance( $name ); if ( ! $this->is_cron_on( $name ) ) { return false; } $cron_blog_id = $this->get_cron_blog_id( $name ); if ( 0 < $cron_blog_id ) { switch_to_blog( $cron_blog_id ); } if ( empty( $action_tag ) ) { $action_tag = $name; } $next_scheduled = wp_next_scheduled( $this->get_action_tag( $action_tag ) ); if ( 0 < $cron_blog_id ) { restore_current_blog(); } return $next_scheduled; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * @param string $action_tag Callback action tag. * @param string $recurrence 'single' or 'daily'. * @param int $start_at Defaults to now. * @param bool $randomize_start If true, schedule first job randomly during the next 12 hours. Otherwise, schedule job to start right away. * @param int $except_blog_id Target any except the excluded blog ID. */ private function schedule_cron( $name, $action_tag = '', $recurrence = 'single', $start_at = WP_FS__SCRIPT_START_TIME, $randomize_start = true, $except_blog_id = 0 ) { $this->_logger->entrance( $name ); $this->clear_cron( $name, $action_tag, true ); $cron_blog_id = $this->get_cron_target_blog_id( $except_blog_id ); if ( is_multisite() && 0 == $cron_blog_id ) { // Don't schedule cron since couldn't find a target blog. return; } if ( 0 < $cron_blog_id ) { switch_to_blog( $cron_blog_id ); } if ( 'daily' === $recurrence ) { if ( $randomize_start ) { // Schedule first sync with a random 12 hour time range from now. $start_at += rand( 0, ( WP_FS__TIME_24_HOURS_IN_SEC / 2 ) ); } // Schedule daily WP cron. wp_schedule_event( $start_at, 'daily', $this->get_action_tag( $action_tag ) ); } else if ( 'single' === $recurrence ) { // Schedule single cron. wp_schedule_single_event( $start_at, $this->get_action_tag( $action_tag ) ); } $this->set_cron_data( $name, $cron_blog_id ); if ( 0 < $cron_blog_id ) { restore_current_blog(); } } /** * Consolidated cron execution for performance optimization. The max number of API requests is based on the number of unique opted-in users. * that doesn't halt page loading. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $name Cron name. * @param callable $callable The function that should be executed. */ private function execute_cron( $name, $callable ) { $this->_logger->entrance( $name ); // Store the last time data sync was executed. $this->set_cron_execution_timestamp( $name ); // Check if API is temporary down. if ( FS_Api::is_temporary_down() ) { return; } // @todo Add logic that identifies API latency, and reschedule the next background sync randomly between 8-16 hours. $users_2_blog_ids = array(); if ( ! is_multisite() ) { // Add dummy blog. $users_2_blog_ids[0] = array( 0 ); } else { $installs = $this->get_blog_install_map(); foreach ( $installs as $blog_id => $install ) { if ( $this->is_tracking_allowed( $blog_id, $install ) ) { if ( ! isset( $users_2_blog_ids[ $install->user_id ] ) ) { $users_2_blog_ids[ $install->user_id ] = array(); } $users_2_blog_ids[ $install->user_id ][] = $blog_id; } } } $current_blog_id = get_current_blog_id(); foreach ( $users_2_blog_ids as $user_id => $blog_ids ) { if ( 0 < $blog_ids[0] ) { $this->switch_to_blog( $blog_ids[0] ); } call_user_func_array( $callable, array( $blog_ids, ( is_multisite() ? $current_blog_id : null ) ) ); foreach ( $blog_ids as $blog_id ) { $this->do_action( "after_{$name}_cron", $blog_id ); } } if ( is_multisite() ) { $this->switch_to_blog( $current_blog_id, fs_is_network_admin() ? $this->get_network_install() : null ); $this->do_action( "after_{$name}_cron_multisite" ); } } #endregion #---------------------------------------------------------------------------------- #region Daily Sync Cron #---------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return bool */ private function is_sync_cron_scheduled() { return $this->is_cron_on( 'sync' ); } /** * Get the sync cron's executing blog ID. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return int */ private function get_sync_cron_blog_id() { return $this->get_cron_blog_id( 'sync' ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.3 */ private function run_manual_sync() { if ( ! $this->is_user_admin() ) { return; } // Run manual sync. $this->_sync_cron(); // Reschedule next cron to run 24 hours from now (performance optimization). $this->schedule_sync_cron( time() + WP_FS__TIME_24_HOURS_IN_SEC, false ); } /** * Data sync cron job. Replaces the background sync non blocking HTTP request * that doesn't halt page loading. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * @since 2.0.0 Consolidate all the data sync into the same cron for performance optimization. The max number of API requests is based on the number of unique opted-in users. */ function _sync_cron() { $this->_logger->entrance(); $this->execute_cron( 'sync', array( &$this, '_sync_cron_method' ) ); } /** * The actual data sync cron logic. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int[] $blog_ids * @param int|null $current_blog_id @since 2.2.3. This is passed from the `execute_cron` method and used by the * `_sync_plugin_license` method in order to switch to the previous blog when sending * updates for a single site in case `execute_cron` has switched to a different blog. */ function _sync_cron_method( array $blog_ids, $current_blog_id = null ) { if ( $this->is_registered() ) { if ( $this->has_paid_plan() ) { // Initiate background plan sync. $this->_sync_license( true, false, $current_blog_id ); if ( $this->is_paying() ) { // Check for premium plugin updates. $this->check_updates( true ); } } else { // Sync install(s) (only if something changed locally). if ( 1 < count( $blog_ids ) ) { $this->sync_installs(); } else { $this->sync_install(); } $this->maybe_sync_install_user(); } } } /** * Check if sync was executed in the last $period of seconds. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @param int $period In seconds * * @return bool */ private function is_sync_executed( $period = WP_FS__TIME_24_HOURS_IN_SEC ) { return $this->is_cron_executed( 'sync', $period ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @return bool */ private function is_sync_cron_on() { return $this->is_cron_on( 'sync' ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ private function maybe_schedule_sync_cron() { $next_schedule = $this->next_sync_cron(); // The event is properly scheduled, so no need to reschedule it. if ( is_numeric( $next_schedule ) && $next_schedule > time() ) { return; } $this->schedule_sync_cron(); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @param int $start_at Defaults to now. * @param bool $randomize_start If true, schedule first job randomly during the next 12 hours. Otherwise, schedule job to start right away. * @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding excluded specified blog ID from being the cron executor. */ private function schedule_sync_cron( $start_at = WP_FS__SCRIPT_START_TIME, $randomize_start = true, $except_blog_id = 0 ) { $this->schedule_cron( 'sync', 'data_sync', 'daily', $start_at, $randomize_start, $except_blog_id ); } /** * Add the actual sync function to the cron job hook. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 */ private function hook_callback_to_sync_cron() { $this->add_action( 'data_sync', array( &$this, '_sync_cron' ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @param bool $is_network_clear Since 2.0.0 If set to TRUE, clear sync cron even if there are installs that are still connected. */ private function clear_sync_cron( $is_network_clear = false ) { $this->_logger->entrance(); $this->clear_cron( 'sync', 'data_sync', $is_network_clear ); } /** * Unix timestamp for next sync cron execution or false if not scheduled. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @return int|false */ function next_sync_cron() { return $this->get_next_scheduled_cron( 'sync', 'data_sync' ); } /** * Unix timestamp for previous sync cron execution or false if never executed. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @return int|false */ function last_sync_cron() { return $this->cron_last_execution( 'sync' ); } #endregion Daily Sync Cron ------------------------------------------------------------------ #---------------------------------------------------------------------------------- #region Async Install Sync #---------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @return bool */ private function is_install_sync_scheduled() { return $this->is_cron_on( 'install_sync' ); } /** * Get the sync cron's executing blog ID. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return int */ private function get_install_sync_cron_blog_id() { return $this->get_cron_blog_id( 'install_sync' ); } /** * Instead of running blocking install sync event, execute non blocking scheduled wp-cron. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @param int $except_blog_id Since 2.0.0 when running in a multisite network environment, the cron execution is consolidated. This param allows excluding excluded specified blog ID from being the cron executor. */ private function schedule_install_sync( $except_blog_id = 0 ) { if ( $this->is_clone() ) { return; } $this->schedule_cron( 'install_sync', 'install_sync', 'single', WP_FS__SCRIPT_START_TIME, false, $except_blog_id ); } /** * Unix timestamp for previous install sync cron execution or false if never executed. * * @todo There's some very strange bug that $this->_storage->install_sync_timestamp value is not being updated. But for sure the sync event is working. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @return int|false */ function last_install_sync() { return $this->cron_last_execution( 'install_sync' ); } /** * Unix timestamp for next install sync cron execution or false if not scheduled. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @return int|false */ function next_install_sync() { return $this->get_next_scheduled_cron( 'install_sync', 'install_sync' ); } /** * Add the actual install sync function to the cron job hook. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 */ private function hook_callback_to_install_sync() { $this->add_action( 'install_sync', array( &$this, '_run_sync_install' ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @param bool $is_network_clear Since 2.0.0 If set to TRUE, clear sync cron even if there are installs that are still connected. */ private function clear_install_sync_cron( $is_network_clear = false ) { $this->_logger->entrance(); $this->clear_cron( 'install_sync', 'install_sync', $is_network_clear ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * @since 2.0.0 Consolidate all the data sync into the same cron for performance optimization. The max number of API requests is based on the number of unique opted-in users. */ public function _run_sync_install() { $this->_logger->entrance(); $this->execute_cron( 'sync', array( &$this, '_sync_install_cron_method' ) ); } /** * The actual install(s) sync cron logic. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int[] $blog_ids * @param int|null $current_blog_id */ function _sync_install_cron_method( array $blog_ids, $current_blog_id = null ) { if ( $this->is_registered() ) { if ( 1 < count( $blog_ids ) ) { $this->sync_installs( array(), true ); } else { $this->sync_install( array(), true ); } $this->maybe_sync_install_user(); } } #endregion Async Install Sync ------------------------------------------------------------------ /** * Show a notice that activation is currently pending. * * @todo Add some sort of mechanism to allow users to update the email address they would like to opt-in with when $is_suspicious_email is true. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param bool|string $email_address * @param bool $is_pending_trial Since 1.2.1.5 * @param bool $is_suspicious_email Since 2.5.0 Set to true when there's an indication that email address the user opted in with is fake/dummy/placeholder. * @param bool $has_upgrade_context Since 2.5.3 * @param bool $support_email_address Since 2.5.3 */ function _add_pending_activation_notice( $email_address = false, $is_pending_trial = false, $is_suspicious_email = false, $has_upgrade_context = false, $support_email_address = false ) { if ( ! is_string( $email_address ) ) { $current_user = self::_get_current_wp_user(); $email_address = $current_user->user_email; } $formatted_message_args = array( "{$this->get_plugin_name()}", "{$email_address}", ); if ( ! $has_upgrade_context || ! fs_is_network_admin() ) { /* translators: %3$s: action (e.g.: "start the trial" or "complete the opt-in") */ $formatted_message = $this->get_text_inline( 'You should receive a confirmation email for %1$s to your mailbox at %2$s. Please make sure you click the button in that email to %3$s.', 'pending-activation-message' ); $formatted_message_args[] = $is_pending_trial ? $this->get_text_inline( 'start the trial', 'start-the-trial' ) : $this->get_text_inline( 'complete the opt-in', 'complete-the-opt-in' ); $notice_title = $this->get_text_inline( 'Thanks!', 'thanks' ); } else { /* translators: %3$s: What the user is expected to receive via email (e.g.: "the installation instructions" or "a license key") */ $formatted_message = $this->get_text_inline( 'You should receive %3$s for %1$s to your mailbox at %2$s in the next 5 minutes.' ); if ( $this->has_release_on_freemius() ) { $formatted_message_args[] = $this->get_text_x_inline( 'the installation instructions', 'Part of the message telling the user what they should receive via email.', 'the-installation-instructions-phrase' ); } else { $formatted_message_args[] = $this->get_text_x_inline( 'a license key', 'Part of the message telling the user what they should receive via email.', 'a-license-key-phrase' ); $formatted_message .= ( ' ' . sprintf( /* translators: %s: activation link (e.g.: Click here) */ $this->get_text_inline( '%s to activate the license once you get it.', 'license-activation-link-message' ), sprintf( '%s', $this->get_activation_url( array( 'fs_action' => 'reset_pending_activation_mode', 'require_license' => 'true', 'fs_unique_affix' => $this->get_unique_affix(), ) ), $this->get_text_x_inline( 'Click here', 'Part of an activation link message.', 'click-here' ) ) ) ); } $formatted_message_args[] = ( ! empty( $support_email_address ) ) ? ( "{$support_email_address}" ) : $this->get_text_x_inline( "the product's support email address", 'Part of the message that tells the user to check their spam folder for a specific email.', 'product-support-email-address-phrase' ); $formatted_message .= ( ' ' . $this->get_text_inline( 'If you didn\'t get the email, try checking your spam folder or search for emails from %4$s.', 'check-spam-folder-message' ) ); $notice_title = $this->get_text_inline( 'Thanks for upgrading.', 'after-upgrade-thank-you-message' ); } $this->_admin_notices->add_sticky( vsprintf( $formatted_message, $formatted_message_args ), 'activation_pending', $notice_title ); } /** * Check if currently in plugin activation. * * @author Vova Feldman (@svovaf) * @since 1.1.4 * * @return bool */ function is_plugin_activation() { $result = get_transient( "fs_{$this->_module_type}_{$this->_slug}_activated" ); return !empty($result); } /** * * NOTE: admin_menu action executed before admin_init. * * @author Vova Feldman (@svovaf) * @since 1.0.7 */ function _admin_init_action() { $is_migration = $this->is_migration(); /** * Automatically redirect to connect/activation page after plugin activation. * * @since 1.1.7 Do NOT redirect to opt-in when running in network admin mode. */ if ( $this->is_plugin_activation() ) { delete_transient( "fs_{$this->_module_type}_{$this->_slug}_activated" ); if ( isset( $_GET['activate-multi'] ) ) { /** * Don't redirect if activating multiple plugins at once (bulk activation). */ } else if ( self::is_deactivation_snoozed() && ( // Either running the free code base. ! $this->is_premium() || // Or if has a free version. ! $this->is_only_premium() || // If premium only, don't redirect if license is activated. ( $this->is_registered() && ! $this->can_use_premium_code() ) ) ) { /** * Don't redirect if activating during the deactivation snooze period (aka troubleshooting), unless activating a paid product version that the admin didn't enter its license key yet. */ } else if ( ! $is_migration ) { $this->_redirect_on_activation_hook(); return; } } if ( $is_migration ) { return; } if ( fs_request_is_action( $this->get_unique_affix() . '_skip_activation' ) ) { check_admin_referer( $this->get_unique_affix() . '_skip_activation' ); $this->skip_connection( fs_is_network_admin() ); fs_redirect( $this->get_after_activation_url( 'after_skip_url' ) ); } if ( $this->is_network_activation_mode() && fs_request_is_action( $this->get_unique_affix() . '_delegate_activation' ) ) { check_admin_referer( $this->get_unique_affix() . '_delegate_activation' ); $this->delegate_connection(); fs_redirect( $this->get_after_activation_url( 'after_delegation_url' ) ); } $this->_add_upgrade_action_link(); if ( ! ( ! $this->_is_network_active && fs_is_network_admin() ) && ( ( true === $this->_storage->require_license_activation ) || // Not registered nor anonymous. ( ! $this->is_registered() && ! $this->is_anonymous() ) || // OR, network level and in network upgrade mode. ( fs_is_network_admin() && $this->_is_network_active && $this->is_network_upgrade_mode() ) ) ) { if ( ! $this->is_pending_activation() ) { if ( ! $this->is_activation_page() ) { /** * If a user visits any other admin page before activating the premium-only theme with a valid * license, reactivate the previous theme. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ if ( $this->is_theme() && ! $this->has_settings_menu() && ! isset( $_REQUEST['fs_action'] ) && $this->can_activate_previous_theme() ) { if ( $this->is_only_premium() ) { $this->activate_previous_theme(); return; } if ( true === $this->_storage->require_license_activation ) { $this->_storage->require_license_activation = false; } } if ( ! fs_is_network_admin() && $this->is_network_activation_mode() && ! $this->is_delegated_connection() ) { return; } if ( $this->is_plugin_new_install() || $this->is_only_premium() ) { if ( ! $this->_anonymous_mode && ( ! $this->is_addon() || ! $this->_parent->is_anonymous() ) ) { // Show notice for new plugin installations. $this->_admin_notices->add( sprintf( $this->get_text_inline( 'You are just one step away - %s', 'you-are-step-away' ), sprintf( '%s', $this->get_activation_url( array(), ! $this->is_delegated_connection() ), sprintf( $this->get_text_x_inline( 'Complete "%s" Activation Now', '%s - plugin name. As complete "PluginX" activation now', 'activate-x-now' ), $this->get_plugin_name() ) ) ), '', 'update-nag' ); } } else { if ( $this->should_add_sticky_optin_notice() ) { $this->add_sticky_optin_admin_notice(); } if ( $this->has_filter( 'optin_pointer_element' ) ) { // Don't show admin nag if plugin update. wp_enqueue_script( 'wp-pointer' ); wp_enqueue_style( 'wp-pointer' ); $this->_enqueue_connect_essentials(); add_action( 'admin_print_footer_scripts', array( $this, '_add_connect_pointer_script' ) ); } } } } if ( $this->show_opt_in_on_themes_page() && $this->is_activation_page() ) { $this->_show_theme_activation_optin_dialog(); } } } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return bool */ private function should_add_sticky_optin_notice() { if ( $this->is_addon() && $this->_parent->is_anonymous() ) { return false; } if ( fs_is_network_admin() ) { if ( ! $this->_is_network_active ) { return false; } if ( ! $this->is_network_activation_mode() ) { return false; } return ! isset( $this->_storage->sticky_optin_added_ms ); } if ( ! $this->is_activation_mode() ) { return false; } // If running from a blog admin and delegated the connection. return ! isset( $this->_storage->sticky_optin_added ); } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 */ private function add_sticky_optin_admin_notice() { if ( ! $this->_is_network_active || ! fs_is_network_admin() ) { $this->_storage->sticky_optin_added = true; } else { $this->_storage->sticky_optin_added_ms = true; } // Show notice for new plugin installations. $this->_admin_notices->add_sticky( sprintf( $this->get_text_inline( 'We made a few tweaks to the %s, %s', 'few-plugin-tweaks' ), $this->_module_type, sprintf( '%s', $this->get_activation_url(), sprintf( $this->get_text_inline( 'Opt in to make "%s" better!', 'optin-x-now' ), $this->get_plugin_name() ) ) ), 'connect_account', '', 'update-nag' ); } /** * Enqueue connect requires scripts and styles. * * @author Vova Feldman (@svovaf) * @since 1.1.4 */ function _enqueue_connect_essentials() { wp_enqueue_script( 'jquery' ); wp_enqueue_script( 'json2' ); fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); } /** * Add connect / opt-in pointer. * * @author Vova Feldman (@svovaf) * @since 1.1.4 */ function _add_connect_pointer_script() { $vars = array( 'id' => $this->_module_id ); $pointer_content = fs_get_template( 'connect.php', $vars ); ?> _menu->get_raw_slug() ) || fs_is_plugin_page( $this->_slug ); } /* Events ------------------------------------------------------------------------------------------------------------------*/ /** * Delete site install from Database. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param bool $store * @param int|null $blog_id Since 2.0.0 * * @return false|int The install ID if deleted. Otherwise, FALSE (when install not exist). */ function _delete_site( $store = true, $blog_id = null ) { return self::_delete_site_by_slug( $this->_slug, $this->_module_type, $store, $blog_id ); } /** * Delete site install from Database. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @param string $slug * @param string $module_type * @param bool $store * @param int|null $blog_id Since 2.0.0 * * @return false|int The install ID if deleted. Otherwise, FALSE (when install not exist). */ static function _delete_site_by_slug( $slug, $module_type, $store = true, $blog_id = null ) { $sites = self::get_all_sites( $module_type, $blog_id ); $install_id = false; if ( isset( $sites[ $slug ] ) ) { if ( is_object( $sites[ $slug ] ) ) { $install_id = $sites[ $slug ]->id; } unset( $sites[ $slug ] ); self::set_account_option_by_module( $module_type, 'sites', $sites, $store, $blog_id ); } return $install_id; } /** * Delete user. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $user_id * @param bool $store * * @return false|int The user ID if deleted. Otherwise, FALSE (when install not exist). */ private static function delete_user( $user_id, $store = true ) { $users = self::get_all_users(); if ( ! is_array( $users ) || ! isset( $users[ $user_id ] ) ) { return false; } unset( $users[ $user_id ] ); self::$_accounts->set_option( 'users', $users, $store ); return $user_id; } /** * Delete plugin's plans information. * * @param bool $store Flush to Database if true. * @param bool $keep_associated_plans If set to false, delete all plans, even if a plan is associated with an install. * * @author Vova Feldman (@svovaf) * @since 1.0.9 */ private function _delete_plans( $store = true, $keep_associated_plans = true ) { $this->_logger->entrance(); $plans = self::get_all_plans( $this->_module_type ); $plans_to_keep = array(); if ( $keep_associated_plans ) { $plans_ids_to_keep = $this->get_plans_ids_associated_with_installs(); foreach ( $plans_ids_to_keep as $plan_id ) { $plan = self::_get_plan_by_id( $plan_id ); if ( is_object( $plan ) ) { $plans_to_keep[] = self::_encrypt_entity( $plan ); } } } if ( ! empty( $plans_to_keep ) ) { $plans[ $this->_slug ] = $plans_to_keep; } else { unset( $plans[ $this->_slug ] ); } $this->set_account_option( 'plans', $plans, $store ); } /** * Delete all plugin licenses. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param bool $store */ private function _delete_licenses( $store = true ) { $this->_logger->entrance(); $all_licenses = self::get_all_licenses(); unset( $all_licenses[ $this->_module_id ] ); self::$_accounts->set_option( 'all_licenses', $all_licenses, $store ); } /** * Check if Freemius was added on new plugin installation. * * @author Vova Feldman (@svovaf) * @since 1.1.5 * * @return bool */ function is_plugin_new_install() { return isset( $this->_storage->is_plugin_new_install ) && $this->_storage->is_plugin_new_install; } /** * Check if it's the first plugin release that is running Freemius. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @return bool */ function is_first_freemius_powered_version() { return empty( $this->_storage->plugin_last_version ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return bool|string */ private function get_previous_theme_slug() { return isset( $this->_storage->previous_theme ) ? $this->_storage->previous_theme : false; } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return bool */ private function can_activate_previous_theme() { return $this->can_activate_theme( $this->get_previous_theme_slug() ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @return bool */ private function can_activate_theme( $slug ) { if ( false !== $slug && current_user_can( 'switch_themes' ) ) { $theme_instance = wp_get_theme( $slug ); return $theme_instance->exists(); } return false; } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 */ private function activate_previous_theme() { switch_theme( $this->get_previous_theme_slug() ); unset( $this->_storage->previous_theme ); global $pagenow; if ( 'themes.php' === $pagenow ) { /** * Refresh the active theme information. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ fs_redirect( $this->admin_url( $pagenow ) ); } } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return string */ function get_previous_theme_activation_url() { if ( ! $this->can_activate_previous_theme() ) { return ''; } /** * Activation URL * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ return wp_nonce_url( $this->admin_url( 'themes.php?action=activate&stylesheet=' . urlencode( $this->get_previous_theme_slug() ) ), 'switch-theme_' . $this->get_previous_theme_slug() ); } /** * Saves the slug of the previous theme if it still exists so that it can be used by the logic in the opt-in * form that decides whether to add a close button to the opt-in dialog or not. So after a premium-only theme is * activated, the close button will appear and will reactivate the previous theme if clicked. If the previous * theme doesn't exist, then there will be no close button. * * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @param string $slug_or_name Old theme's slug or name. * @param bool|WP_Theme $old_theme WP_Theme instance of the old theme if it still exists. */ function _activate_theme_event_hook( $slug_or_name, $old_theme = false ) { $this->_storage->previous_theme = ( false !== $old_theme ) ? $old_theme->get_stylesheet() : $slug_or_name; $this->_activate_plugin_event_hook(); } /** * Plugin activated hook. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @uses FS_Api */ function _activate_plugin_event_hook() { $this->_logger->entrance( 'slug = ' . $this->_slug ); if ( ! $this->is_user_admin() ) { return; } $this->unregister_uninstall_hook(); // Clear API cache on activation. FS_Api::clear_cache(); $is_premium_version_activation = $this->is_plugin() ? ( current_filter() !== ( 'activate_' . $this->_free_plugin_basename ) ) : $this->is_premium(); if ( $is_premium_version_activation && $this->is_pending_activation() ) { $this->clear_pending_activation_mode(); } $this->_logger->info( 'Activating ' . ( $is_premium_version_activation ? 'premium' : 'free' ) . ' plugin version.' ); if ( $this->is_plugin() ) { // This logic is relevant only to plugins since both the free and premium versions of a plugin can be active at the same time. // 1. If running in the activation of the FREE module, get the basename of the PREMIUM. // 2. If running in the activation of the PREMIUM module, get the basename of the FREE. $other_version_basename = $is_premium_version_activation ? $this->_free_plugin_basename : $this->premium_plugin_basename(); if ( ! $this->_is_network_active ) { /** * Themes are always network activated, but the ACTUAL activation is per site. * * During the activation, the plugin isn't yet active, therefore, * _is_network_active will be set to false even if it's a network level * activation. So we need to fix that by looking at the is_network_admin() value. * * @author Vova Feldman */ $this->_is_network_active = ( $this->_is_multisite_integrated && fs_is_network_admin() ); } /** * If the other module version is active, deactivate it. * * is_plugin_active() checks if the plugin is active on the site or the network level and * deactivate_plugins() deactivates the plugin whether it's activated on the site or network level. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ if ( is_plugin_active( $other_version_basename ) && $this->apply_filters( 'deactivate_on_activation', true ) ) { deactivate_plugins( $other_version_basename ); } } if ( $this->is_registered() ) { if ( $is_premium_version_activation ) { $this->reconnect_locally(); } // Schedule re-activation event and sync. // $this->sync_install( array(), true ); $this->schedule_install_sync(); // If activating the premium module version, add an admin notice to congratulate for an upgrade completion. if ( $is_premium_version_activation ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'The upgrade of %s was successfully completed.', 'successful-version-upgrade-message' ), sprintf( '%s', $this->_plugin->title ) ), $this->get_text_x_inline( 'W00t', 'Used to express elation, enthusiasm, or triumph (especially in electronic communication).', 'woot' ) . '!' ); } } else if ( $this->is_anonymous() ) { if ( isset( $this->_storage->is_anonymous_ms ) && $this->_storage->is_anonymous_ms['is'] ) { $plugin_version = $this->_storage->is_anonymous_ms['version']; $network = true; } else { $plugin_version = isset( $this->_storage->is_anonymous ) ? $this->_storage->is_anonymous['version'] : null; $network = false; } /** * Reset "skipped" click cache on the following: * 1. Freemius DEV mode. * 2. WordPress DEBUG mode. * 3. If a plugin and the user skipped the exact same version before. * * @since 1.2.2.7 Ulrich Pogson (@grapplerulrich) asked to not reset the SKIPPED flag if the exact same THEME version was activated before unless the developer is running with WP_DEBUG on, or Freemius debug mode on (WP_FS__DEV_MODE). * * @todo 4. If explicitly asked to retry after every activation. */ if ( WP_FS__DEV_MODE || ( ( $this->is_plugin() || ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ) && $this->get_plugin_version() == $plugin_version ) ) { $this->reset_anonymous_mode( $network ); } } $is_trial_or_has_features_enabled_license = ( $this->is_trial() || $this->has_features_enabled_license() ); if ( $this->is_addon() && ! $is_trial_or_has_features_enabled_license ) { /** * When activating an add-on, try to also activate a license. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ if ( ! $this->_is_network_active ) { $this->maybe_activate_addon_license(); } else { $this->maybe_network_activate_addon_license(); } /** * Avoid redirecting to the license activation screen after automatically activating an add-on license. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $is_trial_or_has_features_enabled_license = ( $this->is_trial() || $this->has_features_enabled_license() ); if ( $is_trial_or_has_features_enabled_license && true === $this->_storage->require_license_activation ) { $this->_storage->require_license_activation = false; } } if ( $is_premium_version_activation && ( ( ! $this->is_registered() && $this->is_anonymous() ) || ( $this->is_registered() && ! $is_trial_or_has_features_enabled_license ) ) ) { $this->_storage->require_license_activation = true; } if ( ! isset( $this->_storage->is_plugin_new_install ) ) { /** * If no previous version of plugin's version exist, it means that it's either * the first time that the plugin installed on the site, or the plugin was installed * before but didn't have Freemius integrated. * * Since register_activation_hook() do NOT fires on updates since 3.1, and only fires * on manual activation via the dashboard, is_plugin_activation() is TRUE * only after immediate activation. * * @since 1.1.4 * @link https://make.wordpress.org/core/2010/10/27/plugin-activation-hooks-no-longer-fire-for-updates/ */ $this->_storage->is_plugin_new_install = empty( $this->_storage->plugin_last_version ); } /** * Also flush when activating the premium version so that even if Freemius was off before, the API * connectivity test can be run again. * * @author Leo Fajardo (@leorw) * @since 2.2.3.1 */ $has_api_connectivity = $this->has_api_connectivity( WP_FS__DEV_MODE || $is_premium_version_activation ); if ( ! $this->_anonymous_mode && ( false !== $has_api_connectivity ) && ! $this->_isAutoInstall ) { // Store hint that the plugin was just activated to enable auto-redirection to settings. set_transient( "fs_{$this->_module_type}_{$this->_slug}_activated", true, 60 ); } /** * Activation hook is executed after the plugin's main file is loaded, therefore, * after the plugin was loaded. The logic is located at activate_plugin() * ./wp-admin/includes/plugin.php. * * @author Vova Feldman (@svovaf) * @since 1.1.9 */ $this->_storage->was_plugin_loaded = true; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 */ private function maybe_activate_addon_license() { $parent_fs = $this->get_parent_instance(); if ( ! is_object( $parent_fs ) || ( ! $parent_fs->is_registered() && ! $parent_fs->is_network_registered() ) ) { // Try to activate a license only if the parent plugin is active and has a valid `install`. return; } $license = $this->get_active_parent_license(); if ( ! is_object( $license ) ) { return; } if ( $this->is_bundle_license_auto_activation_enabled() && ! empty( $license->products ) ) { $this->activate_bundle_license( $license ); return; } if ( ! $this->is_registered() ) { // Opt in with a license key. $this->opt_in( $parent_fs->get_current_or_network_user()->email, false, false, $license->secret_key ); } else { // Activate the license. $install = $this->api_site_call( '/', 'put', array( 'license_key' => $this->apply_filters( 'license_key', $license->secret_key ) ) ); if ( ! FS_Api::is_api_error( $install ) ) { $this->_sync_addon_license( $this->get_id(), true ); } } } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param FS_Plugin_License $license */ private function maybe_network_activate_addon_license( $license = null ) { $parent_fs = $this->get_parent_instance(); if ( ! is_object( $parent_fs ) || ( ! $parent_fs->is_registered() && ! $parent_fs->is_network_registered() ) ) { // Try to activate a license only if the parent plugin is active and has a valid `install`. return; } $license = ( ! is_null( $license ) ) ? $license : $this->get_active_parent_license(); if ( ! is_object( $license ) ) { return; } if ( $this->is_bundle_license_auto_activation_enabled() && ! empty( $license->products ) ) { $this->activate_bundle_license( $license ); return; } if ( ! $this->is_network_registered() ) { $sites = $this->get_sites_for_network_level_optin(); if ( count( $sites ) > $license->left() ) { // If the add-on is network active, try to activate the license only if it can be activated on all sites. return; } // Opt in with a license key. $this->opt_in( $parent_fs->get_user()->email, false, false, $license->secret_key, false, false, false, null, $sites ); } else { $blog_2_install_map = array(); $site_ids = array(); $all_sites = Freemius::get_sites(); foreach ( $all_sites as $site ) { $blog_id = Freemius::get_site_blog_id( $site ); $install = $this->get_install_by_blog_id( $blog_id ); if ( is_object( $install ) && FS_Plugin_License::is_valid_id( $install->license_id ) ) { // Skip license activation for installs that are already associated with a license. continue; } if ( is_object( $install ) ) { $blog_2_install_map[ $blog_id ] = $install; } else { $site_ids[] = $blog_id; } } if ( ( count( $blog_2_install_map ) + count( $site_ids ) ) > $license->left() ) { return; } $user = $this->get_current_or_network_user(); if ( ! empty( $blog_2_install_map ) ) { $result = $this->activate_license_on_many_installs( $user, $license->secret_key, $blog_2_install_map ); if ( true !== $result ) { return; } } if ( ! empty( $site_ids ) ) { $this->activate_license_on_many_sites( $user, $license->secret_key, $site_ids ); } } } /** * Tries to activate a bundle license for all supported products if the current product is activated with a bundle license. This is called after activating an available license (not via the license activation dialog but by clicking on a license activation button) for a product via its "Account" page. * * @author Leo Fajardo (@leorw) * @since 2.4.0 * * @param FS_Plugin_License $license * @param array $sites * @param int $blog_id */ private function maybe_activate_bundle_license( FS_Plugin_License $license = null, $sites = array(), $blog_id = 0 ) { if ( ! is_object( $license ) && $this->has_active_valid_license() ) { $license = $this->_license; } if ( ! is_object( $license ) ) { return; } $parent_license = ( ! empty( $license->products ) ) ? $license : $this->get_active_parent_license( $license->secret_key ); if ( is_object( $parent_license ) ) { $this->activate_bundle_license( $parent_license, $sites, $blog_id ); } } /** * Try to activate a bundle license for all the bundle products installed on the site. * (1) If a child product install already has a license, the bundle license won't be activated. * (2) On multi-site networks, if the attempt to activate the bundle license is triggered from the network admin, the bundle license activation will only work for non-delegated sites and only if none of them is associated with a license. Even if one of the sites has the product installed with a license key, skip the bundle license activation for the product. * (3) On multi-site networks, if the attempt to activate the bundle license is triggered from a site-level admin, only activate the license if the product is site-level activated or delegated, and the product installation is not yet associated with a license. * * @author Leo Fajardo (@leorw) * @since 2.4.0 * * @param FS_Plugin_License $license * @param array $sites * @param int $current_blog_id */ private function activate_bundle_license( $license, $sites = array(), $current_blog_id = 0 ) { $is_network_admin = fs_is_network_admin(); $installs_by_blog_map = array(); $site_info_by_blog_map = array(); /** * Try to activate the license for all supported products. * * @author Leo Fajardo */ foreach ( $license->products as $product_id ) { $fs = self::get_instance_by_id( $product_id ); if ( ! is_object( $fs ) ) { continue; } if ( ! $fs->has_paid_plan() ) { continue; } if ( ! $fs->is_addon() && ! FS_Plan_Manager::instance()->has_paid_plan( $fs->_plans ) ) { /** * The parent product can be free-only but can have its `has_paid_plan` flag set to `true` when * there is a context bundle. */ continue; } if ( $current_blog_id > 0 ) { $fs->switch_to_blog( $current_blog_id ); } if ( $fs->has_active_valid_license() ) { continue; } if ( ! $is_network_admin || $current_blog_id > 0 ) { if ( $fs->is_network_active() && ! $fs->is_delegated_connection( $current_blog_id ) ) { // Do not try to activate the license in the site level if the product is network active and the connection was not delegated. continue; } } else { if ( ! $fs->is_network_active() ) { // Do not try to activate the license in the network level if the product is not network active. continue; } if ( $fs->is_network_delegated_connection() ) { // Do not try to activate the license in the network level if the activation has been delegated to site admins. continue; } $has_install_with_license = false; // Collection of sites that have an install entity that is not activated with a license or non-delegated sites that have no install entity, or both types of site. $filtered_sites = array(); if ( empty( $sites ) ) { $all_sites = self::get_sites(); foreach ( $all_sites as $site ) { $sites[] = array( 'blog_id' => self::get_site_blog_id( $site ) ); } } else { // Populate the map here to avoid calling `$fs->get_site_info( $site );` in the other `for` loop below. foreach ( $sites as $site ) { if ( ! isset( $site['blog_id'] ) || ! is_numeric( $site['blog_id'] ) ) { continue; } $site_info_by_blog_map[ $site['blog_id'] ] = $site; } } foreach ( $sites as $site ) { if ( ! isset( $site['blog_id'] ) || ! is_numeric( $site['blog_id'] ) ) { continue; } $blog_id = $site['blog_id']; if ( ! isset( $installs_by_blog_map[ $blog_id ] ) ) { $installs_by_blog_map[ $blog_id ] = self::get_all_sites( $fs->get_module_type(), $blog_id ); } $installs = $installs_by_blog_map[ $blog_id ]; $install = null; if ( isset( $installs[ $fs->get_slug() ] ) ) { $install = $installs[ $fs->get_slug() ]; if ( is_object( $install ) && ( ! FS_Site::is_valid_id( $install->id ) || ! FS_User::is_valid_id( $install->user_id ) || ! FS_Plugin_Plan::is_valid_id( $install->plan_id ) ) ) { $install = null; } } if ( is_object( $install ) && FS_Plugin_License::is_valid_id( $install->license_id ) ) { $has_install_with_license = true; break; } if ( $fs->is_site_delegated_connection( $blog_id ) ) { // Site activation delegated, don't activate bundle license on the site in the network admin. continue; } if ( ! isset( $site_info_by_blog_map[ $blog_id ] ) ) { $site_info_by_blog_map[ $blog_id ] = $fs->get_site_info( $site ); } $filtered_sites[] = $site_info_by_blog_map[ $blog_id ]; } if ( $has_install_with_license || empty( $filtered_sites ) ) { // Do not try to activate the license at the network level if there's any install with a license or there's no site to activate the license on. continue; } $sites = $filtered_sites; } $fs->activate_migrated_license( $license->secret_key, null, null, $sites, ( $current_blog_id > 0 ? $current_blog_id : null ) ); } } /** * Returns a parent license that can be activated for the context product. * * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param string|null $license_key * @param bool $flush * * @return FS_Plugin_License */ function get_active_parent_license( $license_key = null, $flush = true ) { $parent_licenses_endpoint = "/plugins/{$this->get_id()}/parent_licenses.json?filter=activatable"; $fs = $this; if ( $this->is_addon() ) { $parent_instance = $this->get_parent_instance(); if ( is_object( $parent_instance ) && $parent_instance->is_registered() ) { $fs = $parent_instance; } } $foreign_licenses = $fs->get_foreign_licenses_info( self::get_all_licenses( $this->get_parent_id() ) ); if ( ! empty ( $foreign_licenses ) ) { $foreign_licenses = array( // Prefix with `+` to tell the server to include foreign licenses in the licenses collection. 'ids' => ( urlencode( '+' ) . implode( ',', $foreign_licenses['ids'] ) ), 'license_keys' => implode( ',', array_map( 'urlencode', $foreign_licenses['license_keys'] ) ) ); $parent_licenses_endpoint = add_query_arg( $foreign_licenses, $parent_licenses_endpoint ); } $result = $fs->get_current_or_network_user_api_scope()->get( $parent_licenses_endpoint, $flush ); if ( ! $this->is_api_result_object( $result, 'licenses' ) || ! is_array( $result->licenses ) || empty( $result->licenses ) ) { return null; } $parent_license = null; if ( empty( $license_key ) ) { $parent_license = $result->licenses[0]; } else { foreach ( $result->licenses as $license ) { if ( $license_key === $license->secret_key ) { $parent_license = $license; break; } } } if ( ! is_null( $parent_license ) ) { $parent_license = new FS_Plugin_License( $parent_license ); } return $parent_license; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @return array */ function get_sites_for_network_level_optin() { $sites = array(); $all_sites = self::get_sites(); foreach ( $all_sites as $site ) { $blog_id = self::get_site_blog_id( $site ); if ( ! $this->is_site_delegated_connection( $blog_id ) && ! $this->is_installed_on_site( $blog_id ) ) { $sites[] = $this->get_site_info( $site ); } } return $sites; } /** * Delete account. * * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @param bool $check_user Enforce checking if user have plugins activation privileges. */ function delete_account_event( $check_user = true ) { $this->_logger->entrance( 'slug = ' . $this->_slug ); if ( $check_user && ! $this->is_user_admin() ) { return; } $this->do_action( 'before_account_delete' ); // Clear all admin notices. $this->_admin_notices->clear_all_sticky( false ); $this->_delete_site( false ); $delete_network_common_data = true; if ( $this->_is_network_active ) { $installs = $this->get_blog_install_map(); // Don't delete common network data unless no other installs left. $delete_network_common_data = empty( $installs ); } if ( $delete_network_common_data ) { $this->_delete_plans( false ); $this->_delete_licenses( false ); // Delete add-ons related to plugin's account. $this->_delete_account_addons( false ); } // @todo Delete plans and licenses of add-ons. self::$_accounts->store(); /** * IMPORTANT: * Clear crons must be executed before clearing all storage. * Otherwise, the cron will not be cleared. */ if ( $delete_network_common_data ) { $this->clear_sync_cron(); } $this->clear_install_sync_cron(); // Clear all storage data. $this->_storage->clear_all( true, array( 'is_delegated_connection', 'connectivity_test', 'is_on', ), false ); // Send delete event. $this->get_api_site_scope()->call( '/', 'delete' ); $this->do_action( 'after_account_delete' ); } /** * Delete network level account. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param bool $check_user Enforce checking if user have plugins activation privileges. */ function delete_network_account_event( $check_user = true ) { $this->_logger->entrance( 'slug = ' . $this->_slug ); if ( $check_user && ! $this->is_user_admin() ) { return; } $this->do_action( 'before_network_account_delete' ); // Clear all admin notices. $this->_admin_notices->clear_all_sticky(); $this->_delete_plans( false, false ); $this->_delete_licenses( false ); // Delete add-ons related to plugin's account. $this->_delete_account_addons( false ); // @todo Delete plans and licenses of add-ons. self::$_accounts->store( true ); /** * IMPORTANT: * Clear crons must be executed before clearing all storage. * Otherwise, the cron will not be cleared. */ $this->clear_sync_cron( true ); $this->clear_install_sync_cron( true ); $sites = self::get_sites(); $install_ids = array(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); if ( $this->is_site_delegated_connection( $blog_id ) ) { continue; } $install_id = $this->_delete_site( true, $blog_id ); // Clear all storage data. $this->_storage->clear_all( true, array( 'connectivity_test' ), $blog_id ); if ( FS_Site::is_valid_id( $install_id ) ) { $install_ids[] = $install_id; } switch_to_blog( $blog_id ); $this->do_action( 'after_account_delete' ); restore_current_blog(); } $this->_storage->clear_all( true, array( 'connectivity_test', 'is_on', ), true ); // Send delete event. if ( ! empty( $install_ids ) ) { $result = $this->get_current_or_network_user_api_scope()->call( "/plugins/{$this->_module_id}/installs.json?ids=" . implode( ',', $install_ids ), 'delete' ); } $this->do_action( 'after_network_account_delete' ); } /** * Plugin deactivation hook. * * @author Vova Feldman (@svovaf) * @since 1.0.1 */ function _deactivate_plugin_hook() { $this->_logger->entrance( 'slug = ' . $this->_slug ); if ( ! $this->is_user_admin() ) { return; } $is_network_deactivation = fs_is_network_admin(); $storage_keys_for_removal = array(); $this->_admin_notices->clear_all_sticky(); $storage_keys_for_removal[] = 'sticky_optin_added'; if ( isset( $this->_storage->sticky_optin_added ) ) { unset( $this->_storage->sticky_optin_added ); } if ( ! isset( $this->_storage->is_plugin_new_install ) ) { // Remember that plugin was already installed. $this->_storage->is_plugin_new_install = false; } // Hook to plugin uninstall. register_uninstall_hook( $this->_plugin_main_file_path, array( 'Freemius', '_uninstall_plugin_hook' ) ); $this->clear_module_main_file_cache(); $this->clear_sync_cron( $this->_is_network_active ); $this->clear_install_sync_cron(); if ( $this->is_registered() ) { if ( $this->is_premium() && ! $this->has_active_valid_license() ) { FS_Plugin_Updater::instance( $this )->delete_update_data(); } if ( $is_network_deactivation ) { // Send deactivation event. $this->sync_installs( array( 'is_active' => false, ) ); } else { // Send deactivation event. $this->sync_install( array( 'is_active' => false, ) ); } } else { if ( false === $this->has_api_connectivity() && ! $this->is_premium() ) { // Reset connectivity test cache. $this->clear_connectivity_info(); $storage_keys_for_removal[] = 'connectivity_test'; } } if ( $is_network_deactivation ) { if ( isset( $this->_storage->sticky_optin_added_ms ) ) { unset( $this->_storage->sticky_optin_added_ms ); } if ( ! empty( $storage_keys_for_removal ) ) { $sites = self::get_sites(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); foreach ( $storage_keys_for_removal as $key ) { $this->_storage->remove( $key, false, $blog_id ); } $this->_storage->save( $blog_id ); } } } // Clear API cache on deactivation. FS_Api::clear_cache(); $this->remove_sdk_reference(); } /** * @author Vova Feldman (@svovaf) * @since 1.1.6 */ private function remove_sdk_reference() { global $fs_active_plugins; foreach ( $fs_active_plugins->plugins as $sdk_path => $data ) { if ( $this->_plugin_basename == $data->plugin_path ) { unset( $fs_active_plugins->plugins[ $sdk_path ] ); break; } } fs_fallback_to_newest_active_sdk(); } /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param bool $is_anonymous * @param bool|int $network_or_blog_id Since 2.0.0 */ private function set_anonymous_mode( $is_anonymous = true, $network_or_blog_id = 0 ) { // Store information regarding skip to try and opt-in the user // again in the future. $skip_info = array( 'is' => $is_anonymous, 'timestamp' => WP_FS__SCRIPT_START_TIME, 'version' => $this->get_plugin_version(), ); if ( true === $network_or_blog_id ) { $this->_storage->is_anonymous_ms = $skip_info; } else { $this->_storage->store( 'is_anonymous', $skip_info, $network_or_blog_id ); } $this->network_upgrade_mode_completed(); // Update anonymous mode cache. $this->_is_anonymous = $is_anonymous; } /** * @author Vova Feldman (@svovaf) * @since 2.5.1 * * @param bool|int $network_or_blog_id */ private function unset_anonymous_mode( $network_or_blog_id = 0 ) { if ( true === $network_or_blog_id ) { unset( $this->_storage->is_anonymous_ms ); } else { $this->_storage->remove( 'is_anonymous', true, $network_or_blog_id ); } } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id Site ID. * @param int $user_id User ID. * @param string $domain Site domain. * @param string $path Site path. * @param int $network_id Network ID. Only relevant on multi-network installations. * @param array $meta Metadata. Used to set initial site options. * * @uses Freemius::is_license_network_active() to check if the context license was network activated by the super-admin. * @uses Freemius::is_network_connected() to check if the super-admin network opted-in. * @uses Freemius::is_network_anonymous() to check if the super-admin network skipped. * @uses Freemius::is_network_delegated_connection() to check if the super-admin network delegated the connection to the site admins. */ public function _after_new_blog_callback( $blog_id, $user_id, $domain, $path, $network_id, $meta ) { $this->_logger->entrance(); if ( ! $this->_is_network_active ) { FS_Clone_Manager::instance()->store_blog_install_info( $blog_id ); return; } $site = null; $new_blog_id = $blog_id; if ( $this->is_premium() && $this->is_network_connected() && is_object( $this->_license ) && $this->_license->can_activate( FS_Site::is_localhost_by_address( $domain ) ) && $this->is_license_network_active( $blog_id ) ) { /** * Running the premium version, the license was network activated, and the license can also be activated on the current site -> so try to opt-in with the license key. */ $current_blog_id = get_current_blog_id(); $license = clone $this->_license; $this->switch_to_blog( $blog_id ); // Opt-in with network user. $this->install_with_user( $this->get_network_user(), $license->secret_key, false, false, false ); if ( is_object( $this->_site ) ) { if ( $this->_site->license_id == $license->id ) { /** * If the license was activated successfully, sync the license data from the remote server. */ $this->_license = $license; $this->sync_site_license(); } } $site = $this->_site; $this->switch_to_blog( $current_blog_id ); if ( is_object( $site ) ) { FS_Clone_Manager::instance()->store_blog_install_info( $blog_id, $site ); // Already connected (with or without a license), so no need to continue. return; } } if ( $this->is_network_anonymous() ) { /** * Opt-in was network skipped so automatically skip the opt-in for the new site. */ $this->skip_site_connection( $blog_id ); } else if ( $this->is_network_delegated_connection() ) { /** * Opt-in was network delegated so automatically delegate the opt-in for the new site's admin. */ $this->delegate_site_connection( $blog_id ); } else if ( $this->is_network_connected() ) { /** * Opt-in was network activated so automatically opt-in with the network user and new site admin. */ $current_blog_id = get_current_blog_id(); $this->switch_to_blog( $blog_id ); // Opt-in with network user. $this->install_with_user( $this->get_network_user(), false, false, false, false ); $site = $this->_site; $this->switch_to_blog( $current_blog_id ); } else { /** * If the super-admin mixed different options (connect, skip, delegated): * a) If at least one site connection was delegated, then automatically delegate connection. * b) Otherwise, it means that at least one site was skipped and at least one site was connected. For a simplified UX in the initial release of the multisite network integration, skip the connection for the newly created site. If the super-admin will want to opt-in they can still do that from the network level Account page. */ $has_delegated_site = false; $sites = self::get_sites(); foreach ( $sites as $wp_site ) { $blog_id = self::get_site_blog_id( $wp_site ); if ( $this->is_site_delegated_connection( $blog_id ) ) { $has_delegated_site = true; break; } } if ( $has_delegated_site ) { $this->delegate_site_connection( $blog_id ); } else { $this->skip_site_connection( $blog_id ); } } /** * Store the new blog's information even if there's no install so that when a clone install is stored in the new blog's storage, we can try to resolve it automatically. * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ FS_Clone_Manager::instance()->store_blog_install_info( $new_blog_id, $site ); } /** * @author Vova Feldman (@svovaf) * @since 2.5.0 * * @param \WP_Site $new_site * @param array $args */ public function _after_wp_initialize_site_callback( WP_Site $new_site, $args ) { $this->_logger->entrance(); $this->_after_new_blog_callback( $new_site->id, // Dummy user ID (not in use). 0, $new_site->domain, $new_site->path, $new_site->network_id, // Dummy meta, not in use. array() ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param bool|int|int[] $network_or_blog_ids Since 2.0.0. */ private function reset_anonymous_mode( $network_or_blog_ids = false ) { if ( true === $network_or_blog_ids ) { $this->unset_anonymous_mode( true ); if ( fs_is_network_admin() ) { $this->_is_anonymous = null; } // Rest anonymous mode for all non-delegated sub-sites. $blog_ids = $this->get_non_delegated_blog_ids(); } else { if ( false === $network_or_blog_ids ) { $network_or_blog_ids = 0; } $blog_ids = is_array( $network_or_blog_ids ) ? $network_or_blog_ids : array( $network_or_blog_ids ); foreach ( $blog_ids as $blog_id ) { if ( 0 === $blog_id || get_current_blog_id() == $blog_id ) { $this->_is_anonymous = null; } } } foreach ( $blog_ids as $blog_id ) { $this->unset_anonymous_mode( $blog_id ); } /** * Ensure that this field is also "false", otherwise, if the current module's type is "theme" and the module * has no menus, the opt-in popup will not be shown immediately (in this case, the user will have to click * on the admin notice that contains the opt-in link in order to trigger the opt-in popup). * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ if ( ! $this->_is_network_active ) { $this->_is_anonymous = null; } } /** * @author Leo Fajardo (@leorw) * @since 2.5.3 */ private function update_license_required_permissions_if_anonymous() { if ( ! $this->is_anonymous() ) { return; } $this->reset_anonymous_mode( fs_is_network_admin() ); FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array( 'essentials' => true, 'events' => true, 'diagnostic' => false, 'extensions' => false, 'site' => false, ) ); } /** * This is used to ensure that before redirecting to the opt-in page after resetting the anonymous mode or * deleting the account in the network level, the URL of the page to redirect to is correct. * * @author Leo Fajardo (@leorw) * * @since 2.1.3 */ private function maybe_set_slug_and_network_menu_exists_flag() { if ( ! empty( $this->_dynamically_added_top_level_page_hook_name ) ) { $this->_menu->set_slug_and_network_menu_exists_flag( $this->_menu->has_menu() ? $this->_menu->get_slug() : $this->_slug ); } } /** * Clears the anonymous mode and redirects to the opt-in screen. * * @author Vova Feldman (@svovaf) * @since 1.1.7 */ function connect_again() { if ( ! $this->is_anonymous() && ! $this->is_pending_activation() ) { return; } if ( $this->is_anonymous() ) { $this->reset_anonymous_mode( fs_is_network_admin() ); } $activation_url_params = array(); if ( $this->is_pending_activation() ) { $this->clear_pending_activation_mode(); if ( fs_request_get_bool( 'require_license' ) ) { $activation_url_params['require_license'] = true; } } $this->maybe_set_slug_and_network_menu_exists_flag(); fs_redirect( $this->get_activation_url( $activation_url_params ) ); } /** * Skip account connect, and set anonymous mode. * * @author Vova Feldman (@svovaf) * @since 1.1.1 * * @param bool|int|int[] $network_or_blog_ids Since 2.5.1 */ function skip_connection( $network_or_blog_ids = false ) { $this->_logger->entrance(); $this->_admin_notices->remove_sticky( 'connect_account' ); if ( true === $network_or_blog_ids ) { $this->set_anonymous_mode( true, true ); if ( fs_is_network_admin() ) { $this->_is_anonymous = null; } // Rest anonymous mode for all non-delegated sub-sites. $blog_ids = $this->get_non_delegated_blog_ids(); } else { if ( false === $network_or_blog_ids ) { $network_or_blog_ids = 0; } $blog_ids = is_array( $network_or_blog_ids ) ? $network_or_blog_ids : array( $network_or_blog_ids ); foreach ( $blog_ids as $blog_id ) { if ( 0 === $blog_id || get_current_blog_id() == $blog_id ) { $this->_is_anonymous = null; } } } foreach ( $blog_ids as $blog_id ) { $this->skip_site_connection( $blog_id ); } $this->network_upgrade_mode_completed(); } /** * Skip connection for specific site in the network. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int|null $blog_id * @param bool $send_skip */ private function skip_site_connection( $blog_id = null ) { $this->_logger->entrance(); $this->_admin_notices->remove_sticky( 'connect_account', $blog_id ); $this->set_anonymous_mode( true, $blog_id ); } /** * Plugin version update hook. * * @author Vova Feldman (@svovaf) * @since 1.0.4 */ private function update_plugin_version_event() { $this->_logger->entrance(); if ( ! $this->is_registered() ) { return; } $this->schedule_install_sync(); // $this->sync_install( array(), true ); } /** * Generate an MD5 signature of a plugins collection. * This helper methods used to identify changes in a plugins collection. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param array [string]array $plugins * * @return string */ private function get_plugins_thumbprint( $plugins ) { ksort( $plugins ); $thumbprint = ''; foreach ( $plugins as $basename => $data ) { $thumbprint .= $data['slug'] . ',' . $data['Version'] . ',' . ( $data['is_active'] ? '1' : '0' ) . ';'; } return md5( $thumbprint ); } /** * Return a list of modified plugins since the last sync. * * Note: * There's no point to store a plugins counter since even if the number of * plugins didn't change, we still need to check if the versions are all the * same and the activity state is similar. * * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @return array|false */ private function get_plugins_data_for_api() { // Alias. $site_active_plugins_option_name = 'active_plugins'; $network_plugins_option_name = 'all_plugins'; /** * Collection of all site level active plugins. */ $site_active_plugins_cache = self::$_accounts->get_option( $site_active_plugins_option_name ); if ( ! is_object( $site_active_plugins_cache ) ) { $site_active_plugins_cache = (object) array( 'timestamp' => '', 'md5' => '', 'plugins' => array(), ); } $time = time(); if ( ! empty( $site_active_plugins_cache->timestamp ) && ( $time - $site_active_plugins_cache->timestamp ) < WP_FS__TIME_5_MIN_IN_SEC ) { // Don't send plugin updates if last update was in the past 5 min. return false; } // Write timestamp to lock the logic. $site_active_plugins_cache->timestamp = $time; self::$_accounts->set_option( $site_active_plugins_option_name, $site_active_plugins_cache, true ); // Reload options from DB. self::$_accounts->load( true ); $site_active_plugins_cache = self::$_accounts->get_option( $site_active_plugins_option_name ); if ( $time != $site_active_plugins_cache->timestamp ) { // If timestamp is different, then another thread captured the lock. return false; } /** * Collection of all plugins (network level). */ $network_plugins_cache = self::$_accounts->get_option( $network_plugins_option_name ); if ( ! is_object( $network_plugins_cache ) ) { $network_plugins_cache = (object) array( 'timestamp' => '', 'md5' => '', 'plugins' => array(), ); } // Check if there's a change in plugins. $network_plugins = self::get_network_plugins(); $site_active_plugins = self::get_site_active_plugins(); $network_plugins_thumbprint = $this->get_plugins_thumbprint( $network_plugins ); $site_active_plugins_thumbprint = $this->get_plugins_thumbprint( $site_active_plugins ); // Check if plugins status changed (version or active/inactive). $network_plugins_changed = ( $network_plugins_cache->md5 !== $network_plugins_thumbprint ); $site_active_plugins_changed = ( $site_active_plugins_cache->md5 !== $site_active_plugins_thumbprint ); if ( ! $network_plugins_changed && ! $site_active_plugins_changed ) { // No changes. return array(); } $plugins_update_data = array(); foreach ( $network_plugins_cache->plugins as $basename => $data ) { if ( ! isset( $network_plugins[ $basename ] ) ) { // Plugin uninstalled. $uninstalled_plugin_data = $data; $uninstalled_plugin_data['is_active'] = false; $uninstalled_plugin_data['is_uninstalled'] = true; $plugins_update_data[] = $uninstalled_plugin_data; unset( $network_plugins[ $basename ] ); unset( $network_plugins_cache->plugins[ $basename ] ); unset( $site_active_plugins_cache->plugins[ $basename ] ); continue; } $was_active = $data['is_active'] || ( isset( $site_active_plugins_cache->plugins[ $basename ] ) && true === $site_active_plugins_cache->plugins[ $basename ]['is_active'] ); $is_active = $network_plugins[ $basename ]['is_active'] || ( isset( $site_active_plugins[ $basename ] ) && $site_active_plugins[ $basename ]['is_active'] ); if ( ! isset( $site_active_plugins_cache->plugins[ $basename ] ) && isset( $site_active_plugins[ $basename ] ) ) { // Plugin was site level activated. $site_active_plugins_cache->plugins[ $basename ] = $network_plugins[ $basename ]; $site_active_plugins_cache->plugins[ $basename ]['is_active'] = true; } else if ( isset( $site_active_plugins_cache->plugins[ $basename ] ) && ! isset( $site_active_plugins[ $basename ] ) ) { // Plugin was site level deactivated. unset( $site_active_plugins_cache->plugins[ $basename ] ); } $prev_version = $data['version']; $current_version = $network_plugins[ $basename ]['Version']; if ( $was_active !== $is_active || $prev_version !== $current_version ) { // Plugin activated or deactivated, or version changed. if ( $was_active !== $is_active ) { if ( $data['is_active'] != $network_plugins[ $basename ]['is_active'] ) { $network_plugins_cache->plugins[ $basename ]['is_active'] = $data['is_active']; } } if ( $prev_version !== $current_version ) { $network_plugins_cache->plugins[ $basename ]['Version'] = $current_version; } $updated_plugin_data = $data; $updated_plugin_data['is_active'] = $is_active; $updated_plugin_data['version'] = $current_version; $updated_plugin_data['title'] = $network_plugins[ $basename ]['Name']; $plugins_update_data[] = $updated_plugin_data; } } // Find new plugins that weren't yet seen before. foreach ( $network_plugins as $basename => $data ) { if ( ! isset( $network_plugins_cache->plugins[ $basename ] ) ) { // New plugin. $new_plugin = array( 'slug' => $data['slug'], 'version' => $data['Version'], 'title' => $data['Name'], 'is_active' => $data['is_active'], 'is_uninstalled' => false, ); $network_plugins_cache->plugins[ $basename ] = $new_plugin; $is_site_level_active = ( isset( $site_active_plugins[ $basename ] ) && $site_active_plugins[ $basename ]['is_active'] ); /** * If not network active, set the activity status based on the site-level plugin status. */ if ( ! $new_plugin['is_active'] ) { $new_plugin['is_active'] = $is_site_level_active; } $plugins_update_data[] = $new_plugin; if ( isset( $site_active_plugins[ $basename ] ) ) { $site_active_plugins_cache->plugins[ $basename ] = $new_plugin; $site_active_plugins_cache->plugins[ $basename ]['is_active'] = $is_site_level_active; } } } $site_active_plugins_cache->md5 = $site_active_plugins_thumbprint; $site_active_plugins_cache->timestamp = $time; self::$_accounts->set_option( $site_active_plugins_option_name, $site_active_plugins_cache, true ); $network_plugins_cache->md5 = $network_plugins_thumbprint; $network_plugins_cache->timestamp = $time; self::$_accounts->set_option( $network_plugins_option_name, $network_plugins_cache, true ); return $plugins_update_data; } /** * Return a list of modified themes since the last sync. * * Note: * There's no point to store a themes counter since even if the number of * themes didn't change, we still need to check if the versions are all the * same and the activity state is similar. * * @author Vova Feldman (@svovaf) * @since 1.1.8 * * @return array|false */ private function get_themes_data_for_api() { // Alias. $option_name = 'all_themes'; $all_cached_themes = self::$_accounts->get_option( $option_name ); if ( ! is_object( $all_cached_themes ) ) { $all_cached_themes = (object) array( 'timestamp' => '', 'md5' => '', 'themes' => array(), ); } $time = time(); if ( ! empty( $all_cached_themes->timestamp ) && ( $time - $all_cached_themes->timestamp ) < WP_FS__TIME_5_MIN_IN_SEC ) { // Don't send theme updates if last update was in the past 5 min. return false; } // Write timestamp to lock the logic. $all_cached_themes->timestamp = $time; self::$_accounts->set_option( $option_name, $all_cached_themes, true ); // Reload options from DB. self::$_accounts->load( true ); $all_cached_themes = self::$_accounts->get_option( $option_name ); if ( $time != $all_cached_themes->timestamp ) { // If timestamp is different, then another thread captured the lock. return false; } // Get active theme. $active_theme = wp_get_theme(); $active_theme_stylesheet = $active_theme->get_stylesheet(); // Check if there's a change in themes. $all_themes = wp_get_themes(); // Check if themes changed. ksort( $all_themes ); $themes_signature = ''; foreach ( $all_themes as $slug => $data ) { $is_active = ( $slug === $active_theme_stylesheet ); $themes_signature .= $slug . ',' . $data->version . ',' . ( $is_active ? '1' : '0' ) . ';'; } // Check if themes status changed (version or active/inactive). $themes_changed = ( $all_cached_themes->md5 !== md5( $themes_signature ) ); $themes_update_data = array(); if ( $themes_changed ) { // Change in themes, report changes. // Update existing themes info. foreach ( $all_cached_themes->themes as $slug => $data ) { $is_active = ( $slug === $active_theme_stylesheet ); if ( ! isset( $all_themes[ $slug ] ) ) { // Plugin uninstalled. $uninstalled_theme_data = $data; $uninstalled_theme_data['is_active'] = false; $uninstalled_theme_data['is_uninstalled'] = true; $themes_update_data[] = $uninstalled_theme_data; unset( $all_themes[ $slug ] ); unset( $all_cached_themes->themes[ $slug ] ); } else if ( $data['is_active'] !== $is_active || $data['version'] !== $all_themes[ $slug ]->version ) { // Plugin activated or deactivated, or version changed. $all_cached_themes->themes[ $slug ]['is_active'] = $is_active; $all_cached_themes->themes[ $slug ]['version'] = $all_themes[ $slug ]->version; $themes_update_data[] = $all_cached_themes->themes[ $slug ]; } } // Find new themes that weren't yet seen before. foreach ( $all_themes as $slug => $data ) { if ( ! isset( $all_cached_themes->themes[ $slug ] ) ) { $is_active = ( $slug === $active_theme_stylesheet ); // New plugin. $new_plugin = array( 'slug' => $slug, 'version' => $data->version, 'title' => $data->name, 'is_active' => $is_active, 'is_uninstalled' => false, ); $themes_update_data[] = $new_plugin; $all_cached_themes->themes[ $slug ] = $new_plugin; } } $all_cached_themes->md5 = md5( $themes_signature ); $all_cached_themes->timestamp = time(); self::$_accounts->set_option( $option_name, $all_cached_themes, true ); } return $themes_update_data; } /** * Get site data for API install request. * * @author Vova Feldman (@svovaf) * @since 1.1.2 * * @param string[] $override * @param bool $include_plugins Since 1.1.8 by default include plugin changes. * @param bool $include_themes Since 1.1.8 by default include plugin changes. * @param bool $include_blog_data Since 2.3.0 by default include the current blog's data (language, title, and URL). * * @return array */ private function get_install_data_for_api( array $override, $include_plugins = true, $include_themes = true, $include_blog_data = true ) { // Alias. $permissions = FS_Permission_Manager::instance( $this ); if ( $permissions->is_extensions_tracking_allowed() ) { if ( ! defined( 'WP_FS__TRACK_PLUGINS' ) || false !== WP_FS__TRACK_PLUGINS ) { /** * @since 1.1.8 Also send plugin updates. */ if ( $include_plugins && ! isset( $override['plugins'] ) ) { $plugins = $this->get_plugins_data_for_api(); if ( ! empty( $plugins ) ) { $override['plugins'] = $plugins; } } } if ( ! defined( 'WP_FS__TRACK_THEMES' ) || false !== WP_FS__TRACK_THEMES ) { /** * @since 1.1.8 Also send themes updates. */ if ( $include_themes && ! isset( $override['themes'] ) ) { $themes = $this->get_themes_data_for_api(); if ( ! empty( $themes ) ) { $override['themes'] = $themes; } } } } $versions = $this->get_versions(); $blog_data = array(); if ( $include_blog_data ) { $blog_data['url'] = self::get_unfiltered_site_url(); if ( $permissions->is_diagnostic_tracking_allowed() ) { $blog_data = array_merge( $blog_data, array( 'language' => self::get_sanitized_language(), 'title' => get_bloginfo( 'name' ), ) ); } } return array_merge( $versions, $blog_data, array( 'version' => $this->get_plugin_version(), 'is_premium' => $this->is_premium(), // Special params. 'is_active' => true, 'is_uninstalled' => false, ), $override ); } /** * Update installs details. * * @todo V1 of multiste network support doesn't support plugin and theme data sending. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string[] string $override * @param bool $only_diff * @param bool $is_keepalive * @param bool $include_plugins Since 1.1.8 by default include plugin changes. * @param bool $include_themes Since 1.1.8 by default include plugin changes. * * @return array */ private function get_installs_data_for_api( array $override, $only_diff = false, $is_keepalive = false, $include_plugins = true, $include_themes = true ) { /** * @since 1.1.8 Also send plugin updates. */ // if ( $include_plugins && ! isset( $override['plugins'] ) ) { // $plugins = $this->get_plugins_data_for_api(); // if ( ! empty( $plugins ) ) { // $override['plugins'] = $plugins; // } // } /** * @since 1.1.8 Also send themes updates. */ // if ( $include_themes && ! isset( $override['themes'] ) ) { // $themes = $this->get_themes_data_for_api(); // if ( ! empty( $themes ) ) { // $override['themes'] = $themes; // } // } // Common properties. $versions = $this->get_versions(); $common = array_merge( $versions, array( 'version' => $this->get_plugin_version(), 'is_premium' => $this->is_premium(), ), $override ); $is_common_diff_for_any_site = false; $common_diff_union = array(); $installs_data = array(); $sites = self::get_sites(); $subsite_data_for_api_by_install_id = array(); $install_url_by_install_id = array(); $subsite_registration_date_by_install_id = array(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $install = $this->get_install_by_blog_id( $blog_id ); if ( is_object( $install ) ) { if ( $install->user_id != $this->_user->id ) { // Install belongs to a different owner. continue; } if ( ! $this->is_tracking_allowed( $blog_id, $install ) ) { // Don't send updates regarding opted-out installs. continue; } $install_data = $this->get_site_info( $site, true ); if ( FS_Clone_Manager::instance()->is_temporary_duplicate_by_blog_id( $install_data['blog_id'] ) ) { continue; } $uid = $install_data['uid']; $url = $install_data['url']; $registration_date = $install_data['registration_date']; if ( isset( $subsite_data_for_api_by_install_id[ $install->id ] ) ) { $clone_subsite_data = $subsite_data_for_api_by_install_id[ $install->id ]; $clone_install_url = $install_url_by_install_id[ $install->id ]; $clone_subsite_registration_date = $subsite_registration_date_by_install_id[ $install->id ]; $skip = false; if ( ! empty( $install_data['registration_date'] ) && ! empty( $clone_subsite_registration_date ) ) { /** * If the current subsite was created after the other subsite that is also linked to the same install ID, we assume that it's a clone (not the original), and therefore, would skip its processing. * * @author Leo Fajardo (@leorw) * @since 2.5.1 */ $skip = ( strtotime( $install_data['registration_date'] ) > strtotime( $clone_subsite_registration_date ) ); } else if ( /** * If we already have an install with the same URL as the subsite it's stored in, skip the current subsite. Otherwise, replace the existing install's data with the current subsite's install's data if the URLs match. * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ fs_strip_url_protocol( untrailingslashit( $clone_install_url ) ) === fs_strip_url_protocol( untrailingslashit( $clone_subsite_data['url'] ) ) || fs_strip_url_protocol( untrailingslashit( $install->url ) ) !== fs_strip_url_protocol( untrailingslashit( $url ) ) ) { $skip = true; } if ( $skip ) { // Store the skipped subsite's ID so that the clone resolution manager can try to resolve the clone install that is stored in that subsite later on. FS_Clone_Manager::instance()->store_blog_install_info( $blog_id ); continue; } } unset( $install_data['blog_id'] ); unset( $install_data['uid'] ); unset( $install_data['url'] ); unset( $install_data['registration_date'] ); $install_data['is_active'] = $this->is_active_for_site( $blog_id ); $install_data['is_uninstalled'] = $install->is_uninstalled; $common_diff = null; $is_common_diff = false; if ( $only_diff ) { $install_data = $this->get_install_diff_for_api( $install_data, $install, $override ); $common_diff = $this->get_install_diff_for_api( $common, $install, $override ); $is_common_diff = ! empty( $common_diff ); if ( $is_common_diff ) { foreach ( $common_diff as $k => $v ) { if ( ! isset( $common_diff_union[ $k ] ) ) { $common_diff_union[ $k ] = $v; } } } $is_common_diff_for_any_site = $is_common_diff_for_any_site || $is_common_diff; } if ( ! empty( $install_data ) || $is_common_diff || $is_keepalive ) { // Add install ID and site unique ID. $install_data['id'] = $install->id; $install_data['uid'] = $uid; $install_data['url'] = $url; $subsite_data_for_api_by_install_id[ $install->id ] = $install_data; $install_url_by_install_id[ $install->id ] = $install->url; $subsite_registration_date_by_install_id[ $install->id ] = $registration_date; } } } restore_current_blog(); $installs_data = array_merge( $installs_data, array_values( $subsite_data_for_api_by_install_id ) ); if ( 0 < count( $installs_data ) && ( $is_common_diff_for_any_site || ! $only_diff ) ) { if ( ! $only_diff ) { $installs_data[] = $common; } else if ( ! empty( $common_diff_union ) ) { $installs_data[] = $common_diff_union; } } foreach ( $installs_data as &$data ) { $data = (object) $data; } return $installs_data; } /** * Compare site actual data to the stored install data and return the differences for an API data sync. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param array $site * @param FS_Site $install * @param string[] string $override * * @return array */ private function get_install_diff_for_api( $site, $install, $override = array() ) { $diff = array(); $special = array(); $special_override = false; foreach ( $site as $p => $v ) { if ( property_exists( $install, $p ) ) { if ( ( is_bool( $install->{$p} ) || ! empty( $install->{$p} ) ) && $install->{$p} != $v ) { $val = self::get_api_sanitized_property( $p, $v ); if ( $install->{$p} != $val ) { $install->{$p} = $val; $diff[ $p ] = $val; } } } else { $special[ $p ] = $v; if ( isset( $override[ $p ] ) || 'plugins' === $p || 'themes' === $p ) { $special_override = true; } } } if ( $special_override || 0 < count( $diff ) ) { // Add special params only if has at least one // standard param, or if explicitly requested to // override a special param or a param which is not exist // in the install object. $diff = array_merge( $diff, $special ); } return $diff; } /** * @author Leo Fajardo (@leorw) * @since 2.5.1 */ private function send_pending_clone_update_once() { $this->_logger->entrance(); if ( ! empty( $this->_storage->clone_id ) ) { return; } $install_clone = $this->get_api_site_scope()->call( '/clones', 'post', array( 'site_url' => self::get_unfiltered_site_url() ) ); if ( $this->is_api_result_entity( $install_clone ) ) { $this->_storage->clone_id = $install_clone->id; } } /** * @author Leo Fajardo (@leorw) * @since 2.5.1 * * @param string $resolution_type * @param FS_Site $clone_context_install */ function send_clone_resolution_update( $resolution_type, $clone_context_install ) { $this->_logger->entrance(); if ( empty( $this->_storage->clone_id ) ) { return; } $new_install_id = null; $current_site = null; $flush = false; /** * If the current site is now different from the context install before the clone resolution, we need to override `$this->_site` so that the API call below will be made with the right install scope entity. */ if ( $clone_context_install->id != $this->_site->id ) { $new_install_id = $this->_site->id; $current_site = $this->_site; $this->_site = $clone_context_install; $flush = true; } $this->get_api_site_scope( $flush )->call( "/clones/{$this->_storage->clone_id}", 'put', array( 'resolution' => $resolution_type, 'new_install_id' => $new_install_id, ) ); if ( is_object( $current_site ) ) { /** * Ensure that the install scope entity is updated back to the previous install entity. */ $this->_site = $current_site; // Restore the previous install scope entity of the API. $this->get_api_site_scope( true ); } } /** * Update install only if changed. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string[] string $override * @param bool $flush * @param bool $is_two_way_sync @since 2.5.0 If true and there's a successful API request, the install sync cron will be cleared. * * @return false|object|string */ private function send_install_update( $override = array(), $flush = false, $is_two_way_sync = false ) { $this->_logger->entrance(); $check_properties = $this->get_install_data_for_api( $override ); if ( $flush ) { $params = $check_properties; } else { $params = $this->get_install_diff_for_api( $check_properties, $this->_site, $override ); } if ( empty( $params ) ) { $keepalive_only_update = $this->should_send_keepalive_update(); if ( ! $keepalive_only_update ) { /** * There are no updates to send including keepalive. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ return false; } } if ( $is_two_way_sync ) { /** * Update last install sync timestamp during a two-way sync call as we expect that updates are sent during this call. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ if ( ! is_multisite() ) { // Update last install sync timestamp. $this->set_cron_execution_timestamp( 'install_sync' ); } $params['uid'] = $this->get_anonymous_id(); } $this->set_keepalive_timestamp(); // Send updated values to FS. $site = $this->api_site_call( '/', 'put', $params, true ); if ( $is_two_way_sync && $this->is_api_result_entity( $site ) ) { /** * Clear scheduled install sync after a two-way sync call. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ if ( ! is_multisite() ) { // I successfully sent install update, clear scheduled sync if exist. $this->clear_install_sync_cron(); } } return $site; } /** * Update installs only if changed. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string[] string $override * @param bool $flush * @param bool $is_two_way_sync @since 2.5.0 If true and there's a successful API request, the install sync cron will be cleared. * * @return false|object|string */ private function send_installs_update( $override = array(), $flush = false, $is_two_way_sync = false ) { $this->_logger->entrance(); /** * Pass `true` to use the network level storage since the update is for many installs. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ $should_send_keepalive = $this->should_send_keepalive_update( true ); $installs_data = $this->get_installs_data_for_api( $override, ! $flush, $should_send_keepalive ); if ( empty( $installs_data ) ) { return false; } if ( $is_two_way_sync ) { // Update last install sync timestamp during a two-way sync call as we expect that updates are sent during this call. $this->set_cron_execution_timestamp( 'install_sync' ); } /** * Pass `true` to use the network level storage since the update is for many installs. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ $this->set_keepalive_timestamp( true ); // Send updated values to FS. $result = $this->get_api_user_scope()->call( "/plugins/{$this->_plugin->id}/installs.json", 'put', $installs_data ); if ( $is_two_way_sync && $this->is_api_result_object( $result, 'installs' ) ) { // I successfully sent a two-way installs update, clear the scheduled install sync if it exists. $this->clear_install_sync_cron(); } return $result; } /** * @author Leo Fajardo (@leorw) * * @param bool|null $use_network_level_storage * * @return bool */ private function should_send_keepalive_update( $use_network_level_storage = null ) { $keepalive_timestamp = $this->_storage->get( 'keepalive_timestamp', 0, $use_network_level_storage ); if ( $keepalive_timestamp < ( time() - WP_FS__TIME_WEEK_IN_SEC ) ) { // If updated more than 7 days ago, trigger a keepalive and update the time it was triggered. return true; } else { // If updated 7 days ago or less, "flip a coin", if the value is 7 trigger a keepalive and update the last time it was triggered. return ( 7 == rand( 1, 7 ) ); } } /** * Syncs the install owner's data if needed (i.e., if the install owner is different from the loaded user). * * @author Leo Fajardo (@leorw) * @since 2.3.2 */ private function maybe_sync_install_user() { if ( $this->_user->id == $this->_site->user_id ) { return; } // Fetch user data and store if found. $this->sync_user_by_current_install(); } /** * Update install only if changed. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string[] string $override * @param bool $flush */ function sync_install( $override = array(), $flush = false ) { $this->_logger->entrance(); $site = $this->send_install_update( $override, $flush, true ); if ( false === $site ) { // No sync required. return; } if ( ! $this->is_api_result_entity( $site ) ) { // Failed to sync, don't update locally. return; } $this->_site = new FS_Site( $site ); $this->_store_site( true ); } /** * Update install only if changed. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string[] string $override * @param bool $flush */ private function sync_installs( $override = array(), $flush = false ) { $this->_logger->entrance(); $result = $this->send_installs_update( $override, $flush, true ); if ( false === $result ) { // No sync required. return; } if ( ! $this->is_api_result_object( $result, 'installs' ) ) { // Failed to sync, don't update locally. return; } $address_to_blog_map = $this->get_address_to_blog_map(); foreach ( $result->installs as $install ) { $this->_site = new FS_Site( $install ); $address = trailingslashit( fs_strip_url_protocol( $install->url ) ); $blog_id = $address_to_blog_map[ $address ]; $this->_store_site( true, $blog_id ); } } /** * Track install's custom event. * * IMPORTANT: * Custom event tracking is currently only supported for specific clients. * If you are not one of them, please don't use this method. If you will, * the API will simply ignore your request based on the plugin ID. * * Need custom tracking for your plugin or theme? * If you are interested in custom event tracking please contact yo@freemius.com * for further details. * * @author Vova Feldman (@svovaf) * @since 1.2.1 * * @param string $name Event name. * @param array $properties Associative key/value array with primitive values only * @param bool $process_at A valid future date-time in the following format Y-m-d H:i:s. * @param bool $once If true, event will be tracked only once. IMPORTANT: Still trigger the API call. * * @return object|false Event data or FALSE on failure. * * @throws \Freemius_InvalidArgumentException */ public function track_event( $name, $properties = array(), $process_at = false, $once = false ) { $this->_logger->entrance( http_build_query( array( 'name' => $name, 'once' => $once ) ) ); if ( ! $this->is_registered() ) { return false; } $event = array( 'type' => $name ); if ( is_numeric( $process_at ) && $process_at > time() ) { $event['process_at'] = $process_at; } if ( $once ) { $event['once'] = true; } if ( ! empty( $properties ) ) { // Verify associative array values are primitive. foreach ( $properties as $k => $v ) { if ( ! is_scalar( $v ) ) { throw new Freemius_InvalidArgumentException( 'The $properties argument must be an associative key/value array with primitive values only.' ); } } $event['properties'] = $properties; } $result = $this->get_api_site_scope()->call( 'events.json', 'post', $event ); return $this->is_api_error( $result ) ? false : $result; } /** * Track install's custom event only once, but it still triggers the API call. * * IMPORTANT: * Custom event tracking is currently only supported for specific clients. * If you are not one of them, please don't use this method. If you will, * the API will simply ignore your request based on the plugin ID. * * Need custom tracking for your plugin or theme? * If you are interested in custom event tracking please contact yo@freemius.com * for further details. * * @author Vova Feldman (@svovaf) * @since 1.2.1 * * @param string $name Event name. * @param array $properties Associative key/value array with primitive values only * @param bool $process_at A valid future date-time in the following format Y-m-d H:i:s. * * @return object|false Event data or FALSE on failure. * * @throws \Freemius_InvalidArgumentException * * @user Freemius::track_event() */ public function track_event_once( $name, $properties = array(), $process_at = false ) { return $this->track_event( $name, $properties, $process_at, true ); } /** * Plugin uninstall hook. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param bool $check_user Enforce checking if user have plugins activation privileges. */ function _uninstall_plugin_event( $check_user = true ) { $this->_logger->entrance( 'slug = ' . $this->_slug ); if ( $check_user && ! current_user_can( 'activate_plugins' ) ) { return; } $params = array(); $uninstall_reason = null; if ( isset( $this->_storage->uninstall_reason ) ) { $uninstall_reason = $this->_storage->uninstall_reason; $params['reason_id'] = $uninstall_reason->id; $params['reason_info'] = $uninstall_reason->info; } if ( ! $this->is_registered() ) { // Send anonymous uninstall event only if user submitted a feedback. if ( isset( $uninstall_reason ) ) { if ( isset( $uninstall_reason->is_anonymous ) && ! $uninstall_reason->is_anonymous ) { $this->opt_in( false, false, false, false, true ); } else { $params['uid'] = $this->get_anonymous_id(); $this->get_api_plugin_scope()->call( 'uninstall.json', 'put', $params ); } } } else { $params = array_merge( $params, array( 'is_active' => false, 'is_uninstalled' => true, ) ); if ( $this->_is_network_active ) { // Send uninstall event. $this->send_installs_update( $params ); } else { // Send uninstall event and handle the result. $this->sync_install( $params ); } } // @todo Decide if we want to delete plugin information from db. } /** * Set the basename of the current product and hook _activate_plugin_event_hook() to the activation action. * * @author Vova Feldman (@svovaf) * @since 2.2.1 * * @param string $is_premium * @param string $caller * * @return string */ function set_basename( $is_premium, $caller ) { $basename = plugin_basename( $caller ); $current_basename = $is_premium ? $this->_premium_plugin_basename : $this->_free_plugin_basename; if ( $current_basename == $basename ) { // Basename value set correctly. return; } if ( $is_premium ) { $this->_premium_plugin_basename = $basename; } else { $this->_free_plugin_basename = $basename; } $plugin_dir = dirname( $this->_plugin_dir_path ) . '/'; register_activation_hook( $plugin_dir . $basename, array( &$this, '_activate_plugin_event_hook' ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.1 * @since 2.2.1 If the context product is in its premium version, use the current module's basename, even if it was renamed. * * @return string */ function premium_plugin_basename() { if ( ! isset( $this->_premium_plugin_basename ) ) { $this->_premium_plugin_basename = $this->is_premium() ? // The product is premium, so use the current basename. $this->_plugin_basename : $this->get_premium_slug() . '/' . basename( $this->_free_plugin_basename ); } return $this->_premium_plugin_basename; } /** * Uninstall plugin hook. Called only when connected his account with Freemius for active sites tracking. * * @author Vova Feldman (@svovaf) * @since 1.0.2 */ public static function _uninstall_plugin_hook() { self::_load_required_static(); self::$_static_logger->entrance(); if ( ! current_user_can( 'activate_plugins' ) ) { return; } $plugin_file = substr( current_filter(), strlen( 'uninstall_' ) ); self::$_static_logger->info( 'plugin = ' . $plugin_file ); define( 'WP_FS__UNINSTALL_MODE', true ); $fs = self::get_instance_by_file( $plugin_file ); if ( is_object( $fs ) ) { $fs->remove_sdk_reference(); self::require_plugin_essentials(); if ( is_plugin_active( $fs->_free_plugin_basename ) || is_plugin_active( $fs->premium_plugin_basename() ) ) { // Deleting Free or Premium plugin version while the other version still installed. return; } if ( ! $fs->is_clone() && /** * If there's a context install, run this method only when there's also a context user (e.g., when cloning a subsite of a multisite network into a single-site installation, it's possible for an install to be associated with a non-existing user entity; we want Freemius to be off in this case, while we are trying to recover the user). * * @author Leo Fajardo */ ( ! is_object( $fs->_site ) || $fs->is_registered() ) ) { $fs->_uninstall_plugin_event(); } $fs->do_action( 'after_uninstall' ); } } #---------------------------------------------------------------------------------- #region Plugin Information #---------------------------------------------------------------------------------- /** * Load WordPress core plugin.php essential module. * * @author Vova Feldman (@svovaf) * @since 1.1.1 */ private static function require_plugin_essentials() { if ( ! function_exists( 'get_plugins' ) ) { self::$_static_logger->log( 'Including wp-admin/includes/plugin.php...' ); require_once ABSPATH . 'wp-admin/includes/plugin.php'; } } /** * Load WordPress core pluggable.php module. * * @author Vova Feldman (@svovaf) * @since 1.1.2 */ private static function require_pluggable_essentials() { if ( ! function_exists( 'wp_get_current_user' ) ) { require_once ABSPATH . 'wp-includes/pluggable.php'; } } /** * Return plugin data. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param bool $reparse_plugin_metadata * * @return array */ function get_plugin_data( $reparse_plugin_metadata = false ) { if ( ! isset( $this->_plugin_data ) || $reparse_plugin_metadata ) { self::require_plugin_essentials(); if ( $this->is_plugin() ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.0 When using get_plugin_data() do NOT translate plugin data. * * @link https://github.com/Freemius/wordpress-sdk/issues/77 */ $plugin_data = get_plugin_data( $this->_plugin_main_file_path, false, false ); } else { $theme_data = wp_get_theme(); if ( $this->_plugin_basename !== $theme_data->get_stylesheet() && is_child_theme() ) { $parent_theme = $theme_data->parent(); if ( ( $parent_theme instanceof WP_Theme ) && $this->_plugin_basename === $parent_theme->get_stylesheet() ) { $theme_data = $parent_theme; } } $plugin_data = array( 'Name' => $theme_data->get( 'Name' ), 'Version' => $theme_data->get( 'Version' ), 'Author' => $theme_data->get( 'Author' ), 'Description' => $theme_data->get( 'Description' ), 'PluginURI' => $theme_data->get( 'ThemeURI' ), ); } $this->_plugin_data = $plugin_data; } return $this->_plugin_data; } /** * @author Vova Feldman (@svovaf) * @since 1.0.1 * @since 1.2.2.5 If slug not set load slug by module ID. * * @return string Plugin slug. */ function get_slug() { if ( ! isset( $this->_slug ) ) { $id_slug_type_path_map = self::$_accounts->get_option( 'id_slug_type_path_map', array() ); $this->_slug = $id_slug_type_path_map[ $this->_module_id ]['slug']; } return $this->_slug; } /** * @author Leo Fajardo (@leorw) * @since 2.2.1 * * @return string */ function get_premium_slug() { return ( is_object( $this->_plugin ) && ! empty( $this->_plugin->premium_slug ) ) ? $this->_plugin->premium_slug : "{$this->_slug}-premium"; } /** * Retrieve the desired folder name for the product. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @return string Plugin slug. */ function get_target_folder_name() { return $this->can_use_premium_code() ? $this->_plugin->premium_slug : $this->_slug; } /** * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @return number Plugin ID. */ function get_id() { return $this->_plugin->id; } /** * @author Leo Fajardo (@leorw) * @since 2.2.4 * * @return number|null Bundle ID. */ function get_bundle_id() { return ( isset( $this->_plugin->bundle_id ) && FS_Plugin::is_valid_id( $this->_plugin->bundle_id ) ) ? $this->_plugin->bundle_id : null; } /** * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @return string|null Bundle public key. */ function get_bundle_public_key() { return isset( $this->_plugin->bundle_public_key ) ? $this->_plugin->bundle_public_key : null; } /** * Get whether the SDK has been initiated in the context of a Bundle. * * This will return true, if `bundle_id` is present in the SDK init parameters. * * ```php * $my_fs = fs_dynamic_init( array( * // ... * 'bundle_id' => 'XXXX', // Will return true since we have bundle id. * 'bundle_public_key' => 'pk_XXXX', * ) ); * ``` * * @author Swashata Ghosh (@swashata) * @since 2.5.0 * * @return bool True if we are running in bundle context, false otherwise. */ private function has_bundle_context() { return ! is_null( $this->get_bundle_id() ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @return string Freemius SDK version */ function get_sdk_version() { return $this->version; } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @return number Parent plugin ID (if parent exist). */ function get_parent_id() { return $this->is_addon() ? $this->get_parent_instance()->get_id() : $this->_plugin->id; } /** * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @return string */ function get_usage_tracking_terms_url() { return $this->apply_filters( 'usage_tracking_terms_url', "https://freemius.com/product/opt-in/{$this->_plugin->id}/{$this->_slug}/" ); } /** * @todo (For LiteSDK) We can refactor this and other related functions giving links to several landing pages on freemius.com to come from a separate class like `FS_Terms_Pages`. This would get a `FS_WP_Hook` (hypothetical) instance as a dependency and use it to hook into the `license_activation_terms_url` or related filters. The entry level instance from `ms_fs()` would hold a public read-only variable `my_fs()->terms_pages` which would be an instance of `FS_Terms_Pages` and would hold all the links to the terms pages. * @since 2.5.8 * * @return string */ function get_license_activation_terms_url() { return $this->apply_filters( 'license_activation_terms_url', "https://freemius.com/product/license-activation/{$this->_plugin->id}/{$this->_slug}/" ); } /** * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @return string */ function get_eula_url() { return $this->apply_filters( 'eula_url', "https://freemius.com/product/{$this->_plugin->id}/{$this->_slug}/legal/eula/" ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @return string Plugin public key. */ function get_public_key() { return $this->_plugin->public_key; } /** * Will be available only on sandbox mode. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @return mixed Plugin secret key. */ function get_secret_key() { return $this->_plugin->secret_key; } /** * @author Vova Feldman (@svovaf) * @since 1.1.1 * * @return bool */ function has_secret_key() { return ! empty( $this->_plugin->secret_key ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string|bool $premium_suffix * * @return string */ function get_plugin_name( $premium_suffix = false ) { $this->_logger->entrance(); /** * This `if-else` can be squeezed into a single `if` but I intentionally split it for code readability. * * @author Vova Feldman */ if ( ! isset( $this->_plugin_name ) ) { // Name is not yet set. $this->set_name( $premium_suffix ); } else if ( ! empty( $premium_suffix ) && ( ! is_object( $this->_plugin ) || $this->_plugin->premium_suffix !== $premium_suffix ) ) { // Name is already set, but there's a change in the premium suffix. $this->set_name( $premium_suffix ); } return $this->_plugin_name; } /** * Calculates and stores the product's name. This helper function was created specifically for get_plugin_name() just to make the code clearer. * * @author Vova Feldman (@svovaf) * @since 2.2.1 * * @param string $premium_suffix */ private function set_name( $premium_suffix = '' ) { $plugin_data = $this->get_plugin_data(); // Get name. $this->_plugin_name = $plugin_data['Name']; if ( is_string( $premium_suffix ) ) { $premium_suffix = trim( $premium_suffix ); if ( ! empty( $premium_suffix ) ) { // Check if plugin name contains " (premium)" or a custom suffix and remove it. $suffix = ( ' ' . strtolower( $premium_suffix ) ); $suffix_len = strlen( $suffix ); if ( strlen( $plugin_data['Name'] ) > $suffix_len && $suffix === substr( strtolower( $plugin_data['Name'] ), - $suffix_len ) ) { $this->_plugin_name = substr( $plugin_data['Name'], 0, - $suffix_len ); } } } $this->_logger->departure( 'Name = ' . $this->_plugin_name ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.0 * * @param bool $reparse_plugin_metadata * * @return string */ function get_plugin_version( $reparse_plugin_metadata = false ) { $this->_logger->entrance(); $plugin_data = $this->get_plugin_data( $reparse_plugin_metadata ); $this->_logger->departure( 'Version = ' . $plugin_data['Version'] ); return $this->apply_filters( 'plugin_version', $plugin_data['Version'] ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @return string */ function get_plugin_title() { $this->_logger->entrance(); $title = $this->_plugin->title; return $this->apply_filters( 'plugin_title', $title ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @param bool $lowercase * * @return string */ function get_module_label( $lowercase = false ) { $label = $this->is_addon() ? $this->get_text_inline( 'Add-On', 'addon' ) : ( $this->is_plugin() ? $this->get_text_inline( 'Plugin', 'plugin' ) : $this->get_text_inline( 'Theme', 'theme' ) ); if ( $lowercase ) { $label = strtolower( $label ); } return $label; } /** * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @return string */ function get_plugin_basename() { if ( ! isset( $this->_plugin_basename ) ) { if ( $this->is_plugin() ) { $this->_plugin_basename = plugin_basename( $this->_plugin_main_file_path ); } else { $this->_plugin_basename = basename( dirname( $this->_plugin_main_file_path ) ); } } return $this->_plugin_basename; } function get_plugin_folder_name() { $this->_logger->entrance(); $plugin_folder = $this->_plugin_basename; while ( '.' !== dirname( $plugin_folder ) ) { $plugin_folder = dirname( $plugin_folder ); } $this->_logger->departure( 'Folder Name = ' . $plugin_folder ); return $plugin_folder; } #endregion ------------------------------------------------------------------ /* Account ------------------------------------------------------------------------------------------------------------------*/ /** * Find plugin's slug by plugin's basename. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string $plugin_base_name * * @return false|string */ private static function find_slug_by_basename( $plugin_base_name ) { $file_slug_map = self::$_accounts->get_option( 'file_slug_map', array() ); if ( ! array( $file_slug_map ) || ! isset( $file_slug_map[ $plugin_base_name ] ) ) { return false; } return $file_slug_map[ $plugin_base_name ]; } /** * Store the map between the plugin's basename to the slug. * * @author Vova Feldman (@svovaf) * @since 1.0.9 */ private function store_file_slug_map() { $file_slug_map = self::$_accounts->get_option( 'file_slug_map', array() ); if ( ! array( $file_slug_map ) ) { $file_slug_map = array(); } if ( ! isset( $file_slug_map[ $this->_plugin_basename ] ) || $file_slug_map[ $this->_plugin_basename ] !== $this->_slug ) { $file_slug_map[ $this->_plugin_basename ] = $this->_slug; self::$_accounts->set_option( 'file_slug_map', $file_slug_map, true ); } } /** * @return array[number]FS_User */ static function get_all_users() { $users = self::maybe_get_entities_account_option( 'users', array() ); if ( ! is_array( $users ) ) { $users = array(); } return $users; } /** * @param string $module_type * @param null|int $blog_id Since 2.0.0 * * @return array[string]FS_Site */ private static function get_all_sites( $module_type = WP_FS__MODULE_TYPE_PLUGIN, $blog_id = null, $is_backup = false ) { $sites = self::get_account_option( ( $is_backup ? 'prev_' : '' ) . 'sites', $module_type, $blog_id ); if ( ! is_array( $sites ) ) { $sites = array(); } return $sites; } /** * @author Leo Fajardo (@leorw) * * @since 1.2.2 * * @param string $option_name * @param string $module_type * @param null|int $network_level_or_blog_id Since 2.0.0 * * @return mixed */ private static function get_account_option( $option_name, $module_type = null, $network_level_or_blog_id = null ) { if ( ! is_null( $module_type ) && WP_FS__MODULE_TYPE_PLUGIN !== $module_type ) { $option_name = $module_type . '_' . $option_name; } return self::maybe_get_entities_account_option( $option_name, array(), $network_level_or_blog_id ); } /** * @author Leo Fajardo (@leorw) * * @since 1.2.2 * * @param string $option_name * @param mixed $option_value * @param bool $store * @param null|int $network_level_or_blog_id Since 2.0.0 */ private function set_account_option( $option_name, $option_value, $store, $network_level_or_blog_id = null ) { self::set_account_option_by_module( $this->_module_type, $option_name, $option_value, $store, $network_level_or_blog_id ); } /** * @author Vova Feldman (@svovaf) * * @since 1.2.2.7 * * @param string $module_type * @param string $option_name * @param mixed $option_value * @param bool $store * @param null|int $network_level_or_blog_id Since 2.0.0 */ private static function set_account_option_by_module( $module_type, $option_name, $option_value, $store, $network_level_or_blog_id = null ) { if ( WP_FS__MODULE_TYPE_PLUGIN != $module_type ) { $option_name = $module_type . '_' . $option_name; } self::$_accounts->set_option( $option_name, $option_value, $store, $network_level_or_blog_id ); } /** * This method can also return non-entity or non-entities collection option like the `user_id_license_ids_map` option. * * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @param string $option_name * @param mixed $default * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS). * * @return mixed|FS_Plugin[]|FS_User[]|FS_Site[]|FS_Plugin_License[]|FS_Plugin_Plan[]|FS_Plugin_Tag[] */ private static function maybe_get_entities_account_option( $option_name, $default = null, $network_level_or_blog_id = null ) { $option = self::$_accounts->get_option( $option_name, $default, $network_level_or_blog_id ); $class_name = ''; if ( fs_starts_with( $option_name, WP_FS__MODULE_TYPE_THEME . '_' ) ) { $option_name = str_replace( WP_FS__MODULE_TYPE_THEME . '_', '', $option_name ); } switch ( $option_name ) { case 'plugins': case 'themes': case 'addons': $class_name = FS_Plugin::get_class_name(); break; case 'users': $class_name = FS_User::get_class_name(); break; case 'sites': $class_name = FS_Site::get_class_name(); break; case 'licenses': case 'all_licenses': $class_name = FS_Plugin_License::get_class_name(); break; case 'plans': $class_name = FS_Plugin_Plan::get_class_name(); break; case 'updates': $class_name = FS_Plugin_Tag::get_class_name(); break; } if ( empty( $class_name ) ) { return $option; } return fs_get_entities( $option, $class_name ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param number|null $module_id * * @return FS_Plugin_License[] */ private static function get_all_licenses( $module_id = null ) { $licenses = self::get_account_option( 'all_licenses' ); if ( ! is_array( $licenses ) ) { $licenses = array(); } if ( is_null( $module_id ) ) { return $licenses; } $licenses = isset( $licenses[ $module_id ] ) ? $licenses[ $module_id ] : array(); return $licenses; } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @return array */ private static function get_all_licenses_by_module_type() { $licenses = self::get_account_option( 'all_licenses' ); $licenses_by_module_type = array( WP_FS__MODULE_TYPE_PLUGIN => array(), WP_FS__MODULE_TYPE_THEME => array() ); if ( ! is_array( $licenses ) ) { return $licenses_by_module_type; } foreach ( $licenses as $module_id => $module_licenses ) { $fs = self::get_instance_by_id( $module_id ); if ( false === $fs ) { continue; } $licenses_by_module_type[ $fs->_module_type ] = array_merge( $licenses_by_module_type[ $fs->_module_type ], $module_licenses ); } return $licenses_by_module_type; } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param number $module_id * @param number|null $user_id * * @return array */ private static function get_user_id_license_ids_map( $module_id, $user_id = null ) { $all_modules_user_id_license_ids_map = self::get_account_option( 'user_id_license_ids_map' ); if ( ! is_array( $all_modules_user_id_license_ids_map ) ) { $all_modules_user_id_license_ids_map = array(); } $user_id_license_ids_map = isset( $all_modules_user_id_license_ids_map[ $module_id ] ) ? $all_modules_user_id_license_ids_map[ $module_id ] : array(); if ( FS_User::is_valid_id( $user_id ) ) { $user_id_license_ids_map = isset( $user_id_license_ids_map[ $user_id ] ) ? $user_id_license_ids_map[ $user_id ] : array(); } return $user_id_license_ids_map; } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param array $new_user_id_license_ids_map * @param number $module_id * @param number|null $user_id */ private static function store_user_id_license_ids_map( $new_user_id_license_ids_map, $module_id, $user_id = null ) { $all_modules_user_id_license_ids_map = self::get_account_option( 'user_id_license_ids_map' ); if ( ! is_array( $all_modules_user_id_license_ids_map ) ) { $all_modules_user_id_license_ids_map = array(); } if ( ! isset( $all_modules_user_id_license_ids_map[ $module_id ] ) ) { $all_modules_user_id_license_ids_map[ $module_id ] = array(); } if ( FS_User::is_valid_id( $user_id ) ) { $all_modules_user_id_license_ids_map[ $module_id ][ $user_id ] = $new_user_id_license_ids_map; } else { $all_modules_user_id_license_ids_map[ $module_id ] = $new_user_id_license_ids_map; } self::$_accounts->set_option( 'user_id_license_ids_map', $all_modules_user_id_license_ids_map, true ); } /** * Get a collection of the user's linked license IDs. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $user_id * * @return number[] */ private function get_user_linked_license_ids( $user_id ) { return self::get_user_id_license_ids_map( $this->_module_id, $user_id ); } /** * Override the user's linked license IDs with a new IDs collection. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $user_id * @param number[] $license_ids */ private function set_user_linked_license_ids( $user_id, array $license_ids ) { self::store_user_id_license_ids_map( $license_ids, $this->_module_id, $user_id ); } /** * Link a specified license ID to a given user. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $license_id * @param number $user_id */ private function link_license_2_user( $license_id, $user_id ) { $license_ids = $this->get_user_linked_license_ids( $user_id ); if ( in_array( $license_id, $license_ids ) ) { // License already linked. return; } $license_ids[] = $license_id; $this->set_user_linked_license_ids( $user_id, $license_ids ); } /** * @param string|bool $module_type * * @return FS_Plugin_Plan[] */ private static function get_all_plans( $module_type = false ) { $plans = self::get_account_option( 'plans', $module_type ); if ( ! is_array( $plans ) ) { $plans = array(); } return $plans; } /** * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @return FS_Plugin_Tag[] */ private static function get_all_updates() { $updates = self::maybe_get_entities_account_option( 'updates', array() ); if ( ! is_array( $updates ) ) { $updates = array(); } return $updates; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return array|false */ private static function get_all_addons() { $addons = self::maybe_get_entities_account_option( 'addons', array() ); if ( ! is_array( $addons ) ) { $addons = array(); } return $addons; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return number[]|false */ private static function get_all_account_addons() { $addons = self::$_accounts->get_option( 'account_addons', array() ); if ( ! is_array( $addons ) ) { $addons = array(); } return $addons; } /** * Check if user has connected his account (opted-in). * * Note: * If the user opted-in and opted-out on a later stage, * this will still return true. If you want to check if the * user is currently opted-in, use: * `$fs->is_registered() && $fs->is_tracking_allowed()` * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param bool $ignore_anonymous_state Since 2.5.1 * * @return bool */ function is_registered( $ignore_anonymous_state = false ) { return ( is_object( $this->_user ) && ( $this->is_premium() || $ignore_anonymous_state || ! $this->is_anonymous() ) ); } /** * Returns TRUE if the user opted-in and didn't disconnect (opt-out). * * @author Leo Fajardo (@leorw) * @since 1.2.1.5 * * @return bool */ function is_tracking_allowed( $blog_id = null, $install = null ) { if ( is_null( $install ) ) { $install = is_null( $blog_id ) ? $this->_site : $this->get_install_by_blog_id( $blog_id ); } return ( is_object( $install ) && FS_Permission_Manager::instance( $this )->is_homepage_url_tracking_allowed( $blog_id ) ); } /** * Returns TRUE if the user never opted-in or manually opted-out. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param int|null $blog_id * * @return bool */ function is_tracking_prohibited( $blog_id = null ) { return ( ! $this->is_registered( true ) || ! $this->is_tracking_allowed( $blog_id ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.4.0 * * @return bool */ function is_bundle_license_auto_activation_enabled() { return $this->is_addon() ? ( is_object( $this->_parent ) && $this->_parent->is_bundle_license_auto_activation_enabled() ) : $this->_is_bundle_license_auto_activation_enabled; } /** * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @return FS_Plugin */ function get_plugin() { return $this->_plugin; } /** * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @return FS_User */ function get_user() { return $this->_user; } /** * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @return FS_Site */ function get_site() { return $this->_site; } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function store_site( $site ) { $this->_site = $site; $this->_store_site( true ); } /** * Deletes the current install with an option to back it up in case restoration will be needed (e.g., if the automatic clone resolution attempt fails). * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function delete_current_install( $back_up ) { // Back up and delete the unique ID. if ( $back_up ) { self::$_accounts->set_option( 'prev_unique_id', $this->get_anonymous_id() ); } self::$_accounts->set_option( 'unique_id', null ); if ( $back_up ) { // Back up the install before deleting it so that it can be restored later on if necessary (e.g., if the automatic clone resolution attempt fails). $this->back_up_site(); } $this->_delete_site(); $this->_site = null; } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function restore_backup_site() { self::$_accounts->set_option( 'unique_id', self::$_accounts->get_option( 'prev_unique_id' ) ); $sites = self::get_all_sites( $this->_module_type, null, true ); $this->store_site( clone $sites[ $this->_slug ] ); } /** * Get plugin add-ons. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @since 1.1.7.3 If not yet loaded, fetch data from the API. * * @param bool $flush * * @return FS_Plugin[]|false */ function get_addons( $flush = false ) { $this->_logger->entrance(); if ( ! $this->_has_addons ) { return false; } $addons = $this->sync_addons( $flush ); return ( ! is_array( $addons ) || empty( $addons ) ) ? false : $addons; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return number[]|false */ function get_account_addons() { $this->_logger->entrance(); $addons = self::get_all_account_addons(); if ( ! is_array( $addons ) || ! isset( $addons[ $this->_plugin->id ] ) || ! is_array( $addons[ $this->_plugin->id ] ) || 0 === count( $addons[ $this->_plugin->id ] ) ) { return false; } return $addons[ $this->_plugin->id ]; } /** * Check if user has any * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @return bool */ function has_account_addons() { $addons = $this->get_account_addons(); return is_array( $addons ) && ( 0 < count( $addons ) ); } /** * Get add-on by ID (from local data). * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param number $id * * @return FS_Plugin|false */ function get_addon( $id ) { $this->_logger->entrance(); $addons = $this->get_addons(); if ( is_array( $addons ) ) { foreach ( $addons as $addon ) { if ( $id == $addon->id ) { return $addon; } } } return false; } /** * Get add-on by slug (from local data). * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param string $slug * * @param bool $flush * * @return FS_Plugin|false */ function get_addon_by_slug( $slug, $flush = false ) { $this->_logger->entrance(); $addons = $this->get_addons( $flush ); if ( is_array( $addons ) ) { foreach ( $addons as $addon ) { if ( $slug === $addon->slug ) { return $addon; } } } return false; } /** * @var array { * @key number Add-on ID. * @val object[] The add-on's plans and prices object. * } */ private $plans_and_pricing_by_addon_id; /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @return array { * @key number Add-on ID. * @val object[] The add-on's plans and prices object. * } */ function _get_addons_plans_and_pricing_map_by_id() { if ( ! isset( $this->plans_and_pricing_by_addon_id ) ) { $result = $this->get_api_plugin_scope()->get( $this->add_show_pending( "/addons/pricing.json?type=visible" ) ); $plans_and_pricing_by_addon_id = array(); if ( $this->is_api_result_object( $result, 'addons' ) ) { foreach ( $result->addons as $addon ) { $plans_and_pricing_by_addon_id[ $addon->id ] = $addon->plans; } } $this->plans_and_pricing_by_addon_id = $plans_and_pricing_by_addon_id; } return $this->plans_and_pricing_by_addon_id; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param number $addon_id * @param bool $is_installed * * @return array */ function _get_addon_info( $addon_id, $is_installed ) { $addon = $this->get_addon( $addon_id ); if ( ! is_object( $addon ) ) { // Unexpected call. return array(); } $slug = $addon->slug; $addon_storage = FS_Storage::instance( WP_FS__MODULE_TYPE_PLUGIN, $slug ); if ( ! fs_is_network_admin() ) { // Get blog-level activated installations. $sites = self::maybe_get_entities_account_option( 'sites', array() ); } else { $sites = null; if ( $this->is_addon_activated( $addon_id ) && $this->get_addon_instance( $addon_id )->is_network_active() ) { if ( FS_Site::is_valid_id( $addon_storage->network_install_blog_id ) ) { // Get network-level activated installations. $sites = self::maybe_get_entities_account_option( 'sites', array(), $addon_storage->network_install_blog_id ); } } } $addon_info = array( 'is_connected' => false, 'slug' => $slug, 'title' => $addon->title, 'is_whitelabeled' => $addon_storage->is_whitelabeled ); if ( ! $is_installed ) { $plans_and_pricing_by_addon_id = $this->_get_addons_plans_and_pricing_map_by_id(); if ( isset( $plans_and_pricing_by_addon_id[ $addon_id ] ) ) { $has_paid_plan = false; $plans = $plans_and_pricing_by_addon_id[ $addon_id ]; if ( is_array( $plans ) && count( $plans ) > 0 ) { foreach ( $plans as $plan ) { if ( isset( $plan->pricing ) && is_array( $plan->pricing ) && count( $plan->pricing ) > 0 ) { $has_paid_plan = true; break; } } } $addon_info['has_paid_plan'] = $has_paid_plan; } } if ( ! is_array( $sites ) || ! isset( $sites[ $slug ] ) ) { return $addon_info; } $site = $sites[ $slug ]; $addon_info['is_connected'] = ( ( $addon->parent_plugin_id == $this->get_id() ) && is_object( $site ) && FS_Site::is_valid_id( $site->id ) && FS_User::is_valid_id( $site->user_id ) && FS_Plugin_Plan::is_valid_id( $site->plan_id ) ); if ( $addon_info['is_connected'] && $is_installed ) { return $addon_info; } $addon_info['site'] = $site; $plugins_data = self::maybe_get_entities_account_option( WP_FS__MODULE_TYPE_PLUGIN . 's', array() ); if ( isset( $plugins_data[ $slug ] ) ) { $plugin_data = $plugins_data[ $slug ]; $addon_info['version'] = $plugin_data->version; } $all_plans = self::maybe_get_entities_account_option( 'plans', array() ); if ( isset( $all_plans[ $slug ] ) ) { $plans = $all_plans[ $slug ]; foreach ( $plans as $plan ) { if ( $site->plan_id == Freemius::_decrypt( $plan->id ) ) { $addon_info['plan_name'] = Freemius::_decrypt( $plan->name ); $addon_info['plan_title'] = Freemius::_decrypt( $plan->title ); break; } } } $licenses = self::maybe_get_entities_account_option( 'all_licenses', array() ); if ( is_array( $licenses ) && isset( $licenses[ $addon_id ] ) ) { foreach ( $licenses[ $addon_id ] as $license ) { if ( $license->id == $site->license_id ) { $addon_info['license'] = $license; break; } } } if ( isset( $addon_info['license'] ) ) { if ( isset( $addon_storage->subscriptions ) && ! empty( $addon_storage->subscriptions ) ) { $addon_subscriptions = fs_get_entities( $addon_storage->subscriptions, FS_Subscription::get_class_name() ); foreach ( $addon_subscriptions as $subscription ) { if ( $subscription->license_id == $site->license_id ) { $addon_info['subscription'] = $subscription; break; } } } } return $addon_info; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $user_id * * @return FS_User */ static function _get_user_by_id( $user_id ) { self::$_static_logger->entrance( "user_id = {$user_id}" ); $users = self::get_all_users(); if ( is_array( $users ) ) { if ( isset( $users[ $user_id ] ) && $users[ $user_id ] instanceof FS_User && $user_id == $users[ $user_id ]->id ) { return $users[ $user_id ]; } // If user wasn't found by the key, iterate over all the users collection. foreach ( $users as $user ) { /** * @var FS_User $user */ if ( $user_id == $user->id ) { return $user; } } } return null; } /** * Checks if a Freemius user_id is associated with a super-admin. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $user_id * * @return bool */ private static function is_super_admin( $user_id ) { $is_super_admin = false; $user = self::_get_user_by_id( $user_id ); if ( $user instanceof FS_User && ! empty( $user->email ) ) { self::require_pluggable_essentials(); $wp_user = get_user_by( 'email', $user->email ); if ( $wp_user instanceof WP_User ) { $super_admins = get_super_admins(); $is_super_admin = ( is_array( $super_admins ) && in_array( $wp_user->user_login, $super_admins ) ); } } return $is_super_admin; } #---------------------------------------------------------------------------------- #region Plans & Licensing #---------------------------------------------------------------------------------- /** * Check if running premium plugin code. * * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @return bool */ function is_premium() { /** * `$this->_plugin` will be `false` when `is_activation_mode` calls this method directly from the * `register_constructor_hooks` method. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ return is_object( $this->_plugin ) ? $this->_plugin->is_premium : false; } /** * Get site's plan ID. * * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @return number */ function get_plan_id() { return $this->_site->plan_id; } /** * Get site's plan title. * * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @return string */ function get_plan_title() { $plan = $this->get_plan(); return is_object( $plan ) ? $plan->title : 'PLAN_TITLE'; } /** * Get site's plan name. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return string */ function get_plan_name() { $plan = $this->get_plan(); return is_object( $plan ) ? $plan->name : 'PLAN_NAME'; } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return FS_Plugin_Plan|false */ function get_plan() { if ( ! is_object( $this->_site ) ) { return false; } return FS_Plugin_Plan::is_valid_id( $this->_site->plan_id ) ? $this->_get_plan_by_id( $this->_site->plan_id ) : false; } /** * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @return bool */ function is_trial() { $this->_logger->entrance(); if ( ! $this->is_registered( true ) || ! is_object( $this->_site ) ) { return false; } return $this->_site->is_trial(); } /** * Check if currently in a trial with payment method (credit card or paypal). * * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @return bool */ function is_paid_trial() { $this->_logger->entrance(); if ( ! $this->is_trial() ) { return false; } if ( ! $this->has_active_valid_license() ) { return false; } if ( $this->_site->trial_plan_id != $this->_license->plan_id ) { return false; } /** * @var FS_Subscription $subscription */ $subscription = $this->_get_subscription( $this->_license->id ); return ( is_object( $subscription ) && $subscription->is_active() ); } /** * Check if trial already utilized. * * @since 1.0.9 * * @return bool */ function is_trial_utilized() { $this->_logger->entrance(); if ( ! $this->is_registered() ) { return false; } return $this->_site->is_trial_utilized(); } /** * Get trial plan information (if in trial). * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool|FS_Plugin_Plan */ function get_trial_plan() { $this->_logger->entrance(); if ( ! $this->is_trial() ) { return false; } // Try to load plan from local cache. $trial_plan = $this->_get_plan_by_id( $this->_site->trial_plan_id ); if ( ! is_object( $trial_plan ) ) { $trial_plan = $this->_fetch_site_plan( $this->_site->trial_plan_id ); /** * If managed to fetch the plan, add it to the plans collection. */ if ( $trial_plan instanceof FS_Plugin_Plan ) { if ( ! is_array( $this->_plans ) ) { $this->_plans = array(); } $this->_plans[] = $trial_plan; $this->_store_plans(); } } if ( $trial_plan instanceof FS_Plugin_Plan ) { return $trial_plan; } /** * If for some reason failed to get the trial plan, fallback to a dummy name and title. */ $trial_plan = new FS_Plugin_Plan(); $trial_plan->id = $this->_site->trial_plan_id; $trial_plan->name = 'pro'; $trial_plan->title = 'Pro'; return $trial_plan; } /** * Check if the user has an activate, non-expired license on current plugin's install. * * @since 1.0.9 * * @return bool */ function is_paying() { $this->_logger->entrance(); if ( ! $this->is_registered( true ) ) { return false; } if ( ! $this->has_paid_plan() ) { return false; } return ( ! $this->is_trial() && 'free' !== $this->get_plan_name() && $this->has_active_valid_license() ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @return bool */ function is_free_plan() { if ( ! $this->is_registered() ) { return true; } if ( ! $this->has_paid_plan() ) { return true; } return ( 'free' === $this->get_plan_name() || ! $this->has_features_enabled_license() ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @return bool */ function _has_premium_license() { $this->_logger->entrance(); $premium_license = $this->_get_available_premium_license(); return ( false !== $premium_license ); } /** * Check if user has any licenses associated with the plugin (including expired or blocking). * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @param bool $including_foreign * * @return bool */ function has_any_license( $including_foreign = true ) { if ( ! is_array( $this->_licenses ) || 0 === count( $this->_licenses ) ) { return false; } if ( $including_foreign ) { return true; } foreach ( $this->_licenses as $license ) { if ( $this->_user->id == $license->user_id ) { return true; } } return false; } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param bool|null $is_localhost * * @return FS_Plugin_License|false */ function _get_available_premium_license( $is_localhost = null ) { $this->_logger->entrance(); $licenses = $this->get_available_premium_licenses( $is_localhost ); if ( ! empty( $licenses ) ) { return $licenses[0]; } return false; } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param bool|null $is_localhost * * @return FS_Plugin_License[] */ function get_available_premium_licenses( $is_localhost = null ) { $this->_logger->entrance(); $licenses = array(); if ( ! $this->has_paid_plan() ) { return $licenses; } if ( is_array( $this->_licenses ) ) { foreach ( $this->_licenses as $license ) { if ( ! $license->can_activate( $is_localhost ) ) { continue; } $licenses[] = $license; } } return $licenses; } /** * Sync local plugin plans with remote server. * * IMPORTANT: If for some reason a site is associated with deleted plan, we'll preserve the plan's information and append it as the last plan. This means that if plan is deleted, the is_plan() method will ALWAYS return true for any given argument (it becomes the most inclusive plan). * * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @return FS_Plugin_Plan[]|object */ function _sync_plans() { $plans = $this->_fetch_plugin_plans(); if ( $this->is_array_instanceof( $plans, 'FS_Plugin_Plan' ) ) { $plans_map = array(); foreach ( $plans as $plan ) { $plans_map[ $plan->id ] = true; } $plans_ids_to_keep = $this->get_plans_ids_associated_with_installs(); foreach ( $plans_ids_to_keep as $plan_id ) { if ( isset( $plans_map[ $plan_id ] ) ) { continue; } $missing_plan = self::_get_plan_by_id( $plan_id ); if ( is_object( $missing_plan ) ) { $plans[] = $missing_plan; } } $this->_plans = $plans; $this->_store_plans(); } $this->do_action( 'after_plans_sync', $plans ); return $this->_plans; } /** * Check if specified plan exists locally. If not, fetch it and store it. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $plan_id * * @return \FS_Plugin_Plan|object The plan entity or the API error object on failure. */ private function sync_plan_if_not_exist( $plan_id ) { $plan = self::_get_plan_by_id( $plan_id ); if ( is_object( $plan ) ) { // Plan already exists. return $plan; } $plan = $this->fetch_plan_by_id( $plan_id ); if ( $plan instanceof FS_Plugin_Plan ) { $this->_plans[] = $plan; $this->_store_plans(); return $plan; } return $plan; } /** * Check if specified license exists locally. If not, fetch it and store it. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $license_id * @param string $license_key * * @return \FS_Plugin_Plan|object The plan entity or the API error object on failure. */ private function sync_license_if_not_exist( $license_id, $license_key ) { $license = $this->_get_license_by_id( $license_id ); if ( is_object( $license ) ) { // License already exists. return $license; } $license = $this->fetch_license_by_key( $license_id, $license_key ); if ( $license instanceof FS_Plugin_License ) { $this->_licenses[] = $license; $this->set_license( $license ); $this->_store_licenses(); return $license; } return $license; } /** * Get a collection of unique plan IDs that are associated with any installs in the network. * * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @return number[] */ private function get_plans_ids_associated_with_installs() { if ( ! is_multisite() ) { if ( ! is_object( $this->_site ) || ! FS_Plugin_Plan::is_valid_id( $this->_site->plan_id ) ) { return array(); } return array( $this->_site->plan_id ); } $plan_ids = array(); $sites = self::get_sites(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $install = $this->get_install_by_blog_id( $blog_id ); if ( ! is_object( $install ) || ! FS_Plugin_Plan::is_valid_id( $install->plan_id ) ) { continue; } $plan_ids[ $install->plan_id ] = true; } return array_keys( $plan_ids ); } /** * Get a collection of unique license IDs that are associated with any installs in the network. * * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @return number[] */ private function get_license_ids_associated_with_installs() { if ( ! $this->_is_network_active ) { if ( ! is_object( $this->_site ) || ! FS_Plugin_License::is_valid_id( $this->_site->license_id ) ) { return array(); } return array( $this->_site->license_id ); } $license_ids = array(); $sites = self::get_sites(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $install = $this->get_install_by_blog_id( $blog_id ); if ( ! is_object( $install ) || ! FS_Plugin_License::is_valid_id( $install->license_id ) ) { continue; } $license_ids[ $install->license_id ] = true; } return array_keys( $license_ids ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param number $id * * @return FS_Plugin_Plan|false */ function _get_plan_by_id( $id ) { $this->_logger->entrance(); if ( ! is_array( $this->_plans ) || 0 === count( $this->_plans ) ) { $this->_sync_plans(); } foreach ( $this->_plans as $plan ) { if ( $id == $plan->id ) { return $plan; } } return false; } /** * @author Vova Feldman (@svovaf) * @since 1.1.8.1 * * @param string $name * * @return FS_Plugin_Plan|false */ private function get_plan_by_name( $name ) { $this->_logger->entrance(); if ( ! is_array( $this->_plans ) || 0 === count( $this->_plans ) ) { $this->_sync_plans(); } foreach ( $this->_plans as $plan ) { if ( $name == $plan->name ) { return $plan; } } return false; } /** * Sync local licenses with remote server. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param number|bool $site_license_id * @param number|null $blog_id * * @return FS_Plugin_License[]|object */ function _sync_licenses( $site_license_id = false, $blog_id = null ) { $this->_logger->entrance(); $is_network_admin = fs_is_network_admin(); if ( $is_network_admin && is_null( $blog_id ) ) { $all_licenses = self::get_all_licenses( $this->_module_id ); } else { $all_licenses = $this->get_user_licenses( $this->_user->id ); } $foreign_licenses = $this->get_foreign_licenses_info( $all_licenses, $site_license_id ); $all_licenses_map = array(); foreach ( $all_licenses as $license ) { $all_licenses_map[ $license->id ] = true; } $licenses = $this->_fetch_licenses( false, $site_license_id, $foreign_licenses, $blog_id ); if ( $this->is_array_instanceof( $licenses, 'FS_Plugin_License' ) ) { $licenses_map = array(); foreach ( $licenses as $license ) { $licenses_map[ $license->id ] = true; } // $license_ids_to_keep = $this->get_license_ids_associated_with_installs(); // foreach ( $license_ids_to_keep as $license_id ) { // if ( isset( $licenses_map[ $license_id ] ) ) { // continue; // } // // $missing_license = self::_get_license_by_id( $license_id, false ); // if ( is_object( $missing_license ) ) { // $licenses[] = $missing_license; // $licenses_map[ $missing_license->id ] = true; // } // } $user_license_ids = $this->get_user_linked_license_ids( $this->_user->id ); foreach ( $user_license_ids as $key => $license_id ) { if ( ! isset( $licenses_map[ $license_id ] ) ) { // Remove access to licenses that no longer exist. unset( $user_license_ids[ $key ] ); } } if ( ! empty( $user_license_ids ) ) { foreach ( $licenses_map as $license_id => $value ) { if ( ! isset( $all_licenses_map[ $license_id ] ) ) { // Associate new licenses with the user who triggered the license syncing. $user_license_ids[] = $license_id; } } $user_license_ids = array_unique( $user_license_ids ); } else { $user_license_ids = array_keys( $licenses_map ); } if ( ! $is_network_admin || ! is_null( $blog_id ) ) { $user_licenses = array(); foreach ( $licenses as $license ) { if ( ! in_array( $license->id, $user_license_ids ) ) { continue; } $user_licenses[] = $license; } $this->_licenses = $user_licenses; } else { $this->_licenses = $licenses; } $this->set_user_linked_license_ids( $this->_user->id, $user_license_ids ); $this->_store_licenses( true, $this->_module_id, $licenses ); } // Update current license. if ( is_object( $this->_license ) ) { $license = $this->_get_license_by_id( $this->_license->id ); if ( is_object( $license ) ) { /** * `$license` can be `false` in case a user change action has just been completed and this method * has synced the `$this->_licenses` collection for the new user. In this case, the * `$this->_licenses` collection may have only the newly activated license that is associated with * the new user. `set_license` will eventually be called in the same request by the logic that * follows outside this method which will detect that the install's license has been updated, and * then `_update_site_license` will be called which in turn will call `set_license`. * * @author Leo Fajardo (@leorw) * @since 2.3.2 */ $this->set_license( $license ); } } return $this->_licenses; } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param number $id * @param bool $sync_licenses * * @return FS_Plugin_License|false */ function _get_license_by_id( $id, $sync_licenses = true ) { $this->_logger->entrance(); if ( ! FS_Plugin_License::is_valid_id( $id ) ) { return false; } /** * When running from the network level admin and opted-in from the network, * check if the license exists in the network user licenses collection. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ if ( fs_is_network_admin() && $this->is_network_registered() && ( ! is_object( $this->_user ) || $this->_storage->network_user_id != $this->_user->id ) ) { $licenses = $this->get_user_licenses( $this->_storage->network_user_id ); foreach ( $licenses as $license ) { if ( $id == $license->id ) { return $license; } } } if ( ! $this->has_any_license() && $sync_licenses ) { $this->_sync_licenses( $id ); } if ( is_array( $this->_licenses ) ) { foreach ( $this->_licenses as $license ) { if ( $id == $license->id ) { return $license; } } } return false; } /** * Get license by ID. Unlike _get_license_by_id(), this method only checks the local storage and return any license, whether it's associated with the current context user/install or not. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $id * * @return FS_Plugin_License */ private function get_license_by_id( $id ) { $licenses = self::get_all_licenses( $this->_module_id ); if ( is_array( $licenses ) && ! empty( $licenses ) ) { foreach ( $licenses as $license ) { if ( $id == $license->id ) { return $license; } } } return null; } /** * Synchronize the site's context license by fetching the license form the API and updating the local data with it. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return \FS_Plugin_License|mixed */ private function sync_site_license() { $api = $this->get_api_user_scope(); $result = $api->get( "/licenses/{$this->_license->id}.json?license_key=" . urlencode( $this->_license->secret_key ), true ); if ( ! $this->is_api_result_entity( $result ) ) { return $result; } $license = $this->_update_site_license( new FS_Plugin_License( $result ) ); $this->_store_licenses(); return $license; } /** * Get all user's available licenses for the current module. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $user_id * * @return FS_Plugin_License[] */ private function get_user_licenses( $user_id ) { $all_licenses = self::get_all_licenses( $this->_module_id ); if ( empty( $all_licenses ) ) { return array(); } $user_license_ids = $this->get_user_linked_license_ids( $user_id ); if ( empty( $user_license_ids ) ) { return array(); } $licenses = array(); foreach ( $all_licenses as $license ) { if ( in_array( $license->id, $user_license_ids ) ) { $licenses[] = $license; } } return $licenses; } /** * Checks if the context license is network activated except on the given blog ID. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $except_blog_id * * @return bool */ private function is_license_network_active( $except_blog_id = 0 ) { $this->_logger->entrance(); if ( ! is_object( $this->_license ) ) { return false; } $sites = self::get_sites(); if ( $this->_license->total_activations() < ( count( $sites ) - 1 ) ) { // There are more sites than the number of activations, so license cannot be network activated. return false; } foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); if ( $except_blog_id == $blog_id ) { // Skip excluded blog. continue; } $install = $this->get_install_by_blog_id( $blog_id ); if ( is_object( $install ) && $install->license_id != $this->_license->id ) { return false; } } return true; } /** * Checks if license can be activated on all the network sites (opted-in or skipped) that are not yet associated with a license. If possible, try to make the activation, if not return false. * * Notice: On success, this method will also update the license activations counters (without updating the license in the storage). * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_User $user * @param \FS_Plugin_License $license * * @return bool */ private function try_activate_license_on_network( FS_User $user, FS_Plugin_License $license ) { $this->_logger->entrance(); $result = $this->can_activate_license_on_network( $license ); if ( false === $result ) { return false; } $installs_without_license = $result['installs']; if ( ! empty( $installs_without_license ) ) { $this->activate_license_on_many_installs( $user, $license->secret_key, $installs_without_license ); } $disconnected_site_ids = $result['sites']; if ( ! empty( $disconnected_site_ids ) ) { $this->activate_license_on_many_sites( $user, $license->secret_key, $disconnected_site_ids ); } $this->link_license_2_user( $license->id, $user->id ); // Sync license after activations. $license->activated += $result['production_count']; $license->activated_local += $result['localhost_count']; // $this->_store_licenses() return true; } /** * Checks if the given license can be activated on the whole network. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_Plugin_License $license * * @return false|array { * @type array[int]FS_Site $installs Blog ID to install map. * @type int[] $sites Non-connected blog IDs. * @type int $production_count Production sites count. * @type int $localhost_count Production sites count. * } */ private function can_activate_license_on_network( FS_Plugin_License $license ) { $sites = self::get_sites(); $production_count = 0; $localhost_count = 0; $installs_without_license = array(); $disconnected_site_ids = array(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $install = $this->get_install_by_blog_id( $blog_id ); if ( is_object( $install ) ) { if ( FS_Plugin_License::is_valid_id( $install->license_id ) ) { // License already activated on the install. continue; } $url = $install->url; $installs_without_license[ $blog_id ] = $install; } else { $url = is_object( $site ) ? $site->siteurl : self::get_unfiltered_site_url( $blog_id ); $disconnected_site_ids[] = $blog_id; } if ( FS_Site::is_localhost_by_address( $url ) ) { $localhost_count ++; } else { $production_count ++; } } if ( ! $license->can_activate_bulk( $production_count, $localhost_count ) ) { return false; } return array( 'installs' => $installs_without_license, 'sites' => $disconnected_site_ids, 'production_count' => $production_count, 'localhost_count' => $localhost_count, ); } /** * Activate a given license on a collection of installs. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_User $user * @param string $license_key * @param array $blog_2_install_map { * @key int Blog ID. * @value FS_Site Blog's associated install. * } * * @return mixed|true */ private function activate_license_on_many_installs( FS_User $user, $license_key, array $blog_2_install_map ) { $params = array( array( 'license_key' => $this->apply_filters( 'license_key', $license_key ) ) ); $install_2_blog_map = array(); foreach ( $blog_2_install_map as $blog_id => $install ) { $params[] = array( 'id' => $install->id ); $install_2_blog_map[ $install->id ] = $blog_id; } $result = $this->get_api_user_scope_by_user( $user )->call( "plugins/{$this->_plugin->id}/installs.json", 'PUT', $params ); if ( ! $this->is_api_result_object( $result, 'installs' ) ) { return $result; } foreach ( $result->installs as $r_install ) { $install = new FS_Site( $r_install ); $install->is_disconnected = false; // Update install. $this->_store_site( true, $install_2_blog_map[ $r_install->id ], $install ); } return true; } /** * Activate a given license on a collection of blogs/sites that are not yet opted-in. * * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @param \FS_User $user * @param string $license_key * * @return true|mixed True if successful, otherwise, the API result. */ private function activate_license_on_site( FS_User $user, $license_key ) { return $this->activate_license_on_many_sites( $user, $license_key ); } /** * Activate a given license on a collection of blogs/sites that are not yet opted-in. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_User $user * @param string $license_key * @param int[] $site_ids * * @return true|mixed True if successful, otherwise, the API result. */ private function activate_license_on_many_sites( FS_User $user, $license_key, array $site_ids = array() ) { $sites = array(); foreach ( $site_ids as $site_id ) { $sites[] = $this->get_site_info( array( 'blog_id' => $site_id ) ); } // Install the plugin. $result = $this->create_installs_with_user( $user, $license_key, false, $sites, false, true ); if ( ! $this->is_api_result_entity( $result ) && ! $this->is_api_result_object( $result, 'installs' ) ) { return $result; } $installs = array(); if ( $this->is_api_result_entity( $result ) ) { $install = new FS_Site( $result ); $this->_user = $user; $this->_store_site( true, null, $install ); $this->_site = $install; $this->reset_anonymous_mode(); } else { foreach ( $result->installs as $install ) { $installs[] = new FS_Site( $install ); } // Map site addresses to their blog IDs. $address_to_blog_map = $this->get_address_to_blog_map(); $first_blog_id = null; foreach ( $installs as $install ) { $address = trailingslashit( fs_strip_url_protocol( $install->url ) ); $blog_id = $address_to_blog_map[ $address ]; $this->_store_site( true, $blog_id, $install ); $this->reset_anonymous_mode( $blog_id ); if ( is_null( $first_blog_id ) ) { $first_blog_id = $blog_id; } } if ( ! FS_Site::is_valid_id( $this->_storage->network_install_blog_id ) ) { $this->_storage->network_install_blog_id = $first_blog_id; } } return true; } /** * Sync site's license with user licenses. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param FS_Plugin_License|null $new_license * * @return FS_Plugin_License|null */ function _update_site_license( $new_license ) { $this->_logger->entrance(); /** * In case this call will be removed in the future, the `_sync_licenses()` method needs to be updated * accordingly so that it will also handle the case when an ownership change is done via license * activation. * * @author Leo Fajardo (@leorw) * @since 2.3.2 */ $this->set_license( $new_license ); if ( ! is_object( $new_license ) ) { $this->_site->license_id = null; $this->_sync_site_subscription( null ); return $this->_license; } $this->_site->license_id = $this->_license->id; if ( ! is_array( $this->_licenses ) ) { $this->_licenses = array(); } $is_license_found = false; for ( $i = 0, $len = count( $this->_licenses ); $i < $len; $i ++ ) { if ( $new_license->id == $this->_licenses[ $i ]->id ) { $this->_licenses[ $i ] = $new_license; $is_license_found = true; break; } } // If new license just append. if ( ! $is_license_found ) { $this->_licenses[] = $new_license; } $this->_sync_site_subscription( $new_license ); return $this->_license; } /** * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @param \FS_Plugin_License $license */ private function set_license( FS_Plugin_License $license = null ) { $this->_license = $license; $this->maybe_update_whitelabel_flag( $license ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @param FS_Plugin_License $license */ private function maybe_update_whitelabel_flag( $license ) { $is_whitelabeled = isset( $this->_storage->is_whitelabeled ) ? $this->_storage->is_whitelabeled : false; if ( is_object( $license ) ) { $license_user = self::_get_user_by_id( $license->user_id ); if ( ! is_object( $license_user ) ) { // If foreign license, do not update the `is_whitelabeled` flag. return; } if ( $this->is_addon() ) { /** * Store the last license data to the parent's storage since it's needed only when showing the * "Start Debug" dialog which is triggered from the "Account" page. This way, there's no need to * iterate over the add-ons just to get the last license data. */ $this->get_parent_instance()->store_last_activated_license_data( $license, $license_user ); } else { $this->store_last_activated_license_data( $license ); } if ( $license->is_whitelabeled ) { // Activated a developer license, data should be hidden. $is_whitelabeled = true; } else if ( $this->is_registered() && $this->_user->id == $license->user_id ) { // The account owner activated a regular license key, no need to hide the data. $is_whitelabeled = false; } } $this->_storage->is_whitelabeled = $is_whitelabeled; // Reset the whitelabeled status after update. $this->is_whitelabeled = null; if ( $this->is_addon() ) { $parent_fs = $this->get_parent_instance(); if ( is_object( $parent_fs ) ) { $parent_fs->is_whitelabeled = null; } } } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @param FS_Plugin_License $license * @param FS_User $license_user */ private function store_last_activated_license_data( FS_Plugin_License $license, $license_user = null ) { if ( ! is_object( $license_user ) ) { $this->_storage->last_license_key = md5( $license->secret_key ); $this->_storage->last_license_user_id = null; } else { $this->_storage->last_license_user_key = md5( $license_user->secret_key ); $this->_storage->last_license_user_id = $license_user->id; } } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @param bool $ignore_data_debug_mode * * @return bool */ function is_whitelabeled_by_flag( $ignore_data_debug_mode = false ) { if ( true !== $this->_storage->is_whitelabeled ) { return false; } else if ( $ignore_data_debug_mode ) { return true; } $fs = $this->is_addon() ? $this->get_parent_instance() : $this; return ! $fs->is_data_debug_mode(); } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @return number */ function get_last_license_user_id() { return ( FS_User::is_valid_id( $this->_storage->last_license_user_id ) ) ? $this->_storage->last_license_user_id : null; } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @param int $blog_id * @param bool $ignore_data_debug_mode * * @return bool */ function is_whitelabeled( $ignore_data_debug_mode = false, $blog_id = null ) { if ( ! is_null( $blog_id ) ) { $this->switch_to_blog( $blog_id ); } if ( ! is_null( $this->is_whitelabeled ) ) { $is_whitelabeled = $this->is_whitelabeled; } else { $is_whitelabeled = false; $is_whitelabeled_flag = $this->is_whitelabeled_by_flag( true ); if ( ! $this->has_addons() ) { $is_whitelabeled = $is_whitelabeled_flag; } else if ( $is_whitelabeled_flag ) { $is_whitelabeled = true; } else { if ( $this->is_registered() || $this->is_premium() ) { $addon_ids = $this->get_updated_account_addons(); } else { $addons = self::get_all_addons(); $plugin_addons = isset( $addons[ $this->_plugin->id ] ) ? $addons[ $this->_plugin->id ] : array(); $addon_ids = array(); foreach ( $plugin_addons as $addon ) { $addon_ids[] = $addon->id; } } $installed_addons = $this->get_installed_addons(); foreach ( $installed_addons as $fs_addon ) { $addon_ids[] = $fs_addon->get_id(); } if ( ! empty( $addon_ids ) ) { $addon_ids = array_unique( $addon_ids ); $is_network_level = ( fs_is_network_admin() && $this->is_network_active() ); foreach ( $addon_ids as $addon_id ) { $addon = $this->get_addon( $addon_id ); if ( ! is_object( $addon ) ) { continue; } $addon_storage = FS_Storage::instance( WP_FS__MODULE_TYPE_PLUGIN, $addon->slug ); $fs_addon = $this->is_addon_activated( $addon_id ) ? self::get_addon_instance( $addon_id ) : null; $was_addon_network_activated = false; if ( is_object( $fs_addon ) ) { $was_addon_network_activated = $fs_addon->is_network_active(); } else if ( $is_network_level ) { $was_addon_network_activated = $addon_storage->get( 'was_plugin_loaded', false, true ); } $network_delegated_connection = ( $was_addon_network_activated && $addon_storage->get( 'is_delegated_connection', false, true ) ); if ( $is_network_level && ( ! $was_addon_network_activated || $network_delegated_connection ) ) { $sites = self::get_sites(); /** * If in network admin area and the add-on was not network-activated or network-activated * and network-delegated, find any add-on whose is_whitelabeled flag is true. */ foreach ( $sites as $site ) { $site_info = $this->get_site_info( $site ); if ( $addon_storage->get( 'is_whitelabeled', false, $site_info['blog_id'] ) ) { $is_whitelabeled = true; break; } } if ( $is_whitelabeled ) { break; } } else { /** * This will be executed when any of the following is met: * 1. Add-on was network-activated, not network-delegated, and in network admin area. * 2. Add-on was network-activated, network-delegated, and in site admin area. * 3. Add-on was not network-activated and in site admin area. */ if ( true === $addon_storage->is_whitelabeled ) { $is_whitelabeled = true; break; } } } } } $this->is_whitelabeled = $is_whitelabeled; if ( ! $is_whitelabeled || ! $this->is_data_debug_mode() ) { $this->_admin_notices->remove_sticky( 'data_debug_mode_enabled' ); } if ( ! is_null( $blog_id ) ) { $this->restore_current_blog(); } } return ( $is_whitelabeled && ( $ignore_data_debug_mode || ! $this->is_data_debug_mode() ) ); } /** * Sync site's subscription. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param FS_Plugin_License|null $license * * @return bool|\FS_Subscription */ private function _sync_site_subscription( $license ) { if ( ! is_object( $license ) ) { $this->delete_unused_subscriptions(); return false; } // Load subscription details if not lifetime. $subscription = $license->is_lifetime() ? false : $this->_fetch_site_license_subscription(); if ( is_object( $subscription ) && ! isset( $subscription->error ) ) { $this->store_subscription( $subscription ); } else { $this->delete_unused_subscriptions(); } return $subscription; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return bool|\FS_Plugin_License */ function _get_license() { if ( ! fs_is_network_admin() || is_object( $this->_license ) ) { return $this->_license; } return $this->_get_available_premium_license(); } /** * @param number $license_id * * @return null|\FS_Subscription */ function _get_subscription( $license_id ) { if ( ! isset( $this->_storage->subscriptions ) || empty( $this->_storage->subscriptions ) ) { return null; } foreach ( fs_get_entities( $this->_storage->subscriptions, FS_Subscription::get_class_name() ) as $subscription ) { if ( $subscription->license_id == $license_id ) { return $subscription; } } return null; } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param FS_Subscription $subscription */ function store_subscription( FS_Subscription $subscription ) { if ( ! isset( $this->_storage->subscriptions ) ) { $this->_storage->subscriptions = array(); } if ( empty( $this->_storage->subscriptions ) || ! is_multisite() ) { $this->_storage->subscriptions = array( $subscription ); return; } $subscriptions = fs_get_entities( $this->_storage->subscriptions, FS_Subscription::get_class_name() ); $updated_subscription = false; foreach ( $subscriptions as $key => $existing_subscription ) { if ( $existing_subscription->id == $subscription->id ) { $subscriptions[ $key ] = $subscription; $updated_subscription = true; break; } } if ( ! $updated_subscription ) { $subscriptions[] = $subscription; } $this->_storage->subscriptions = $subscriptions; } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 */ function delete_unused_subscriptions() { if ( ! isset( $this->_storage->subscriptions ) || empty( $this->_storage->subscriptions ) || // Clean up only if there are already at least 3 subscriptions. ( count( $this->_storage->subscriptions ) < 3 ) ) { return; } if ( ! is_multisite() ) { // If not multisite, there should only be 1 subscription, so just clear the array. $this->_storage->subscriptions = array(); return; } $subscriptions_to_keep_by_license_id_map = array(); $sites = self::get_sites(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $install = $this->get_install_by_blog_id( $blog_id ); if ( ! is_object( $install ) || ! FS_Plugin_License::is_valid_id( $install->license_id ) ) { continue; } $subscriptions_to_keep_by_license_id_map[ $install->license_id ] = true; } if ( empty( $subscriptions_to_keep_by_license_id_map ) ) { $this->_storage->subscriptions = array(); return; } foreach ( $this->_storage->subscriptions as $key => $subscription ) { if ( ! isset( $subscriptions_to_keep_by_license_id_map[ $subscription->license_id ] ) ) { unset( $this->_storage->subscriptions[ $key ] ); } } } /** * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @param string $plan Plan name * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. * * @return bool */ function is_plan( $plan, $exact = false ) { $this->_logger->entrance(); if ( ! $this->is_registered() ) { return false; } $plan = strtolower( $plan ); $current_plan_name = $this->get_plan_name(); if ( $current_plan_name === $plan ) { // Exact plan. return true; } else if ( $exact ) { // Required exact, but plans are different. return false; } $current_plan_order = - 1; $required_plan_order = PHP_INT_MAX; for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { if ( $plan === $this->_plans[ $i ]->name ) { $required_plan_order = $i; } else if ( $current_plan_name === $this->_plans[ $i ]->name ) { $current_plan_order = $i; } } return ( $current_plan_order > $required_plan_order ); } /** * Check if module has only one plan. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param bool $double_check In some cases developers prefer to release their paid offering as premium-only, even though there is a free version. For those cases, looking at the 'is_premium_only' value isn't enough because the result will return false even when the product has only signle paid plan. * * @return bool */ function is_single_plan( $double_check = false ) { $this->_logger->entrance(); if ( ! $this->is_registered() || ! is_array( $this->_plans ) || 0 === count( $this->_plans ) ) { return true; } $has_free_plan = $this->has_free_plan(); if ( ! $has_free_plan && $double_check ) { foreach ( $this->_plans as $plan ) { if ( $plan->is_free() ) { $has_free_plan = true; break; } } } return ( 1 === ( count( $this->_plans ) - ( $has_free_plan ? 1 : 0 ) ) ); } /** * Check if plan based on trial. If not in trial mode, should return false. * * @since 1.0.9 * * @param string $plan Plan name * @param bool $exact If true, looks for exact plan. If false, also check "higher" plans. * * @return bool */ function is_trial_plan( $plan, $exact = false ) { $this->_logger->entrance(); if ( ! $this->is_registered() ) { return false; } if ( ! $this->is_trial() ) { return false; } $trial_plan = $this->get_trial_plan(); if ( $trial_plan->name === $plan ) { // Exact plan. return true; } else if ( $exact ) { // Required exact, but plans are different. return false; } $current_plan_order = - 1; $required_plan_order = - 1; for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { if ( $plan === $this->_plans[ $i ]->name ) { $required_plan_order = $i; } else if ( $trial_plan->name === $this->_plans[ $i ]->name ) { $current_plan_order = $i; } } return ( $current_plan_order > $required_plan_order ); } /** * Check if plugin has any paid plans. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return bool */ function has_paid_plan() { return $this->_has_paid_plans || FS_Plan_Manager::instance()->has_paid_plan( $this->_plans ); } /** * Check if plugin has any plan with a trail. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function has_trial_plan() { /** * @author Vova Feldman(@svovaf) * @since 1.2.1.5 * * Allow setting a trial from the SDK without calling the API. * But, if the user did opt-in, continue using the real data from the API. */ if ( $this->_trial_days >= 0 ) { return true; } return $this->_storage->get( 'has_trial_plan', false ); } /** * Check if plugin has any free plan, or is it premium only. * * Note: If no plans configured, assume plugin is free. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return bool */ function has_free_plan() { return ! $this->is_only_premium(); } /** * Displays a license activation dialog box when the user clicks on the "Activate License" * or "Change License" link on the plugins * page. * * @author Leo Fajardo (@leorw) * @since 1.1.9 */ function _add_license_activation_dialog_box() { $vars = array( 'id' => $this->_module_id, ); fs_require_template( 'forms/license-activation.php', $vars ); fs_require_template( 'forms/resend-key.php', $vars ); } /** * Displays an email address update dialog box when the user clicks on the email address "Edit" button on the "Account" page. * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function _add_email_address_update_dialog_box() { $vars = array( 'id' => $this->_module_id ); fs_require_template( 'forms/email-address-update.php', $vars ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function _add_email_address_update_option() { if ( ! $this->should_handle_user_change() ) { return; } // Add email address update AJAX handler. $this->add_ajax_action( 'update_email_address', array( &$this, '_email_address_update_ajax_handler' ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function _email_address_update_ajax_handler() { $this->check_ajax_referer( 'update_email_address' ); $new_email_address = fs_request_get( 'email_address' ); $transfer_type = fs_request_get( 'transfer_type' ); $result = $this->update_email( $new_email_address ); if ( ! FS_Api::is_api_error( $result ) ) { self::shoot_ajax_success(); } $error = ''; if ( FS_Api::is_api_error_object( $result ) ) { switch ( $result->error->code ) { case 'user_exist': case 'account_verification_required': $error = array( 'code' => 'change_ownership', 'url' => $this->get_account_url( 'change_owner', array( 'state' => 'init', 'candidate_email' => $new_email_address, 'transfer_type' => $transfer_type, ) ), ); break; } } if ( empty( $error ) ) { $error = is_object( $result ) ? var_export( $result->error, true ) : $result; } self::shoot_ajax_failure( $error ); } /** * Returns a collection of IDs of installs that are associated with the context product and its add-ons, and activated with foreign licenses. * * @author Leo Fajardo (@leorw) * @since 2.3.2 * * @return number[] */ function get_installs_ids_with_foreign_licenses() { $installs = array(); if ( is_object( $this->_license ) && $this->_site->user_id != $this->_license->user_id ) { $installs[] = $this->_site->id; } /** * Also try to get foreign licenses for the context product's add-ons. */ $installs_by_slug_map = $this->get_parent_and_addons_installs_info(); foreach ( $installs_by_slug_map as $slug => $install_info ) { if ( $slug == $this->get_slug() ) { continue; } $install = $install_info['install']; $license = $install_info['license']; if ( is_object( $license ) && $install->user_id != $license->user_id ) { $installs[] = $install->id; } } return $installs; } /** * Displays the "Change User" dialog box when the user clicks on the "Change User" button on the "Account" page. * * @author Leo Fajardo (@leorw) * @since 2.3.2 * * @param number[] $install_ids */ function _add_user_change_dialog_box( $install_ids ) { $vars = array( 'id' => $this->_module_id, 'license_owners' => $this->fetch_installs_licenses_owners_data( $install_ids ) ); fs_require_template( 'forms/user-change.php', $vars ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 */ function _add_data_debug_mode_dialog_box() { $vars = array( 'id' => $this->_module_id, ); fs_require_template( 'forms/data-debug-mode.php', $vars ); } /** * Displays a subscription cancellation dialog box when the user clicks on the "Deactivate License" * link on the "Account" page or deactivates a plugin and there's an active subscription that is * either associated with a non-lifetime single-site license or non-lifetime multisite license that * is only activated on a single production site. * * @author Leo Fajardo (@leorw) * @since 2.2.1 * * @param bool $is_license_deactivation * * @return array */ function _get_subscription_cancellation_dialog_box_template_params( $is_license_deactivation = false ) { if ( fs_is_network_admin() ) { // Subscription cancellation dialog box is currently not supported for multisite networks. return array(); } if ( $this->is_whitelabeled() ) { return array(); } $license = $this->_get_license(); /** * If the installation is associated with a non-lifetime license, which is either a single-site or only activated on a single production site (or zero), and connected to an active subscription, suggest the customer to cancel the subscription upon deactivation. * * @author Leo Fajardo (@leorw) (Comment added by Vova Feldman @svovaf) * @since 2.2.1 */ if ( ! is_object( $license ) || $license->is_lifetime() || ( ! $license->is_single_site() && $license->activated > 1 ) ) { return array(); } /** * @var FS_Subscription $subscription */ $subscription = $this->_get_subscription( $license->id ); if ( ! is_object( $subscription ) || ! $subscription->is_active() ) { return array(); } return array( 'id' => $this->_module_id, 'license' => $license, 'has_trial' => $this->is_paid_trial(), 'is_license_deactivation' => $is_license_deactivation, ); } /** * @author Leo Fajardo (@leorw) * @since 2.0.2 */ function _add_premium_version_upgrade_selection_dialog_box() { $modules_update = get_site_transient( $this->is_theme() ? 'update_themes' : 'update_plugins' ); if ( ! isset( $modules_update->response[ $this->_plugin_basename ] ) ) { return; } $vars = array( 'id' => $this->_module_id, 'new_version' => is_object( $modules_update->response[ $this->_plugin_basename ] ) ? $modules_update->response[ $this->_plugin_basename ]->new_version : $modules_update->response[ $this->_plugin_basename ]['new_version'] ); fs_require_template( 'forms/premium-versions-upgrade-metadata.php', $vars ); fs_require_once_template( 'forms/premium-versions-upgrade-handler.php', $vars ); } /** * Displays the opt-out dialog box when the user clicks on the "Opt Out" link on the "Plugins" * page. * * @author Leo Fajardo (@leorw) * @since 1.2.1.5 */ function _add_optout_dialog() { if ( $this->is_theme() ) { $vars = null; fs_require_once_template( '/js/jquery.content-change.php', $vars ); } $vars = array( 'id' => $this->_module_id ); fs_require_template( 'forms/optout.php', $vars ); } /** * Prepare page to include all required UI and logic for the license activation dialog. * * @author Vova Feldman (@svovaf) * @since 1.2.0 */ function _add_license_activation() { if ( $this->is_migration() ) { return; } if ( ! $this->is_user_admin() ) { // Only admins can activate a license. return; } if ( ! $this->has_paid_plan() ) { // Module doesn't have any paid plans. return; } if ( $this->has_premium_version() && ! $this->is_premium() && /** * Also handle the case when an upgrade was made using the free version. * * @author Leo Fajardo (@leorw) * @since 2.3.2 */ ! is_object( $this->_get_license() ) ) { // Only add license activation logic to the premium version, or in case of a serviceware plugin, also in the free version. return; } // Add license activation link and AJAX request handler. if ( self::is_plugins_page() ) { $is_network_admin = fs_is_network_admin(); if ( ( $is_network_admin && $this->is_network_active() && ! $this->is_network_delegated_connection() ) || ( ! $is_network_admin && ( ! $this->is_network_active() || $this->is_delegated_connection() ) ) ) { if ( $this->is_premium() || ( $this->has_paid_plan() && ! $this->has_premium_version() ) ) { /** * @since 1.2.0 Add license action link only on plugins page. */ $this->_add_license_action_link(); } } } // Add license activation AJAX callback. $this->add_ajax_action( 'activate_license', array( &$this, '_activate_license_ajax_action' ) ); // Add resend license AJAX callback. $this->add_ajax_action( 'resend_license_key', array( &$this, '_resend_license_key_ajax_action' ) ); } /** * Prepares page to include all required UI and logic for the "Change User" dialog. * * @author Leo Fajardo (@leorw) * @since 2.3.2 */ function _add_user_change_option() { if ( ! $this->should_handle_user_change() ) { return; } $installs_ids_with_foreign_licenses = $this->get_installs_ids_with_foreign_licenses(); if ( empty( $installs_ids_with_foreign_licenses ) ) { // Handle user change only when the parent product or one of its add-ons is activated with a foreign license. return; } // Add user change AJAX handler. $this->add_ajax_action( 'change_user', array( &$this, '_user_change_ajax_action' ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.2 */ function should_handle_user_change() { if ( ! $this->is_user_admin() ) { // Only admins can change user. return false; } if ( $this->is_addon() ) { return false; } if ( ! $this->is_registered() ) { return false; } if ( $this->is_network_active() && ( fs_is_network_admin() || ! $this->is_site_delegated_connection() ) ) { // Handle only on site-level "Account" section for now. return false; } return true; } /** * @author Leo Fajardo (@leorw) * @since 2.0.2 */ function _add_premium_version_upgrade_selection() { if ( ! $this->is_user_admin() ) { return; } if ( ! $this->is_premium() || $this->has_any_active_valid_license() ) { // This is relevant only to the free versions and premium versions without an active license. return; } if ( self::is_updates_page() || ( $this->is_plugin() && self::is_plugins_page() ) ) { $this->_add_premium_version_upgrade_selection_action(); } } /** * @author Edgar Melkonyan * @since 2.4.1 * * @throws Freemius_Exception */ function _toggle_whitelabel_mode_ajax_handler() { $this->_logger->entrance(); $this->check_ajax_referer( 'toggle_whitelabel_mode' ); if ( ! $this->is_user_admin() ) { // Only for admins. self::shoot_ajax_failure(); } $license = $this->get_api_user_scope()->call( "/licenses/{$this->_site->license_id}.json", 'put', array( 'is_whitelabeled' => ! $this->_license->is_whitelabeled ) ); if ( ! $this->is_api_result_entity( $license ) ) { self::shoot_ajax_failure( FS_Api::is_api_error_object( $license ) ? $license->error->message : fs_text_inline( "An unknown error has occurred while trying to toggle the license's white-label mode.", 'unknown-error-occurred', $this->get_slug() ) ); } $this->_license->is_whitelabeled = $license->is_whitelabeled; $this->_store_licenses(); $this->_sync_license(); if ( ! $license->is_whitelabeled ) { $this->_admin_notices->remove_sticky( 'license_whitelabeled' ); } else { $this->_admin_notices->add_sticky( sprintf( $this->get_text_inline( 'Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s.', 'license_whitelabeled' ), "{$this->get_plugin_title()}", sprintf( '%s', $this->get_text_inline( 'User Dashboard', 'user-dashboard' ) ), sprintf( '%s', $this->get_text_inline( 'revert it now', 'revert-it-now' ) ) ), 'license_whitelabeled' ); } self::shoot_ajax_response( array( 'success' => true ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 */ function _add_beta_mode_update_handler() { if ( ! $this->is_user_admin() ) { return; } if ( ! $this->is_premium() ) { return; } $this->add_ajax_action( 'set_beta_mode', array( &$this, '_set_beta_mode_ajax_handler' ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 */ function _set_beta_mode_ajax_handler() { $this->_logger->entrance(); $this->check_ajax_referer( 'set_beta_mode' ); if ( ! $this->is_user_admin() ) { // Only for admins. self::shoot_ajax_failure(); } $is_beta = trim( fs_request_get( 'is_beta', '', 'post' ) ); if ( empty( $is_beta ) || ! in_array( $is_beta, array( 'true', 'false' ) ) ) { self::shoot_ajax_failure(); } $site = $this->api_site_call( '', 'put', array( 'is_beta' => ( 'true' == $is_beta ), 'fields' => 'is_beta' ) ); if ( ! $this->is_api_result_entity( $site ) ) { self::shoot_ajax_failure( FS_Api::is_api_error_object( $site ) ? $site->error->message : fs_text_inline( "An unknown error has occurred while trying to set the user's beta mode.", 'unknown-error-occurred', $this->get_slug() ) ); } $this->_site->is_beta = $site->is_beta; $this->_store_site(); self::shoot_ajax_response( array( 'success' => true ) ); } /** * License activation WP AJAX handler. * * @author Leo Fajardo (@leorw) * @since 1.1.9 * * @uses Freemius::activate_license() */ function _activate_license_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'activate_license' ); $license_key = trim( fs_request_get( 'license_key' ) ); if ( empty( $license_key ) ) { exit; } $sites = fs_is_network_admin() ? fs_request_get( 'sites', array(), 'post' ) : array(); $result = $this->activate_license( $license_key, $sites, fs_request_get_bool( 'is_marketing_allowed', null ), fs_request_get( 'blog_id', null ), fs_request_get( 'module_id', null, 'post' ), fs_request_get( 'user_id', null ), fs_request_get_bool( 'is_extensions_tracking_allowed', null ), fs_request_get_bool( 'is_diagnostic_tracking_allowed', null ) ); if ( $result['success'] && $this->is_bundle_license_auto_activation_enabled() ) { $license = new FS_Plugin_License(); $license->secret_key = $license_key; $this->maybe_activate_bundle_license( $license, $sites ); } echo json_encode( $result ); exit; } /** * User change WP AJAX handler. * * @author Leo Fajardo (@leorw) * @since 2.3.2 */ function _user_change_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'change_user' ); $new_email_address = trim( fs_request_get( 'email_address', '' ) ); $new_user_id = fs_request_get( 'user_id' ); if ( empty( $new_email_address ) && ! FS_User::is_valid_id( $new_user_id ) ) { self::shoot_ajax_failure( fs_text_inline( 'Invalid new user ID or email address.', 'invalid-new-user-id-or-email', $this->get_slug() ) ); } $params = array(); if ( ! empty( $new_email_address ) ) { $params['user_email'] = $new_email_address; } else { $params['user_id'] = $new_user_id; } $installs_info_by_slug_map = $this->get_parent_and_addons_installs_info(); $install_ids = array(); foreach ( $installs_info_by_slug_map as $slug => $install_info ) { $install_ids[ $slug ] = $install_info['install']->id; } $params['install_ids'] = implode( ',', array_values( $install_ids ) ); $install = $this->get_api_site_scope()->call( $this->add_show_pending( '/' ), 'put', $params ); if ( FS_Api::is_api_error( $install ) ) { $error = ''; if ( is_object( $install ) ) { switch ( $install->error->code ) { case 'user_exist': $error = ( $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...' . $this->get_text_inline( 'Sorry, we could not complete the email update. Another user with the same email is already registered.', 'user-exist-message' ) . ' ' . sprintf( $this->get_text_inline( 'If you would like to give up the ownership of the %s\'s account to %s click the Change Ownership button.', 'user-exist-message_ownership' ), $this->_module_type, '' . $new_email_address . '' ) . sprintf( '', $this->get_account_url( 'change_owner', array( 'state' => 'init', 'candidate_email' => $new_email_address ) ), $this->get_text_inline( 'Change Ownership', 'change-ownership' ) ) ); break; } } if ( empty( $error ) ) { $error = FS_Api::is_api_error_object( $install ) ? $install->error->message : var_export( $install->error, true ); } self::shoot_ajax_failure( $error ); } else { if ( // If successful ownership change. $this->get_user()->id != $install->user_id || ! empty( $new_email_address ) ) { $this->complete_ownership_change_by_license( $install->user_id, $install_ids ); } } self::shoot_ajax_success(); } /** * @author Leo Fajardo (@leorw) * @since 2.3.2.14 */ function starting_migration() { if ( ! empty( $this->_storage->license_migration ) ) { // Do not overwrite the data if already set. return; } $this->_storage->license_migration = array( 'is_migrating' => true, 'start_timestamp' => time() ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.2.14 */ function is_migration() { if ( $this->is_addon() ) { return $this->get_parent_instance()->is_migration(); } if ( empty( $this->_storage->license_migration ) ) { return false; } if ( ! $this->_storage->license_migration['is_migrating'] ) { return false; } return ( // Return `true` if the migration is within 5 minutes from the starting time. ( time() - $this->_storage->license_migration['start_timestamp'] ) <= WP_FS__TIME_5_MIN_IN_SEC ); } /** * * A helper method to activate migrated licenses. If the product is network activated and integrated, the method will network activate the license. * * @author Vova Feldman (@svovaf) * @since 2.3.0 * * @param string $license_key * @param null|bool $is_marketing_allowed * @param null|number $plugin_id * @param array $sites * @param int $blog_id * * @return array { * @var bool $success * @var string $error * @var string $next_page * } * * @uses Freemius::activate_license() */ function activate_migrated_license( $license_key, $is_marketing_allowed = null, $plugin_id = null, $sites = array(), $blog_id = null ) { $this->_logger->entrance(); $result = $this->activate_license( $license_key, ( empty( $sites ) && is_null( $blog_id ) && $this->is_network_active() ) ? $this->get_sites_for_network_level_optin() : $sites, $is_marketing_allowed, $blog_id, $plugin_id ); // No need to show the sticky after license activation notice after migrating a license. $this->_admin_notices->remove_sticky( 'plan_upgraded' ); return $result; } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @return string */ function get_pricing_js_path() { if ( ! isset( $this->_pricing_js_path ) ) { $pricing_js_path = $this->apply_filters( 'freemius_pricing_js_path', '' ); if ( empty( $pricing_js_path ) ) { global $fs_active_plugins; foreach ( $fs_active_plugins->plugins as $sdk_path => $data ) { if ( $data->plugin_path == $this->get_plugin_basename() ) { $plugin_or_theme_root_dir = ( $this->is_plugin() ? WP_PLUGIN_DIR : get_theme_root( get_stylesheet() ) ); $pricing_js_path = $plugin_or_theme_root_dir . '/' // The basename will be `plugins`, `themes`, or the basename of a custom plugins or themes directory. . str_replace( '../' . basename( $plugin_or_theme_root_dir ) . '/', '', $sdk_path ) . '/includes/freemius-pricing/freemius-pricing.js'; break; } } } $this->_pricing_js_path = $pricing_js_path; } return $this->_pricing_js_path; } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 * * @return bool */ function should_use_external_pricing() { if ( is_null( $this->_use_external_pricing ) ) { $pricing_js_path = $this->get_pricing_js_path(); $this->_use_external_pricing = ( empty( $pricing_js_path ) || ! file_exists( $pricing_js_path ) ); } return $this->_use_external_pricing; } /** * The implementation of this method was previously in `_activate_license_ajax_action()`. * * @author Vova Feldman (@svovaf) * @since 2.2.4 * @since 2.0.0 When a super-admin that hasn't connected before is network activating a license and excluding some of the sites for the license activation, go over the unselected sites in the network and if a site is not connected, skipped, nor delegated, if it's a freemium product then just skip the connection for the site, if it's a premium only product, delegate the connection and license activation to the site admin (Vova Feldman @svovaf). * @param string $license_key * @param array $sites * @param null|bool $is_marketing_allowed * @param null|int $blog_id * @param null|number $plugin_id * @param null|number $license_owner_id * @param bool|null $is_extensions_tracking_allowed * @param bool|null $is_diagnostic_tracking_allowed Since 2.5.0.2 to allow license activation with minimal data footprint. * * * @return array { * @var bool $success * @var string $error * @var string $next_page * } */ private function activate_license( $license_key, $sites = array(), $is_marketing_allowed = null, $blog_id = null, $plugin_id = null, $license_owner_id = null, $is_extensions_tracking_allowed = null, $is_diagnostic_tracking_allowed = null ) { $this->_logger->entrance(); $license_key = trim( $license_key ); $is_network_activation_or_migration = ( fs_is_network_admin() || ( ! empty( $sites ) && $this->is_migration() ) ); if ( ! $is_network_activation_or_migration ) { // If the license activation is executed outside the context of a network admin, ignore the sites collection. $sites = array(); } $fs = ( empty($plugin_id) || $plugin_id == $this->_module_id ) ? $this : $this->get_addon_instance( $plugin_id ); FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array( FS_Permission_Manager::PERMISSION_DIAGNOSTIC => $is_diagnostic_tracking_allowed, FS_Permission_Manager::PERMISSION_EXTENSIONS => $is_extensions_tracking_allowed, ) ); $error = false; $next_page = false; $has_valid_blog_id = is_numeric( $blog_id ); $user = null; if ( $fs->is_addon() && $fs->get_parent_instance()->is_registered() ) { /** * When activating an add-on's license and the parent is opted-in, activate the license with the parent's opted-in user context. * * @author Vova Feldman (@svovaf) */ $user = $fs->get_parent_instance()->get_current_or_network_user(); } else if ( $fs->is_registered() ) { $user = $fs->get_current_or_network_user(); } if ( $has_valid_blog_id ) { /** * If a specific blog ID was provided, activate the license only on the specific blog that is associated with the given blog ID. * * @author Leo Fajardo (@leorw) */ $fs->switch_to_blog( $blog_id ); } if ( is_object( $user ) ) { $result = true; if ( $is_network_activation_or_migration && ! $has_valid_blog_id ) { // If no specific blog ID was provided, activate the license for all sites in the network. $blog_2_install_map = array(); $site_ids = array(); foreach ( $sites as $site ) { if ( ! isset( $site['blog_id'] ) || ! is_numeric( $site['blog_id'] ) ) { continue; } $install = $fs->get_install_by_blog_id( $site['blog_id'] ); if ( is_object( $install ) ) { $blog_2_install_map[ $site['blog_id'] ] = $install; } else { $site_ids[] = $site['blog_id']; } } if ( ! empty( $blog_2_install_map ) ) { $result = $fs->activate_license_on_many_installs( $user, $license_key, $blog_2_install_map ); } if ( true === $result && ! empty( $site_ids ) ) { $result = $fs->activate_license_on_many_sites( $user, $license_key, $site_ids ); } } else { if ( $fs->is_registered() ) { $params = array( 'license_key' => $fs->apply_filters( 'license_key', $license_key ) ); $install_ids = array(); $change_owner = FS_User::is_valid_id( $license_owner_id ); if ( $change_owner ) { $params['user_id'] = $license_owner_id; $installs_info_by_slug_map = $fs->get_parent_and_addons_installs_info(); foreach ( $installs_info_by_slug_map as $slug => $install_info ) { $install_ids[ $slug ] = $install_info['install']->id; } $params['install_ids'] = implode( ',', array_values( $install_ids ) ); } $api = $fs->get_api_site_scope(); $result = $api->call( $fs->add_show_pending( '/' ), 'put', $params ); if ( ! FS_Api::is_api_error( $result ) ) { $install = $result; $fs->reconnect_locally( $has_valid_blog_id ); if ( $change_owner && // If successful ownership change. $fs->get_user()->id != $install->user_id ) { $fs->complete_ownership_change_by_license( $install->user_id, $install_ids ); } } } else /* ( $fs->is_addon() && $fs->get_parent_instance()->is_registered() ) */ { $result = $fs->activate_license_on_site( $user, $license_key ); } } if ( true !== $result && ! FS_Api::is_api_result_entity( $result ) ) { if ( FS_Api::is_blocked( $result ) ) { $result->error->message = $this->generate_api_blocked_notice_message_from_result( $result ); } $error = FS_Api::is_api_error_object( $result ) ? $result->error->message : var_export( $result, true ); } else { $fs->network_upgrade_mode_completed(); $fs->_user = $user; if ( fs_is_network_admin() && ! $has_valid_blog_id ) { $fs->_site = $fs->get_network_install(); } $fs->_sync_license( true, $has_valid_blog_id ); $this->maybe_sync_install_user(); $next_page = $fs->is_addon() ? $fs->get_parent_instance()->get_account_url() : $fs->get_after_activation_url( 'after_connect_url' ); } } else { $next_page = $fs->opt_in( false, false, false, $license_key, false, false, false, $is_marketing_allowed, $sites ); if ( isset( $next_page->error ) ) { $error = $next_page->error; } else { if ( $is_network_activation_or_migration ) { /** * Get the list of sites that were just opted-in (and license activated). * This is an optimization for the next part below saving some DB queries. */ $connected_sites = array(); foreach ( $sites as $site ) { if ( isset( $site['blog_id'] ) && is_numeric( $site['blog_id'] ) ) { $connected_sites[ $site['blog_id'] ] = true; } } $all_sites = self::get_sites(); $pending_blog_ids = array(); /** * Check if there are any sites that are not connected, skipped, nor delegated. For every site that falls into that category, if the product is freemium, skip the connection. If the product is premium only, delegate the connection to the site administrator. * * @author Vova Feldman (@svovaf) */ foreach ( $all_sites as $site ) { $blog_id = self::get_site_blog_id( $site ); if ( isset( $connected_sites[ $blog_id ] ) ) { // Site was just connected. continue; } if ( $fs->is_installed_on_site( $blog_id ) ) { // Site was already connected before. continue; } if ( $fs->is_site_delegated_connection( $blog_id ) ) { // Site's connection was delegated. continue; } if ( $fs->is_anonymous_site( $blog_id ) ) { // Site connection was already skipped. continue; } $pending_blog_ids[] = $blog_id; } if ( ! empty( $pending_blog_ids ) ) { if ( $fs->is_freemium() && $fs->is_enable_anonymous() ) { $fs->skip_connection( $pending_blog_ids ); } else { $fs->delegate_connection( $pending_blog_ids ); } } } } } if ( false === $error && true === $fs->_storage->require_license_activation ) { $fs->_storage->require_license_activation = false; } $result = array( 'success' => ( false === $error ) ); if ( false !== $error ) { $result['error'] = $fs->apply_filters( 'opt_in_error_message', $error ); } else { if ( $fs->is_addon() || $fs->has_addons() ) { /** * Purge the valid user licenses cache so that when the "Account" or the "Add-Ons" page is loaded, * an updated valid user licenses collection will be fetched from the server which is used to also * update the account add-ons (add-ons the user has licenses for). * * @author Leo Fajardo (@leorw) * @since 2.2.4 */ $fs->purge_valid_user_licenses_cache(); } $result['next_page'] = $next_page; } return $result; } /** * @author Leo Fajardo (@leorw) * @since 2.3.2 * * @return array { * @key string Product slug. * @value array { * @property FS_Site $site * @property FS_Plugin_License $license * } * } */ private function get_parent_and_addons_installs_info() { $fs = $this->is_addon() ? $this->get_parent_instance() : $this; $installed_addons_ids = array(); $installed_addons_instances = $fs->get_installed_addons(); foreach ( $installed_addons_instances as $instance ) { $installed_addons_ids[] = $instance->get_id(); } $addons_ids = array_unique( array_merge( $installed_addons_ids, $fs->get_updated_account_addons() ) ); // Add parent product info. $installs_info_by_slug_map = array( $fs->get_slug() => array( 'install' => $fs->get_site(), 'license' => $fs->_get_license() ) ); foreach ( $addons_ids as $addon_id ) { $is_installed = isset( $installed_addons_ids_map[ $addon_id ] ); $addon_info = $fs->_get_addon_info( $addon_id, $is_installed ); if ( ! isset( $addon_info['is_connected'] ) || ! $addon_info['is_connected'] ) { // Add-on is not associated with an install entity. continue; } $installs_info_by_slug_map[ $addon_info['slug'] ] = array( 'install' => $addon_info['site'], 'license' => isset( $addon_info['license'] ) ? $addon_info['license'] : null ); } return $installs_info_by_slug_map; } /** * @author Leo Fajardo (@leorw) * @since 1.2.3.1 */ function _network_activate_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'network_activate' ); $plugin_id = fs_request_get( 'module_id', '', 'post' ); $fs = ( $plugin_id == $this->_module_id ) ? $this : $this->get_addon_instance( $plugin_id ); $error = false; $sites = fs_request_get( 'sites', array(), 'post' ); if ( is_array( $sites ) && ! empty( $sites ) ) { $sites_by_action = array( 'allow' => array(), 'delegate' => array(), 'skip' => array() ); foreach ( $sites as $site ) { $sites_by_action[ $site['action'] ][] = $site; } $total_sites = count( $sites ); $total_sites_to_delegate = count( $sites_by_action['delegate'] ); $next_page = ''; $has_any_install = fs_request_get_bool( 'has_any_install' ); if ( $total_sites === $total_sites_to_delegate && ! $this->is_network_upgrade_mode() && ! $has_any_install ) { $this->delegate_connection(); } else { if ( ! empty( $sites_by_action['delegate'] ) ) { $this->delegate_connection( self::get_sites_blog_ids( $sites_by_action['delegate'] ) ); } if ( ! empty( $sites_by_action['skip'] ) ) { $this->skip_connection( self::get_sites_blog_ids( $sites_by_action['skip'] ) ); } if ( empty( $sites_by_action['allow'] ) ) { if ( $has_any_install ) { $first_install = $fs->find_first_install(); if ( ! is_null( $first_install ) ) { $fs->_site = $first_install['install']; $fs->_storage->network_install_blog_id = $first_install['blog_id']; $fs->_user = self::_get_user_by_id( $fs->_site->user_id ); $fs->_storage->network_user_id = $fs->_user->id; } } } else { if ( ! $fs->is_registered() || ! $this->_is_network_active ) { $next_page = $fs->opt_in( false, false, false, false, false, false, false, fs_request_get_bool( 'is_marketing_allowed', null ), $sites_by_action['allow'] ); } else { $next_page = $fs->install_with_user( $this->get_network_user(), false, false, false, true, $sites_by_action['allow'] ); } if ( is_object( $next_page ) && isset( $next_page->error ) ) { $error = $next_page->error; } } } if ( empty( $next_page ) ) { $next_page = $this->get_after_activation_url( 'after_network_activation_url' ); } } else { $error = $this->get_text_inline( 'Invalid site details collection.', 'invalid_site_details_collection' ); } $result = array( 'success' => ( false === $error ) ); if ( false !== $error ) { $result['error'] = $error; } else { $result['next_page'] = $next_page; } echo json_encode( $result ); exit; } /** * Billing update AJAX callback. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 */ function _update_billing_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'update_billing' ); if ( ! $this->is_user_admin() ) { // Only for admins. self::shoot_ajax_failure(); } $billing = fs_request_get( 'billing' ); $api = $this->get_api_user_scope(); $result = $api->call( '/billing.json', 'put', array_merge( $billing, array( 'plugin_id' => $this->get_parent_id(), ) ) ); if ( ! $this->is_api_result_entity( $result ) ) { self::shoot_ajax_failure(); } // Purge cached billing. $this->get_api_user_scope()->purge_cache( 'billing.json' ); self::shoot_ajax_success(); } /** * Trial start for anonymous users (AJAX callback). * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 */ function _start_trial_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'start_trial' ); if ( ! $this->is_user_admin() ) { // Only for admins. self::shoot_ajax_failure(); } $trial_data = fs_request_get( 'trial' ); $next_page = $this->opt_in( false, false, false, false, false, $trial_data['plan_id'] ); if ( is_object( $next_page ) && $this->is_api_error( $next_page ) ) { self::shoot_ajax_failure( isset( $next_page->error ) ? $next_page->error->message : var_export( $next_page, true ) ); } $this->shoot_ajax_success( array( 'next_page' => $next_page, ) ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.0 */ function _resend_license_key_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'resend_license_key' ); $email_address = sanitize_email( trim( fs_request_get( 'email', '', 'post' ) ) ); if ( empty( $email_address ) ) { exit; } $error = false; $api = $this->get_api_plugin_scope(); $result = $api->call( '/licenses/resend.json', 'post', array( 'email' => $email_address, 'url' => home_url(), ) ); if ( is_object( $result ) && isset( $result->error ) ) { $error = $result->error; if ( in_array( $error->code, array( 'invalid_email', 'no_user' ) ) ) { $error = $this->get_text_inline( "We couldn't find your email address in the system, are you sure it's the right address?", 'email-not-found' ); } else if ( 'no_license' === $error->code ) { $error = $this->get_text_inline( "We can't see any active licenses associated with that email address, are you sure it's the right address?", 'no-active-licenses' ); } else { $error = $error->message; } } $licenses = array( 'success' => ( false === $error ) ); if ( false !== $error ) { $licenses['error'] = sprintf( '%s... %s', $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ), strtolower( $error ) ); } echo json_encode( $licenses ); exit; } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.8 * * @var string */ private static $_pagenow; /** * Get current page or the referer if executing a WP AJAX request. * * @author Vova Feldman (@svovaf) * @since 1.2.1.8 * * @return string */ static function get_current_page() { if ( ! isset( self::$_pagenow ) ) { global $pagenow; if ( empty( $pagenow ) && is_admin() && is_multisite() ) { /** * It appears that `$pagenow` is not yet initialized in some network admin pages when this method * is called, so initialize it here using some pieces of code from `wp-includes/vars.php`. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ if ( is_network_admin() ) { preg_match( '#/wp-admin/network/?(.*?)$#i', $_SERVER['PHP_SELF'], $self_matches ); } else if ( is_user_admin() ) { preg_match( '#/wp-admin/user/?(.*?)$#i', $_SERVER['PHP_SELF'], $self_matches ); } else { preg_match( '#/wp-admin/?(.*?)$#i', $_SERVER['PHP_SELF'], $self_matches ); } $pagenow = $self_matches[1]; $pagenow = trim( $pagenow, '/' ); $pagenow = preg_replace( '#\?.*?$#', '', $pagenow ); if ( '' === $pagenow || 'index' === $pagenow || 'index.php' === $pagenow ) { $pagenow = 'index.php'; } else { preg_match( '#(.*?)(/|$)#', $pagenow, $self_matches ); $pagenow = strtolower( $self_matches[1] ); if ( '.php' !== substr($pagenow, -4, 4) ) $pagenow .= '.php'; // for Options +Multiviews: /wp-admin/themes/index.php (themes.php is queried) } } self::$_pagenow = $pagenow; if ( self::is_ajax() && 'admin-ajax.php' === $pagenow ) { $referer = fs_get_raw_referer(); if ( is_string( $referer ) ) { $parts = explode( '?', $referer ); self::$_pagenow = basename( $parts[0] ); } } } return self::$_pagenow; } /** * Helper method to check if user in the plugins page. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @return bool */ static function is_plugins_page() { return ( 'plugins.php' === self::get_current_page() ); } /** * @author Leo Fajardo (@leorw) * @since 2.2.3 * * @return bool */ static function is_plugin_install_page() { return ( 'plugin-install.php' === self::get_current_page() ); } /** * @author Leo Fajardo (@leorw) * @since 2.0.2 * * @return bool */ static function is_updates_page() { return ( 'update-core.php' === self::get_current_page() ); } /** * Helper method to check if user in the themes page. * * @author Vova Feldman (@svovaf) * @since 1.2.2.6 * * @return bool */ static function is_themes_page() { return ( 'themes.php' === self::get_current_page() ); } #---------------------------------------------------------------------------------- #region Affiliation #---------------------------------------------------------------------------------- /** * @author Leo Fajardo (@leorw) * @since 1.2.3 * * @return bool */ function has_affiliate_program() { if ( ! is_object( $this->_plugin ) ) { return false; } return $this->_plugin->has_affiliate_program(); } /** * Get Plugin ID under which we will track affiliate application. * * This could either be the Bundle ID or the main plugin ID. * * @return number Bundle ID if developer has provided one, else the main plugin ID. */ private function get_plugin_id_for_affiliate_terms() { return $this->has_bundle_context() ? $this->get_bundle_id() : $this->_plugin->id; } /** * @author Leo Fajardo (@leorw) * @since 1.2.4 */ private function fetch_affiliate_terms() { if ( ! is_object( $this->plugin_affiliate_terms ) ) { /** * In case we have a bundle set in SDK configuration, we would like to use that for affiliates, not the main plugin. */ $plugins_api = $this->has_bundle_context() ? $this->get_api_bundle_scope() : $this->get_api_plugin_scope(); $affiliate_terms = $plugins_api->get( '/aff.json?type=affiliation', false ); /** * At this point, we intentionally don't fallback to the main plugin, because the developer has chosen to use bundle. So it makes sense the affiliate program should be in context to the bundle too. */ if ( ! $this->is_api_result_entity( $affiliate_terms ) ) { return; } $this->plugin_affiliate_terms = new FS_AffiliateTerms( $affiliate_terms ); } } /** * @author Leo Fajardo (@leorw) * @since 1.2.4 */ private function fetch_affiliate_and_custom_terms() { if ( ! empty( $this->_storage->affiliate_application_data ) ) { $application_data = $this->_storage->affiliate_application_data; $flush = ( ! isset( $application_data['status'] ) || 'pending' === $application_data['status'] ); $plugin_id_for_affiliate = $this->get_plugin_id_for_affiliate_terms(); $users_api = $this->get_api_user_scope(); $result = $users_api->get( "/plugins/{$plugin_id_for_affiliate}/aff/{$this->plugin_affiliate_terms->id}/affiliates.json", $flush ); if ( $this->is_api_result_object( $result, 'affiliates' ) ) { if ( ! empty( $result->affiliates ) ) { $affiliate = new FS_Affiliate( $result->affiliates[0] ); if ( ! isset( $application_data['status'] ) || $application_data['status'] !== $affiliate->status ) { $application_data['status'] = $affiliate->status; $this->_storage->affiliate_application_data = $application_data; } if ( $affiliate->is_using_custom_terms ) { $affiliate_terms = $users_api->get( "/plugins/{$this->_plugin->id}/affiliates/{$affiliate->id}/aff/{$affiliate->custom_affiliate_terms_id}.json", $flush ); if ( $this->is_api_result_entity( $affiliate_terms ) ) { $this->custom_affiliate_terms = new FS_AffiliateTerms( $affiliate_terms ); } } $this->affiliate = $affiliate; } } } } /** * @author Leo Fajardo (@leorw) * @since 1.2.3 */ private function fetch_affiliate_and_terms() { $this->_logger->entrance(); $this->fetch_affiliate_terms(); $this->fetch_affiliate_and_custom_terms(); } /** * @author Leo Fajardo (@leorw) * @since 1.2.3 * * @return FS_Affiliate */ function get_affiliate() { return $this->affiliate; } /** * @author Leo Fajardo (@leorw) * @since 1.2.3 * * @return FS_AffiliateTerms */ function get_affiliate_terms() { return is_object( $this->custom_affiliate_terms ) ? $this->custom_affiliate_terms : $this->plugin_affiliate_terms; } /** * @author Leo Fajardo (@leorw) * @since 1.2.3 */ function _submit_affiliate_application() { $this->_logger->entrance(); $this->check_ajax_referer( 'submit_affiliate_application' ); if ( ! $this->is_user_admin() ) { // Only for admins. self::shoot_ajax_failure(); } $affiliate = fs_request_get( 'affiliate' ); if ( empty( $affiliate['promotion_methods'] ) ) { unset( $affiliate['promotion_methods'] ); } if ( ! empty( $affiliate['additional_domains'] ) ) { $affiliate['additional_domains'] = array_unique( $affiliate['additional_domains'] ); } if ( ! $this->is_registered() ) { // Opt in but don't track usage. $next_page = $this->opt_in( false, false, false, false, false, false, true ); if ( is_object( $next_page ) && $this->is_api_error( $next_page ) ) { self::shoot_ajax_failure( isset( $next_page->error ) ? $next_page->error->message : var_export( $next_page, true ) ); } else if ( $this->is_pending_activation() ) { self::shoot_ajax_failure( $this->get_text_inline( 'Account is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.', 'account-is-pending-activation' ) ); } } $this->fetch_affiliate_terms(); $plugin_id_for_affiliate = $this->get_plugin_id_for_affiliate_terms(); $api = $this->get_api_user_scope(); $result = $api->call( ( "/plugins/{$plugin_id_for_affiliate}/aff/{$this->plugin_affiliate_terms->id}/affiliates.json" ), 'post', $affiliate ); if ( $this->is_api_error( $result ) ) { self::shoot_ajax_failure( isset( $result->error ) ? $result->error->message : var_export( $result, true ) ); } else { if ( $this->_admin_notices->has_sticky( 'affiliate_program' ) ) { $this->_admin_notices->remove_sticky( 'affiliate_program' ); } $affiliate_application_data = array( 'status' => 'pending', 'stats_description' => $affiliate['stats_description'], 'promotion_method_description' => $affiliate['promotion_method_description'], ); if ( ! empty( $affiliate['promotion_methods'] ) ) { $affiliate_application_data['promotion_methods'] = $affiliate['promotion_methods']; } if ( ! empty( $affiliate['domain'] ) ) { $affiliate_application_data['domain'] = $affiliate['domain']; } if ( ! empty( $affiliate['additional_domains'] ) ) { $affiliate_application_data['additional_domains'] = $affiliate['additional_domains']; } $this->_storage->affiliate_application_data = $affiliate_application_data; } // Purge cached affiliate. $api->purge_cache( 'affiliate.json' ); self::shoot_ajax_success( $result ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.3 * * @return array|null */ function get_affiliate_application_data() { if ( empty( $this->_storage->affiliate_application_data ) ) { return null; } return $this->_storage->affiliate_application_data; } #endregion Affiliation ------------------------------------------------------------ #---------------------------------------------------------------------------------- #region URL Generators #---------------------------------------------------------------------------------- /** * Alias to pricing_url(). * * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @uses pricing_url() * * @param string $period Billing cycle * @param bool $is_trial * * @return string */ function get_upgrade_url( $period = WP_FS__PERIOD_ANNUALLY, $is_trial = false ) { return $this->pricing_url( $period, $is_trial ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @uses get_upgrade_url() * * @return string */ function get_trial_url() { return $this->get_upgrade_url( WP_FS__PERIOD_ANNUALLY, true ); } /** * @author Leo Fajardo (@leorw) * @since 2.1.4 * * @param string $new_version * * @return string */ function version_upgrade_checkout_link( $new_version ) { if ( ! is_object( $this->_license ) ) { $url = $this->pricing_url(); $purchase_license_text = $this->get_text_inline( 'Buy a license now', 'buy-license-now' ); } else { $subscription = $this->_get_subscription( $this->_license->id ); $url = $this->checkout_url( is_object( $subscription ) ? ( 1 == $subscription->billing_cycle ? WP_FS__PERIOD_MONTHLY : WP_FS__PERIOD_ANNUALLY ) : WP_FS__PERIOD_LIFETIME, false, array( 'licenses' => $this->_license->quota ) ); $purchase_license_text = $this->get_text_inline( 'Renew your license now', 'renew-license-now' ); } return sprintf( $this->get_text_inline( '%s to access version %s security & feature updates, and support.', 'x-for-updates-and-support' ), sprintf( '%s', $this->apply_filters( 'update_notice_checkout_url', $url ), $purchase_license_text ), $new_version ); } /** * Plugin's pricing URL. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param string $billing_cycle Billing cycle * * @param bool $is_trial * * @return string */ function pricing_url( $billing_cycle = WP_FS__PERIOD_ANNUALLY, $is_trial = false ) { $this->_logger->entrance(); $params = array( 'billing_cycle' => $billing_cycle ); if ( $is_trial ) { $params['trial'] = 'true'; } $url = $this->is_addon() ? $this->_parent->addon_url( $this->_slug ) : $this->_get_admin_page_url( 'pricing', $params ); return $this->apply_filters( 'pricing_url', $url ); } /** * Checkout page URL. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param string $billing_cycle Billing cycle * @param bool $is_trial * @param array $extra (optional) Extra parameters, override other query params. * @param bool|null $network * * @return string */ function checkout_url( $billing_cycle = WP_FS__PERIOD_ANNUALLY, $is_trial = false, $extra = array(), $network = null ) { $this->_logger->entrance(); $params = array( 'checkout' => 'true', 'billing_cycle' => $billing_cycle, ); if ( $is_trial ) { $params['trial'] = 'true'; } /** * Params in extra override other params. */ $params = array_merge( $params, $extra ); return $this->apply_filters( 'checkout_url', $this->_get_admin_page_url( 'pricing', $params, $network ) ); } /** * Add-on checkout URL. * * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @param number $addon_id * @param number $pricing_id * @param string $billing_cycle * @param bool $is_trial * @param bool|null $network * * @return string */ function addon_checkout_url( $addon_id, $pricing_id, $billing_cycle = WP_FS__PERIOD_ANNUALLY, $is_trial = false, $network = null ) { return $this->checkout_url( $billing_cycle, $is_trial, array( 'plugin_id' => $addon_id, 'pricing_id' => $pricing_id, ), $network ); } #endregion #endregion ------------------------------------------------------------------ /** * Check if plugin has any add-ons. * * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @since 1.1.7.3 Base logic only on the parameter provided by the developer in the init function. * * @return bool */ function has_addons() { $this->_logger->entrance(); return $this->_has_addons; } /** * Check if plugin can work in anonymous mode. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool * * @deprecated Please use is_enable_anonymous() instead. */ function enable_anonymous() { return $this->_enable_anonymous; } /** * Check if plugin can work in anonymous mode. * * @author Vova Feldman (@svovaf) * @since 1.1.9 * * @return bool */ function is_enable_anonymous() { return $this->_enable_anonymous; } /** * Check if plugin is premium only (no free plans). * * @author Vova Feldman (@svovaf) * @since 1.1.9 * * @return bool */ function is_only_premium() { return $this->_is_premium_only; } /** * Checks if the plugin's type is "plugin". The other type is "theme". * * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return bool */ function is_plugin() { return ( WP_FS__MODULE_TYPE_PLUGIN === $this->_module_type ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return string */ function get_module_type() { if ( ! isset( $this->_module_type ) ) { $id_slug_type_path_map = self::$_accounts->get_option( 'id_slug_type_path_map', array() ); $this->_module_type = $id_slug_type_path_map[ $this->_module_id ]['type']; } return $this->_module_type; } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return string */ function get_plugin_main_file_path() { return $this->_plugin_main_file_path; } /** * Check if module has a premium code version. * * Serviceware module might be freemium without any * premium code version, where the paid features * are all part of the service. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @return bool */ function has_premium_version() { return $this->_has_premium_version; } /** * Check if feature supported with current site's plan. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @todo IMPLEMENT * * @param number $feature_id * * @throws Exception */ function is_feature_supported( $feature_id ) { throw new Exception( 'not implemented' ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @return bool Is running in SSL/HTTPS */ function is_ssl() { return WP_FS__IS_HTTPS; } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool Is running in AJAX call. * * @link http://wordpress.stackexchange.com/questions/70676/how-to-check-if-i-am-in-admin-ajax */ static function is_ajax() { return ( defined( 'DOING_AJAX' ) && DOING_AJAX ); } /** * Check if it's an AJAX call targeted for the current module. * * @author Vova Feldman (@svovaf) * @since 1.2.0 * * @param array|string $actions Collection of AJAX actions. * * @return bool */ function is_ajax_action( $actions ) { // Verify it's an ajax call. if ( ! self::is_ajax() ) { return false; } // Verify the call is relevant for the plugin. if ( $this->_module_id != fs_request_get( 'module_id' ) ) { return false; } // Verify it's one of the specified actions. if ( is_string( $actions ) ) { $actions = explode( ',', $actions ); } if ( is_array( $actions ) && 0 < count( $actions ) ) { $ajax_action = fs_request_get( 'action' ); foreach ( $actions as $action ) { if ( $ajax_action === $this->get_action_tag( $action ) ) { return true; } } } return false; } /** * Check if it's an AJAX call targeted for current request. * * @author Vova Feldman (@svovaf) * @since 1.2.0 * * @param array|string $actions Collection of AJAX actions. * @param number|null $module_id * * @return bool */ static function is_ajax_action_static( $actions, $module_id = null ) { // Verify it's an ajax call. if ( ! self::is_ajax() ) { return false; } if ( ! empty( $module_id ) ) { // Verify the call is relevant for the plugin. if ( $module_id != fs_request_get( 'module_id' ) ) { return false; } } // Verify it's one of the specified actions. if ( is_string( $actions ) ) { $actions = explode( ',', $actions ); } if ( is_array( $actions ) && 0 < count( $actions ) ) { $ajax_action = fs_request_get( 'action' ); foreach ( $actions as $action ) { if ( $ajax_action === self::get_ajax_action_static( $action, $module_id ) ) { return true; } } } return false; } /** * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @return bool */ static function is_cron() { return ( defined( 'DOING_CRON' ) && DOING_CRON ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @return bool */ static function is_admin_post() { return ( 'admin-post.php' === self::get_current_page() ); } /** * Check if a real user is visiting the admin dashboard. * * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @return bool */ function is_user_in_admin() { return ( is_admin() && ! self::is_ajax() && ! self::is_cron() && ! self::is_admin_post() ); } /** * Check if a real user is in the customizer view. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool */ static function is_customizer() { return is_customize_preview(); } /** * Check if running in HTTPS and if site's plan matching the specified plan. * * @param string $plan * @param bool $exact * * @return bool */ function is_ssl_and_plan( $plan, $exact = false ) { return ( $this->is_ssl() && $this->is_plan( $plan, $exact ) ); } /** * Construct plugin's settings page URL. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param string $page * @param array $params * @param bool|null $network * * @return string */ function _get_admin_page_url( $page = '', $params = array(), $network = null ) { if ( is_null( $network ) ) { $network = ( $this->_is_network_active && ( fs_is_network_admin() || ! $this->is_delegated_connection() ) ); } if ( 0 < count( $params ) ) { foreach ( $params as $k => $v ) { $params[ $k ] = urlencode( $v ); } } $page_param = $this->_menu->get_slug( $page ); if ( empty( $page ) && // Show the opt-in as an overlay for free wp.org themes or themes without any settings page. $this->show_opt_in_on_themes_page() ) { $params[ $this->get_unique_affix() . '_show_optin' ] = 'true'; return add_query_arg( $params, $this->admin_url( 'themes.php', 'admin', $network ) ); } if ( ! $this->has_settings_menu() ) { if ( ! empty( $page ) ) { // Module doesn't have a setting page, but since the request is for // a specific Freemius page, use the admin.php path. return add_query_arg( array_merge( $params, array( 'page' => $page_param, ) ), $this->admin_url( 'admin.php', 'admin', $network ) ); } else { if ( $this->is_activation_mode() ) { /** * @author Vova Feldman * @since 1.2.1.6 * * If plugin doesn't have a settings page, create one for the opt-in screen. */ return add_query_arg( array_merge( $params, array( 'page' => $this->_slug, ) ), $this->admin_url( 'admin.php', 'admin', $network ) ); } else { // Plugin without a settings page. return add_query_arg( $params, $this->admin_url( 'plugins.php', 'admin', $network ) ); } } } // Module has a submenu settings page. if ( ! $this->_menu->is_top_level() ) { $parent_slug = $this->_menu->get_parent_slug(); $menu_file = ( false !== strpos( $parent_slug, '.php' ) ) ? $parent_slug : 'admin.php'; return add_query_arg( array_merge( $params, array( 'page' => $page_param, ) ), $this->admin_url( $menu_file, 'admin', $network ) ); } // Module has a top level CPT settings page. if ( $this->_menu->is_cpt() ) { if ( empty( $page ) && $this->is_activation_mode() ) { return add_query_arg( array_merge( $params, array( 'page' => $page_param ) ), $this->admin_url( 'admin.php', 'admin', $network ) ); } else { if ( ! empty( $page ) ) { $params['page'] = $page_param; } return add_query_arg( $params, $this->admin_url( $this->_menu->get_raw_slug(), 'admin', $network ) ); } } // Module has a custom top level settings page. return add_query_arg( array_merge( $params, array( 'page' => $page_param, ) ), $this->admin_url( 'admin.php', 'admin', $network ) ); } #-------------------------------------------------------------------------------- #region Multisite #-------------------------------------------------------------------------------- /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @return bool */ function is_network_active() { return $this->_is_network_active; } /** * Delegate activation for the given sites in the network (or all sites if `null`) to site admins. * * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param bool|int[] $all_or_blog_ids */ private function delegate_connection( $all_or_blog_ids = true ) { $this->_logger->entrance(); $this->_admin_notices->remove_sticky( 'connect_account' ); if ( true === $all_or_blog_ids ) { // All sites delegation. $this->_storage->store( 'is_delegated_connection', true, true ); } else { // Specified sites delegation. foreach ( $all_or_blog_ids as $blog_id ) { $this->delegate_site_connection( $blog_id ); } } $this->network_upgrade_mode_completed(); } /** * Delegate specific network site conncetion to the site admin. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id */ private function delegate_site_connection( $blog_id ) { $this->_storage->store( 'is_delegated_connection', true, $blog_id ); } /** * Check if super-admin delegated the connection of ALL sites to the site admins. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return bool */ function is_network_delegated_connection() { if ( ! $this->_is_network_active ) { return false; } return $this->_storage->get( 'is_delegated_connection', false, true ); } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param int $blog_id * * @return bool */ function is_site_delegated_connection( $blog_id = 0 ) { if ( ! $this->_is_network_active ) { return false; } if ( 0 == $blog_id ) { $blog_id = get_current_blog_id(); } return $this->_storage->get( 'is_delegated_connection', false, $blog_id ); } /** * Check if delegated the connection. When running within the network admin, * and haven't specified the blog ID, checks if network level delegated. If running * within a site admin or specified a blog ID, check if delegated the connection for * the current context site. * * If executed outside the the admin, check if delegated the connection * for the current context site OR the whole network. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id If set, checks if network delegated or blog specific delegated. * * @return bool */ function is_delegated_connection( $blog_id = 0 ) { if ( ! $this->_is_network_active ) { return false; } if ( fs_is_network_admin() && 0 == $blog_id ) { return $this->is_network_delegated_connection(); } return ( $this->is_network_delegated_connection() || $this->is_site_delegated_connection( $blog_id ) ); } /** * Check if the current module is active for the site. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id * * @return bool */ function is_active_for_site( $blog_id ) { if ( ! is_multisite() ) { // Not a multisite and this code is executed, means that the plugin is active. return true; } if ( $this->is_theme() ) { // All themes are site level activated. return true; } if ( $this->_is_network_active ) { // Plugin was network activated so it's active. return true; } return in_array( $this->_plugin_basename, (array) get_blog_option( $blog_id, 'active_plugins', array() ) ); } /** * @todo Implement pagination when accessing the subsites collection. * * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param int $limit Default to 1,000 * @param int $offset Default to 0 * * @return array Active & public sites collection. */ static function get_sites( $limit = 1000, $offset = 0 ) { if ( ! is_multisite() ) { return array(); } /** * For consistency with get_blog_list() which only return active public sites. * * @author Vova Feldman (@svovaf) */ $args = array( /** * Commented out in order to handle the migration of site options whether the site is public or not. * * @author Leo Fajardo (@leorw) * @since 2.2.1 */ // 'public' => 1, 'archived' => 0, 'mature' => 0, 'spam' => 0, 'deleted' => 0, 'number' => $limit, 'offset' => $offset, ); return get_sites( $args ); } /** * Checks if a given blog is active. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param $blog_id * * @return bool */ private static function is_site_active( $blog_id ) { global $wpdb; $blog_info = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->blogs} WHERE blog_id = %d", $blog_id ) ); if ( ! is_object( $blog_info ) ) { return false; } return ( true == $blog_info->public && false == $blog_info->archived && false == $blog_info->mature && false == $blog_info->spam && false == $blog_info->deleted ); } /** * Get a mapping between the site addresses to their blog IDs. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return array { * @key string Site address without protocol with a trailing slash. * @value int Site's blog ID. * } */ private function get_address_to_blog_map() { $sites = self::get_sites(); // Map site addresses to their blog IDs. $address_to_blog_map = array(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $address = self::get_unfiltered_site_url( $blog_id, true, true ); $address_to_blog_map[ $address ] = $blog_id; } return $address_to_blog_map; } /** * Get a mapping between the site addresses to their blog IDs. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return array { * @key int Site's blog ID. * @value FS_Site Associated install. * } */ function get_blog_install_map() { $sites = self::get_sites(); // Map site blog ID to its install. $install_map = array(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $install = $this->get_install_by_blog_id( $blog_id ); if ( is_object( $install ) ) { $install_map[ $blog_id ] = $install; } } return $install_map; } /** * @author Vova Feldman (@svovaf) * @since 2.5.1 * * @param bool|null $is_delegated When `true`, returns only connection delegated blog IDs. When `false`, only non-delegated blog IDs. * * @return int[] */ private function get_blog_ids( $is_delegated = null ) { $blog_ids = array(); $sites = self::get_sites(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); if ( is_null( $is_delegated ) || $is_delegated === $this->is_site_delegated_connection( $blog_id ) ) { $blog_ids[] = $blog_id; } } return $blog_ids; } /** * @author Vova Feldman (@svovaf) * @since 2.5.1 * * @return int[] */ private function get_non_delegated_blog_ids() { return $this->get_blog_ids( false ); } /** * Gets a map of module IDs that the given user has opted-in to. * * @author Leo Fajardo (@leorw) * @since 2.1.0 * * @param number $fs_user_id * * @return array { * @key number $plugin_id * @value bool Always true. * } */ private static function get_user_opted_in_module_ids_map( $fs_user_id ) { self::$_static_logger->entrance(); if ( ! is_multisite() ) { $installs = array_merge( self::get_all_sites( WP_FS__MODULE_TYPE_PLUGIN ), self::get_all_sites( WP_FS__MODULE_TYPE_THEME ) ); } else { $sites = self::get_sites(); $installs = array(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $installs = array_merge( $installs, self::get_all_sites( WP_FS__MODULE_TYPE_PLUGIN, $blog_id ), self::get_all_sites( WP_FS__MODULE_TYPE_THEME, $blog_id ) ); } } $module_ids_map = array(); foreach ( $installs as $install ) { if ( is_object( $install ) && FS_Site::is_valid_id( $install->id ) && FS_User::is_valid_id( $install->user_id ) && ( $install->user_id == $fs_user_id ) ) { $module_ids_map[ $install->plugin_id ] = true; } } return $module_ids_map; } /** * @author Leo Fajardo (@leorw) * * @return null|array { * 'install' => FS_Site Module's install, * 'blog_id' => string The associated blog ID. * } */ function find_first_install() { $sites = self::get_sites(); foreach ( $sites as $site ) { $blog_id = self::get_site_blog_id( $site ); $install = $this->get_install_by_blog_id( $blog_id ); if ( is_object( $install ) ) { return array( 'install' => $install, 'blog_id' => $blog_id ); } } return null; } /** * Switches the Freemius site level context to a specified blog. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id * @param FS_Site $install * @param bool $flush * * @return bool Since 2.3.1 returns if a switch was made. */ function switch_to_blog( $blog_id, FS_Site $install = null, $flush = false ) { if ( ! is_numeric( $blog_id ) ) { return false; } if ( ! $flush && $blog_id == $this->_context_is_network_or_blog_id ) { return false; } switch_to_blog( $blog_id ); $this->_context_is_network_or_blog_id = $blog_id; self::$_accounts->set_site_blog_context( $blog_id ); $this->_storage->set_site_blog_context( $blog_id ); $this->_storage->set_network_active( $this->_is_network_active, $this->is_delegated_connection( $blog_id ) ); $this->_site = is_object( $install ) ? $install : $this->get_install_by_blog_id( $blog_id ); $this->_user = false; $this->_licenses = false; $this->_license = null; $this->is_whitelabeled = null; if ( is_object( $this->_site ) ) { // Try to fetch user from install. $this->_user = self::_get_user_by_id( $this->_site->user_id ); if ( ! is_object( $this->_user ) && FS_User::is_valid_id( $this->_storage->prev_user_id ) ) { // Try to fetch previously saved user. $this->_user = self::_get_user_by_id( $this->_storage->prev_user_id ); if ( ! is_object( $this->_user ) ) { // Fallback to network's user. $this->_user = $this->get_network_user(); } } $all_plugin_licenses = self::get_all_licenses( $this->_module_id ); if ( ! empty( $all_plugin_licenses ) ) { if ( ! FS_Plugin_License::is_valid_id( $this->_site->license_id ) ) { $this->_license = null; } else { $license_found = false; foreach ( $all_plugin_licenses as $license ) { if ( $license->id == $this->_site->license_id ) { // License found. $this->_license = $license; $license_found = true; break; } } if ( $license_found ) { $this->link_license_2_user( $this->_license->id, $this->_user->id ); } } $this->_licenses = $this->get_user_licenses( $this->_user->id ); } } unset( $this->_site_api ); unset( $this->_user_api ); return true; } /** * Restore the blog context to the blog that originally loaded the module. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function restore_current_blog() { $this->switch_to_blog( $this->_blog_id ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param array|WP_Site $site * * @return int */ static function get_site_blog_id( &$site ) { return ( $site instanceof WP_Site ) ? $site->blog_id : ( is_object( $site ) && isset( $site->userblog_id ) ? $site->userblog_id : $site['blog_id'] ); } /** * @author Vova Feldman (@svovaf) * @since 2.5.1 * * @param WP_Site[]|array[] $sites * * @return int[] */ static function get_sites_blog_ids( $sites ) { $blog_ids = array(); foreach ( $sites as $site ) { $blog_ids[] = self::get_site_blog_id( $site ); } return $blog_ids; } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param array|WP_Site|null $site * @param bool $load_registration Since 2.5.1 When set to `true` the method will attempt to return the subsite's registration date, regardless of the `$site` type and value. In most calls, the registration date will be returned anyway, even when the value is `false`. This param is purely for performance optimization. * * @return array */ function get_site_info( $site = null, $load_registration = false ) { $this->_logger->entrance(); $switched = false; $registration_date = null; if ( is_null( $site ) ) { $url = self::get_unfiltered_site_url(); $name = get_bloginfo( 'name' ); $blog_id = null; } else { $blog_id = self::get_site_blog_id( $site ); if ( get_current_blog_id() != $blog_id ) { switch_to_blog( $blog_id ); $switched = true; } if ( $site instanceof WP_Site ) { $url = $site->siteurl; $name = $site->blogname; $registration_date = $site->registered; } else { $url = self::get_unfiltered_site_url( $blog_id ); $name = get_bloginfo( 'name' ); } } if ( empty( $registration_date ) && $load_registration ) { $blog_details = get_blog_details( $blog_id, false ); if ( is_object( $blog_details ) && isset( $blog_details->registered ) ) { $registration_date = $blog_details->registered; } } $info = array( 'uid' => $this->get_anonymous_id( $blog_id ), 'url' => $url, ); // Add these diagnostic information only if user allowed to track. if ( FS_Permission_Manager::instance( $this )->is_diagnostic_tracking_allowed() ) { $info = array_merge( $info, array( 'title' => $name, 'language' => self::get_sanitized_language(), ) ); } if ( is_numeric( $blog_id ) ) { $info['blog_id'] = $blog_id; } if ( ! empty( $registration_date ) ) { $info[ 'registration_date' ] = $registration_date; } if ( $switched ) { restore_current_blog(); } return $info; } /** * Load the module's install based on the blog ID. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int|null $blog_id * * @return FS_Site */ function get_install_by_blog_id( $blog_id = null ) { $installs = self::get_all_sites( $this->_module_type, $blog_id ); $install = isset( $installs[ $this->_slug ] ) ? $installs[ $this->_slug ] : null; if ( is_object( $install ) && is_numeric( $install->id ) && is_numeric( $install->user_id ) && FS_Plugin_Plan::is_valid_id( $install->plan_id ) ) { // Load site. $install = clone $install; } return $install; } /** * Check if module is installed on a specified site. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int|null $blog_id * * @return bool */ function is_installed_on_site( $blog_id = null ) { $installs = self::get_all_sites( $this->_module_type, $blog_id ); $install = isset( $installs[ $this->_slug ] ) ? $installs[ $this->_slug ] : null; return ( is_object( $install ) && is_numeric( $install->id ) && is_numeric( $install->user_id ) && FS_Plugin_Plan::is_valid_id( $install->plan_id ) ); } /** * Check if super-admin connected at least one site via the network opt-in. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return bool */ function is_network_registered() { if ( ! $this->_is_network_active ) { return false; } return FS_User::is_valid_id( $this->_storage->network_user_id ); } /** * Returns the main user associated with the network. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return FS_User */ function get_network_user() { if ( ! $this->_is_network_active ) { return null; } return FS_User::is_valid_id( $this->_storage->network_user_id ) ? self::_get_user_by_id( $this->_storage->network_user_id ) : null; } /** * Returns the current context user or the network's main user. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return FS_User */ function get_current_or_network_user() { return ( $this->_user instanceof FS_User ) ? $this->_user : $this->get_network_user(); } /** * Returns the main install associated with the network. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return FS_Site */ function get_network_install() { if ( ! $this->_is_network_active ) { return null; } return FS_Site::is_valid_id( $this->_storage->network_install_blog_id ) ? $this->get_install_by_blog_id( $this->_storage->network_install_blog_id ) : null; } /** * Returns the blog ID that is associated with the main install. * * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @return int|null */ function get_network_install_blog_id() { if ( ! $this->_is_network_active ) { return null; } return FS_Site::is_valid_id( $this->_storage->network_install_blog_id ) ? $this->_storage->network_install_blog_id : null; } /** * Returns the current context install or the network's main install. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return FS_Site */ function get_current_or_network_install() { return ( $this->_site instanceof FS_Site ) ? $this->_site : $this->get_network_install(); } /** * Check if executing a site level action from the network level admin. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return false|int If yes, return the requested blog ID. */ private function is_network_level_site_specific_action() { if ( ! $this->_is_network_active ) { return false; } if ( ! fs_is_network_admin() ) { return false; } $blog_id = fs_request_get( 'blog_id', '' ); return is_numeric( $blog_id ) ? $blog_id : false; } /** * Check if executing an action from the network level admin. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return bool */ private function is_network_level_action() { return ( $this->_is_network_active && fs_is_network_admin() ); } /** * Needs to be executed after site deactivation, archive, deletion, or flag as spam. * The logic updates the network level user and blog, and reschedule the crons if the cron executing site matching the site that is no longer publicly active. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $context_blog_id */ private function update_multisite_data_after_site_deactivation( $context_blog_id = 0 ) { $this->_logger->entrance(); if ( $this->_is_network_active ) { if ( $context_blog_id == $this->_storage->network_install_blog_id ) { $installs_map = $this->get_blog_install_map(); foreach ( $installs_map as $blog_id => $install ) { /** * @var FS_Site $install */ if ( $context_blog_id == $blog_id ) { continue; } if ( $install->user_id != $this->_storage->network_user_id ) { continue; } // Switch reference to a blog that is opted-in and belong to the same super-admin. $this->_storage->network_install_blog_id = $blog_id; break; } } } if ( ! $this->is_registered() ) { return; } if ( $this->is_sync_cron_scheduled() && $context_blog_id == $this->get_sync_cron_blog_id() ) { $this->schedule_sync_cron( WP_FS__SCRIPT_START_TIME, true, $context_blog_id ); } if ( $this->is_install_sync_scheduled() && $context_blog_id == $this->get_install_sync_cron_blog_id() ) { $this->schedule_install_sync( $context_blog_id ); } } /** * Executed after site deactivation, archive, or flag as spam. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $context_blog_id */ public function _after_site_deactivated_callback( $context_blog_id = 0 ) { $this->_logger->entrance(); $install = $this->get_install_by_blog_id( $context_blog_id ); if ( ! is_object( $install ) ) { // Site not connected. return; } $this->update_multisite_data_after_site_deactivation( $context_blog_id ); if ( ! $this->is_registered() ) { return; } $current_blog_id = get_current_blog_id(); $this->switch_to_blog( $context_blog_id ); // Send deactivation event. $this->sync_install( array( 'is_active' => false, ) ); $this->switch_to_blog( $current_blog_id ); } /** * Executed after site deletion. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $context_blog_id * @param bool $drop True if site's database tables should be dropped. Default is false. */ public function _after_site_deleted_callback( $context_blog_id = 0, $drop = false ) { $this->_logger->entrance(); $install = $this->get_install_by_blog_id( $context_blog_id ); if ( ! is_object( $install ) ) { // Site not connected. return; } $this->update_multisite_data_after_site_deactivation( $context_blog_id ); if ( ! $this->is_registered() ) { return; } $current_blog_id = get_current_blog_id(); $this->switch_to_blog( $context_blog_id ); if ( $drop ) { // Delete install if dropping site DB. $this->delete_account_event(); } else { // Send deactivation event. $this->sync_install( array( 'is_active' => false, ) ); } $this->switch_to_blog( $current_blog_id ); } /** * Executed after site deletion, called from wp_delete_site * * @author Dario Curvino (@dudo) * @since 2.5.0 * * @param WP_Site $old_site */ public function _after_wpsite_deleted_callback( WP_Site $old_site ) { $this->_logger->entrance(); $this->_after_site_deleted_callback( $old_site->blog_id, true ); } /** * Executed after site re-activation. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $context_blog_id */ public function _after_site_reactivated_callback( $context_blog_id = 0 ) { $this->_logger->entrance(); $install = $this->get_install_by_blog_id( $context_blog_id ); if ( ! is_object( $install ) ) { // Site not connected. return; } if ( ! self::is_site_active( $context_blog_id ) ) { // Site not yet active (can be in spam mode, archived, deleted...). return; } $current_blog_id = get_current_blog_id(); $this->switch_to_blog( $context_blog_id ); // Send re-activation event. $this->sync_install( array( 'is_active' => true, ) ); $this->switch_to_blog( $current_blog_id ); } #endregion Multisite /** * @author Leo Fajardo (@leorw) * * @param string $path * @param string $scheme * @param bool $network * * @return string */ private function admin_url( $path = '', $scheme = 'admin', $network = true ) { return ( $this->_is_network_active && $network ) ? network_admin_url( $path, $scheme ) : admin_url( $path, $scheme ); } /** * Check if currently in a specified admin page. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @param string $page * * @return bool */ function is_admin_page( $page ) { return ( $this->_menu->get_slug( $page ) === fs_request_get( 'page', '', 'get' ) ); } /** * Check if currently in the product's main admin page. * * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @return bool */ function is_main_admin_page() { return $this->is_admin_page( '' ); } /** * Get module's main admin setting page URL. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return string */ function main_menu_url() { return $this->_menu->main_menu_url(); } /** * Check if currently on the theme's setting page or * on any of the Freemius added pages (via tabs). * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool * * @deprecated Please use is_product_settings_page() instead; */ function is_theme_settings_page() { return $this->is_product_settings_page(); } /** * Check if currently on the product's main setting page or on any of the Freemius added pages (via tabs). * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool */ function is_product_settings_page() { $page = fs_request_get( 'page', '', 'get' ); $menu_slug = $this->_menu->get_slug(); if ( $page === $menu_slug ) { return true; } return fs_starts_with( // e.g., {$menu_slug}-account, {$menu_slug}-affiliation, etc. $page, ( $menu_slug . '-' ) ); } /** * Plugin's account page + sync license URL. * * @author Vova Feldman (@svovaf) * @since 1.1.9.1 * * @param bool|number $plugin_id * @param bool $add_action_nonce * @param array $params * * @return string */ function _get_sync_license_url( $plugin_id = false, $add_action_nonce = true, $params = array() ) { if ( is_numeric( $plugin_id ) ) { $params['plugin_id'] = $plugin_id; } return $this->get_account_url( $this->get_unique_affix() . '_sync_license', $params, $add_action_nonce ); } /** * Plugin's account URL. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param bool|string $action * @param array $params * * @param bool $add_action_nonce * * @return string */ function get_account_url( $action = false, $params = array(), $add_action_nonce = true ) { if ( is_string( $action ) ) { $params['fs_action'] = $action; } self::require_pluggable_essentials(); return ( $add_action_nonce && is_string( $action ) ) ? fs_nonce_url( $this->_get_admin_page_url( 'account', $params ), $action ) : $this->_get_admin_page_url( 'account', $params ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.0 * * @param string $tab * @param bool $action * @param array $params * @param bool $add_action_nonce * * @return string * * @uses get_account_url() */ function get_account_tab_url( $tab, $action = false, $params = array(), $add_action_nonce = true ) { $params['tab'] = $tab; return $this->get_account_url( $action, $params, $add_action_nonce ); } /** * Plugin's account URL. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param bool|string $topic * @param bool|string $message * @param bool|string $summary Since 2.5.1. * * @return string */ function contact_url( $topic = false, $message = false, $summary = false ) { $params = array(); if ( is_string( $topic ) ) { $params['topic'] = $topic; } if ( is_string( $message ) ) { $params['message'] = $message; } if ( is_string( $summary ) ) { $params['summary'] = $summary; } if ( $this->is_addon() ) { $params['addon_id'] = $this->get_id(); return $this->get_parent_instance()->_get_admin_page_url( 'contact', $params ); } else { return $this->_get_admin_page_url( 'contact', $params ); } } /** * Add-on direct info URL. * * @author Vova Feldman (@svovaf) * @since 1.1.0 * * @param string $slug * * @return string */ function addon_url( $slug ) { return $this->_get_admin_page_url( 'addons', array( 'slug' => $slug ) ); } /** * Add-ons URL. * * @author Vova Feldman (@svovaf) * @since 2.4.5 * * @return string */ function get_addons_url() { return $this->_get_admin_page_url( 'addons' ); } /* Logger ------------------------------------------------------------------------------------------------------------------*/ /** * @param string $id * @param bool $prefix_slug * * @return FS_Logger */ function get_logger( $id = '', $prefix_slug = true ) { return FS_Logger::get_logger( ( $prefix_slug ? $this->_slug : '' ) . ( ( ! $prefix_slug || empty( $id ) ) ? '' : '_' ) . $id ); } /** * Note: This method is used externally so don't delete it. * * @param $id * @param bool $load_options * @param bool $prefix_slug * * @return FS_Option_Manager */ function get_options_manager( $id, $load_options = false, $prefix_slug = true ) { return FS_Option_Manager::get_manager( ( $prefix_slug ? $this->_slug : '' ) . ( ( ! $prefix_slug || empty( $id ) ) ? '' : '_' ) . $id, $load_options ); } /* Security ------------------------------------------------------------------------------------------------------------------*/ private static function _encrypt( $str ) { if ( is_null( $str ) ) { return null; } /** * The encrypt/decrypt functions are used to protect * the user from messing up with some of the sensitive * data stored for the module as a JSON in the database. * * I used the same suggested hack by the theme review team. * For more details, look at the function `Base64UrlDecode()` * in `./sdk/FreemiusBase.php`. * * @todo Remove this hack once the base64 error is removed from the Theme Check. * * @author Vova Feldman (@svovaf) * @since 1.2.2 */ $fn = 'base64' . '_encode'; return $fn( $str ); } static function _decrypt( $str ) { if ( is_null( $str ) ) { return null; } /** * The encrypt/decrypt functions are used to protect * the user from messing up with some of the sensitive * data stored for the module as a JSON in the database. * * I used the same suggested hack by the theme review team. * For more details, look at the function `Base64UrlDecode()` * in `./sdk/FreemiusBase.php`. * * @todo Remove this hack once the base64 error is removed from the Theme Check. * * @author Vova Feldman (@svovaf) * @since 1.2.2 */ $fn = 'base64' . '_decode'; return $fn( $str ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param FS_Entity $entity * * @return FS_Entity Return an encrypted clone entity. */ private static function _encrypt_entity( FS_Entity $entity ) { $clone = clone $entity; $props = get_object_vars( $entity ); foreach ( $props as $key => $val ) { $clone->{$key} = self::_encrypt( $val ); } return $clone; } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param FS_Entity $entity * * @return FS_Entity Return an decrypted clone entity. */ private static function decrypt_entity( FS_Entity $entity ) { $clone = clone $entity; $props = get_object_vars( $entity ); foreach ( $props as $key => $val ) { $clone->{$key} = self::_decrypt( $val ); } return $clone; } /** * Tries to activate account based on POST params. * * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @deprecated Not in use, outdated. */ function _activate_account() { if ( $this->is_registered() ) { // Already activated. return; } self::_clean_admin_content_section(); if ( fs_request_is_action( 'activate' ) && fs_request_is_post() ) { // check_admin_referer( 'activate_' . $this->_plugin->public_key ); // Verify matching plugin details. if ( $this->_plugin->id != fs_request_get( 'plugin_id' ) || $this->_slug != fs_request_get( 'plugin_slug' ) ) { return; } $user = new FS_User(); $user->id = fs_request_get( 'user_id' ); $user->public_key = fs_request_get( 'user_public_key' ); $user->secret_key = fs_request_get( 'user_secret_key' ); $user->email = fs_request_get( 'user_email' ); $user->first = fs_request_get( 'user_first' ); $user->last = fs_request_get( 'user_last' ); $user->is_verified = fs_request_get_bool( 'user_is_verified' ); $site = new FS_Site(); $site->id = fs_request_get( 'install_id' ); $site->public_key = fs_request_get( 'install_public_key' ); $site->secret_key = fs_request_get( 'install_secret_key' ); $site->plan_id = fs_request_get( 'plan_id' ); $plans = array(); $plans_data = json_decode( urldecode( fs_request_get( 'plans' ) ) ); foreach ( $plans_data as $p ) { $plan = new FS_Plugin_Plan( $p ); if ( $site->plan_id == $plan->id ) { $plan->title = fs_request_get( 'plan_title' ); $plan->name = fs_request_get( 'plan_name' ); } $plans[] = $plan; } $this->_set_account( $user, $site, $plans ); // Reload the page with the keys. fs_redirect( $this->_get_admin_page_url() ); } } /** * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param string $email * * @return FS_User|false */ static function _get_user_by_email( $email ) { self::$_static_logger->entrance(); $email = trim( strtolower( $email ) ); $users = self::get_all_users(); if ( is_array( $users ) ) { foreach ( $users as $user ) { if ( $email === trim( strtolower( $user->email ) ) ) { return $user; } } } return false; } #---------------------------------------------------------------------------------- #region Account (Loading, Updates & Activation) #---------------------------------------------------------------------------------- /*** * Load account information (user + site). * * @author Vova Feldman (@svovaf) * @since 1.0.1 */ private function _load_account() { $this->_logger->entrance(); $this->do_action( 'before_account_load' ); $users = self::get_all_users(); $plans = self::get_all_plans( $this->_module_type ); if ( $this->_logger->is_on() && is_admin() ) { $this->_logger->log( 'users = ' . var_export( $users, true ) ); $this->_logger->log( 'plans = ' . var_export( $plans, true ) ); } $site = fs_is_network_admin() ? $this->get_network_install() : $this->get_install_by_blog_id(); if ( fs_is_network_admin() && $this->is_network_active() && ! is_object( $site ) && FS_Site::is_valid_id( $this->_storage->network_install_blog_id ) ) { $first_install = $this->find_first_install(); if ( is_null( $first_install ) ) { unset( $this->_storage->network_install_blog_id ); } else { $site = $first_install['install']; $this->_storage->network_install_blog_id = $first_install['blog_id']; } } if ( is_object( $site ) && is_numeric( $site->id ) && is_numeric( $site->user_id ) && FS_Plugin_Plan::is_valid_id( $site->plan_id ) ) { // Load site. $this->_site = $site; } $user = null; if ( fs_is_network_admin() && $this->_is_network_active ) { $user = $this->get_network_user(); } if ( is_object( $user ) ) { $this->_user = clone $user; } else if ( $this->_site ) { $user = self::_get_user_by_id( $this->_site->user_id ); if ( ! is_object( $user ) && FS_User::is_valid_id( $this->_storage->prev_user_id ) ) { /** * Try to load the previous owner. This recovery is used for the following use-case: * 1. Opt-in * 2. Cloning site1 to site2 * 3. Ownership switch in site1 (same applies for site2) * 4. Install data sync on site2 * 5. Now site2's install is associated with the new owner which does not exists locally. */ $user = self::_get_user_by_id( $this->_storage->prev_user_id ); } if ( ! is_object( $user ) ) { /** * This is a special fault tolerance mechanism to handle a scenario that the user data is missing. */ if ( ! isset( $this->_storage->user_recovery_from_install_last_attempt_timestamp ) || time() > ( $this->_storage->user_recovery_from_install_last_attempt_timestamp + FS_Clone_Manager::CLONE_RESOLUTION_MAX_EXECUTION_TIME ) ) { $user = $this->sync_user_by_current_install(); } else { return; } if ( is_object( $user ) ) { $this->_storage->user_was_recovered_from_install = true; } else { $this->_storage->user_recovery_from_install_attempts = isset( $this->_storage->user_recovery_from_install_attempts ) ? ( $this->_storage->user_recovery_from_install_attempts + 1 ) : 1; if ( $this->_storage->user_recovery_from_install_attempts >= 3 ) { $this->delete_current_install( false ); } else { $this->_storage->user_recovery_from_install_last_attempt_timestamp = time(); return; } } } $this->_user = ( $user instanceof FS_User ) ? clone $user : null; } if ( is_object( $this->_user ) ) { // Load licenses. $this->_licenses = $this->get_user_licenses( $this->_user->id ); } if ( is_object( $this->_site ) ) { // Load plans. $this->_plans = isset( $plans[ $this->_slug ] ) ? $plans[ $this->_slug ] : array(); if ( ! is_array( $this->_plans ) || empty( $this->_plans ) ) { $this->_sync_plans(); } else { for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { if ( $this->_plans[ $i ] instanceof FS_Plugin_Plan ) { $this->_plans[ $i ] = self::decrypt_entity( $this->_plans[ $i ] ); } else { unset( $this->_plans[ $i ] ); } } } $this->_license = $this->_get_license_by_id( $this->_site->license_id ); if ( $this->_site->version != $this->get_plugin_version() ) { // If stored install version is different than current installed plugin version, // then update plugin version event. $this->update_plugin_version_event(); } } if ( true === $this->_storage->require_license_activation && ! fs_request_get_bool( 'require_license', true ) ) { $this->_storage->require_license_activation = false; } if ( $this->is_theme() ) { $this->_register_account_hooks(); } if ( $this->is_user_in_admin() && $this->is_clone() ) { if ( empty( FS_Clone_Manager::instance()->get_clone_identification_timestamp() ) ) { FS_Clone_Manager::instance()->store_clone_identification_timestamp(); } FS_Clone_Manager::instance()->maybe_update_clone_resolution_support_flag( $this->_storage->sdk_last_version ); $this->send_pending_clone_update_once(); } } /** * Special user recovery mechanism. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number|null $site_user_id * * @return \FS_User|mixed */ private function sync_user_by_current_install( $site_user_id = null ) { $site_user_id = FS_Site::is_valid_id( $site_user_id ) ? $site_user_id : $this->_site->user_id; $api = $this->get_api_site_scope(); $uid = $this->get_anonymous_id(); $request_path = "/users/{$site_user_id}.json?uid={$uid}"; $result = $api->get( $request_path, false, WP_FS__TIME_10_MIN_IN_SEC ); if ( $this->is_api_result_entity( $result ) ) { $user = new FS_User( $result ); $this->_user = $user; $this->_store_user(); return $user; } $error_code = FS_Api::get_error_code( $result ); if ( in_array( $error_code, array( 'invalid_unique_id', 'user_cannot_be_recovered' ) ) ) { /** * Those API errors will continue coming and are not recoverable with the * current site's data. Therefore, extend the API call's cached result to 7 days. */ $api->update_cache_expiration( $request_path, WP_FS__TIME_WEEK_IN_SEC ); } return $result; } /** * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param FS_User $user * @param FS_Site $site * @param bool|array $plans */ private function _set_account( FS_User $user, FS_Site $site, $plans = false ) { $site->user_id = $user->id; $this->_site = $site; $this->_user = $user; if ( false !== $plans ) { $this->_plans = $plans; } $this->send_install_update(); $this->_store_account(); } /** * Get a sanitized array with the WordPress version, SDK version, and PHP version. * Each version is trimmed after the 16th char. * * @author Vova Feldman (@svovaf) * @since 2.2.1 * * @return array */ private function get_versions() { $versions = array(); $versions['sdk_version'] = $this->version; // Collect these diagnostic information only if it's allowed. if ( FS_Permission_Manager::instance( $this )->is_diagnostic_tracking_allowed() ) { $versions['platform_version'] = get_bloginfo( 'version' ); $versions['programming_language_version'] = phpversion(); } foreach ( $versions as $k => $version ) { $versions[ $k ] = self::get_api_sanitized_property( $k, $version ); } return $versions; } /** * Get sanitized site language. * * @param string $language * @param int $max_len * * @since 2.5.1 * @author Vova Feldman (@svovaf) * * @return string */ private static function get_sanitized_language( $language = '', $max_len = self::LANGUAGE_MAX_CHARS ) { if ( empty( $language ) ) { $language = get_bloginfo( 'language' ); } return substr( $language, 0, $max_len ); } /** * Get core version stripped from pre-release and build. * * @since 2.5.1 * @author Vova Feldman (@svovaf) * * @param string $version * @param int $parts * @param int $max_len * @param bool $include_pre_release * * @return string */ private static function get_core_version( $version, $parts = 3, $max_len = self::VERSION_MAX_CHARS, $include_pre_release = false ) { if ( empty( $version ) ) { // Version is empty. return ''; } if ( is_numeric( $version ) ) { $is_float_version = is_float( $version ); $version = (string) $version; /** * Casting a whole float number to a string cuts the decimal point. This part make sure to add the missing decimal part to the version. */ if ( $is_float_version && false === strpos( $version, '.' ) ) { $version .= '.0'; } } if ( ! is_string( $version ) ) { return ''; } if ( $parts < 1 ) { return ''; } $pre_release_regex = $include_pre_release ? '(\-(alpha|beta|RC)([0-9]+)?)?' : ''; if ( 0 === preg_match( '/^([0-9]+(\.[0-9]+){0,' . ( $parts - 1 ) . '}' . $pre_release_regex . ')/i', $version, $matches ) ) { // Version is not starting with a digit. return ''; } return substr( $matches[1], 0, $max_len ); } /** * @param string $prop * @param mixed $val * * @return mixed *@author Vova Feldman (@svovaf) * * @since 2.5.1 */ private static function get_api_sanitized_property( $prop, $val ) { if ( ! is_string( $val ) || empty( $val ) ) { return $val; } switch ( $prop ) { case 'programming_language_version': // Get core PHP version, which can have up to 3 parts (ignore pre-releases). return self::get_core_version( $val ); case 'platform_version': // Get the exact WordPress version, which can have up to 3 parts (including pre-releases). return self::get_core_version( $val, 3, self::VERSION_MAX_CHARS, true ); case 'sdk_version': // Get the exact SDK version, which can have up to 4 parts. return self::get_core_version( $val, 4 ); case 'version': // Get the entire version but just limited in length. return substr( $val, 0, self::VERSION_MAX_CHARS ); case 'language': return self::get_sanitized_language( $val ); default: return $val; } } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @return bool */ function has_beta_update() { return ( ! empty( $this->_storage->beta_data ) && ( true === $this->_storage->beta_data['is_beta'] ) && version_compare( $this->_storage->beta_data['version'], $this->get_plugin_version(), '>' ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @return bool */ function is_beta() { return ( ! empty( $this->_storage->beta_data ) && ( true === $this->_storage->beta_data['is_beta'] ) && ( $this->get_plugin_version() === $this->_storage->beta_data['version'] ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.4 * * @param array $override_with * @param bool|int|null $network_level_or_blog_id If true, return params for network level opt-in. If integer, get params for specified blog in the network. * * @return array */ function get_opt_in_params( $override_with = array(), $network_level_or_blog_id = null ) { $this->_logger->entrance(); $current_user = self::_get_current_wp_user(); $activation_action = $this->get_unique_affix() . '_activate_new'; $return_url = $this->is_anonymous() ? // If skipped already, then return to the account page. $this->get_account_url( $activation_action, array(), false ) : // Return to the module's main page. $this->get_after_activation_url( 'after_connect_url', array( 'fs_action' => $activation_action ) ); $versions = $this->get_versions(); $params = array_merge( $versions, array( 'user_firstname' => $current_user->user_firstname, 'user_lastname' => $current_user->user_lastname, 'user_email' => $current_user->user_email, 'plugin_slug' => $this->_slug, 'plugin_id' => $this->get_id(), 'plugin_public_key' => $this->get_public_key(), 'plugin_version' => $this->get_plugin_version(), 'return_url' => fs_nonce_url( $return_url, $activation_action ), 'account_url' => fs_nonce_url( $this->_get_admin_page_url( 'account', array( 'fs_action' => 'sync_user' ) ), 'sync_user' ), 'is_premium' => $this->is_premium(), 'is_active' => true, 'is_uninstalled' => false, 'is_localhost' => WP_FS__IS_LOCALHOST, ) ); if ( $this->is_addon() ) { $parent_fs = $this->get_parent_instance(); $params['parent_plugin_slug'] = $parent_fs->_slug; $params['parent_plugin_id'] = $parent_fs->get_id(); } if ( true === $network_level_or_blog_id ) { if ( ! isset( $override_with['sites'] ) ) { $params['sites'] = $this->get_sites_for_network_level_optin(); } } else { $site = is_numeric( $network_level_or_blog_id ) ? array( 'blog_id' => $network_level_or_blog_id ) : null; $site = $this->get_site_info( $site ); $diagnostic_info = array(); if ( FS_Permission_Manager::instance( $this )->is_diagnostic_tracking_allowed() ) { $diagnostic_info = array( 'site_name' => $site['title'], 'language' => self::get_sanitized_language( $site['language'] ), ); } $params = array_merge( $params, $diagnostic_info, array( 'site_uid' => $site['uid'], 'site_url' => $site['url'], ) ); } if ( $this->is_pending_activation() && ! empty( $this->_storage->pending_license_key ) ) { $params['license_key'] = $this->_storage->pending_license_key; } if ( WP_FS__SKIP_EMAIL_ACTIVATION && $this->has_secret_key() ) { // Even though rand() is known for its security issues, // the timestamp adds another layer of protection. // It would be very hard for an attacker to get the secret key form here. // Plus, this should never run in production since the secret should never // be included in the production version. $params['ts'] = WP_FS__SCRIPT_START_TIME; $params['salt'] = md5( uniqid( rand() ) ); $params['secure'] = md5( $params['ts'] . $params['salt'] . $this->get_secret_key() ); } if ( is_multisite() && function_exists( 'get_network' ) ) { $params['network_uid'] = $this->get_anonymous_network_id(); } return array_merge( $params, $override_with ); } /** * 1. If successful opt-in or pending activation returns the next page that the user should be redirected to. * 2. If there was an API error, return the API result. * * @author Vova Feldman (@svovaf) * @since 1.1.7.4 * * @param string|bool $email * @param string|bool $first * @param string|bool $last * @param string|bool $license_key * @param bool $is_uninstall If "true", this means that the module is currently being uninstalled. * In this case, the user and site info will be sent to the server but no * data will be saved to the WP installation's database. * @param number|bool $trial_plan_id * @param bool $is_disconnected Whether to opt in without tracking. * @param null|bool $is_marketing_allowed * @param array $sites If network-level opt-in, an array of containing details of sites. * @param bool $redirect * * @return string|object * @use WP_Error */ function opt_in( $email = false, $first = false, $last = false, $license_key = false, $is_uninstall = false, $trial_plan_id = false, $is_disconnected = false, $is_marketing_allowed = null, $sites = array(), $redirect = true ) { $this->_logger->entrance(); if ( false === $email ) { $current_user = self::_get_current_wp_user(); $email = $current_user->user_email; } /** * @since 1.2.1 If activating with license key, ignore the context-user * since the user will be automatically loaded from the license. */ if ( empty( $license_key ) ) { // Clean up pending license if opt-ing in again. $this->_storage->remove( 'pending_license_key' ); if ( ! $is_uninstall ) { $fs_user = Freemius::_get_user_by_email( $email ); if ( is_object( $fs_user ) && ! $this->is_pending_activation() ) { return $this->install_with_user( $fs_user, false, $trial_plan_id, $redirect, true, $sites ); } } } $user_info = array(); if ( ! empty( $email ) ) { $user_info['user_email'] = $email; } if ( ! empty( $first ) ) { $user_info['user_firstname'] = $first; } if ( ! empty( $last ) ) { $user_info['user_lastname'] = $last; } if ( ! empty( $sites ) ) { $is_network = true; $user_info['sites'] = $sites; } else { $is_network = false; } $params = $this->get_opt_in_params( $user_info, $is_network ); $filtered_license_key = false; if ( is_string( $license_key ) ) { $filtered_license_key = $this->apply_filters( 'license_key', $license_key ); $params['license_key'] = $filtered_license_key; } else if ( FS_Plugin_Plan::is_valid_id( $trial_plan_id ) ) { $params['trial_plan_id'] = $trial_plan_id; } if ( $is_uninstall ) { $params['uninstall_params'] = array( 'reason_id' => $this->_storage->uninstall_reason->id, 'reason_info' => $this->_storage->uninstall_reason->info ); } if ( isset( $params['license_key'] ) ) { $fs_user = Freemius::_get_user_by_email( $email ); if ( is_object( $fs_user ) ) { /** * If opting in with a context license and the context WP Admin user already opted in * before from the current site, add the user context security params to avoid the * unnecessary email activation when the context license is owned by the same context user. * * @author Leo Fajardo (@leorw) * @since 1.2.3 */ $params = array_merge( $params, FS_Security::instance()->get_context_params( $fs_user, false, 'install_with_existing_user' ) ); } } if ( is_bool( $is_marketing_allowed ) ) { $params['is_marketing_allowed'] = $is_marketing_allowed; } $params['is_disconnected'] = $is_disconnected; $params['format'] = 'json'; $params['is_extensions_tracking_allowed'] = FS_Permission_Manager::instance( $this )->is_extensions_tracking_allowed(); $params['is_diagnostic_tracking_allowed'] = FS_Permission_Manager::instance( $this )->is_diagnostic_tracking_allowed(); $request = array( 'method' => 'POST', 'body' => $params, 'timeout' => 60, ); $url = $this->add_show_pending( WP_FS__ADDRESS . '/action/service/user/install/' ); $response = self::safe_remote_post( $url, $request ); if ( is_wp_error( $response ) ) { /** * @var WP_Error $response */ $result = new stdClass(); $error_code = $response->get_error_code(); $error_type = str_replace( ' ', '', ucwords( str_replace( '_', ' ', $error_code ) ) ); $result->error = (object) array( 'type' => $error_type, 'message' => $response->get_error_message(), 'code' => $error_code, 'http' => 402 ); $this->maybe_modify_api_curl_error_message( $result ); if ( FS_Api::is_blocked( $result ) ) { $result->error->message = $this->generate_api_blocked_notice_message_from_result( $result ); } $is_connected = null; if ( empty( $license_key ) && $this->is_enable_anonymous() ) { $this->skip_connection( fs_is_network_admin() ); $is_connected = ( ! FS_Api::is_blocked( $result ) ); } $this->update_connectivity_info( $is_connected ); return $result; } $this->update_connectivity_info( true ); // Module is being uninstalled, don't handle the returned data. if ( $is_uninstall ) { return true; } /** * When json_decode() executed on PHP 5.2 with an invalid JSON, it will throw a PHP warning. Unfortunately, the new Theme Check doesn't allow PHP silencing and the theme review team isn't open to change that, therefore, instead of using `@json_decode()` we had to use the method without the `@` directive. * * @author Vova Feldman (@svovaf) * @since 1.2.3 * @link https://themes.trac.wordpress.org/ticket/46134#comment:5 * @link https://themes.trac.wordpress.org/ticket/46134#comment:9 * @link https://themes.trac.wordpress.org/ticket/46134#comment:12 * @link https://themes.trac.wordpress.org/ticket/46134#comment:14 */ $decoded = is_string( $response['body'] ) ? json_decode( $response['body'] ) : null; if ( empty( $decoded ) ) { return false; } if ( ! $this->is_api_result_object( $decoded ) ) { if ( ! empty( $params['license_key'] ) ) { // Pass the fully entered license key to the failure handler. $params['license_key'] = $license_key; } return $is_uninstall ? $decoded : $this->apply_filters( 'after_install_failure', $decoded, $params ); } else if ( isset( $decoded->pending_activation ) && $decoded->pending_activation ) { if ( $is_network ) { $site_ids = array(); foreach ( $sites as $site ) { $site_ids[] = $site['blog_id']; } /** * Store the sites so that they can be installed once the user has clicked on the activation link * in the email. * * @author Leo Fajardo (@leorw) */ $this->_storage->pending_sites_info = array( 'blog_ids' => $site_ids, 'license_key' => $license_key, 'trial_plan_id' => $trial_plan_id ); } // Pending activation, add message. return $this->set_pending_confirmation( ( isset( $decoded->email ) ? $decoded->email : true ), false, $filtered_license_key, ! empty( $params['trial_plan_id'] ), isset( $decoded->is_suspicious_email ) && $decoded->is_suspicious_email ); } else if ( isset( $decoded->install_secret_key ) ) { return $this->install_with_new_user( $decoded->user_id, $decoded->user_public_key, $decoded->user_secret_key, ( isset( $decoded->is_marketing_allowed ) && ! is_null( $decoded->is_marketing_allowed ) ? $decoded->is_marketing_allowed : null ), ( isset( $decoded->is_extensions_tracking_allowed ) && ! is_null( $decoded->is_extensions_tracking_allowed ) ? $decoded->is_extensions_tracking_allowed : null ), ( isset( $decoded->is_diagnostic_tracking_allowed ) && ! is_null( $decoded->is_diagnostic_tracking_allowed ) ? $decoded->is_diagnostic_tracking_allowed : null ), $decoded->install_id, $decoded->install_public_key, $decoded->install_secret_key, false ); } else if ( is_array( $decoded->installs ) ) { return $this->install_many_with_new_user( $decoded->user_id, $decoded->user_public_key, $decoded->user_secret_key, ( isset( $decoded->is_marketing_allowed ) && ! is_null( $decoded->is_marketing_allowed ) ? $decoded->is_marketing_allowed : null ), ( isset( $decoded->is_extensions_tracking_allowed ) && ! is_null( $decoded->is_extensions_tracking_allowed ) ? $decoded->is_extensions_tracking_allowed : null ), ( isset( $decoded->is_diagnostic_tracking_allowed ) && ! is_null( $decoded->is_diagnostic_tracking_allowed ) ? $decoded->is_diagnostic_tracking_allowed : null ), $decoded->installs, false ); } return $decoded; } /** * Set user and site identities. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param FS_User $user * @param FS_Site $site * @param bool $redirect * @param bool $auto_install Since 1.2.1.7 If `true` and setting up an account with a valid license, will * redirect (or return a URL) to the account page with a special parameter to * trigger the auto installation processes. * * @return string If redirect is `false`, returns the next page the user should be redirected to. */ function setup_account( FS_User $user, FS_Site $site, $redirect = true, $auto_install = false ) { return $this->setup_network_account( $user, array( $site ), $redirect, $auto_install, false ); } /** * Set user and site identities. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param FS_User $user * @param FS_Site[] $installs * @param bool $redirect * @param bool $auto_install Since 1.2.1.7 If `true` and setting up an account with a valid license, will redirect (or return a URL) to the account page with a special parameter to trigger the auto installation processes. * @param bool $is_network_level_opt_in * * @return string If redirect is `false`, returns the next page the user should be redirected to. */ function setup_network_account( FS_User $user, array $installs, $redirect = true, $auto_install = false, $is_network_level_opt_in = true ) { $first_install = $installs[0]; $this->_user = $user; $this->_site = $first_install; $this->_sync_plans(); if ( $this->_storage->handle_gdpr_admin_notice && $this->should_handle_gdpr_admin_notice() && FS_GDPR_Manager::instance()->should_show_opt_in_notice() ) { /** * Clear user lock after an opt-in. */ require_once WP_FS__DIR_INCLUDES . '/class-fs-user-lock.php'; FS_User_Lock::instance()->unlock(); } if ( 1 < count( $installs ) ) { // Only network level opt-in can have more than one install. $is_network_level_opt_in = true; } $this->update_connectivity_info( true ); // $is_network_level_opt_in = self::is_ajax_action_static( 'network_activate', $this->_module_id ); // If Freemius was OFF before, turn it on. $this->turn_on(); $this->handle_account_connection( $installs, ( ! $this->_is_network_active || ! $is_network_level_opt_in ) ); if ( is_numeric( $first_install->license_id ) ) { $this->set_license( $this->_get_license_by_id( $first_install->license_id ) ); } $this->_admin_notices->remove_sticky( 'connect_account' ); if ( $this->is_pending_activation() || ! $this->has_settings_menu() ) { $this->clear_pending_activation_mode(); if ( ! $this->is_paying_or_trial() ) { $this->_admin_notices->add_sticky( sprintf( $this->get_text_inline( '%s opt-in was successfully completed.', 'plugin-x-activation-message' ), '' . $this->get_plugin_name() . '' ), 'activation_complete' ); } } if ( $this->is_paying_or_trial() ) { if ( ! $this->is_premium() || ! $this->has_premium_version() || ! $this->has_settings_menu() ) { if ( $this->is_paying() ) { $this->add_complete_upgrade_instructions_notice( sprintf( $this->get_text_inline( 'Your account was successfully activated with the %s plan.', 'activation-with-plan-x-message' ), $this->get_plan_title() ), 'plan_upgraded' ); } else { $trial_plan = $this->get_trial_plan(); $this->add_complete_upgrade_instructions_notice( sprintf( $this->get_text_inline( 'Your trial has been successfully started.', 'trial-started-message' ), '' . $this->get_plugin_name() . '' ), 'trial_started', $trial_plan->title ); } } $this->_admin_notices->remove_sticky( array( 'trial_promotion', ) ); } $plugin_id = fs_request_get( 'plugin_id', false ); // Store activation time ONLY for plugins & themes (not add-ons). if ( ! is_numeric( $plugin_id ) || ( $plugin_id == $this->_plugin->id ) ) { if ( empty( $this->_storage->activation_timestamp ) ) { $this->_storage->activation_timestamp = WP_FS__SCRIPT_START_TIME; } } $next_page = ''; $extra = array(); if ( $auto_install ) { $extra['auto_install'] = 'true'; } if ( is_numeric( $plugin_id ) ) { /** * @author Leo Fajardo (@leorw) * @since 1.2.1.6 * * Also sync the license after an anonymous user subscribes. */ if ( $this->is_anonymous() || $plugin_id != $this->_plugin->id ) { // Add-on was installed - sync license right after install. $next_page = $this->_get_sync_license_url( $plugin_id, true, $extra ); } } else { /** * @author Vova Feldman (@svovaf) * @since 1.1.9 If site installed with a valid license, sync license. */ if ( $this->is_paying() ) { $this->_sync_plugin_license( true, // Installs data is already synced in the beginning of this method directly or via _set_account(). false ); } // Reload the page with the keys. $next_page = $this->is_anonymous() ? // If user previously skipped, redirect to account page. $this->get_account_url( false, $extra ) : $this->get_after_activation_url( 'after_connect_url', array(), $is_network_level_opt_in ); } if ( ! empty( $next_page ) && $redirect ) { fs_redirect( $next_page ); } return $next_page; } /** * Install plugin with new user information after approval. * * @author Vova Feldman (@svovaf) * @since 1.0.7 */ function _install_with_new_user() { $this->_logger->entrance(); if ( $this->is_registered() ) { return; } $has_pending_activation_confirmation_param = fs_request_has( 'pending_activation' ); $this->update_license_required_permissions_if_anonymous(); if ( ( $this->is_plugin() && fs_request_is_action( $this->get_unique_affix() . '_activate_new' ) ) || // @todo This logic should be improved because it's executed on every load of a theme. $this->is_theme() ) { // check_admin_referer( $this->_slug . '_activate_new' ); if ( fs_request_has( 'user_secret_key' ) ) { if ( fs_is_network_admin() && isset( $this->_storage->pending_sites_info ) ) { $pending_sites_info = $this->_storage->pending_sites_info; $this->install_many_pending_with_user( fs_request_get( 'user_id' ), fs_request_get( 'user_public_key' ), fs_request_get( 'user_secret_key' ), fs_request_get_bool( 'is_marketing_allowed', null ), fs_request_get_bool( 'is_extensions_tracking_allowed', null ), fs_request_get_bool( 'is_diagnostic_tracking_allowed', null ), $pending_sites_info['blog_ids'], $pending_sites_info['license_key'], $pending_sites_info['trial_plan_id'] ); } else { $this->install_with_new_user( fs_request_get( 'user_id' ), fs_request_get( 'user_public_key' ), fs_request_get( 'user_secret_key' ), fs_request_get_bool( 'is_marketing_allowed', null ), fs_request_get_bool( 'is_extensions_tracking_allowed', null ), fs_request_get_bool( 'is_diagnostic_tracking_allowed', null ), fs_request_get( 'install_id' ), fs_request_get( 'install_public_key' ), fs_request_get( 'install_secret_key' ), true, fs_request_get_bool( 'auto_install' ) ); } } else if ( $has_pending_activation_confirmation_param ) { $this->set_pending_confirmation( fs_request_get( 'user_email' ), true, false, false, fs_request_get_bool( 'is_suspicious_email' ), fs_request_get_bool( 'has_upgrade_context' ), fs_request_get( 'support_email_address' ) ); } } } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $id * @param string $public_key * @param string $secret_key * * @return \FS_User */ private function setup_user( $id, $public_key, $secret_key ) { $user = self::_get_user_by_id( $id ); if ( is_object( $user ) ) { $this->_user = $user; } else { $user = new FS_User(); $user->id = $id; $user->public_key = $public_key; $user->secret_key = $secret_key; $this->_user = $user; $user_result = $this->get_api_user_scope()->get(); $user = new FS_User( $user_result ); $this->_user = $user; $this->_store_user(); } return $user; } /** * Install plugin with new user. * * @author Vova Feldman (@svovaf) * @since 1.1.7.4 * * @param number $user_id * @param string $user_public_key * @param string $user_secret_key * @param bool|null $is_marketing_allowed * @param bool|null $is_extensions_tracking_allowed Since 2.3.2 * @param bool|null $is_diagnostic_tracking_allowed Since 2.5.0.2 * @param number $install_id * @param string $install_public_key * @param string $install_secret_key * @param bool $redirect * @param bool $auto_install Since 1.2.1.7 If `true` and setting up an account with a valid license, will redirect (or return a URL) to the account page with a special parameter to trigger the auto installation processes. * * @return string If redirect is `false`, returns the next page the user should be redirected to. */ private function install_with_new_user( $user_id, $user_public_key, $user_secret_key, $is_marketing_allowed, $is_extensions_tracking_allowed, $is_diagnostic_tracking_allowed, $install_id, $install_public_key, $install_secret_key, $redirect = true, $auto_install = false ) { /** * This method is also executed after opting in with a license key since the * license can be potentially associated with a different owner. * * @since 2.0.0 */ $user = self::_get_user_by_id( $user_id ); if ( ! is_object( $user ) ) { $user = new FS_User(); $user->id = $user_id; $user->public_key = $user_public_key; $user->secret_key = $user_secret_key; $this->_user = $user; $user_result = $this->get_api_user_scope()->get(); $user = new FS_User( $user_result ); } $this->_user = $user; $site = new FS_Site(); $site->id = $install_id; $site->public_key = $install_public_key; $site->secret_key = $install_secret_key; $this->_site = $site; $site_result = $this->get_api_site_scope( true )->get(); $site = new FS_Site( $site_result ); $this->_site = $site; if ( ! is_null( $is_marketing_allowed ) ) { $this->disable_opt_in_notice_and_lock_user(); } FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array( FS_Permission_Manager::PERMISSION_DIAGNOSTIC => $is_diagnostic_tracking_allowed, FS_Permission_Manager::PERMISSION_EXTENSIONS => $is_extensions_tracking_allowed, ) ); return $this->setup_account( $this->_user, $this->_site, $redirect, $auto_install ); } /** * Install plugin with user. * * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param number $user_id * @param string $user_public_key * @param string $user_secret_key * @param bool|null $is_marketing_allowed * @param bool|null $is_extensions_tracking_allowed Since 2.3.2 * @param bool|null $is_diagnostic_tracking_allowed Since 2.5.0.2 * @param array $site_ids * @param bool $license_key * @param bool $trial_plan_id * @param bool $redirect * * @return string If redirect is `false`, returns the next page the user should be redirected to. */ private function install_many_pending_with_user( $user_id, $user_public_key, $user_secret_key, $is_marketing_allowed, $is_extensions_tracking_allowed, $is_diagnostic_tracking_allowed, $site_ids, $license_key = false, $trial_plan_id = false, $redirect = true ) { $user = $this->setup_user( $user_id, $user_public_key, $user_secret_key ); if ( ! is_null( $is_marketing_allowed ) ) { $this->disable_opt_in_notice_and_lock_user(); } FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array( FS_Permission_Manager::PERMISSION_DIAGNOSTIC => $is_diagnostic_tracking_allowed, FS_Permission_Manager::PERMISSION_EXTENSIONS => $is_extensions_tracking_allowed, ) ); $sites = array(); foreach ( $site_ids as $site_id ) { $sites[] = $this->get_site_info( array( 'blog_id' => $site_id ) ); } $this->install_with_user( $user, $license_key, $trial_plan_id, $redirect, true, $sites ); } /** * Multi-site install with a new user. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $user_id * @param string $user_public_key * @param string $user_secret_key * @param bool|null $is_marketing_allowed * @param bool|null $is_extensions_tracking_allowed Since 2.3.2 * @param bool|null $is_diagnostic_tracking_allowed Since 2.5.0.2 * @param object[] $installs * @param bool $redirect * @param bool $auto_install Since 1.2.1.7 If `true` and setting up an account with a valid license, will redirect (or return a URL) to the account page with a special parameter to trigger the auto installation processes. * * @return string If redirect is `false`, returns the next page the user should be redirected to. */ private function install_many_with_new_user( $user_id, $user_public_key, $user_secret_key, $is_marketing_allowed, $is_extensions_tracking_allowed, $is_diagnostic_tracking_allowed, array $installs, $redirect = true, $auto_install = false ) { $this->setup_user( $user_id, $user_public_key, $user_secret_key ); if ( ! is_null( $is_marketing_allowed ) ) { $this->disable_opt_in_notice_and_lock_user(); } FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array( FS_Permission_Manager::PERMISSION_DIAGNOSTIC => $is_diagnostic_tracking_allowed, FS_Permission_Manager::PERMISSION_EXTENSIONS => $is_extensions_tracking_allowed, ) ); $install_ids = array(); foreach ( $installs as $install ) { $install_ids[] = $install->id; } $items_per_request = 25; $left = count( $install_ids ); $offset = 0; $installs = array(); while ( $left > 0 ) { $result = $this->get_api_user_scope()->get( "/plugins/{$this->_module_id}/installs.json?ids=" . implode( ',', array_slice( $install_ids, $offset, $items_per_request ) ) ); if ( ! $this->is_api_result_object( $result, 'installs' ) ) { // @todo Handle API error. } $installs = array_merge( $installs, $result->installs ); $left -= $items_per_request; $offset += $items_per_request; } foreach ( $installs as &$install ) { $install = new FS_Site( $install ); } return $this->setup_network_account( $this->_user, $installs, $redirect, $auto_install ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.4 * * @param string|bool $email * @param bool $redirect * @param string|bool $license_key Since 1.2.1.5 * @param bool $is_pending_trial Since 1.2.1.5 * @param bool $is_suspicious_email Since 2.5.0 * @param bool $has_upgrade_context Since 2.5.3 * @param bool|string $support_email_address Since 2.5.3 * * @return string Since 1.2.1.5 if $redirect is `false`, return the pending activation page. */ private function set_pending_confirmation( $email = false, $redirect = true, $license_key = false, $is_pending_trial = false, $is_suspicious_email = false, $has_upgrade_context = false, $support_email_address = false ) { $is_network_admin = fs_is_network_admin(); if ( $this->_ignore_pending_mode && ! $has_upgrade_context ) { /** * If explicitly asked to ignore pending mode, set to anonymous mode * if require confirmation before finalizing the opt-in except after completing a purchase (otherwise, in this case, they wouldn't see any notice telling them that they should receive their license key via email). * * @author Vova Feldman * @since 1.2.1.6 */ $this->skip_connection( $is_network_admin ); } else { // Install must be activated via email since // user with the same email already exist. $this->_storage->is_pending_activation = true; $this->_add_pending_activation_notice( $email, $is_pending_trial, $is_suspicious_email, $has_upgrade_context, $support_email_address ); } if ( ! empty( $license_key ) ) { $this->_storage->pending_license_key = $license_key; } // Remove the opt-in sticky notice. $this->_admin_notices->remove_sticky( array( 'connect_account', 'trial_promotion', ) ); $next_page = $this->get_after_activation_url( 'after_pending_connect_url' ); if ( $redirect ) { // Reload the page with a pending activation message. fs_redirect( $next_page ); } return $next_page; } /** * Install plugin with current logged WP user info. * * @author Vova Feldman (@svovaf) * @since 1.0.7 */ function _install_with_current_user() { $this->_logger->entrance(); if ( $this->is_registered() ) { return; } if ( fs_request_is_action( $this->get_unique_affix() . '_activate_existing' ) && fs_request_is_post() ) { // check_admin_referer( 'activate_existing_' . $this->_plugin->public_key ); /** * @author Vova Feldman (@svovaf) * @since 1.1.9 Add license key if given. */ $license_key = fs_request_get( 'license_secret_key' ); FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( array( FS_Permission_Manager::PERMISSION_DIAGNOSTIC => fs_request_get_bool( 'is_diagnostic_tracking_allowed', null ), FS_Permission_Manager::PERMISSION_EXTENSIONS => fs_request_get_bool( 'is_extensions_tracking_allowed', null ), ) ); $this->install_with_current_user( $license_key ); } } /** * @author Vova Feldman (@svovaf) * @since 1.1.7.4 * * @param string|bool $license_key * @param number|bool $trial_plan_id * @param array $sites Since 2.0.0 * @param bool $redirect * * @return object|string If redirect is `false`, returns the next page the user should be redirected to, or the API error object if failed to install. */ function install_with_current_user( $license_key = false, $trial_plan_id = false, $sites = array(), $redirect = true ) { // Get current logged WP user. $current_user = self::_get_current_wp_user(); // Find the relevant FS user by the email. $user = self::_get_user_by_email( $current_user->user_email ); return $this->install_with_user( $user, $license_key, $trial_plan_id, $redirect, true, $sites ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_User $user * @param string|bool $license_key * @param number|bool $trial_plan_id * @param bool $redirect * @param bool $setup_account Since 2.0.0. When set to FALSE, executes a light installation without setting up the account as if it's the first opt-in. * @param array $sites Since 2.0.0. If not empty, should be a collection of site details for the bulk install API request. * * @return \FS_Site|object|string If redirect is `false`, returns the next page the user should be redirected to, or the API error object if failed to install. If $setup_account is set to `false`, return the newly created install. */ function install_with_user( FS_User $user, $license_key = false, $trial_plan_id = false, $redirect = true, $setup_account = true, $sites = array() ) { // We have to set the user before getting user scope API handler. $this->_user = $user; // Install the plugin. $result = $this->create_installs_with_user( $user, $license_key, $trial_plan_id, $sites, $redirect ); if ( ! $this->is_api_result_entity( $result ) && ! $this->is_api_result_object( $result, 'installs' ) ) { // @todo Handler potential API error of the $result } if ( empty( $sites ) ) { $site = new FS_Site( $result ); $this->_site = $site; if ( ! $setup_account ) { $this->_store_site(); $this->sync_plan_if_not_exist( $site->plan_id ); if ( ! empty( $license_key ) && FS_Plugin_License::is_valid_id( $site->license_id ) ) { $this->sync_license_if_not_exist( $site->license_id, $license_key ); } $this->_admin_notices->remove_sticky( 'connect_account', false ); return $site; } return $this->setup_account( $this->_user, $this->_site, $redirect ); } else { $installs = array(); foreach ( $result->installs as $install ) { $installs[] = new FS_Site( $install ); } return $this->setup_network_account( $user, $installs, $redirect ); } } /** * Initiate an API request to create a collection of installs. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_User $user * @param bool $license_key * @param bool $trial_plan_id * @param array $sites * @param bool $redirect * @param bool $silent * * @return object|mixed */ private function create_installs_with_user( FS_User $user, $license_key = false, $trial_plan_id = false, $sites = array(), $redirect = false, $silent = false ) { $extra_install_params = array( 'uid' => $this->get_anonymous_id(), 'is_disconnected' => false, ); if ( ! empty( $license_key ) ) { $extra_install_params['license_key'] = $this->apply_filters( 'license_key', $license_key ); if ( $silent ) { $extra_install_params['ignore_license_owner'] = true; } } else if ( FS_Plugin_Plan::is_valid_id( $trial_plan_id ) ) { $extra_install_params['trial_plan_id'] = $trial_plan_id; } if ( ! empty( $sites ) ) { $extra_install_params['sites'] = $sites; } $args = $this->get_install_data_for_api( $extra_install_params, false, false ); // Install the plugin. $result = $this->get_api_user_scope_by_user( $user )->call( "/plugins/{$this->get_id()}/installs.json", 'post', $args ); if ( ! $this->is_api_result_entity( $result ) && ! $this->is_api_result_object( $result, 'installs' ) ) { if ( ! empty( $args['license_key'] ) ) { // Pass the fully entered license key to the failure handler. $args['license_key'] = $license_key; } $result = $this->apply_filters( 'after_install_failure', $result, $args ); if ( ! $silent ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Couldn\'t activate %s.', 'could-not-activate-x' ), $this->get_plugin_name() ) . ' ' . $this->get_text_inline( 'Please contact us with the following message:', 'contact-us-with-error-message' ) . ' ' . '' . $result->error->message . '', $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...', 'error' ); } if ( $redirect ) { /** * We set the user before getting the user scope API handler, so the user became temporarily * registered (`is_registered() = true`). Since the API returned an error and we will redirect, * we have to set the user to `null`, otherwise, the user will be redirected to the wrong * activation page based on the return value of `is_registered()`. In addition, in case the * context plugin doesn't have a settings menu and the default page is the `Plugins` page, * misleading plugin activation errors will be shown on the `Plugins` page. * * @author Leo Fajardo (@leorw) */ $this->_user = null; fs_redirect( $this->get_activation_url( array( 'error' => $result->error->message ) ) ); } } return $result; } /** * Tries to activate add-on account based on parent plugin info. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param Freemius $parent_fs * @param bool|int|null $network_level_or_blog_id True for network level opt-in and integer for opt-in for specified blog in the network. * @param FS_Plugin_License $bundle_license Since 2.4.0. If provided, this license will be activated for the add-on. */ private function _activate_addon_account( Freemius $parent_fs, $network_level_or_blog_id = null, FS_Plugin_License $bundle_license = null ) { if ( $this->is_registered() ) { // Already activated. return; } $permission_ids = FS_Permission_Manager::get_all_permission_ids(); $permissions = array(); foreach ( $permission_ids as $permission_id ) { $permissions[ $permission_id ] = FS_Permission_Manager::instance( $parent_fs )->is_permission( $permission_id, true ); } FS_Permission_Manager::instance( $this )->update_permissions_tracking_flag( $permissions ); /** * Do not override the `uid` if network-level opt-in since the call to `get_sites_for_network_level_optin()` * already returns the data for the current blog. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $uid_param_to_override = ( true === $network_level_or_blog_id ) ? array() : array( 'uid' => $this->get_anonymous_id() ); $params = $this->get_install_data_for_api( $uid_param_to_override, false, false, /** * Do not include the data for the current blog if network-level opt-in since the call to `get_sites_for_network_level_optin` * already includes the data for it. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ ( true !== $network_level_or_blog_id ) ); if ( true === $network_level_or_blog_id ) { $params['sites'] = $this->get_sites_for_network_level_optin(); if ( empty( $params['sites'] ) ) { return; } } if ( is_object( $bundle_license ) ) { $params['license_key'] = $bundle_license->secret_key; } // Activate add-on with parent plugin credentials. $result = $parent_fs->get_api_site_scope()->call( "/addons/{$this->_plugin->id}/installs.json", 'post', $params ); if ( ! $this->is_api_result_object( $result, 'installs' ) ) { if ( is_object( $bundle_license ) ) { /** * When a license object is provided, it's an attempt by the SDK to activate a bundle license and not a user-initiated action, therefore, do not show any admin notice to avoid confusion (e.g.: the notice will show up just above the opt-in link). If the license activation fails, the admin will see an opt-in link instead. * * @author Leo Fajardo (@leorw) * @since 2.4.0 */ } else { $error_message = FS_Api::is_api_error_object( $result ) ? $result->error->message : $this->get_text_inline( 'An unknown error has occurred.', 'unknown-error' ); $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Couldn\'t activate %s.', 'could-not-activate-x' ), $this->get_plugin_name() ) . ' ' . $this->get_text_inline( 'Please contact us with the following message:', 'contact-us-with-error-message' ) . ' ' . '' . $error_message . '', $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...', 'error' ); } return; } $addon_installs = $result->installs; foreach ( $addon_installs as $key => $addon_install ) { $addon_installs[ $key ] = new FS_Site( $addon_install ); } $first_install = $addon_installs[0]; // Get user information based on parent's plugin. $user = $parent_fs->get_user(); // First of all, set site and user info - otherwise we won't // be able to invoke API calls. $this->_site = $first_install; $this->_user = $user; // Sync add-on plans. $this->_sync_plans(); $this->handle_account_connection( $addon_installs, ! fs_is_network_admin() ); // Get site's current plan. //$this->_site->plan = $this->_get_plan_by_id( $this->_site->plan->id ); // Sync licenses. $this->_sync_licenses(); if ( ! fs_is_network_admin() ) { // Try to activate premium license. $this->_activate_license( true, $bundle_license ); if ( is_object( $bundle_license ) ) { $this->maybe_activate_bundle_license( $bundle_license ); } } else { if ( is_object( $bundle_license ) ) { $premium_license = $bundle_license; } else { $license_id = fs_request_get( 'license_id' ); if ( is_object( $this->_site ) && FS_Plugin_License::is_valid_id( $license_id ) && $license_id == $this->_site->license_id ) { // License is already activated. return; } $premium_license = FS_Plugin_License::is_valid_id( $license_id ) ? $this->_get_license_by_id( $license_id ) : $this->_get_available_premium_license(); } if ( is_object( $premium_license ) ) { $this->maybe_network_activate_addon_license( $premium_license ); } } } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param FS_Site[] $installs * @param bool $is_site_level */ private function handle_account_connection( $installs, $is_site_level ) { $first_install = $installs[0]; if ( $is_site_level ) { $this->_set_account( $this->_user, $first_install ); $this->do_action( 'after_account_connection', $this->_user, $first_install ); } else { $this->_store_user(); // Map site addresses to their blog IDs. $address_to_blog_map = $this->get_address_to_blog_map(); $first_blog_id = null; $blog_2_install_map = array(); foreach ( $installs as $install ) { $address = trailingslashit( fs_strip_url_protocol( $install->url ) ); $blog_id = $address_to_blog_map[ $address ]; $this->_store_site( true, $blog_id, $install ); if ( is_null( $first_blog_id ) ) { $first_blog_id = $blog_id; } $blog_2_install_map[ $blog_id ] = $install; } if ( ! FS_User::is_valid_id( $this->_storage->network_user_id ) || ! is_object( self::_get_user_by_id( $this->_storage->network_user_id ) ) ) { // Store network user. $this->_storage->network_user_id = $this->_user->id; } if ( ! FS_Site::is_valid_id( $this->_storage->network_install_blog_id ) ) { $this->_storage->network_install_blog_id = $first_blog_id; } if ( count( $installs ) === count( $address_to_blog_map ) ) { // Super admin opted in for all sites in the network. $this->_storage->is_network_connected = true; } $this->_store_licenses( false ); self::$_accounts->store(); // Don't sync the installs data on network upgrade if ( ! $this->network_upgrade_mode_completed() ) { $this->send_installs_update(); } $current_blog = get_current_blog_id(); foreach ( $blog_2_install_map as $blog_id => $install ) { $this->switch_to_blog( $blog_id ); $this->do_action( 'after_account_connection', $this->_user, $install ); } // Switch install context back to the first install. $this->switch_to_blog( $current_blog, $first_install, ( $this->_site->id != $first_install->id ) ); $this->do_action( 'after_network_account_connection', $this->_user, $blog_2_install_map ); } } /** * Tries to activate parent account based on add-on's info. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @param Freemius $parent_fs */ private function activate_parent_account( Freemius $parent_fs ) { if ( ! $this->is_addon() ) { // This is not an add-on. return; } if ( $parent_fs->is_registered() ) { // Already activated. return; } // Activate parent with add-on's user credentials. $parent_install = $this->get_api_user_scope()->call( "/plugins/{$parent_fs->_plugin->id}/installs.json", 'post', $parent_fs->get_install_data_for_api( array( 'uid' => $parent_fs->get_anonymous_id(), ), false, false ) ); if ( isset( $parent_install->error ) ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Couldn\'t activate %s.', 'could-not-activate-x' ), $this->get_plugin_name() ) . ' ' . $this->get_text_inline( 'Please contact us with the following message:', 'contact-us-with-error-message' ) . ' ' . '' . $parent_install->error->message . '', $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...', 'error' ); return; } $parent_fs->_admin_notices->remove_sticky( 'connect_account' ); if ( $parent_fs->is_pending_activation() ) { $parent_fs->clear_pending_activation_mode(); } // Get user information based on parent's plugin. $user = $this->get_user(); // First of all, set site info - otherwise we won't // be able to invoke API calls. $parent_fs->_site = new FS_Site( $parent_install ); $parent_fs->_user = $user; // Sync add-on plans. $parent_fs->_sync_plans(); $parent_fs->update_license_required_permissions_if_anonymous(); $parent_fs->_set_account( $user, $parent_fs->_site ); } #endregion #---------------------------------------------------------------------------------- #region Admin Menu Items #---------------------------------------------------------------------------------- private $_menu_items = array(); /** * @author Vova Feldman (@svovaf) * @since 1.2.1.8 * * @return array */ function get_menu_items() { return $this->_menu_items; } /** * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return string */ function get_menu_slug() { return $this->_menu->get_slug(); } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 */ function _prepare_admin_menu() { // if ( ! $this->is_on() ) { // return; // } if ( is_object( $this->_site ) && ! $this->is_registered() ) { return; } /** * When running from a site admin with a network activated module and the connection * was NOT delegated and the user still haven't skipped or opted-in, then hide the * site level settings. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ $should_hide_site_admin_settings = ( $this->_is_network_active && ! fs_is_network_admin() && ! $this->is_delegated_connection() && ! $this->is_anonymous() && ! $this->is_registered() ); $should_hide_site_admin_settings = $this->apply_filters( 'should_hide_site_admin_settings_on_network_activation_mode', $should_hide_site_admin_settings ); if ( ( false === $this->has_api_connectivity() && ! $this->is_enable_anonymous() ) || $should_hide_site_admin_settings ) { $this->_menu->remove_menu_item( $should_hide_site_admin_settings ); } else { $this->do_action( fs_is_network_admin() ? 'before_network_admin_menu_init' : 'before_admin_menu_init' ); $this->add_menu_action(); $this->add_network_menu_when_missing(); $this->add_submenu_items(); } } /** * Admin dashboard menu items modifications. * * NOTE: admin_menu action executed before admin_init. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * */ private function add_menu_action() { if ( $this->is_activation_mode() ) { if ( $this->show_opt_in_on_setting_page() ) { $this->override_plugin_menu_with_activation(); } else { /** * Handle theme opt-in when the opt-in form shows as a dialog box in the themes page. */ if ( fs_request_is_action( $this->get_unique_affix() . '_activate_existing' ) ) { add_action( 'load-themes.php', array( &$this, '_install_with_current_user' ) ); } else if ( fs_request_is_action( $this->get_unique_affix() . '_activate_new' ) || fs_request_get_bool( 'pending_activation' ) ) { add_action( 'load-themes.php', array( &$this, '_install_with_new_user' ) ); } } } else { if ( ! $this->is_registered() ) { // If not registered try to install user. if ( fs_request_is_action( $this->get_unique_affix() . '_activate_new' ) ) { $this->_install_with_new_user(); } } else if ( fs_request_is_action( 'sync_user' ) && ( ! $this->has_settings_menu() || $this->show_opt_in_on_themes_page() ) ) { $this->_handle_account_user_sync(); } } } /** * @author Vova Feldman (@svovaf) * @since 1.0.1 */ function _redirect_on_clicked_menu_link() { $this->_logger->entrance(); $page = fs_request_get('page'); $page = is_string($page) ? strtolower($page) : ''; $this->_logger->log( 'page = ' . $page ); foreach ( $this->_menu_items as $priority => $items ) { foreach ( $items as $item ) { if ( isset( $item['url'] ) ) { if ( $page === $this->_menu->get_slug( strtolower( $item['menu_slug'] ) ) ) { $this->_logger->log( 'Redirecting to ' . $item['url'] ); fs_redirect( $item['url'] ); } } } } } /** * Remove plugin's all admin menu items & pages, and replace with activation page. * * @author Vova Feldman (@svovaf) * @since 1.0.1 */ private function override_plugin_menu_with_activation() { $this->_logger->entrance(); $hook = false; if ( ! $this->has_settings_menu() ) { // Add the opt-in page without a menu item. $hook = FS_Admin_Menu_Manager::add_subpage( '', $this->get_plugin_name(), $this->get_plugin_name(), 'manage_options', $this->_slug, array( &$this, '_connect_page_render' ) ); } else if ( $this->_menu->is_top_level() ) { if ( $this->_menu->is_override_exact() ) { // Make sure the current page is matching the activation page. if ( ! $this->is_matching_url( $this->get_activation_url() ) ) { return; } } $hook = $this->_menu->override_menu_item( array( &$this, '_connect_page_render' ) ); if ( false === $hook ) { // Create new menu item just for the opt-in. $hook = FS_Admin_Menu_Manager::add_page( $this->get_plugin_name(), $this->get_plugin_name(), 'manage_options', $this->_menu->get_slug(), array( &$this, '_connect_page_render' ) ); } } else { $menus = array( $this->_menu->get_parent_slug() ); if ( $this->_menu->is_override_exact() ) { // Make sure the current page is matching the activation page. if ( ! $this->is_matching_url( $this->get_activation_url() ) ) { return; } } foreach ( $menus as $parent_slug ) { $hook = $this->_menu->override_submenu_action( $parent_slug, $this->_menu->get_raw_slug(), array( &$this, '_connect_page_render' ) ); if ( false !== $hook ) { // Found plugin's submenu item. break; } } } if ( $this->is_activation_page() ) { // Clean admin page from distracting content. self::_clean_admin_content_section(); } if ( false !== $hook ) { if ( fs_request_is_action( $this->get_unique_affix() . '_activate_existing' ) ) { $this->_install_with_current_user(); } else if ( fs_request_is_action( $this->get_unique_affix() . '_activate_new' ) ) { $this->_install_with_new_user(); } } } /** * If a plugin was network activated and connected but don't have a network * level settings, then add an artificial menu item for the Account and other * Freemius settings. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ private function add_network_menu_when_missing() { $this->_logger->entrance(); if ( ! $this->_is_network_active ) { // Plugin wasn't activated on the network level. return; } if ( ! fs_is_network_admin() ) { // The context is not the network admin. return; } if ( $this->_menu->has_network_menu() ) { // Plugin already has a network level menu. return; } if ( $this->is_network_activation_mode() ) { /** * Do not add during activation mode, otherwise, there will be duplicate menus while the opt-in * screen is being shown. * * @author Leo Fajardo (@leorw) */ return; } if ( ! WP_FS__SHOW_NETWORK_EVEN_WHEN_DELEGATED ) { if ( $this->is_network_delegated_connection() ) { // Super-admin delegated the connection to the site admins. return; } } if ( ! $this->_menu->has_menu() || $this->_menu->is_top_level() ) { if ( $this->_menu->has_menu() || ! $this->is_addon() || $this->is_activation_mode() ) { $this->_dynamically_added_top_level_page_hook_name = $this->_menu->add_page_and_update( $this->get_plugin_name(), $this->get_plugin_name(), 'manage_options', $this->_menu->has_menu() ? $this->_menu->get_slug() : $this->_slug ); } } else { $this->_menu->add_subpage_and_update( $this->_menu->get_parent_slug(), $this->get_plugin_name(), $this->get_plugin_name(), 'manage_options', $this->_menu->get_slug() ); } } /** * @author Leo Fajardo (@leorw) * @since 1.2.1 * * return string */ function get_top_level_menu_capability() { global $menu; $top_level_menu_slug = $this->get_top_level_menu_slug(); foreach ( $menu as $menu_info ) { /** * The second element in the menu info array is the capability/role that has access to the menu and the * third element is the menu slug. */ if ( $menu_info[2] === $top_level_menu_slug ) { return $menu_info[1]; } } return 'read'; } /** * @author Vova Feldman (@svovaf) * @since 1.0.0 * * @return string */ private function get_top_level_menu_slug() { return ( $this->is_addon() ? $this->get_parent_instance()->_menu->get_top_level_menu_slug() : $this->_menu->get_top_level_menu_slug() ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return string */ function get_pricing_cta_label() { $label = $this->get_text_inline( 'Upgrade', 'upgrade' ); if ( $this->is_in_trial_promotion() && ! $this->is_paying_or_trial() ) { // If running a trial promotion, modify the pricing to load the trial. $label = $this->get_text_inline( 'Start Trial', 'start-trial' ); } else if ( $this->is_paying() ) { $label = $this->get_text_inline( 'Pricing', 'pricing' ); } return $label; } /** * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool */ function is_pricing_page_visible() { return ( // Has at least one paid plan. $this->has_paid_plan() && // Didn't ask to hide the pricing page. $this->is_page_visible( 'pricing' ) && // Don't have a valid active license or has more than one plan. ( ! $this->is_paying() || ! $this->is_single_plan( true ) ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param bool $is_activation_mode * * @return bool */ private function should_add_submenu_or_action_links( $is_activation_mode ) { if ( $this->is_addon() ) { // No submenu items or action links for add-ons. return false; } if ( $this->show_opt_in_on_themes_page() ) { if ( ! fs_is_network_admin() ) { // Also add action links or submenu items when running in a free .org theme so the tabs will be visible. return true; } } else if ( $is_activation_mode ) { // Don't show submenu-items/tabs in activation mode, unless it's a wp.org theme. return false; } if ( fs_is_network_admin() ) { /** * Add submenu items or action links to network level when plugin was network activated and the super * admin did NOT delegate the connection of all sites to site admins. */ return ( $this->_is_network_active && ( WP_FS__SHOW_NETWORK_EVEN_WHEN_DELEGATED || ! $this->is_network_delegated_connection() ) ); } return ( ! $this->_is_network_active || $this->is_delegated_connection() ); } /** * Add default Freemius menu items. * * @author Vova Feldman (@svovaf) * @since 1.0.0 * @since 1.2.2.7 Also add submenu items when running in a free .org theme so the tabs will be visible. */ private function add_submenu_items() { $this->_logger->entrance(); $is_activation_mode = $this->is_activation_mode(); $add_submenu_items = $this->should_add_submenu_or_action_links( $is_activation_mode ); if ( $add_submenu_items ) { if ( $this->has_affiliate_program() ) { // Add affiliation page. $this->add_submenu_item( $this->get_text_inline( 'Affiliation', 'affiliation' ), array( &$this, '_affiliation_page_render' ), $this->get_plugin_name() . ' – ' . $this->get_text_inline( 'Affiliation', 'affiliation' ), 'manage_options', 'affiliation', 'Freemius::_clean_admin_content_section', WP_FS__DEFAULT_PRIORITY, $this->is_submenu_item_visible( 'affiliation' ) ); } } if ( $add_submenu_items || ( $is_activation_mode && $this->is_only_premium() && $this->is_admin_page( 'account' ) && fs_request_is_action( $this->get_unique_affix() . '_sync_license' ) ) ) { if ( ! WP_FS__DEMO_MODE && $this->is_registered() ) { $show_account = ( $this->is_submenu_item_visible( 'account' ) && /** * @since 1.2.2.7 Don't show the Account for free WP.org themes without any paid plans. */ ( ! $this->is_free_wp_org_theme() || $this->has_paid_plan() ) ); // Add user account page. $this->add_submenu_item( $this->get_text_inline( 'Account', 'account' ), array( &$this, '_account_page_render' ), $this->get_plugin_name() . ' – ' . $this->get_text_inline( 'Account', 'account' ), 'manage_options', 'account', array( &$this, '_account_page_load' ), WP_FS__DEFAULT_PRIORITY, ( $add_submenu_items && $show_account ) ); } } if ( $add_submenu_items ) { if (! WP_FS__DEMO_MODE && ! $this->is_whitelabeled() ) { // Add contact page. $this->add_submenu_item( $this->get_text_inline( 'Contact Us', 'contact-us' ), array( &$this, '_contact_page_render' ), $this->get_plugin_name() . ' – ' . $this->get_text_inline( 'Contact Us', 'contact-us' ), 'manage_options', 'contact', 'Freemius::_clean_admin_content_section', WP_FS__DEFAULT_PRIORITY, $this->is_submenu_item_visible( 'contact' ) ); } if ( $this->has_addons() ) { $this->add_submenu_item( $this->get_text_inline( 'Add-Ons', 'add-ons' ), array( &$this, '_addons_page_render' ), $this->get_plugin_name() . ' – ' . $this->get_text_inline( 'Add-Ons', 'add-ons' ), 'manage_options', 'addons', array( &$this, '_addons_page_load' ), WP_FS__LOWEST_PRIORITY - 1, $this->is_submenu_item_visible( 'addons' ) ); } } if ( $add_submenu_items || ( $is_activation_mode && $this->is_only_premium() && $this->is_admin_page( 'pricing' ) ) ) { if (! WP_FS__DEMO_MODE && ! $this->is_whitelabeled() ) { $show_pricing = ( $this->is_submenu_item_visible( 'pricing' ) && $this->is_pricing_page_visible() ); $pricing_cta_text = $this->get_pricing_cta_label(); $pricing_class = 'upgrade-mode'; if ( $show_pricing ) { if ( $this->is_in_trial_promotion() && ! $this->is_paying_or_trial() ) { // If running a trial promotion, modify the pricing to load the trial. $pricing_class = 'trial-mode'; } else if ( $this->is_paying() ) { $pricing_class = ''; } } // Add upgrade/pricing page. $this->add_submenu_item( $pricing_cta_text . '  ' . ( is_rtl() ? $this->get_text_x_inline( '←', 'ASCII arrow left icon', 'symbol_arrow-left' ) : $this->get_text_x_inline( '➤', 'ASCII arrow right icon', 'symbol_arrow-right' ) ), array( &$this, '_pricing_page_render' ), $this->get_plugin_name() . ' – ' . $this->get_text_x_inline( 'Pricing', 'noun', 'pricing' ), 'manage_options', 'pricing', 'Freemius::_clean_admin_content_section', WP_FS__LOWEST_PRIORITY, ( $add_submenu_items && $show_pricing ), $pricing_class ); } } if ( ! $is_activation_mode || ( true !== $this->_storage->require_license_activation ) ) { /** * Add the other menu items if there are any when not in activation mode or license activation is not * required (license activation is required for registered or anonymous users after activating the * premium version when the site is not in trial mode or there's no active valid license). * * @author Leo Fajardo (@leorw) * @since 2.2.1 */ if ( 0 < count( $this->_menu_items ) ) { if ( ! $this->_menu->is_top_level() ) { fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); // Append submenu items right after the plugin's submenu item. $this->order_sub_submenu_items(); } else { // Append submenu items. $this->embed_submenu_items(); } } } } /** * Moved the actual submenu item additions to a separated function, * in order to support sub-submenu items when the plugin's settings * only have a submenu and not top-level menu item. * * @author Vova Feldman (@svovaf) * @since 1.1.4 */ private function embed_submenu_items() { $item_template = $this->_menu->is_top_level() ? '%s' : '%s'; $top_level_menu_capability = $this->get_top_level_menu_capability(); ksort( $this->_menu_items ); $is_first_submenu_item = true; foreach ( $this->_menu_items as $priority => $items ) { foreach ( $items as $item ) { $capability = ( ! empty( $item['capability'] ) ? $item['capability'] : $top_level_menu_capability ); $menu_item = sprintf( $item_template, $this->get_unique_affix(), $item['menu_slug'], ! empty( $item['class'] ) ? $item['class'] : '', $item['menu_title'] ); $top_level_menu_slug = $this->get_top_level_menu_slug(); $menu_slug = $this->_menu->get_slug( $item['menu_slug'] ); if ( ! isset( $item['url'] ) ) { $hook = FS_Admin_Menu_Manager::add_subpage( $item['show_submenu'] ? $top_level_menu_slug : '', $item['page_title'], $menu_item, $capability, $menu_slug, $item['render_function'] ); if ( false !== $item['before_render_function'] ) { add_action( "load-$hook", $item['before_render_function'] ); } } else { FS_Admin_Menu_Manager::add_subpage( $item['show_submenu'] ? $top_level_menu_slug : '', $item['page_title'], $menu_item, $capability, $menu_slug, array( $this, '' ) ); } if ( $item['show_submenu'] && $is_first_submenu_item ) { if ( $this->_is_network_active && ! empty( $this->_dynamically_added_top_level_page_hook_name ) ) { /** * If the top-level menu has been dynamically created, remove the first submenu item that * WordPress automatically creates when there's no submenu item whose slug matches the * parent's. In the following example, the `Awesome Plugin` submenu item will be removed. * * Awesome Plugin * - Awesome Plugin <-- we want to remove this since there's no real setting page for the top-level * * @author Leo Fajardo (@leorw) */ remove_submenu_page( $top_level_menu_slug, $top_level_menu_slug ); } $is_first_submenu_item = false; } } } } /** * Re-order the submenu items so all Freemius added new submenu items * are added right after the plugin's settings submenu item. * * @author Vova Feldman (@svovaf) * @since 1.1.4 */ private function order_sub_submenu_items() { global $submenu; $menu_slug = $this->_menu->get_top_level_menu_slug(); /** * Before "admin_menu" fires, WordPress will loop over the default submenus and remove pages for which the user * does not have permissions. So in case a plugin does not have top-level menu but does have submenus under any * of the default menus, only users that have the right role can access its sub-submenus (Account, Contact Us, * Support Forum, etc.) since $submenu[ $menu_slug ] will be empty if the user doesn't have permission. * * In case a plugin does not have submenus under any of the default menus but does have submenus under the menu * of another plugin, only users that have the right role can access its sub-submenus since we will use the * capability needed to access the parent menu as the capability for the submenus that we will add. */ if ( empty( $submenu[ $menu_slug ] ) ) { return; } $top_level_menu = &$submenu[ $menu_slug ]; $all_submenu_items_after = array(); $found_submenu_item = false; foreach ( $top_level_menu as $submenu_id => $meta ) { if ( $found_submenu_item ) { // Remove all submenu items after the plugin's submenu item. $all_submenu_items_after[] = $meta; unset( $top_level_menu[ $submenu_id ] ); } if ( $this->_menu->get_raw_slug() === $meta[2] ) { // Found the submenu item, put all below. $found_submenu_item = true; continue; } } // Embed all plugin's new submenu items. $this->embed_submenu_items(); // Start with specially high number to make sure it's appended. $i = max( 10000, max( array_keys( $top_level_menu ) ) + 1 ); foreach ( $all_submenu_items_after as $meta ) { $top_level_menu[ $i ] = $meta; $i ++; } // Sort submenu items. ksort( $top_level_menu ); } /** * Helper method to return the module's support forum URL. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return string */ function get_support_forum_url() { return $this->apply_filters( 'support_forum_url', "https://wordpress.org/support/{$this->_module_type}/{$this->_slug}" ); } /** * Displays the Support Forum link when enabled. * * Can be filtered like so: * * function _fs_show_support_menu( $is_visible, $menu_id ) { * if ( 'support' === $menu_id ) { * return _fs->is_registered(); * } * return $is_visible; * } * _fs()->add_filter('is_submenu_visible', '_fs_show_support_menu', 10, 2); * */ function _add_default_submenu_items() { if ( ! $this->is_on() ) { return; } if ( ! $this->is_activation_mode() && ( ( $this->_is_network_active && fs_is_network_admin() ) || ( ! $this->_is_network_active && is_admin() ) ) ) { $this->add_submenu_link_item( $this->apply_filters( 'support_forum_submenu', $this->get_text_inline( 'Support Forum', 'support-forum' ) ), $this->get_support_forum_url(), 'wp-support-forum', null, 50, $this->is_submenu_item_visible( 'support' ) ); } } /** * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param string $menu_title * @param callable $render_function * @param bool|string $page_title * @param string $capability * @param bool|string $menu_slug * @param bool|callable $before_render_function * @param int $priority * @param bool $show_submenu * @param string $class Since 1.2.1.5 can add custom classes to menu items. */ function add_submenu_item( $menu_title, $render_function, $page_title = false, $capability = 'manage_options', $menu_slug = false, $before_render_function = false, $priority = WP_FS__DEFAULT_PRIORITY, $show_submenu = true, $class = '' ) { $this->_logger->entrance( 'Title = ' . $menu_title ); if ( $this->is_addon() ) { $parent_fs = $this->get_parent_instance(); if ( is_object( $parent_fs ) ) { $parent_fs->add_submenu_item( $menu_title, $render_function, $page_title, $capability, $menu_slug, $before_render_function, $priority, $show_submenu, $class ); return; } } if ( ! isset( $this->_menu_items[ $priority ] ) ) { $this->_menu_items[ $priority ] = array(); } $this->_menu_items[ $priority ][] = array( 'page_title' => is_string( $page_title ) ? $page_title : $menu_title, 'menu_title' => $menu_title, 'capability' => $capability, 'menu_slug' => is_string( $menu_slug ) ? $menu_slug : strtolower( $menu_title ), 'render_function' => $render_function, 'before_render_function' => $before_render_function, 'show_submenu' => $show_submenu, 'class' => $class, ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param string $menu_title * @param string $url * @param bool $menu_slug * @param string $capability * @param int $priority * @param bool $show_submenu */ function add_submenu_link_item( $menu_title, $url, $menu_slug = false, $capability = 'read', $priority = WP_FS__DEFAULT_PRIORITY, $show_submenu = true ) { $this->_logger->entrance( 'Title = ' . $menu_title . '; Url = ' . $url ); if ( $this->is_addon() ) { $parent_fs = $this->get_parent_instance(); if ( is_object( $parent_fs ) ) { $parent_fs->add_submenu_link_item( $menu_title, $url, $menu_slug, $capability, $priority, $show_submenu ); return; } } if ( ! isset( $this->_menu_items[ $priority ] ) ) { $this->_menu_items[ $priority ] = array(); } $this->_menu_items[ $priority ][] = array( 'menu_title' => $menu_title, 'capability' => $capability, 'menu_slug' => is_string( $menu_slug ) ? $menu_slug : strtolower( $menu_title ), 'url' => $url, 'page_title' => $menu_title, 'render_function' => 'fs_dummy', 'before_render_function' => '', 'show_submenu' => $show_submenu, ); } #endregion ------------------------------------------------------------------ #-------------------------------------------------------------------------------- #region Admin Notices #-------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @param string|string[] $ids * @param int|null $network_level_or_blog_id * * @uses FS_Admin_Notices::remove_sticky() */ function remove_sticky( $ids, $network_level_or_blog_id = null ) { $this->_admin_notices->remove_sticky( $ids, $network_level_or_blog_id ); } #endregion #-------------------------------------------------------------------------------- #region Actions / Hooks / Filters #-------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @param string $tag * * @return string */ public function get_action_tag( $tag ) { return self::get_action_tag_static( $tag, $this->_slug, $this->is_plugin() ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @param string $tag * @param string $slug * @param bool $is_plugin * * @return string */ static function get_action_tag_static( $tag, $slug = '', $is_plugin = true ) { $action = "fs_{$tag}"; if ( ! empty( $slug ) ) { $action .= '_' . self::get_module_unique_affix( $slug, $is_plugin ); } return $action; } /** * Returns a string that can be used to generate a unique action name, * option name, HTML element ID, or HTML element class. * * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return string */ public function get_unique_affix() { return self::get_module_unique_affix( $this->_slug, $this->is_plugin() ); } /** * Returns a string that can be used to generate a unique action name, * option name, HTML element ID, or HTML element class. * * @author Vova Feldman (@svovaf) * @since 1.2.2.5 * * @param string $slug * @param bool $is_plugin * * @return string */ static function get_module_unique_affix( $slug, $is_plugin = true ) { $affix = $slug; if ( ! $is_plugin ) { $affix .= '-' . WP_FS__MODULE_TYPE_THEME; } return $affix; } /** * @author Vova Feldman (@svovaf) * @since 1.2.1 * @since 1.2.2.5 The AJAX action names are based on the module ID, not like the non-AJAX actions that are * based on the slug for backward compatibility. * * @param string $tag * * @return string */ function get_ajax_action( $tag ) { return self::get_ajax_action_static( $tag, $this->_module_id ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param string $tag * * @return string */ function get_ajax_security( $tag ) { return wp_create_nonce( $this->get_ajax_action( $tag ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param string $tag */ function check_ajax_referer( $tag ) { check_ajax_referer( $this->get_ajax_action( $tag ), 'security' ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * @since 1.2.2.5 The AJAX action names are based on the module ID, not like the non-AJAX actions that are * based on the slug for backward compatibility. * * @param string $tag * @param number|null $module_id * * @return string */ static function get_ajax_action_static( $tag, $module_id = null ) { $action = "fs_{$tag}"; if ( ! empty( $module_id ) ) { $action .= "_{$module_id}"; } return $action; } /** * Do action, specific for the current context plugin. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param string $tag The name of the action to be executed. * @param mixed $arg,... Optional. Additional arguments which are passed on to the * functions hooked to the action. Default empty. * * @uses do_action() */ function do_action( $tag, $arg = '' ) { $args = func_get_args(); $this->_logger->entrance( $tag ); call_user_func_array( 'do_action', array_merge( array( $this->get_action_tag( $tag ) ), array_slice( $args, 1 ) ) ); } /** * Add action, specific for the current context plugin. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param string $tag * @param callable $function_to_add * @param int $priority * @param int $accepted_args * * @uses add_action() */ function add_action( $tag, $function_to_add, $priority = WP_FS__DEFAULT_PRIORITY, $accepted_args = 1 ) { $this->_logger->entrance( $tag ); add_action( $this->get_action_tag( $tag ), $function_to_add, $priority, $accepted_args ); } /** * Add AJAX action, specific for the current context plugin. * * @author Vova Feldman (@svovaf) * @since 1.2.1 * * @param string $tag * @param callable $function_to_add * @param int $priority * * @uses add_action() * * @return bool True if action added, false if no need to add the action since the AJAX call isn't matching. */ function add_ajax_action( $tag, $function_to_add, $priority = WP_FS__DEFAULT_PRIORITY ) { $this->_logger->entrance( $tag ); return self::add_ajax_action_static( $tag, $function_to_add, $priority, $this->_module_id ); } /** * Add AJAX action. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @param string $tag * @param callable $function_to_add * @param int $priority * @param number|null $module_id * * @return bool True if action added, false if no need to add the action since the AJAX call isn't matching. * @uses add_action() * */ static function add_ajax_action_static( $tag, $function_to_add, $priority = WP_FS__DEFAULT_PRIORITY, $module_id = null ) { self::$_static_logger->entrance( $tag ); if ( ! self::is_ajax_action_static( $tag, $module_id ) ) { return false; } add_action( 'wp_ajax_' . self::get_ajax_action_static( $tag, $module_id ), $function_to_add, $priority, 0 ); self::$_static_logger->info( "$tag AJAX callback action added." ); return true; } /** * Send a JSON response back to an Ajax request. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $response */ static function shoot_ajax_response( $response ) { wp_send_json( $response ); } /** * Send a JSON response back to an Ajax request, indicating success. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $data Data to encode as JSON, then print and exit. */ static function shoot_ajax_success( $data = null ) { wp_send_json_success( $data ); } /** * Send a JSON response back to an Ajax request, indicating failure. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $error Optional error message. */ static function shoot_ajax_failure( $error = '' ) { $result = array( 'success' => false ); if ( ! empty( $error ) ) { $result['error'] = $error; } wp_send_json( $result ); } /** * Returns an AJAX URL with a special extra param to indicate whether the request was triggered from the network admin or blog admin. * * @author Vova Feldman (@svovaf) * @since 2.5.1 * * @param string $wrap_with By default, returns the AJAX URL wrapped with single quotes. * * @return string */ static function ajax_url( $wrap_with = "'") { if ( fs_is_network_admin() ) { $param_name = '_fs_network_admin'; } else { $param_name = '_fs_blog_admin'; } $url = admin_url( 'admin-ajax.php', 'relative' ); $url .= ( false === strpos( $url, '?' ) ) ? '?' : '&'; $url .= "{$param_name}=true"; return "{$wrap_with}{$url}{$wrap_with}"; } /** * Apply filter, specific for the current context plugin. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string $tag The name of the filter hook. * @param mixed $value The value on which the filters hooked to `$tag` are applied on. * * @return mixed The filtered value after all hooked functions are applied to it. * * @uses apply_filters() */ function apply_filters( $tag, $value ) { $args = func_get_args(); $this->_logger->entrance( $tag ); array_unshift( $args, $this->get_unique_affix() ); return call_user_func_array( 'fs_apply_filter', $args ); } /** * Add filter, specific for the current context plugin. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string $tag * @param callable $function_to_add * @param int $priority * @param int $accepted_args * * @uses add_filter() */ function add_filter( $tag, $function_to_add, $priority = WP_FS__DEFAULT_PRIORITY, $accepted_args = 1 ) { $this->_logger->entrance( $tag ); add_filter( $this->get_action_tag( $tag ), $function_to_add, $priority, $accepted_args ); } /** * Check if has filter. * * @author Vova Feldman (@svovaf) * @since 1.1.4 * * @param string $tag * @param callable|bool $function_to_check Optional. The callback to check for. Default false. * * @return false|int * * @uses has_filter() */ function has_filter( $tag, $function_to_check = false ) { $this->_logger->entrance( $tag ); return has_filter( $this->get_action_tag( $tag ), $function_to_check ); } #endregion /** * Override default i18n text phrases. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string[] string $key_value * * @uses fs_override_i18n() */ function override_i18n( $key_value ) { fs_override_i18n( $key_value, $this->_slug ); } /* Account Page ------------------------------------------------------------------------------------------------------------------*/ /** * Update site information. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param bool $store Flush to Database if true. * @param null|int $network_level_or_blog_id Since 2.0.0 * @param \FS_Site $site Since 2.0.0 */ private function _store_site( $store = true, $network_level_or_blog_id = null, FS_Site $site = null, $is_backup = false ) { $this->_logger->entrance(); if ( is_null( $site ) ) { $site = $this->_site; } if ( !isset( $site ) || !is_object($site) || empty( $site->id ) ) { $this->_logger->error( "Empty install ID, can't store site." ); return; } $site_clone = clone $site; $sites = self::get_all_sites( $this->_module_type, $network_level_or_blog_id, $is_backup ); if ( ! $is_backup && is_object( $this->_user ) && $this->_user->id != $site->user_id ) { $this->sync_user_by_current_install( $site->user_id ); $prev_stored_user_id = $this->_storage->get( 'prev_user_id', false, $network_level_or_blog_id ); if ( empty( $prev_stored_user_id ) && is_object($this->_user) && $this->_user->id != $site->user_id ) { /** * Store the current user ID as the previous user ID so that the previous user can be used * as the install's owner while the new owner's details are not yet available. * * This will be executed only in the `replica` site. For example, there are 2 sites, namely `original` * and `replica`, then an ownership change was initiated and completed in the `original`, the `replica` * will be using the previous user until it is updated again (e.g.: until the next clone of `original` * into `replica`. * * @author Leo Fajardo (@leorw) */ $this->_storage->store( 'prev_user_id', $sites[ $this->_slug ]->user_id, $network_level_or_blog_id ); } } $sites[ $this->_slug ] = $site_clone; $this->set_account_option( ( $is_backup ? 'prev_' : '' ) . 'sites', $sites, $store, $network_level_or_blog_id ); } /** * Stores the context site in the sites backup storage. This logic is used before deleting the site info so that it can be restored later on if necessary (e.g., if the automatic clone resolution attempt fails). * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ private function back_up_site() { $this->_logger->entrance(); $site_clone = clone $this->_site; $this->_store_site( true, null, $site_clone, true ); } /** * Update plugin's plans information. * * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @param bool $store Flush to Database if true. */ private function _store_plans( $store = true ) { $this->_logger->entrance(); $plans = self::get_all_plans( $this->_module_type ); // Copy plans. $encrypted_plans = array(); for ( $i = 0, $len = count( $this->_plans ); $i < $len; $i ++ ) { $encrypted_plans[] = self::_encrypt_entity( $this->_plans[ $i ] ); } $plans[ $this->_slug ] = $encrypted_plans; $this->set_account_option( 'plans', $plans, $store ); } /** * Update user's plugin licenses. * * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param bool $store * @param number|bool $module_id * @param FS_Plugin_License[] $licenses */ private function _store_licenses( $store = true, $module_id = false, $licenses = array() ) { $this->_logger->entrance(); $all_licenses = self::get_all_licenses(); if ( ! FS_Plugin::is_valid_id( $module_id ) ) { $module_id = $this->_module_id; $user_licenses = is_array( $this->_licenses ) ? $this->_licenses : array(); if ( empty( $user_licenses ) ) { // If the context user doesn't have any license, don't update the licenses collection. return; } $new_user_licenses_map = array(); foreach ( $user_licenses as $user_license ) { $new_user_licenses_map[ $user_license->id ] = $user_license; } self::store_user_id_license_ids_map( array_keys( $new_user_licenses_map ), $this->_module_id, $this->_user->id ); // Update user licenses. $licenses_to_update_count = count( $new_user_licenses_map ); foreach ( $all_licenses[ $module_id ] as $key => $license ) { if ( 0 === $licenses_to_update_count ) { break; } if ( isset( $new_user_licenses_map[ $license->id ] ) ) { // Update license. $all_licenses[ $module_id ][ $key ] = $new_user_licenses_map[ $license->id ]; unset( $new_user_licenses_map[ $license->id ] ); $licenses_to_update_count --; } } if ( ! empty( $new_user_licenses_map ) ) { // Add new licenses. $all_licenses[ $module_id ] = array_merge( array_values( $new_user_licenses_map ), $all_licenses[ $module_id ] ); } $licenses = $all_licenses[ $module_id ]; } if ( ! isset( $all_licenses[ $module_id ] ) ) { $all_licenses[ $module_id ] = array(); } $all_licenses[ $module_id ] = $licenses; self::$_accounts->set_option( 'all_licenses', $all_licenses, $store ); } /** * Update user information. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param bool $store Flush to Database if true. */ private function _store_user( $store = true ) { $this->_logger->entrance(); if ( empty( $this->_user->id ) ) { $this->_logger->error( "Empty user ID, can't store user." ); return; } $users = self::get_all_users(); $users[ $this->_user->id ] = $this->_user; self::$_accounts->set_option( 'users', $users, $store ); } /** * Update new updates information. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param FS_Plugin_Tag|null $update * @param bool $store Flush to Database if true. * @param bool|number $plugin_id */ private function _store_update( $update, $store = true, $plugin_id = false ) { $this->_logger->entrance(); if ( $update instanceof FS_Plugin_Tag ) { $update->updated = time(); } if ( ! is_numeric( $plugin_id ) ) { $plugin_id = $this->_plugin->id; } $updates = self::get_all_updates(); $updates[ $plugin_id ] = $update; self::$_accounts->set_option( 'updates', $updates, $store ); } /** * Update new updates information. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param FS_Plugin[] $plugin_addons * @param bool $store Flush to Database if true. */ private function _store_addons( $plugin_addons, $store = true ) { $this->_logger->entrance(); $addons = self::get_all_addons(); $addons[ $this->_plugin->id ] = $plugin_addons; self::$_accounts->set_option( 'addons', $addons, $store ); } /** * Delete plugin's associated add-ons. * * @author Vova Feldman (@svovaf) * @since 1.0.8 * * @param bool $store * * @return bool */ private function _delete_account_addons( $store = true ) { $all_addons = self::get_all_account_addons(); if ( ! isset( $all_addons[ $this->_plugin->id ] ) ) { return false; } unset( $all_addons[ $this->_plugin->id ] ); self::$_accounts->set_option( 'account_addons', $all_addons, $store ); return true; } /** * Update account add-ons list. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param FS_Plugin[] $addons * @param bool $store Flush to Database if true. */ private function _store_account_addons( $addons, $store = true ) { $this->_logger->entrance(); $all_addons = self::get_all_account_addons(); $all_addons[ $this->_plugin->id ] = $addons; self::$_accounts->set_option( 'account_addons', $all_addons, $store ); } /** * Purges the cache for the valid user licenses API call so that when the `Account` or `Add-Ons` page is loaded, * the valid user licenses will be fetched again and the account add-ons may be updated. * * @author Leo Fajardo (@leorw) * @since 2.2.4 */ private function purge_valid_user_licenses_cache() { if ( ! $this->is_registered() ) { return; } $this->get_api_user_scope()->purge_cache( $this->get_valid_user_licenses_endpoint() ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param array $all_licenses * @param number|null $site_license_id * @param bool $include_parent_licenses * * @return array */ private function get_foreign_licenses_info( $all_licenses, $site_license_id = null, $include_parent_licenses = false ) { $foreign_licenses = array( 'ids' => array(), 'license_keys' => array() ); $parent_license_ids_map = array(); foreach ( $all_licenses as $license ) { if ( $license->user_id == $this->_user->id || $license->id == $site_license_id ) { continue; } $foreign_licenses['ids'][] = $license->id; $foreign_licenses['license_keys'][] = $license->secret_key; if ( $include_parent_licenses && is_object( $this->_license ) && FS_Plugin_License::is_valid_id( $this->_license->parent_license_id ) && ! isset( $parent_license_ids_map[ $this->_license->parent_license_id ] ) ) { /** * Include the parent license's info only if it has not been included before since child licenses * can have the same parent license. */ $foreign_licenses['ids'][] = $this->_license->parent_license_id; $foreign_licenses['license_keys'][] = $license->secret_key; $parent_license_ids_map[ $this->_license->parent_license_id ] = true; } } if ( empty( $foreign_licenses['ids'] ) ) { $foreign_licenses = array(); } return $foreign_licenses; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @return string */ private function get_valid_user_licenses_endpoint() { $user_licenses_endpoint = '/licenses.json?type=active' . ( FS_Plugin::is_valid_id( $this->get_bundle_id() ) ? '&is_enriched=true' : '' ); $foreign_licenses = $this->get_foreign_licenses_info( self::get_all_licenses( $this->_module_id ), null, true ); if ( ! empty ( $foreign_licenses ) ) { $foreign_licenses = array( // Prefix with `+` to tell the server to include foreign licenses in the licenses collection. 'ids' => ( urlencode( '+' ) . implode( ',', $foreign_licenses['ids'] ) ), 'license_keys' => implode( ',', array_map( 'urlencode', $foreign_licenses['license_keys'] ) ) ); $user_licenses_endpoint = add_query_arg( $foreign_licenses, $user_licenses_endpoint ); } return $user_licenses_endpoint; } /** * Fetches active licenses that are enriched with product type if there's a context `bundle_id` and bundle * licenses enriched with product IDs if there are any. From the licenses, the `get_updated_account_addons` * method filters out non–add-on product IDs and stores the add-on IDs. * * @author Leo Fajardo (@leorw) * @since 2.2.4 * * @return stdClass[] array */ private function fetch_valid_user_licenses() { $this->_logger->entrance(); $result = $this->get_api_user_scope()->get( $this->get_valid_user_licenses_endpoint() ); if ( ! $this->is_api_result_object( $result, 'licenses' ) || ! is_array( $result->licenses ) ) { return array(); } return $result->licenses; } /** * @author Leo Fajardo (@leorw) * @since 2.2.4 * * @return number[] Account add-on IDs. */ function get_updated_account_addons() { $addons = $this->get_addons(); if ( empty( $addons ) ) { return array(); } $account_addons = $this->get_account_addons(); if ( ! is_array( $account_addons ) ) { $account_addons = array(); } $user_licenses = $this->is_registered() ? $this->fetch_valid_user_licenses() : array(); if ( empty( $user_licenses ) ) { return $account_addons; } $addon_ids = array(); foreach ( $addons as $addon ) { $addon_ids[] = $addon->id; } $license_product_ids = array(); foreach ( $user_licenses as $license ) { if ( isset( $license->plugin_type ) && 'bundle' === $license->plugin_type ) { $license_product_ids = array_merge( $license_product_ids, $license->products ); } else { $license_product_ids[] = $license->plugin_id; } } // Filter out non–add-on IDs. $new_account_addons = array_intersect( $addon_ids, $license_product_ids ); if ( count( $new_account_addons ) !== count( $account_addons ) ) { $this->_store_account_addons( array_unique( $new_account_addons ) ); } return $new_account_addons; } /** * Store account params in the Database. * * @author Vova Feldman (@svovaf) * @since 1.0.1 * * @param null|int $blog_id Since 2.0.0 */ private function _store_account( $blog_id = null ) { $this->_logger->entrance(); $this->_store_site( false, $blog_id ); $this->_store_user( false ); $this->_store_plans( false ); $this->_store_licenses( false ); self::$_accounts->store( $blog_id ); } /** * Sync user's information. * * @author Vova Feldman (@svovaf) * @since 1.0.3 * @uses FS_Api */ private function _handle_account_user_sync() { $this->_logger->entrance(); $api = $this->get_api_user_scope(); // Get user's information. $user = $api->get( '/', true ); if ( isset( $user->id ) ) { $this->_user->first = $user->first; $this->_user->last = $user->last; $this->_user->email = $user->email; $is_menu_item_account_visible = $this->is_submenu_item_visible( 'account' ); if ( $user->is_verified && ( ! isset( $this->_user->is_verified ) || false === $this->_user->is_verified ) ) { $this->_user->is_verified = true; $this->do_action( 'account_email_verified', $user->email ); $this->_admin_notices->add( $this->get_text_inline( 'Your email has been successfully verified - you are AWESOME!', 'email-verified-message' ), $this->get_text_x_inline( 'Right on', 'a positive response', 'right-on' ) . '!', 'success', // Make admin sticky if account menu item is invisible, // since the page will be auto redirected to the plugin's // main settings page, and the non-sticky message // will disappear. ! $is_menu_item_account_visible, 'email_verified' ); } // Flush user details to DB. $this->_store_user(); $this->do_action( 'after_account_user_sync', $user ); /** * If account menu item is hidden, redirect to plugin's main settings page. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @link https://github.com/Freemius/wordpress-sdk/issues/6 */ if ( ! $is_menu_item_account_visible ) { fs_redirect( $this->_get_admin_page_url() ); } } } /** * @author Vova Feldman (@svovaf) * @since 1.0.9 * @uses FS_Api * * @param number|bool $license_id * * @return FS_Subscription|object|bool */ private function _fetch_site_license_subscription( $license_id = false ) { $this->_logger->entrance(); $api = $this->get_api_site_scope(); if ( ! is_numeric( $license_id ) ) { $license_id = FS_Plugin_License::is_valid_id( $this->_license->parent_license_id ) ? $this->_license->parent_license_id : $this->_license->id; } $result = $api->get( "/licenses/{$license_id}/subscriptions.json", true ); return ! isset( $result->error ) ? ( ( is_array( $result->subscriptions ) && 0 < count( $result->subscriptions ) ) ? new FS_Subscription( $result->subscriptions[0] ) : false ) : $result; } /** * @author Vova Feldman (@svovaf) * @since 1.0.4 * @uses FS_Api * * @param number|bool $plan_id * * @return FS_Plugin_Plan|object */ private function _fetch_site_plan( $plan_id = false ) { $this->_logger->entrance(); $api = $this->get_api_site_scope(); if ( ! is_numeric( $plan_id ) ) { $plan_id = $this->_site->plan_id; } $plan = $api->get( "/plans/{$plan_id}.json", true ); return ! isset( $plan->error ) ? new FS_Plugin_Plan( $plan ) : $plan; } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * @uses FS_Api * * @return FS_Plugin_Plan[]|object */ private function _fetch_plugin_plans() { $this->_logger->entrance(); $api = $this->get_current_or_network_user_api_scope(); /** * @since 1.2.3 When running in DEV mode, retrieve pending plans as well. */ $result = $api->get( $this->add_show_pending( "/plugins/{$this->_module_id}/plans.json" ), true ); if ( $this->is_api_result_object( $result, 'plans' ) && is_array( $result->plans ) ) { for ( $i = 0, $len = count( $result->plans ); $i < $len; $i ++ ) { $result->plans[ $i ] = new FS_Plugin_Plan( $result->plans[ $i ] ); } $result = $result->plans; } return $result; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $plan_id * * @return \FS_Plugin_Plan|object */ private function fetch_plan_by_id( $plan_id ) { $this->_logger->entrance(); $api = $this->get_current_or_network_user_api_scope(); $result = $api->get( "/plugins/{$this->_module_id}/plans/{$plan_id}.json", true ); return $this->is_api_result_entity( $result ) ? new FS_Plugin_Plan( $result ) : $result; } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * @uses FS_Api * * @param number|bool $plugin_id * @param number|bool $site_license_id * @param array $foreign_licenses @since 2.0.0. This is used by network-activated plugins. * @param number|null $blog_id * * @return FS_Plugin_License[]|object */ private function _fetch_licenses( $plugin_id = false, $site_license_id = false, $foreign_licenses = array(), $blog_id = null ) { $this->_logger->entrance(); $api = $this->get_api_user_scope(); if ( ! is_numeric( $plugin_id ) ) { $plugin_id = $this->_plugin->id; } $user_licenses_endpoint = "/plugins/{$plugin_id}/licenses.json?is_enriched=true"; if ( ! empty ( $foreign_licenses ) ) { $foreign_licenses = array( // Prefix with `+` to tell the server to include foreign licenses in the licenses collection. 'ids' => ( urlencode( '+' ) . implode( ',', $foreign_licenses['ids'] ) ), 'license_keys' => implode( ',', array_map( 'urlencode', $foreign_licenses['license_keys'] ) ) ); $user_licenses_endpoint = add_query_arg( $foreign_licenses, $user_licenses_endpoint ); } $result = $api->get( $user_licenses_endpoint, true ); $is_site_license_synced = false; $api_errors = array(); if ( $this->is_api_result_object( $result, 'licenses' ) && is_array( $result->licenses ) ) { for ( $i = 0, $len = count( $result->licenses ); $i < $len; $i ++ ) { $result->licenses[ $i ] = new FS_Plugin_License( $result->licenses[ $i ] ); if ( ( ! $is_site_license_synced ) && is_numeric( $site_license_id ) ) { $is_site_license_synced = ( $site_license_id == $result->licenses[ $i ]->id ); } } $result = $result->licenses; } else { $api_errors[] = $result; $result = array(); } if ( ! $is_site_license_synced ) { if ( ! is_null( $blog_id ) ) { /** * If blog ID is not null, the request is for syncing of the license of a single site via the * network-level "Account" page. * * @author Leo Fajardo (@leorw) */ $this->switch_to_blog( $blog_id ); } $api = $this->get_api_site_scope(); if ( is_numeric( $site_license_id ) ) { // Try to retrieve a foreign license that is linked to the install. $api_result = $api->call( '/licenses.json?is_enriched=true' ); if ( $this->is_api_result_object( $api_result, 'licenses' ) && is_array( $api_result->licenses ) ) { $licenses = $api_result->licenses; if ( ! empty( $licenses ) ) { $result[] = new FS_Plugin_License( $licenses[0] ); } } else { $api_errors[] = $api_result; } } else if ( is_object( $this->_license ) && /** * Sync only if the license belongs to the context plugin. `$plugin_id` can be an add-on ID while * the FS instance that does the syncing is the parent FS instance. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $this->_license->plugin_id == $plugin_id ) { $is_license_in_result = false; if ( ! empty( $result ) ) { foreach ( $result as $license ) { if ( $license->id == $this->_license->id ) { $is_license_in_result = true; break; } } } if ( ! $is_license_in_result ) { // Fetch foreign license by ID and license key. $license = $api->get( "/licenses/{$this->_license->id}.json?license_key=" . urlencode( $this->_license->secret_key ) . '&is_enriched=true' ); if ( $this->is_api_result_entity( $license ) ) { $result[] = new FS_Plugin_License( $license ); } else { $api_errors[] = $license; } } } if ( ! is_null( $blog_id ) ) { $this->switch_to_blog( $this->_storage->network_install_blog_id ); } } if ( is_array( $result ) && 0 < count( $result ) ) { // If found at least one license, return license collection even if there are errors. return $result; } if ( ! empty( $api_errors ) ) { // If found any errors and no licenses, return first error. return $api_errors[0]; } // Fallback to empty licenses list. return $result; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param number $license_id * @param string $license_key * * @return \FS_Plugin_License|object */ private function fetch_license_by_key( $license_id, $license_key ) { $this->_logger->entrance(); $api = $this->get_current_or_network_user_api_scope(); $result = $api->get( "/licenses/{$license_id}.json?license_key=" . urlencode( $license_key ) ); return $this->is_api_result_entity( $result ) ? new FS_Plugin_License( $result ) : $result; } /** * @author Vova Feldman (@svovaf) * @since 1.2.0 * @uses FS_Api * * @param number|bool $plugin_id * @param bool $flush * * @return FS_Payment[]|object */ function _fetch_payments( $plugin_id = false, $flush = false ) { $this->_logger->entrance(); $api = $this->get_api_user_scope(); if ( ! is_numeric( $plugin_id ) ) { $plugin_id = $this->_plugin->id; } $include_bundles = ( is_object( $this->_plugin ) && FS_Plugin::is_valid_id( $this->_plugin->bundle_id ) ); $result = $api->get( "/plugins/{$plugin_id}/payments.json?include_addons=true" . ($include_bundles ? '&include_bundles=true' : ''), $flush ); if ( ! isset( $result->error ) ) { for ( $i = 0, $len = count( $result->payments ); $i < $len; $i ++ ) { $result->payments[ $i ] = new FS_Payment( $result->payments[ $i ] ); } $result = $result->payments; } return $result; } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * @uses FS_Api * * @param bool $flush * * @return \FS_Billing|mixed */ function _fetch_billing( $flush = false ) { require_once WP_FS__DIR_INCLUDES . '/entities/class-fs-billing.php'; $billing = $this->get_api_user_scope()->get( 'billing.json', $flush ); if ( $this->is_api_result_entity( $billing ) ) { $billing = new FS_Billing( $billing ); } return $billing; } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param FS_Plugin_License[] $licenses * @param number $module_id */ private function _update_licenses( $licenses, $module_id ) { $this->_logger->entrance(); if ( is_array( $licenses ) ) { for ( $i = 0, $len = count( $licenses ); $i < $len; $i ++ ) { $licenses[ $i ]->updated = time(); } } $this->_store_licenses( true, $module_id, $licenses ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param bool|number $plugin_id * @param bool $flush Since 1.1.7.3 * @param int $expiration Since 1.2.2.7 * @param bool|string $newer_than Since 2.2.1 * * @return object|false New plugin tag info if exist. */ private function _fetch_newer_version( $plugin_id = false, $flush = true, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $newer_than = false ) { $latest_tag = $this->_fetch_latest_version( $plugin_id, $flush, $expiration, $newer_than ); if ( ! is_object( $latest_tag ) ) { return false; } $plugin_version = $this->get_plugin_version(); // Check if version is actually newer. $has_new_version = // If it's an non-installed add-on then always return latest. ( $this->_is_addon_id( $plugin_id ) && ! $this->is_addon_activated( $plugin_id ) ) || // Compare versions. version_compare( $plugin_version, $latest_tag->version, '<' ); $this->_logger->departure( $has_new_version ? 'Found newer plugin version ' . $latest_tag->version : 'No new version' ); $is_latest_version_beta = ( 'beta' === $latest_tag->release_mode ); $this->_storage->beta_data = array( 'is_beta' => $is_latest_version_beta, 'version' => $latest_tag->version ); return $has_new_version ? $latest_tag : false; } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param bool|number $plugin_id * @param bool $flush Since 1.1.7.3 * @param int $expiration Since 1.2.2.7 * @param bool|string $newer_than Since 2.2.1 * * @return bool|FS_Plugin_Tag */ function get_update( $plugin_id = false, $flush = true, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $newer_than = false ) { $this->_logger->entrance(); if ( ! is_numeric( $plugin_id ) ) { $plugin_id = $this->_plugin->id; } $this->check_updates( true, $plugin_id, $flush, $expiration, $newer_than ); $updates = $this->get_all_updates(); return isset( $updates[ $plugin_id ] ) && is_object( $updates[ $plugin_id ] ) ? $updates[ $plugin_id ] : false; } /** * Check if site assigned with active license. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @deprecated Please use has_active_valid_license() instead because license can be cancelled. */ function has_active_license() { return ( is_object( $this->_license ) && is_numeric( $this->_license->id ) && ! $this->_license->is_expired() ); } /** * Check if site assigned with active & valid (not expired) license. * * @author Vova Feldman (@svovaf) * @since 1.2.1 * * @param bool $check_expiration */ function has_active_valid_license( $check_expiration = true ) { return self::is_active_valid_license( $this->_license, $check_expiration ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 */ function is_data_debug_mode() { if ( is_null( $this->is_whitelabeled ) || ! $this->is_whitelabeled ) { return false; } $fs = $this->is_addon() ? $this->get_parent_instance() : $this; if ( $fs->is_network_active() && fs_is_network_admin() ) { $is_developer_license_debug_mode = get_site_transient( "fs_{$this->get_id()}_data_debug_mode" ); } else { $is_developer_license_debug_mode = get_transient( "fs_{$this->get_id()}_data_debug_mode" ); } return ( 'true' === $is_developer_license_debug_mode ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 */ function _set_data_debug_mode() { if ( ! $this->is_whitelabeled( true ) ) { return; } $license_or_user_key = fs_request_get( 'license_or_user_key' ); $transient_value = ( ! empty( $license_or_user_key ) ) ? 'true' : 'false'; if ( 'true' === $transient_value ) { $stored_key = $this->_storage->get( ! FS_User::is_valid_id( $this->_storage->last_license_user_id ) ? 'last_license_key' : 'last_license_user_key' ); if ( md5( $license_or_user_key ) !== $stored_key ) { $this->shoot_ajax_failure( sprintf( '%s... %s', $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ), $this->get_text_inline( 'seems like the key you entered doesn\'t match our records.', 'developer-or-license-not-found' ) ) ); } } if ( $this->is_network_active() && fs_is_network_admin() ) { set_site_transient( "fs_{$this->get_id()}_data_debug_mode", $transient_value, WP_FS__TIME_24_HOURS_IN_SEC / 24 ); } else { set_transient( "fs_{$this->get_id()}_data_debug_mode", $transient_value, WP_FS__TIME_24_HOURS_IN_SEC / 24 ); } if ( 'true' === $transient_value ) { $this->_admin_notices->add_sticky( $this->get_text_inline( 'Debug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.', 'data_debug_mode_enabled' ), 'data_debug_mode_enabled' ); } $this->shoot_ajax_success(); } /** * Check if a given license is active & valid (not expired). * * @author Vova Feldman (@svovaf) * @since 2.1.3 * * @param FS_Plugin_License $license * @param bool $check_expiration * * @return bool */ private static function is_active_valid_license( $license, $check_expiration = true ) { return ( is_object( $license ) && FS_Plugin_License::is_valid_id( $license->id ) && $license->is_active() && ( ! $check_expiration || $license->is_valid() ) ); } /** * Checks if there's any site that is associated with an active & valid license. * This logic is used to determine if the admin can download the premium code base from a network level admin. * * @author Vova Feldman (@svovaf) * @since 2.1.3 * * @return bool */ function has_any_active_valid_license() { if ( ! fs_is_network_admin() ) { return $this->has_active_valid_license(); } $installs = $this->get_blog_install_map(); $all_plugin_licenses = self::get_all_licenses( $this->_module_id ); foreach ( $installs as $blog_id => $install ) { if ( ! FS_Plugin_License::is_valid_id( $install->license_id ) ) { continue; } foreach ( $all_plugin_licenses as $license ) { if ( $license->id == $install->license_id ) { if ( self::is_active_valid_license( $license ) ) { return true; } } } } return false; } /** * Check if site assigned with license with enabled features. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return bool */ function has_features_enabled_license() { return ( is_object( $this->_license ) && is_numeric( $this->_license->id ) && $this->_license->is_features_enabled() ); } /** * Checks if the product is activated with a bundle license. * * @author Leo Fajardo (@leorw) * @since 2.4.0 * * @return bool */ function is_activated_with_bundle_license() { if ( ! $this->has_features_enabled_license() ) { return false; } return FS_Plugin_License::is_valid_id( $this->_license->parent_license_id ); } /** * Check if user is a trial or have feature enabled license. * * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @return bool */ function can_use_premium_code() { return $this->is_trial() || $this->has_features_enabled_license(); } /** * Checks if the current user can activate plugins or switch themes. Note that this method should only be used * after the `init` action is triggered because it is using `current_user_can()` which is only functional after * the context user is authenticated. * * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return bool */ function is_user_admin() { /** * Require a super-admin when network activated, running from the network level OR if * running from the site level but not delegated the opt-in. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ if ( $this->_is_network_active && ( fs_is_network_admin() || ! $this->is_delegated_connection() ) ) { return is_super_admin(); } return ( $this->is_plugin() && current_user_can( is_multisite() ? 'manage_options' : 'activate_plugins' ) ) || ( $this->is_theme() && current_user_can( 'switch_themes' ) ); } /** * Sync site's plan. * * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @uses FS_Api * * @param bool $background Hints the method if it's a background sync. If false, it means that was initiated by * the admin. * @param bool $is_context_single_site @since 2.0.0. This is used when syncing a license for a single install from the * network-level "Account" page. * @param int|null $current_blog_id @since 2.2.3. This is passed from the `execute_cron` method and used by the * `_sync_plugin_license` method in order to switch to the previous blog when sending * updates for a single site in case `execute_cron` has switched to a different blog. */ private function _sync_license( $background = false, $is_context_single_site = false, $current_blog_id = null ) { $this->_logger->entrance(); $plugin_id = fs_request_get( 'plugin_id', $this->get_id() ); $is_addon_sync = ( ! $this->_plugin->is_addon() && $plugin_id != $this->get_id() ); if ( $is_addon_sync ) { $this->_sync_addon_license( $plugin_id, $background ); } else { $this->_sync_plugin_license( $background, true, $is_context_single_site, $current_blog_id ); } $this->do_action( 'after_account_plan_sync', $this->get_plan_name() ); } /** * Sync plugin's add-on license. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * @uses FS_Api * * @param number $addon_id * @param bool $background */ private function _sync_addon_license( $addon_id, $background ) { $this->_logger->entrance(); if ( $this->is_addon_activated( $addon_id ) ) { // If already installed, use add-on sync. $fs_addon = self::get_instance_by_id( $addon_id ); if ( // Add-on is network activated and network integrated. $fs_addon->is_network_active() || // Background sync cron. self::is_cron() || // Add-on is not network activated or not network integrated. ! fs_is_network_admin() ) { $fs_addon->_sync_license( $background ); return; } } // Validate add-on exists. $addon = $this->get_addon( $addon_id ); if ( ! is_object( $addon ) ) { return; } // Add add-on into account add-ons. $account_addons = $this->get_account_addons(); if ( ! is_array( $account_addons ) ) { $account_addons = array(); } $account_addons[] = $addon->id; $account_addons = array_unique( $account_addons ); $this->_store_account_addons( $account_addons ); // Load add-on licenses. $licenses = $this->_fetch_licenses( $addon->id ); // Sync add-on licenses. if ( $this->is_array_instanceof( $licenses, 'FS_Plugin_License' ) ) { $this->_update_licenses( $licenses, $addon->id ); if ( ! $this->is_addon_installed( $addon->id ) && FS_License_Manager::has_premium_license( $licenses ) ) { $plans_result = $this->get_api_site_or_plugin_scope()->get( $this->add_show_pending( "/addons/{$addon_id}/plans.json" ) ); if ( ! isset( $plans_result->error ) ) { $plans = array(); foreach ( $plans_result->plans as $plan ) { $plans[] = new FS_Plugin_Plan( $plan ); } $this->_admin_notices->add_sticky( sprintf( ( FS_Plan_Manager::instance()->has_free_plan( $plans ) ? $this->get_text_inline( 'Your %s Add-on plan was successfully upgraded.', 'addon-successfully-upgraded-message' ) : /* translators: %s:product name, e.g. Facebook add-on was successfully... */ $this->get_text_inline( '%s Add-on was successfully purchased.', 'addon-successfully-purchased-message' ) ), $addon->title ) . ' ' . $this->get_latest_download_link( $this->get_text_inline( 'Download the latest version', 'download-latest-version' ), $addon_id ), 'addon_plan_upgraded_' . $addon->slug, $this->get_text_x_inline( 'Yee-haw', 'interjection expressing joy or exuberance', 'yee-haw' ) . '!' ); } } } } /** * Sync site's plugin plan. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * @uses FS_Api * * @param bool $background Hints the method if it's a background sync. If false, it means that was initiated by the admin. * @param bool $send_installs_update Since 2.0.0 * @param bool $is_context_single_site Since 2.0.0. This is used when sending an update for a single install and * syncing its license from the network-level "Account" page (e.g.: after * activating a license only for the single install). * @param int|null $current_blog_id Since 2.2.3. This is passed from the `execute_cron` method so that it * can be used here to switch to the previous blog in case `execute_cron` * has switched to a different blog. */ private function _sync_plugin_license( $background = false, $send_installs_update = true, $is_context_single_site = false, $current_blog_id = null ) { $this->_logger->entrance(); $plan_change = 'none'; $is_site_level_sync = ( $is_context_single_site || fs_is_blog_admin() || ! $this->_is_network_active ); if ( ! $send_installs_update ) { $site = $this->_site; } else { /** * Sync site info. * * @todo This line will execute install sync on a daily basis, even if running the free version (for opted-in users). The reason we want to keep it that way is for cases when the user was a paying customer, then there was a failure in subscription payment, and then after some time the payment was successful. This could be heavily optimized. For example, we can skip the $flush if the current install was never associated with a paid version. */ if ( $is_site_level_sync ) { /** * Switch to the previous blog since `execute_cron` may have switched to a different blog. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ if ( is_numeric( $current_blog_id ) ) { $this->switch_to_blog( $current_blog_id ); } $result = $this->send_install_update( array(), true, true ); $is_valid = $this->is_api_result_entity( $result ); } else { $result = $this->send_installs_update( array(), true, true ); $is_valid = $this->is_api_result_object( $result, 'installs' ); } if ( ! $is_valid ) { if ( $is_context_single_site ) { // Switch back to the main blog so that the following logic will have the right entities. $this->switch_to_blog( $this->_storage->network_install_blog_id ); } // Show API message only if not background sync or if paying customer. if ( ! $background || $this->is_paying() ) { // Try to ping API to see if not blocked. if ( FS_Api::is_blocked( $result ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.1.6 Only show message related to one of the Freemius powered plugins. Once it will be resolved it will fix the issue for all plugins anyways. There's no point to scare users with multiple error messages. */ if ( ! self::$_global_admin_notices->has_sticky( 'api_blocked' ) ) { // Add notice immediately if not a background sync. $add_notice = ( ! $background ); if ( ! $add_notice ) { $counter = (int) get_transient( '_fs_api_connection_retry_counter' ); // We only want to add the notice after 3 consecutive failures. $add_notice = ( 3 <= $counter ); if ( ! $add_notice ) { /** * Update counter transient only if notice shouldn't be added. If it is added the transient will be reset anyway, because the retries mechanism should only start counting if the admin isn't aware of the connectivity issue. * * Also, since the background sync happens once a day, setting the transient expiration for a week should be enough to count 3 failures, if there's an actual connectivity issue. */ set_transient( '_fs_api_connection_retry_counter', $counter + 1, WP_FS__TIME_WEEK_IN_SEC ); } } // Add notice instantly for not-background sync and only after 3 failed attempts for background sync. if ( $add_notice ) { self::$_global_admin_notices->add( $this->generate_api_blocked_notice_message_from_result( $result ), '', 'error', $background, 'api_blocked' ); add_action( 'admin_footer', array( 'Freemius', '_add_api_connectivity_notice_handler_js' ) ); // Notice was just shown, reset connectivity counter. delete_transient( '_fs_api_connection_retry_counter' ); } } } else if ( is_object( $result ) ) { // Authentication params are broken. $this->_admin_notices->add( $this->get_text_inline( 'It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.', 'wrong-authentication-param-message' ) . '
' . $this->get_text_inline( 'Error received from the server:', 'server-error-message' ) . var_export( $result->error, true ), '', 'error' ); } } // No reason to continue with license sync while there are API issues. return; } // API is working now. Delete the transient and start afresh. delete_transient('_fs_api_connection_retry_counter'); if ( $is_site_level_sync ) { $site = new FS_Site( $result ); } else { // Map site addresses to their blog IDs. $address_to_blog_map = $this->get_address_to_blog_map(); // Find the current context install. $site = null; foreach ( $result->installs as $install ) { if ( $install->id == $this->_site->id ) { $site = new FS_Site( $install ); } else { $address = trailingslashit( fs_strip_url_protocol( $install->url ) ); $blog_id = $address_to_blog_map[ $address ]; $this->_store_site( true, $blog_id, new FS_Site( $install ) ); } } } // Sync plans. $this->_sync_plans(); } // Remove sticky API connectivity message. self::$_global_admin_notices->remove_sticky( 'api_blocked' ); if ( ! $this->has_paid_plan() ) { $this->_site = $site; $this->_store_site( true, $is_site_level_sync ? null : $this->get_network_install_blog_id() ); } else { $context_blog_id = 0; if ( $is_context_single_site ) { $context_blog_id = get_current_blog_id(); // Switch back to the main blog in order to properly sync the license. $this->switch_to_blog( $this->_storage->network_install_blog_id ); } /** * Sync licenses. Pass the site's license ID so that the foreign licenses will be fetched if the license * associated with that ID is not included in the user's licenses collection. */ $this->_sync_licenses( $site->license_id, ( $is_context_single_site ? $context_blog_id : null ) ); if ( $is_context_single_site ) { $this->switch_to_blog( $context_blog_id ); } // Check if plan / license changed. if ( $site->plan_id != $this->_site->plan_id || // Check if trial started. $site->trial_plan_id != $this->_site->trial_plan_id || $site->trial_ends != $this->_site->trial_ends || // Check if license changed. $site->license_id != $this->_site->license_id ) { if ( $site->is_trial() && ( ! $this->_site->is_trial() || $site->trial_ends != $this->_site->trial_ends ) ) { // New trial started. $this->_site = $site; $plan_change = 'trial_started'; // For trial with subscription use-case. $new_license = is_null( $site->license_id ) ? null : $this->_get_license_by_id( $site->license_id ); if ( is_object( $new_license ) && $new_license->is_valid() ) { $this->_site = $site; $this->_update_site_license( $new_license ); $this->_store_licenses(); $this->_sync_site_subscription( $this->_license ); } } else if ( $this->_site->is_trial() && ! $site->is_trial() && ! is_numeric( $site->license_id ) ) { // Was in trial, but now trial expired and no license ID. // New trial started. $this->_site = $site; $plan_change = 'trial_expired'; } else { $is_free = $this->is_free_plan(); // Make sure license exist and not expired. $new_license = is_null( $site->license_id ) ? null : $this->_get_license_by_id( $site->license_id ); if ( $is_free && is_null( $new_license ) && $this->has_any_license() && $this->_license->is_cancelled ) { // License cancelled. $this->_site = $site; $this->_update_site_license( $new_license ); $this->_store_licenses(); $plan_change = 'cancelled'; } else if ( $is_free && ( ( ! is_object( $new_license ) || $new_license->is_expired() ) ) ) { // The license is expired, so ignore upgrade method. $this->_site = $site; } else { // License changed. $this->_site = $site; /** * IMPORTANT: * The line below should be executed before trying to activate the license on the rest of the network, otherwise, the license' activation counters may be out of sync + there's no need to activate the license on the context site since it's already activated on it. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ $this->_update_site_license( $new_license ); if ( ! $is_context_single_site && fs_is_network_admin() && $this->_is_network_active && $new_license->quota > 1 && get_blog_count() > 1 ) { // See if license can activated on all sites. if ( ! $this->try_activate_license_on_network( $this->_user, $new_license ) ) { if ( ! fs_request_get_bool( 'auto_install' ) ) { // Open the license activation dialog box on the account page. add_action( 'admin_footer', array( &$this, '_open_license_activation_dialog_box' ) ); } } } $this->_store_licenses(); $plan_change = $is_free ? ( $this->is_only_premium() ? 'activated' : 'upgraded' ) : ( is_object( $new_license ) ? 'changed' : 'downgraded' ); } } // Store updated site info. $this->_store_site( true, $is_site_level_sync ? null : $this->get_network_install_blog_id() ); } else { if ( ! is_object( $this->_license ) ) { $this->maybe_update_whitelabel_flag( FS_Plugin_License::is_valid_id( $site->license_id ) ? $this->get_license_by_id( $site->license_id ) : null ); } else { $this->maybe_update_whitelabel_flag( $this->_license ); if ( $this->_license->is_expired() ) { if ( ! $this->has_features_enabled_license() ) { $this->_deactivate_license(); $plan_change = 'downgraded'; } else { $last_time_expired_license_notice_was_shown = $this->_storage->get( 'expired_license_notice_shown', 0 ); if ( time() - ( 14 * WP_FS__TIME_24_HOURS_IN_SEC ) >= $last_time_expired_license_notice_was_shown ) { /** * Show the expired license notice every 14 days. * * @author Leo Fajardo (@leorw) * @since 2.3.1 */ $plan_change = 'expired'; } } } } if ( is_numeric( $site->license_id ) && is_object( $this->_license ) ) { $this->_sync_site_subscription( $this->_license ); } } if ( ! $this->is_addon() && $this->_site->is_beta() !== $site->is_beta() ) { // Beta flag updated. $this->_site = $site; $this->_store_site( true, $is_site_level_sync ? null : $this->get_network_install_blog_id() ); } if ( $this->is_addon() || $this->has_addons() ) { /** * Purge the valid user licenses cache so that when the "Account" or the "Add-Ons" page is loaded, * an updated valid user licenses collection will be fetched from the server which is used to also * update the account add-ons (add-ons the user has licenses for). * * @author Leo Fajardo (@leorw) * @since 2.2.4 */ $this->purge_valid_user_licenses_cache(); } } $hmm_text = $this->get_text_x_inline( 'Hmm', 'something somebody says when they are thinking about what you have just said.', 'hmm' ) . '...'; if ( $this->apply_filters( 'has_paid_plan_account', $this->has_paid_plan() ) ) { switch ( $plan_change ) { case 'none': if ( ! $background && is_admin() ) { $plan = $this->is_trial() ? $this->get_trial_plan() : $this->get_plan(); if ( $plan->is_free() ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'It looks like you are still on the %s plan. If you did upgrade or change your plan, it\'s probably an issue on our side - sorry.', 'plan-did-not-change-message' ), '' . $plan->title . ( $this->is_trial() ? ' ' . $this->get_text_x_inline( 'Trial', 'trial period', 'trial' ) : '' ) . '' ) . ' ' . sprintf( '%s', $this->contact_url( 'bug', sprintf( $this->get_text_inline( 'I have upgraded my account but when I try to Sync the License, the plan remains %s.', 'plan-did-not-change-email-message' ), strtoupper( $plan->name ) ) ), $this->get_text_inline( 'Please contact us here', 'contact-us-here' ) ), $hmm_text ); } } break; case 'upgraded': case 'activated': $this->add_after_plan_activation_or_upgrade_instructions_notice( 'upgraded' === $plan_change ); $this->_admin_notices->remove_sticky( array( 'trial_started', 'trial_promotion', 'trial_expired', 'activation_complete', 'license_expired', ) ); break; case 'changed': $this->_admin_notices->add_sticky( sprintf( $this->get_text_inline( 'Your plan was successfully changed to %s.', 'plan-changed-to-x-message' ), $this->get_plan_title() ), 'plan_changed' ); $this->_admin_notices->remove_sticky( array( 'trial_started', 'trial_promotion', 'trial_expired', 'activation_complete', ) ); break; case 'downgraded': $this->_admin_notices->add_sticky( ($this->has_free_plan() ? sprintf( $this->get_text_inline( 'Your license has expired. You can still continue using the free %s forever.', 'license-expired-blocking-message' ), $this->_module_type ) : /* translators: %1$s: product title; %2$s, %3$s: wrapping HTML anchor element; %4$s: 'plugin', 'theme', or 'add-on'. */ sprintf( $this->get_text_inline( 'Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.', 'license-expired-blocking-message_premium-only' ), sprintf('', $this->pricing_url()), '', $this->get_module_label(true) ) ), 'license_expired', $hmm_text ); $this->_admin_notices->remove_sticky( 'plan_upgraded' ); break; case 'cancelled': $this->_admin_notices->add( $this->get_text_inline( 'Your license has been cancelled. If you think it\'s a mistake, please contact support.', 'license-cancelled' ) . ' ' . sprintf( '%s', $this->contact_url( 'bug' ), $this->get_text_inline( 'Please contact us here', 'contact-us-here' ) ), $hmm_text, 'error' ); $this->_admin_notices->remove_sticky( 'plan_upgraded' ); break; case 'expired': $this->_admin_notices->add_sticky( sprintf( $this->get_text_inline( 'Your license has expired. You can still continue using all the %s features, but you\'ll need to renew your license to continue getting updates and support.', 'license-expired-non-blocking-message' ), $this->get_plan()->title ), 'license_expired', $hmm_text ); $this->_storage->expired_license_notice_shown = WP_FS__SCRIPT_START_TIME; $this->_admin_notices->remove_sticky( 'plan_upgraded' ); break; case 'trial_started': $this->add_complete_upgrade_instructions_notice( sprintf( $this->get_text_inline( 'Your trial has been successfully started.', 'trial-started-message' ), '' . $this->get_plugin_name() . '' ), 'trial_started', $this->get_trial_plan()->title ); $this->_admin_notices->remove_sticky( array( 'trial_promotion', ) ); break; case 'trial_expired': $this->_admin_notices->add_sticky( ($this->has_free_plan() ? $this->get_text_inline( 'Your free trial has expired. You can still continue using all our free features.', 'trial-expired-message' ) : /* translators: %1$s: product title; %2$s, %3$s: wrapping HTML anchor element; %4$s: 'plugin', 'theme', or 'add-on'. */ sprintf( $this->get_text_inline( 'Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.', 'trial-expired-message_premium-only' ), sprintf('', $this->pricing_url()), '', $this->get_module_label(true))), 'trial_expired', $hmm_text ); $this->_admin_notices->remove_sticky( array( 'trial_started', 'trial_promotion', 'plan_upgraded', ) ); break; } } if ( 'none' !== $plan_change ) { if ( ! is_object( $this->_license ) || ! $this->_license->is_whitelabeled ) { $this->_admin_notices->remove_sticky( 'license_whitelabeled' ); } $this->do_action( 'after_license_change', $plan_change, $this->get_plan() ); } } /** * @author Leo Fajardo (@leorw) * @since 2.5.4 * * @param mixed $result * * @return string */ private function generate_api_blocked_notice_message_from_result( $result ) { $api_domains = $this->apply_filters( 'api_domains', array( 'api.freemius.com', 'wp.freemius.com', ) ); $api_domains_list_items = ''; foreach( $api_domains as $api_domain ) { $api_domains_list_items .= "
  • {$api_domain}
  • "; } $error_message = sprintf( $this->get_text_inline( 'Your server is blocking the access to Freemius\' API, which is crucial for %1$s synchronization. Please contact your host to whitelist the following domains:%2$s', 'server-blocking-access' ), $this->get_plugin_name(), "
      {$api_domains_list_items}
    " . $this->get_text_inline( 'Show error details', 'show-error-details' ) . " " ); $error_message = "
    {$error_message}
    " . ''; return $error_message; } /** * Include the required JS at the footer of the admin to trigger the license activation dialog box. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ public function _open_license_activation_dialog_box() { $vars = array( 'license_id' => $this->_site->license_id ); fs_require_once_template( 'js/open-license-activation.php', $vars ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param bool $background * @param FS_Plugin_License|null $premium_license */ protected function _activate_license( $background = false, $premium_license = null ) { $this->_logger->entrance(); if ( is_null( $premium_license ) ) { $license_id = fs_request_get( 'license_id' ); if ( is_object( $this->_site ) && FS_Plugin_License::is_valid_id( $license_id ) && $license_id == $this->_site->license_id ) { // License is already activated. return; } $premium_license = FS_Plugin_License::is_valid_id( $license_id ) ? $this->_get_license_by_id( $license_id ) : $this->_get_available_premium_license(); } if ( ! is_object( $premium_license ) ) { return; } if ( ! is_object( $this->_site ) ) { // Not yet opted-in. $user = $this->get_current_or_network_user(); if ( ! is_object( $user ) ) { $user = self::_get_user_by_id( $premium_license->user_id ); } if ( is_object( $user ) ) { $this->install_with_user( $user, $premium_license->secret_key, false, false, false ); } else { $this->opt_in( false, false, false, $premium_license->secret_key ); return; } } /** * If the premium license is already associated with the install, just * update the license reference (activation is not required). * * @since 1.1.9 */ if ( $premium_license->id == $this->_site->license_id ) { // License is already activated. $this->_update_site_license( $premium_license ); $this->_store_account(); return; } if ( $this->_site->user_id != $premium_license->user_id ) { $api_request_params = array( 'license_key' => $premium_license->secret_key ); } else { $api_request_params = array(); } $api = $this->get_api_site_scope(); $license = $api->call( "/licenses/{$premium_license->id}.json?is_enriched=true", 'put', $api_request_params ); if ( ! $this->is_api_result_entity( $license ) ) { if ( ! $background ) { $this->_admin_notices->add( sprintf( '%s %s', $this->get_text_inline( 'It looks like the license could not be activated.', 'license-activation-failed-message' ), ( is_object( $license ) && isset( $license->error ) ? $license->error->message : sprintf( '%s
    %s', $this->get_text_inline( 'Error received from the server:', 'server-error-message' ), var_export( $license, true ) ) ) ), $this->get_text_x_inline( 'Hmm', 'something somebody says when they are thinking about what you have just said.', 'hmm' ) . '...', 'error' ); } return; } $premium_license = new FS_Plugin_License( $license ); // Updated site plan. $site = $this->get_api_site_scope()->get( '/', true ); if ( $this->is_api_result_entity( $site ) ) { $this->_site = new FS_Site( $site ); } $this->_update_site_license( $premium_license ); $this->_store_account(); if ( $this->is_addon() || $this->has_addons() ) { /** * Purge the valid user licenses cache so that when the "Account" or the "Add-Ons" page is loaded, * an updated valid user licenses collection will be fetched from the server which is used to also * update the account add-ons (add-ons the user has licenses for). * * @author Leo Fajardo (@leorw) * @since 2.2.4 */ $this->purge_valid_user_licenses_cache(); } if ( ! $background ) { $this->add_complete_upgrade_instructions_notice( $this->get_text_inline( 'Your license was successfully activated.', 'license-activated-message' ), 'license_activated' ); } $this->_admin_notices->remove_sticky( array( 'trial_promotion', 'license_expired', ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param bool $show_notice */ protected function _deactivate_license( $show_notice = true ) { $this->_logger->entrance(); $hmm_text = $this->get_text_x_inline( 'Hmm', 'something somebody says when they are thinking about what you have just said.', 'hmm' ) . '...'; if ( ! FS_Plugin_License::is_valid_id( $this->_site->license_id ) ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'It looks like your site currently doesn\'t have an active license.', 'no-active-license-message' ), $this->get_plan_title() ), $hmm_text ); return; } $api = $this->get_api_site_scope(); $license = $api->call( "/licenses/{$this->_site->license_id}.json", 'delete' ); $this->handle_license_deactivation_result( $license, $hmm_text, $show_notice ); } /** * @author Leo Fajardo (@leorw) * @since 2.2.1 * * @param FS_Plugin_License $license * @param bool|string $hmm_text * @param bool $show_notice */ private function handle_license_deactivation_result( $license, $hmm_text = false, $show_notice = true ) { if ( isset( $license->error ) ) { $this->_admin_notices->add( $this->get_text_inline( 'It looks like the license deactivation failed.', 'license-deactivation-failed-message' ) . '
    ' . $this->get_text_inline( 'Error received from the server:', 'server-error-message' ) . ' ' . var_export( $license->error, true ), $hmm_text, 'error' ); return; } // Update license cache. if ( is_array( $this->_licenses ) ) { for ( $i = 0, $len = count( $this->_licenses ); $i < $len; $i ++ ) { if ( $license->id == $this->_licenses[ $i ]->id ) { $this->_licenses[ $i ] = new FS_Plugin_License( $license ); } } } // Update site plan to default. $this->_sync_plans(); $this->_site->plan_id = $this->_plans[0]->id; // Unlink license from site. $this->_update_site_license( null ); $this->_store_account(); if ( $show_notice ) { $this->_admin_notices->add( sprintf( $this->is_only_premium() ? $this->get_text_inline( 'Your %s license was successfully deactivated.', 'license-deactivation-message_premium-only' ) : $this->get_text_inline( 'Your license was successfully deactivated, you are back to the %s plan.', 'license-deactivation-message' ), $this->get_plan_title() ), $this->get_text_inline( 'O.K', 'ok' ) ); } $this->_admin_notices->remove_sticky( array( 'plan_upgraded', 'license_activated', ) ); } /** * Site plan downgrade. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @return object * * @uses FS_Api */ private function _downgrade_site() { $this->_logger->entrance(); $deactivate_license = fs_request_get_bool( 'deactivate_license' ); $api = $this->get_api_site_scope(); $site = $api->call( 'downgrade.json', 'put', array( 'deactivate_license' => $deactivate_license ) ); $plan_downgraded = false; $plan = false; if ( $this->is_api_result_entity( $site ) ) { $prev_plan_id = $this->_site->plan_id; // Update new site plan id. $this->_site->plan_id = $site->plan_id; $plan = $this->get_plan(); $subscription = $this->_sync_site_subscription( $this->_license ); // Plan downgraded if plan was changed or subscription was cancelled. $plan_downgraded = ( $plan instanceof FS_Plugin_Plan && $prev_plan_id != $plan->id ) || ( is_object( $subscription ) && ! isset( $subscription->error ) && ! $subscription->is_active() ); } else { // handle different error cases. $this->handle_license_deactivation_result( $site, $this->get_text_x_inline( 'Hmm', 'something somebody says when they are thinking about what you have just said.', 'hmm' ) . '...' ); } if ( ! $plan_downgraded ) { return (object) array( 'error' => (object) array( 'message' => $this->get_text_inline( 'Seems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.', 'subscription-cancellation-failure-message' ) ) ); } // Remove previous sticky message about upgrade (if exist). $this->_admin_notices->remove_sticky( 'plan_upgraded' ); $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Your subscription was successfully cancelled. Your %s plan license will expire in %s.', 'plan-x-downgraded-message' ), $plan->title, human_time_diff( time(), strtotime( $this->_license->expiration ) ) ) ); // Store site updates. $this->_store_site(); if ( $deactivate_license && ! FS_Plugin_License::is_valid_id( $site->license_id ) ) { if ( $this->_site->is_localhost() ) { $this->_license->activated_local = max( 0, $this->_license->activated_local - 1 ); } else { $this->_license->activated = max( 0, $this->_license->activated - 1 ); } // Handle successful license deactivation result. $this->handle_license_deactivation_result( $this->_license ); } return $site; } /** * @author Vova Feldman (@svovaf) * @since 1.1.8.1 * * @param bool|string $plan_name * * @return bool If trial was successfully started. */ function start_trial( $plan_name = false ) { $this->_logger->entrance(); // Alias. $oops_text = $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...'; if ( $this->is_trial() ) { // Already in trial mode. $this->_admin_notices->add( sprintf( $this->get_text_inline( 'You are already running the %s in a trial mode.', 'in-trial-mode' ), $this->_module_type ), $oops_text, 'error' ); return false; } if ( $this->_site->is_trial_utilized() ) { // Trial was already utilized. $this->_admin_notices->add( $this->get_text_inline( 'You already utilized a trial before.', 'trial-utilized' ), $oops_text, 'error' ); return false; } if ( false !== $plan_name ) { $plan = $this->get_plan_by_name( $plan_name ); if ( false === $plan ) { // Plan doesn't exist. $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Plan %s do not exist, therefore, can\'t start a trial.', 'trial-plan-x-not-exist' ), $plan_name ), $oops_text, 'error' ); return false; } if ( ! $plan->has_trial() ) { // Plan doesn't exist. $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Plan %s does not support a trial period.', 'plan-x-no-trial' ), $plan_name ), $oops_text, 'error' ); return false; } } else { if ( ! $this->has_trial_plan() ) { // None of the plans have a trial. $this->_admin_notices->add( sprintf( $this->get_text_inline( 'None of the %s\'s plans supports a trial period.', 'no-trials' ), $this->_module_type ), $oops_text, 'error' ); return false; } $plans_with_trial = FS_Plan_Manager::instance()->get_trial_plans( $this->_plans ); $plan = $plans_with_trial[0]; } $api = $this->get_api_site_scope(); $plan = $api->call( "plans/{$plan->id}/trials.json", 'post' ); if ( ! $this->is_api_result_entity( $plan ) ) { // Some API error while trying to start the trial. $this->_admin_notices->add( $this->get_api_error_message( $plan ), $oops_text, 'error' ); return false; } // Sync license. $this->_sync_license(); return $this->is_trial(); } /** * Cancel site trial. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return object * * @uses FS_Api */ private function _cancel_trial() { $this->_logger->entrance(); if ( ! $this->is_trial() ) { return (object) array( 'error' => (object) array( 'message' => $this->get_text_inline( 'It looks like you are not in trial mode anymore so there\'s nothing to cancel :)', 'trial-cancel-no-trial-message' ) ) ); } $trial_plan = $this->get_trial_plan(); $api = $this->get_api_site_scope(); $site = $api->call( 'trials.json', 'delete' ); $trial_cancelled = false; if ( $this->is_api_result_entity( $site ) ) { $prev_trial_ends = $this->_site->trial_ends; if ( $this->is_paid_trial() ) { $this->_license->expiration = $site->trial_ends; $this->_license->is_cancelled = true; $this->_update_site_license( $this->_license ); $this->_store_licenses(); // Clear subscription reference. $this->_sync_site_subscription( null ); } // Update site info. $this->_site = new FS_Site( $site ); $trial_cancelled = ( $prev_trial_ends != $site->trial_ends ); } else { // @todo handle different error cases. } if ( ! $trial_cancelled ) { return (object) array( 'error' => (object) array( 'message' => $this->get_text_inline( 'Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.', 'trial-cancel-failure-message' ) ) ); } // Remove previous sticky messages about upgrade or trial (if exist). $this->_admin_notices->remove_sticky( array( 'trial_started', 'trial_promotion', 'plan_upgraded', ) ); // Store site updates. $this->_store_site(); if ( ! $this->is_addon() || ! $this->deactivate_premium_only_addon_without_license( true ) ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Your %s free trial was successfully cancelled.', 'trial-cancel-message' ), $trial_plan->title ) ); } return $site; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param bool|number $plugin_id * * @return bool */ private function _is_addon_id( $plugin_id ) { return is_numeric( $plugin_id ) && ( $this->get_id() != $plugin_id ); } /** * Check if user eligible to download premium version updates. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return bool */ private function _can_download_premium() { return $this->has_any_active_valid_license() || ( $this->is_trial() && ! $this->get_trial_plan()->is_free() ); } /** * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param bool|number $addon_id * @param string $type "json" or "zip" * * @return string */ private function _get_latest_version_endpoint( $addon_id = false, $type = 'json' ) { $is_addon = $this->_is_addon_id( $addon_id ); $is_premium = null; if ( ! $is_addon ) { $is_premium = ( $this->is_premium() || $this->_can_download_premium() ); } else if ( $this->is_addon_activated( $addon_id ) ) { $fs_addon = self::get_instance_by_id( $addon_id ); $is_premium = ( $fs_addon->is_premium() || $fs_addon->_can_download_premium() ); } // If add-on, then append add-on ID. $endpoint = ( $is_addon ? "/addons/$addon_id" : '' ) . '/updates/latest.' . $type; // If add-on and not yet activated, try to fetch based on server licensing. if ( is_bool( $is_premium ) ) { $endpoint = add_query_arg( 'is_premium', json_encode( $is_premium ), $endpoint ); } if ( $this->has_secret_key() ) { $endpoint = add_query_arg( 'type', 'all', $endpoint ); } else if ( is_object( $this->_site ) && $this->_site->is_beta() ) { $endpoint = add_query_arg( 'type', 'beta', $endpoint ); } return $endpoint; } /** * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param bool|number $addon_id * @param bool $flush Since 1.1.7.3 * @param int $expiration Since 1.2.2.7 * @param bool|string $newer_than Since 2.2.1 * @param bool|string $fetch_readme Since 2.2.1 * * @return object|false Plugin latest tag info. */ function _fetch_latest_version( $addon_id = false, $flush = true, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $newer_than = false, $fetch_readme = true ) { $this->_logger->entrance(); if ( $this->is_unresolved_clone( true ) ) { return false; } $switch_to_blog_id = null; /** * @since 1.1.7.3 Check for plugin updates from Freemius only if opted-in. * @since 1.1.7.4 Also check updates for add-ons. */ if ( ( ! $this->is_registered() || ! FS_Permission_Manager::instance( $this )->is_essentials_tracking_allowed() ) && ! $this->_is_addon_id( $addon_id ) ) { if ( ! is_multisite() ) { return false; } $installs_map = $this->get_blog_install_map(); foreach ( $installs_map as $blog_id => $install ) { if ( ! FS_Permission_Manager::instance( $this )->is_essentials_tracking_allowed( $blog_id ) ) { continue; } /** * @var FS_Site $install */ if ( $install->is_trial() ) { $switch_to_blog_id = $blog_id; break; } if ( FS_Plugin_License::is_valid_id( $install->license_id ) ) { $license = $this->get_license_by_id( $install->license_id ); if ( is_object( $license ) && $license->is_features_enabled() ) { $switch_to_blog_id = $blog_id; break; } } } if ( is_null( $switch_to_blog_id ) ) { return false; } } $current_blog_id = is_numeric( $switch_to_blog_id ) ? get_current_blog_id() : 0; if ( is_numeric( $switch_to_blog_id ) ) { $this->switch_to_blog( $switch_to_blog_id ); } $latest_version_endpoint = $this->_get_latest_version_endpoint( $addon_id, 'json' ); if ( ! empty( $newer_than ) ) { $latest_version_endpoint = add_query_arg( 'newer_than', $newer_than, $latest_version_endpoint ); } if ( true === $fetch_readme ) { $latest_version_endpoint = add_query_arg( 'readme', 'true', $latest_version_endpoint ); } $tag = $this->get_api_site_or_plugin_scope()->get( $latest_version_endpoint, $flush, $expiration ); if ( is_numeric( $switch_to_blog_id ) ) { $this->switch_to_blog( $current_blog_id ); } $latest_version = ( is_object( $tag ) && isset( $tag->version ) ) ? $tag->version : 'couldn\'t get'; $this->_logger->departure( 'Latest version ' . $latest_version ); return ( is_object( $tag ) && isset( $tag->version ) ) ? $tag : false; } #---------------------------------------------------------------------------------- #region Download Plugin #---------------------------------------------------------------------------------- /** * Download latest plugin version, based on plan. * * Not like _download_latest(), this will redirect the page * to secure download url to prevent dual download (from FS to WP server, * and then from WP server to the client / browser). * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param bool|number $plugin_id * * @uses FS_Api * @uses wp_redirect() */ private function download_latest_directly( $plugin_id = false ) { $this->_logger->entrance(); wp_redirect( $this->get_latest_download_api_url( $plugin_id ) ); } /** * Get latest plugin FS API download URL. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param bool|number $plugin_id * * @return string */ private function get_latest_download_api_url( $plugin_id = false ) { $this->_logger->entrance(); $download_api_url = $this->get_api_site_scope()->get_signed_url( $this->_get_latest_version_endpoint( $plugin_id, 'zip' ) ); return str_replace( 'http:', 'https:', $download_api_url ); } /** * Get payment invoice URL. * * @author Vova Feldman (@svovaf) * @since 1.2.0 * * @param bool|number $payment_id * * @return string */ function _get_invoice_api_url( $payment_id = false ) { $this->_logger->entrance(); $url = $this->get_api_user_scope()->get_signed_url( "/payments/{$payment_id}/invoice.pdf" ); if ( ! fs_starts_with( $url, 'https://' ) ) { // Always use HTTPS for invoices. $url = 'https' . substr( $url, 4 ); } return $url; } /** * Get latest plugin download link. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string $label * @param bool|number $plugin_id * * @return string */ private function get_latest_download_link( $label, $plugin_id = false ) { return sprintf( '%s', $this->_get_latest_download_local_url( $plugin_id ), $label ); } /** * Get latest plugin download local URL. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param bool|number $plugin_id * * @return string */ function _get_latest_download_local_url( $plugin_id = false ) { // Add timestamp to protect from caching. $params = array( 'ts' => WP_FS__SCRIPT_START_TIME ); if ( ! empty( $plugin_id ) ) { $params['plugin_id'] = $plugin_id; } else if ( $this->is_addon() ) { $params['plugin_id'] = $this->get_id(); } $fs = $this->is_addon() ? $this->get_parent_instance() : $this; return $this->apply_filters( 'download_latest_url', $fs->get_account_url( 'download_latest', $params ) ); } #endregion Download Plugin ------------------------------------------------------------------ /** * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @uses FS_Api * * @param bool $background Hints the method if it's a background updates check. If false, it means that * was initiated by the admin. * @param bool|number $plugin_id * @param bool $flush Since 1.1.7.3 * @param int $expiration Since 1.2.2.7 * @param bool|string $newer_than Since 2.2.1 */ private function check_updates( $background = false, $plugin_id = false, $flush = true, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $newer_than = false ) { $this->_logger->entrance(); // Check if there's a newer version for download. $new_version = $this->_fetch_newer_version( $plugin_id, $flush, $expiration, $newer_than ); $update = null; if ( is_object( $new_version ) ) { $update = new FS_Plugin_Tag( $new_version ); if ( ! $background ) { $this->_admin_notices->add( sprintf( /* translators: %s: Numeric version number (e.g. '2.1.9' */ $this->get_text_inline( 'Version %s was released.', 'version-x-released' ) . ' ' . $this->get_text_inline( 'Please download %s.', 'please-download-x' ), $update->version, sprintf( '%s', $this->get_account_url( 'download_latest' ), sprintf( /* translators: %s: plan name (e.g. latest "Professional" version) */ $this->get_text_inline( 'the latest %s version here', 'latest-x-version' ), $this->get_plan_title() ) ) ), $this->get_text_inline( 'New', 'new' ) . '!' ); } } else if ( false === $new_version && ! $background ) { $this->_admin_notices->add( $this->get_text_inline( 'Seems like you got the latest release.', 'you-have-latest' ), $this->get_text_inline( 'You are all good!', 'you-are-good' ) ); } $this->_store_update( $update, true, $plugin_id ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param bool $flush Since 1.1.7.3 add 24 hour cache by default. * * @return FS_Plugin[] * * @uses FS_Api */ private function sync_addons( $flush = false ) { $this->_logger->entrance(); $api = $this->get_api_site_or_plugin_scope(); $path = $this->add_show_pending( '/addons.json?enriched=true&count=50' ); /** * @since 1.2.1 * * If there's a cached version of the add-ons and not asking * for a flush, just use the currently stored add-ons. */ if ( ! $flush && $api->is_cached( $path ) ) { $addons = self::get_all_addons(); return isset( $addons[ $this->_plugin->id ] ) ? $addons[ $this->_plugin->id ] : array(); } $result = $api->get( $path, $flush ); $addons = array(); if ( $this->is_api_result_object( $result, 'plugins' ) && is_array( $result->plugins ) ) { for ( $i = 0, $len = count( $result->plugins ); $i < $len; $i ++ ) { $addons[ $i ] = new FS_Plugin( $result->plugins[ $i ] ); } $this->_store_addons( $addons, true ); } return $addons; } /** * Handle user email update. * * @author Vova Feldman (@svovaf) * @since 1.0.3 * @uses FS_Api * * @param string $new_email * * @return object */ private function update_email( $new_email ) { $this->_logger->entrance(); $api = $this->get_api_user_scope(); $user = $api->call( "?plugin_id={$this->_plugin->id}&fields=id,email,is_verified", 'put', array( 'email' => $new_email, 'after_email_confirm_url' => $this->_get_admin_page_url( 'account', array( 'fs_action' => 'sync_user' ) ), ) ); if ( ! isset( $user->error ) ) { $this->_user->email = $user->email; $this->_user->is_verified = $user->is_verified; $this->_store_user(); } else { // handle different error cases. } return $user; } #---------------------------------------------------------------------------------- #region API Error Handling #---------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 1.1.1 * * @param mixed $result * * @return bool Is API result contains an error. */ private function is_api_error( $result ) { return FS_Api::is_api_error( $result ); } /** * Checks if given API result is a non-empty and not an error object. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $result * @param string|null $required_property Optional property we want to verify that is set. * * @return bool */ function is_api_result_object( $result, $required_property = null ) { return FS_Api::is_api_result_object( $result, $required_property ); } /** * Checks if given API result is a non-empty entity object with non-empty ID. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $result * * @return bool */ private function is_api_result_entity( $result ) { return FS_Api::is_api_result_entity( $result ); } #endregion /** * Make sure a given argument is an array of a specific type. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $array * @param string $class * * @return bool */ private function is_array_instanceof( $array, $class ) { return ( is_array( $array ) && ( empty( $array ) || $array[0] instanceof $class ) ); } /** * Start install ownership change. * * @author Vova Feldman (@svovaf) * @since 1.1.1 * @uses FS_Api * * @param string $candidate_email * @param string $transfer_type * * @return bool Is ownership change successfully initiated. */ private function init_change_owner( $candidate_email, $transfer_type ) { $this->_logger->entrance(); $installs_info_by_slug_map = $this->get_parent_and_addons_installs_info(); $install_ids = array(); foreach ( $installs_info_by_slug_map as $slug => $install_info ) { $install = $install_info['install']; if ( $this->_user->id != $install->user_id ) { // Skip add-on installs that are not owned by the parent product's install's owner. continue; } $install_ids[ $slug ] = $install->id; } $api = $this->get_api_site_scope(); $result = $api->call( "/users/{$this->_user->id}.json", 'put', array( 'email' => $candidate_email, 'transfer_type' => $transfer_type, 'install_ids' => implode( ',', array_values( $install_ids ) ), 'after_confirm_url' => $this->_get_admin_page_url( 'account', array( 'fs_action' => 'change_owner' ) ), ) ); return ! $this->is_api_error( $result ); } /** * Handle install ownership change. * * @author Vova Feldman (@svovaf) * @since 1.1.1 * @uses FS_Api * * @return bool Was ownership change successfully complete. */ private function complete_change_owner() { $this->_logger->entrance(); $install_ids = fs_request_get( 'install_ids' ); if ( ! empty( $install_ids ) ) { $install_ids = explode( ',', $install_ids ); foreach ( $install_ids as $key => $install_id ) { if ( ! FS_Site::is_valid_id( $install_id ) ) { unset( $install_ids[ $key ] ); } } } if ( ! is_array( $install_ids ) ) { $install_ids = array(); } $user = new FS_User(); $user->id = fs_request_get( 'user_id' ); $user->public_key = fs_request_get( 'user_public_key' ); $user->secret_key = fs_request_get( 'user_secret_key' ); $prev_user = $this->_user; $this->_user = $user; $result = $this->get_api_user_scope( true )->get( "/installs.json?install_ids=" . implode( ',', $install_ids ) ); $current_blog_sites = self::get_all_sites( $this->get_module_type() ); if ( $this->is_api_result_object( $result, 'installs' ) ) { $site_id_slug_map = array(); foreach ( $current_blog_sites as $slug => $site ) { $site_id_slug_map[ $site->id ] = $slug; } foreach ( $result->installs as $install ) { $site = new FS_Site( $install ); if ( ! isset( $site_id_slug_map[ $install->id ] ) ) { continue; } $current_blog_sites[ $site_id_slug_map[ $install->id ] ] = clone $site; if ( $this->_site->id == $site->id ) { $this->_site = $site; } } } // Validate install's user and given user. if ( $user->id != $this->_site->user_id ) { $this->_user = $prev_user; return false; } $this->set_account_option( 'sites', $current_blog_sites, true ); // Fetch new user information. $user_result = $this->get_api_user_scope( true )->get(); $user = new FS_User( $user_result ); $this->_user = $user; $this->_set_account( $user, $this->_site ); $remove_user = true; $all_modules_sites = self::get_all_modules_sites(); foreach ( $all_modules_sites as $sites_by_module_type ) { foreach ( $sites_by_module_type as $sites_by_slug ) { foreach ( $sites_by_slug as $site ) { if ( $prev_user->id == $site->user_id ) { $remove_user = false; break; } } if ( ! $remove_user ) { break; } } if ( ! $remove_user ) { break; } } if ( $remove_user ) { $users = self::get_all_users(); if ( isset( $users[ $prev_user->id ] ) ) { unset( $users[ $prev_user->id ] ); } else { // If the prev user wasn't found by the key, iterate over the users collection. foreach ( $users as $key => $user ) { if ( $user->id == $prev_user->id ) { unset( $users[ $key ] ); break; } } } $this->set_account_option( 'users', $users, true ); } return true; } /** * Completes ownership change by license. * * @author Leo Fajardo (@leorw) * @since 2.3.2 * * @param number $user_id * @param array[string]number $install_ids_by_slug_map * */ private function complete_ownership_change_by_license( $user_id, $install_ids_by_slug_map ) { $this->_logger->entrance(); $this->sync_user_by_current_install( $user_id ); $result = $this->get_api_user_scope( true )->get( "/installs.json?install_ids=" . implode( ',', $install_ids_by_slug_map ) ); if ( $this->is_api_result_object( $result, 'installs' ) ) { $sites = self::get_all_sites( $this->get_module_type() ); $install_ids_by_slug_map = array_flip( $install_ids_by_slug_map ); foreach ( $result->installs as $install ) { $site = new FS_Site( $install ); $sites[ $install_ids_by_slug_map[ $site->id ] ] = clone $site; } $this->set_account_option( 'sites', $sites, true ); } } /** * Handle user name update. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * @uses FS_Api * * @return object */ private function update_user_name() { $this->_logger->entrance(); $name = fs_request_get( 'fs_user_name_' . $this->get_unique_affix(), '' ); $api = $this->get_api_user_scope(); $user = $api->call( "?plugin_id={$this->_plugin->id}&fields=id,first,last", 'put', array( 'name' => $name, ) ); if ( ! isset( $user->error ) ) { $this->_user->first = $user->first; $this->_user->last = $user->last; $this->_store_user(); } else { // handle different error cases. } return $user; } /** * Verify user email. * * @author Vova Feldman (@svovaf) * @since 1.0.3 * @uses FS_Api */ private function verify_email() { $this->_handle_account_user_sync(); if ( $this->_user->is_verified() ) { return; } $api = $this->get_api_site_scope(); $result = $api->call( "/users/{$this->_user->id}/verify.json", 'put', array( 'after_email_confirm_url' => $this->_get_admin_page_url( 'account', array( 'fs_action' => 'sync_user' ) ) ) ); if ( ! isset( $result->error ) ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Verification mail was just sent to %s. If you can\'t find it after 5 min, please check your spam box.', 'verification-email-sent-message' ), sprintf( '%2$s', esc_url( $this->_user->email ), $this->_user->email ) ) ); } else { // handle different error cases. } } /** * @author Vova Feldman (@svovaf) * @since 1.1.2 * * @param array $params * @param bool|null $network * * @return string */ function get_activation_url( $params = array(), $network = null ) { if ( $this->is_addon() && $this->has_free_plan() ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.1.7 Add-on's activation is the parent's module activation. */ return $this->get_parent_instance()->get_activation_url( $params ); } return $this->apply_filters( 'connect_url', $this->_get_admin_page_url( '', $params, $network ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param array $params * * @return string */ function get_reconnect_url( $params = array() ) { $params['fs_action'] = 'reset_anonymous_mode'; $params['fs_unique_affix'] = $this->get_unique_affix(); return $this->get_activation_url( $params ); } /** * Get the URL of the page that should be loaded after the user connect * or skip in the opt-in screen. * * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param string $filter Filter name. * @param array $params Since 1.2.2.7 * @param bool|null $network * * @return string */ function get_after_activation_url( $filter, $params = array(), $network = null ) { if ( $this->show_opt_in_on_themes_page() && ( fs_request_has( 'pending_activation' ) || // For cases when the first time path is set, even though it's a WP.org theme. fs_request_get_bool( $this->get_unique_affix() . '_show_optin' ) ) ) { $first_time_path = ''; } else { $first_time_path = $this->_menu->get_first_time_path( fs_is_network_admin() && $this->_is_network_active ); } if ( $this->_is_network_active && fs_is_network_admin() && ! $this->_menu->has_network_menu() && $this->is_network_registered() ) { $target_url = $this->get_account_url(); } else { // Default plugin's page. $target_url = $this->_get_admin_page_url( '', array(), $network ); } return add_query_arg( $params, $this->apply_filters( $filter, empty( $first_time_path ) ? $target_url : $first_time_path ) ); } /** * Handle account page updates / edits / actions. * * @author Vova Feldman (@svovaf) * @since 1.0.2 * */ private function _handle_account_edits() { if ( ! $this->is_user_admin() ) { return; } $action = fs_get_action(); if ( empty( $action ) ) { return; } $plugin_id = fs_request_get( 'plugin_id', $this->get_id() ); $install_id = fs_request_get( 'install_id', '' ); // Alias. $oops_text = $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...'; $is_network_action = $this->is_network_level_action(); $blog_id = $this->is_network_level_site_specific_action(); $is_parent_plugin_action = ( $plugin_id == $this->get_id() ); if ( is_numeric( $blog_id ) ) { $this->switch_to_blog( $blog_id ); } else { $blog_id = ''; } switch ( $action ) { case 'opt_in': check_admin_referer( trim( "{$action}:{$blog_id}:{$install_id}", ':' ) ); if ( $is_parent_plugin_action ) { if ( $is_network_action && ! empty( $blog_id ) ) { if ( ! $this->is_registered() ) { $this->install_with_user( $this->get_network_user(), false, false, false, false ); $this->_admin_notices->add( $this->get_text_inline( 'Site successfully opted in.', 'successful-opt-in' ), $this->get_text_inline( 'Awesome', 'awesome' ) ); } } } break; case 'toggle_tracking': check_admin_referer( trim( "{$action}:{$blog_id}:{$install_id}", ':' ) ); if ( $is_parent_plugin_action ) { if ( $is_network_action && ! empty( $blog_id ) ) { if ( $this->is_registered( true ) ) { if ( $this->is_tracking_prohibited( $blog_id ) ) { if ( $this->toggle_site_tracking( true, $blog_id ) ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Sharing diagnostic data with %s helps to provide functionality that\'s more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to.', 'opt-out-message-appreciation' ), "{$this->get_plugin_title()}" ), $this->get_text_inline( 'Thank you!', 'thank-you' ) ); } } else { if ( $this->toggle_site_tracking( false, $blog_id ) ) { $install = $this->get_install_by_blog_id( $blog_id ); $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Diagnostic data will no longer be sent from %s to %s.', 'opted-out-successfully' ), self::get_unfiltered_site_url( $blog_id, true ), "{$this->get_plugin_title()}" ) ); } } } } } break; case 'delete_account': check_admin_referer( trim( "{$action}:{$blog_id}:{$install_id}", ':' ) ); $is_network_deletion = $is_network_action && empty( $blog_id ); if ( $is_parent_plugin_action ) { // Delete add-on installs if have any. $installed_addons = $this->get_installed_addons(); foreach ( $installed_addons as $fs_addon ) { if ( $is_network_deletion ) { $fs_addon->delete_network_account_event(); } else { $fs_addon->delete_account_event(); } } if ( $is_network_deletion ) { $this->delete_network_account_event(); } else { $this->delete_account_event(); } // Clear user and site. $this->_site = null; $this->_user = null; $this->maybe_set_slug_and_network_menu_exists_flag(); fs_redirect( $this->get_activation_url() ); } else { if ( $this->is_addon_activated( $plugin_id ) ) { $fs_addon = self::get_instance_by_id( $plugin_id ); if ( $is_network_deletion ) { $fs_addon->delete_network_account_event(); } else { $fs_addon->delete_account_event(); } fs_redirect( $this->_get_admin_page_url( 'account' ) ); } } return; case 'downgrade_account': if ( is_numeric( $blog_id ) ) { check_admin_referer( trim( "{$action}:{$blog_id}:{$install_id}", ':' ) ); } else { check_admin_referer( $action ); } $switch_to_network_install_blog_after_cancellation = ( is_numeric( $blog_id ) && $plugin_id == $this->get_id() && ! $this->is_trial() ); $result = $this->cancel_subscription_or_trial( $plugin_id ); if ( $this->is_api_error( $result ) ) { $this->_admin_notices->add( $result->error->message, $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...', 'error' ); } if ( $switch_to_network_install_blog_after_cancellation ) { $this->switch_to_blog( $this->_storage->network_install_blog_id ); } return; case 'activate_license': check_admin_referer( trim( "{$action}:{$blog_id}:{$install_id}", ':' ) ); $fs = $this; if ( $plugin_id != $this->get_id() ) { $fs = $this->is_addon_activated( $plugin_id ) ? self::get_instance_by_id( $plugin_id ) : null; } if ( is_object( $fs ) ) { $fs->_activate_license(); /** * Remove the product ID from `$_REQUEST` so that the syncing of the license for the other products will work properly. * * @author Leo Fajardo (@leorw) * @since 2.4.0 */ unset( $_REQUEST['plugin_id'] ); if ( $this->is_bundle_license_auto_activation_enabled() ) { $fs->maybe_activate_bundle_license( null, array(), is_numeric( $blog_id ) ? $blog_id : 0 ); } } return; case 'deactivate_license': check_admin_referer( trim( "{$action}:{$blog_id}:{$install_id}", ':' ) ); if ( $plugin_id == $this->get_id() ) { $this->_deactivate_license(); if ( $this->is_only_premium() ) { // Clear user and site. $this->_site = null; $this->_user = null; if ( ! $is_network_action ) { fs_redirect( $this->get_activation_url() ); } else if ( is_numeric( $blog_id ) ) { $this->switch_to_blog( $this->_storage->network_install_blog_id ); } } } else { if ( $this->is_addon_activated( $plugin_id ) ) { $fs_addon = self::get_instance_by_id( $plugin_id ); $fs_addon->_deactivate_license(); } } return; case 'check_updates': check_admin_referer( $action ); $this->check_updates(); return; case 'change_owner': $state = fs_request_get( 'state', 'init' ); switch ( $state ) { case 'init': $candidate_email = fs_request_get( 'candidate_email' ); $transfer_type = fs_request_get( 'transfer_type' ); if ( $this->init_change_owner( $candidate_email, $transfer_type ) ) { if ( 'transfer' === $transfer_type ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.', 'change-owner-request-sent-x-transfer' ), '' . $this->_user->email . '' ) ); } else { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.', 'change-owner-request-sent-x' ), '' . $this->_user->email . '' ) ); } } break; case 'owner_confirmed': $candidate_email = fs_request_get( 'candidate_email', '' ); $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Thanks for confirming the ownership change. An email was just sent to %s for final approval.', 'change-owner-request_owner-confirmed' ), '' . $candidate_email . '' ) ); break; case 'candidate_confirmed': if ( $this->complete_change_owner() ) { $this->_admin_notices->add_sticky( sprintf( $this->get_text_inline( '%s is the new owner of the account.', 'change-owner-request_candidate-confirmed' ), '' . $this->_user->email . '' ), 'ownership_changed', $this->get_text_x_inline( 'Congrats', 'as congratulations', 'congrats' ) . '!' ); } else { // @todo Handle failed ownership change message. } break; } return; case 'update_user_name': check_admin_referer( 'update_user_name' ); $result = $this->update_user_name(); if ( isset( $result->error ) ) { $this->_admin_notices->add( $this->get_text_inline( 'Please provide your full name.', 'name-update-failed-message' ), $oops_text, 'error' ); } else { $this->_admin_notices->add( $this->get_text_inline( 'Your name was successfully updated.', 'name-updated-message' ) ); } return; #region Actions that might be called from external links (e.g. email) case 'cancel_trial': $result = $this->cancel_subscription_or_trial( $plugin_id ); if ( $this->is_api_error( $result ) ) { $this->_admin_notices->add( $result->error->message, $this->get_text_x_inline( 'Oops', 'exclamation', 'oops' ) . '...', 'error' ); } return; case 'verify_email': $this->verify_email(); return; case 'sync_user': $this->_handle_account_user_sync(); return; case $this->get_unique_affix() . '_sync_license': $this->_sync_license(); return; case 'download_latest': $this->download_latest_directly( $plugin_id ); return; #endregion } if ( WP_FS__IS_POST_REQUEST ) { $properties = array( 'site_secret_key', 'site_id', 'site_public_key' ); foreach ( $properties as $p ) { if ( 'update_' . $p === $action ) { check_admin_referer( $action ); $this->_logger->log( $action ); $site_property = substr( $p, strlen( 'site_' ) ); $site_property_value = fs_request_get( 'fs_' . $p . '_' . $this->get_unique_affix(), '' ); $this->get_site()->{$site_property} = $site_property_value; // Store account after modification. $this->_store_site(); $this->do_action( 'account_property_edit', 'site', $site_property, $site_property_value ); $this->_admin_notices->add( sprintf( /* translators: %s: User's account property (e.g. email address, name) */ $this->get_text_inline( 'You have successfully updated your %s.', 'x-updated' ), '' . str_replace( '_', ' ', $p ) . '' ) ); return; } } } } /** * Account page resources load. * * @author Vova Feldman (@svovaf) * @since 1.0.6 */ function _account_page_load() { $this->_logger->entrance(); $this->_logger->info( var_export( $_REQUEST, true ) ); fs_enqueue_local_style( 'fs_account', '/admin/account.css' ); if ( $this->has_addons() ) { wp_enqueue_script( 'plugin-install' ); add_thickbox(); function fs_addons_body_class( $classes ) { $classes .= ' plugins-php'; return $classes; } add_filter( 'admin_body_class', 'fs_addons_body_class' ); } if ( $this->has_paid_plan() && ! $this->has_any_license() && ! $this->is_sync_executed() && $this->is_tracking_allowed() ) { /** * If no licenses found and no sync job was executed during the last 24 hours, * just execute the sync job right away (blocking execution). * * @since 1.1.7.3 */ $this->run_manual_sync(); } $this->_handle_account_edits(); if ( is_object( $this->_license ) && $this->_license->user_id == $this->_user->id && ! $this->is_whitelabeled( true ) ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( "Is this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.", 'license_not_whitelabeled' ), sprintf( '%s', $this->get_text_inline( 'Click here', 'click-here' ) ) ), '', 'success', false, 'license_not_whitelabeled' ); } $this->do_action( 'account_page_load_before_departure' ); } /** * Renders the "Affiliation" page. * * @author Leo Fajardo (@leorw) * @since 1.2.3 */ function _affiliation_page_render() { $this->_logger->entrance(); $this->fetch_affiliate_and_terms(); fs_enqueue_local_style( 'fs_affiliation', '/admin/affiliation.css' ); $is_bundle_context = $this->has_bundle_context(); $plugin_title = $this->get_plugin_title(); if ( $is_bundle_context ) { $plugin_title = $this->plugin_affiliate_terms->plugin_title; // Add the suffix "Bundle" only if the word is not present in the title itself. if ( false === mb_stripos( $plugin_title, fs_text_inline( 'Bundle', 'bundle' ) ) ) { $plugin_title = $this->apply_filters( 'formatted_bundle_title', $plugin_title . ' ' . fs_text_inline( 'Bundle', 'bundle' ) ); } } $vars = array( 'id' => $this->_module_id, 'plugin_title' => $plugin_title, ); echo $this->apply_filters( "/forms/affiliation.php", fs_get_template( '/forms/affiliation.php', $vars ) ); } /** * Render account page. * * @author Vova Feldman (@svovaf) * @since 1.0.0 */ function _account_page_render() { $this->_logger->entrance(); $template = 'account.php'; $vars = array( 'id' => $this->_module_id ); /** * Added filter to the template to allow developers wrapping the template * in custom HTML (e.g. within a wizard/tabs). * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 */ echo $this->apply_filters( "templates/{$template}", fs_get_template( $template, $vars ) ); } /** * Render account connect page. * * @author Vova Feldman (@svovaf) * @since 1.0.7 */ function _connect_page_render() { $this->_logger->entrance(); $vars = array( 'id' => $this->_module_id ); /** * Added filter to the template to allow developers wrapping the template * in custom HTML (e.g. within a wizard/tabs). * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 */ echo $this->apply_filters( 'templates/connect.php', fs_get_template( 'connect.php', $vars ) ); } /** * Load required resources before add-ons page render. * * @author Vova Feldman (@svovaf) * @since 1.0.6 */ function _addons_page_load() { $this->_logger->entrance(); fs_enqueue_local_style( 'fs_addons', '/admin/add-ons.css' ); wp_enqueue_script( 'plugin-install' ); add_thickbox(); function fs_addons_body_class( $classes ) { $classes .= ' plugins-php'; return $classes; } add_filter( 'admin_body_class', 'fs_addons_body_class' ); if ( ! $this->is_registered() && $this->is_org_repo_compliant() ) { $this->_admin_notices->add( sprintf( $this->get_text_inline( 'Just letting you know that the add-ons information of %s is being pulled from an external server.', 'addons-info-external-message' ), '' . $this->get_plugin_name() . '' ), $this->get_text_x_inline( 'Heads up', 'advance notice of something that will need attention.', 'heads-up' ), 'update-nag' ); } } /** * Render add-ons page. * * @author Vova Feldman (@svovaf) * @since 1.0.6 */ function _addons_page_render() { $this->_logger->entrance(); $vars = array( 'id' => $this->_module_id ); /** * Added filter to the template to allow developers wrapping the template * in custom HTML (e.g. within a wizard/tabs). * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 */ echo $this->apply_filters( 'templates/add-ons.php', fs_get_template( 'add-ons.php', $vars ) ); } /* Pricing & Upgrade ------------------------------------------------------------------------------------------------------------------*/ /** * Render pricing page. * * @author Vova Feldman (@svovaf) * @since 1.0.0 */ function _pricing_page_render() { $this->_logger->entrance(); $vars = array( 'id' => $this->_module_id ); if ( 'true' === fs_request_get( 'checkout', false ) ) { echo $this->apply_filters( 'templates/checkout.php', fs_get_template( 'checkout.php', $vars ) ); } else { echo $this->apply_filters( 'templates/pricing.php', fs_get_template( 'pricing.php', $vars ) ); } } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 */ function _maybe_add_pricing_ajax_handler() { if ( ! $this->should_use_external_pricing() ) { $this->add_ajax_action( 'pricing_ajax_action', array( &$this, '_fs_pricing_ajax_action_handler' ) ); } } /** * @author Leo Fajardo (@leorw) * @since 2.3.1 */ function _fs_pricing_ajax_action_handler() { $this->check_ajax_referer( 'pricing_ajax_action' ); $result = null; $pricing_action = fs_request_get( 'pricing_action' ); switch ( $pricing_action ) { case 'fetch_pricing_data': $params = array( 'is_enriched' => true, 'trial' => fs_request_get_bool( 'trial' ), 'sandbox' => fs_request_get( 'sandbox' ), 's_ctx_type' => fs_request_get( 's_ctx_type' ), 's_ctx_id' => fs_request_get( 's_ctx_id' ), 's_ctx_ts' => fs_request_get( 's_ctx_ts' ), 's_ctx_secure' => fs_request_get( 's_ctx_secure' ), ); $bundle_id = $this->get_bundle_id(); $bundle_public_key = $this->get_bundle_public_key(); $has_bundle_context = ( FS_Plugin::is_valid_id( $bundle_id ) && ! empty( $bundle_public_key ) ); if ( ! $has_bundle_context ) { $api = $this->get_api_plugin_scope(); } else { $api = FS_Api::instance( $bundle_id, 'plugin', $bundle_id, $bundle_public_key, ! $this->is_live(), false, $this->get_sdk_version() ); $params['plugin_id'] = $this->get_id(); $params['plugin_public_key'] = $this->get_public_key(); } $result = $api->get( 'pricing.json?' . http_build_query( $params ) ); break; case 'start_trial': $result = $this->opt_in( false, false, false, false, false, fs_request_get( 'plan_id' ) ); } if ( is_object( $result ) && $this->is_api_error( $result ) ) { $this->_logger->api_error( $result ); self::shoot_ajax_failure( isset( $result->error ) ? ( is_string( $result->error ) ? $result->error : $result->error->message ) : var_export( $result, true ) ); } $this->shoot_ajax_success( $result ); } #---------------------------------------------------------------------------------- #region Contact Us #---------------------------------------------------------------------------------- /** * Render contact-us page. * * @author Vova Feldman (@svovaf) * @since 1.0.3 */ function _contact_page_render() { $this->_logger->entrance(); $vars = array( 'id' => $this->_module_id ); /** * Added filter to the template to allow developers wrapping the template * in custom HTML (e.g. within a wizard/tabs). * * @author Vova Feldman (@svovaf) * @since 2.1.3 */ echo $this->apply_filters( 'templates/contact.php', fs_get_template( 'contact.php', $vars ) ); } #endregion ------------------------------------------------------------------------ /** * Hide all admin notices to prevent distractions. * * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @uses remove_all_actions() */ private static function _hide_admin_notices() { remove_all_actions( 'admin_notices' ); remove_all_actions( 'network_admin_notices' ); remove_all_actions( 'all_admin_notices' ); remove_all_actions( 'user_admin_notices' ); } static function _clean_admin_content_section_hook() { $hide_admin_notices = true; if ( fs_request_is_action( 'allow_clone_resolution_notice' ) ) { check_admin_referer( 'fs_allow_clone_resolution_notice' ); $hide_admin_notices = false; } if ( $hide_admin_notices ) { self::_hide_admin_notices(); } // Hide footer. echo ''; } /** * Attach to admin_head hook to hide all admin notices. * * @author Vova Feldman (@svovaf) * @since 1.0.3 */ static function _clean_admin_content_section() { add_action( 'admin_head', 'Freemius::_clean_admin_content_section_hook' ); } /* CSS & JavaScript ------------------------------------------------------------------------------------------------------------------*/ /* function _enqueue_script($handle, $src) { $url = plugins_url( substr( WP_FS__DIR_JS, strlen( $this->_plugin_dir_path ) ) . '/assets/js/' . $src ); $this->_logger->entrance( 'script = ' . $url ); wp_enqueue_script( $handle, $url ); }*/ /* SDK ------------------------------------------------------------------------------------------------------------------*/ private $_user_api; /** * * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @param bool $flush * * @return FS_Api */ function get_api_user_scope( $flush = false ) { if ( ! isset( $this->_user_api ) || $flush ) { $this->_user_api = $this->get_api_user_scope_by_user( $this->_user ); } return $this->_user_api; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_User $user * * @return \FS_Api */ private function get_api_user_scope_by_user( FS_User $user ) { return FS_Api::instance( $this->_module_id, 'user', $user->id, $user->public_key, ! $this->is_live(), $user->secret_key, $this->get_sdk_version() ); } /** * * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param bool $flush * * @return FS_Api */ private function get_current_or_network_user_api_scope( $flush = false ) { if ( ! $this->_is_network_active || ( isset( $this->_user ) && $this->_user instanceof FS_User ) ) { return $this->get_api_user_scope( $flush ); } $user = $this->get_current_or_network_user(); $this->_user_api = FS_Api::instance( $this->_module_id, 'user', $user->id, $user->public_key, ! $this->is_live(), $user->secret_key, $this->get_sdk_version() ); return $this->_user_api; } private $_site_api; /** * * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @param bool $flush * * @return FS_Api */ private function get_api_site_scope( $flush = false ) { if ( ! isset( $this->_site_api ) || $flush ) { $this->_site_api = FS_Api::instance( $this->_module_id, 'install', $this->_site->id, $this->_site->public_key, ! $this->is_live(), $this->_site->secret_key, $this->get_sdk_version(), self::get_unfiltered_site_url() ); } return $this->_site_api; } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param string $path * @param string $method * @param array $params * @param bool $flush_instance * * @return array|mixed|string|void * @throws Freemius_Exception */ private function api_site_call( $path, $method = 'GET', $params = array(), $flush_instance = false ) { $result = $this->get_api_site_scope( $flush_instance )->call( $path, $method, $params ); /** * Checks if the local install's URL is different from the remote install's URL, update the local install if necessary, and then run the clone handler if the install's URL is different from the URL of the site. * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ if ( $this->is_registered() && FS_Api::is_api_result_entity( $result ) && isset( $result->url ) ) { $stored_local_url = trailingslashit( $this->_site->url ); $stored_remote_url = trailingslashit( $result->url ); if ( $stored_local_url !== $stored_remote_url ) { $this->_site->url = $result->url; $this->_store_site(); } if ( fs_strip_url_protocol( $stored_remote_url ) !== self::get_unfiltered_site_url( null, true, true ) ) { FS_Clone_Manager::instance()->maybe_run_clone_resolution(); } } return $result; } private $_plugin_api; /** * Get plugin public API scope. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return FS_Api */ function get_api_plugin_scope() { if ( ! isset( $this->_plugin_api ) ) { $this->_plugin_api = FS_Api::instance( $this->_module_id, 'plugin', $this->_plugin->id, $this->_plugin->public_key, ! $this->is_live(), false, $this->get_sdk_version() ); } return $this->_plugin_api; } /** * Get bundle public API scope. * * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @return FS_Api */ function get_api_bundle_scope() { return FS_Api::instance( $this->get_bundle_id(), 'plugin', $this->get_bundle_id(), $this->get_bundle_public_key(), ! $this->is_live(), false, $this->get_sdk_version() ); } /** * Get site API scope object (fallback to public plugin scope when not registered). * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return FS_Api */ function get_api_site_or_plugin_scope() { return $this->is_registered() ? $this->get_api_site_scope() : $this->get_api_plugin_scope(); } /** * @author Leo Fajardo (@leorw) * @since 2.2.3.1 * * @param object $result */ private function maybe_modify_api_curl_error_message( $result ) { if ( 'cUrlMissing' !== $result->error->type && ( 'CurlException' !== $result->error->type || CURLE_COULDNT_CONNECT != $result->error->code ) && ( 'HttpRequestFailed' !== $result->error->type || false === strpos( $result->error->message, 'cURL error ' . CURLE_COULDNT_CONNECT ) ) ) { return; } $result->error->message = $this->esc_html_inline( 'We use PHP cURL library for the API calls, which is a very common library and usually installed and activated out of the box. Unfortunately, cURL is not activated (or disabled) on your server.', 'curl-missing-message' ) . ' ' . $this->esc_html_inline( sprintf( 'Please contact your hosting provider and ask them to whitelist %s for external connection.', implode( ', ', $this->apply_filters( 'api_domains', array( 'api.freemius.com', 'wp.freemius.com' ) ) ) ), 'connectivity-whitelist' ) . ' ' . sprintf( $this->esc_html_inline( 'Once you are done, deactivate the %s and activate it again.', 'connectivity-reactivate-module' ), $this->get_module_type() ); } /** * Show trial promotional notice (if any trial exist). * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param FS_Plugin_Plan[] $plans */ function _check_for_trial_plans( $plans ) { /** * For some reason core's do_action() flattens arrays when it has a single object item. Therefore, we need to restructure the array as expected. * * @author Vova Feldman (@svovaf) * @since 2.1.2 */ if ( ! is_array( $plans ) && is_object( $plans ) ) { $plans = array( $plans ); } if ( ! $this->is_array_instanceof( $plans, 'FS_Plugin_Plan' ) ) { $plans = array(); } $this->_storage->has_trial_plan = FS_Plan_Manager::instance()->has_trial_plan( $plans ); } /** * During trial promotion the "upgrade" submenu item turns to * "start trial" to encourage the trial. Since we want to keep * the same menu item handler and there's no robust way to * add new arguments to the menu item link's querystring, * use JavaScript to find the menu item and update the href of * the link. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 */ function _fix_start_trial_menu_item_url() { $template_args = array( 'id' => $this->_module_id ); fs_require_template( 'add-trial-to-pricing.php', $template_args ); } /** * Check if module is currently in a trial promotion mode. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool */ function is_in_trial_promotion() { return $this->_admin_notices->has_sticky( 'trial_promotion' ); } /** * Show trial promotional notice (if any trial exist). * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool If trial notice added. */ function _add_trial_notice() { if ( ! $this->is_user_admin() ) { return false; } if ( ! $this->is_user_in_admin() ) { return false; } if ( $this->_is_network_active ) { if ( fs_is_network_admin() ) { // Network level trial is disabled at the moment. return false; } if ( ! $this->is_delegated_connection() ) { // Only delegated sites should support trials. return false; } } // Check if trial message is already shown. if ( $this->is_in_trial_promotion() ) { add_action( 'admin_footer', array( &$this, '_fix_start_trial_menu_item_url' ) ); $this->_menu->add_counter_to_menu_item( 1, 'fs-trial' ); return false; } if ( $this->is_premium() && ! WP_FS__DEV_MODE ) { // Don't show trial if running the premium code, unless running in DEV mode. return false; } if ( ! $this->has_trial_plan() ) { // No plans with trial. return false; } if ( ! $this->apply_filters( 'show_trial', true ) ) { // Developer explicitly asked not to show the trial promo. return false; } if ( $this->is_registered() ) { // Check if trial already utilized. if ( $this->_site->is_trial_utilized() ) { return false; } if ( $this->is_paying_or_trial() ) { // Don't show trial if paying or already in trial. return false; } } if ( $this->is_activation_mode() || $this->is_pending_activation() ) { // If not yet opted-in/skipped, or pending activation, don't show trial. return false; } $last_time_trial_promotion_shown = $this->_storage->get( 'trial_promotion_shown', false ); $was_promotion_shown_before = ( false !== $last_time_trial_promotion_shown ); // Show promotion if never shown before and 24 hours after initial activation with FS. if ( ! $was_promotion_shown_before && $this->_storage->install_timestamp > ( time() - $this->apply_filters( 'show_first_trial_after_n_sec', WP_FS__TIME_24_HOURS_IN_SEC ) ) ) { return false; } // OR if promotion was shown before, try showing it every 30 days. if ( $was_promotion_shown_before && $this->apply_filters( 'reshow_trial_after_every_n_sec', 30 * WP_FS__TIME_24_HOURS_IN_SEC ) > time() - $last_time_trial_promotion_shown ) { return false; } $trial_period = $this->_trial_days; $require_payment = $this->_is_trial_require_payment; $trial_url = $this->get_trial_url(); $plans_string = strtolower( $this->get_text_inline( 'Awesome', 'awesome' ) ); if ( $this->is_registered() ) { // If opted-in, override trial with up to date data from API. $trial_plans = FS_Plan_Manager::instance()->get_trial_plans( $this->_plans ); $trial_plans_count = count( $trial_plans ); if ( 0 === $trial_plans_count ) { // If there's no plans with a trial just exit. return false; } /** * @var FS_Plugin_Plan $paid_plan */ $paid_plan = $trial_plans[0]; $require_payment = $paid_plan->is_require_subscription; $trial_period = $paid_plan->trial_period; $total_paid_plans = count( $this->_plans ) - ( FS_Plan_Manager::instance()->has_free_plan( $this->_plans ) ? 1 : 0 ); if ( $total_paid_plans !== $trial_plans_count ) { // Not all paid plans have a trial - generate a string of those that have it. for ( $i = 0; $i < $trial_plans_count; $i ++ ) { $plans_string .= sprintf( ' %s', $trial_url, $trial_plans[ $i ]->title ); if ( $i < $trial_plans_count - 2 ) { $plans_string .= ', '; } else if ( $i == $trial_plans_count - 2 ) { $plans_string .= ' and '; } } } } $message = sprintf( $this->get_text_x_inline( 'Hey', 'exclamation', 'hey' ) . '! ' . $this->get_text_inline( 'How do you like %s so far? Test all our %s premium features with a %d-day free trial.', 'trial-x-promotion-message' ), sprintf( '%s', $this->get_plugin_name() ), $plans_string, $trial_period ); // "No Credit-Card Required" or "No Commitment for N Days". $cc_string = $require_payment ? sprintf( $this->get_text_inline( 'No commitment for %s days - cancel anytime!', 'no-commitment-for-x-days' ), $trial_period ) : $this->get_text_inline( 'No credit card required', 'no-cc-required' ) . '!'; // Start trial button. $button = ' ' . sprintf( '', $trial_url, $this->get_text_x_inline( 'Start free trial', 'call to action', 'start-free-trial' ) ); $this->_admin_notices->add_sticky( $this->apply_filters( 'trial_promotion_message', "{$message} {$cc_string} {$button}" ), 'trial_promotion', '', 'promotion' ); $this->_storage->trial_promotion_shown = WP_FS__SCRIPT_START_TIME; return true; } /** * Lets users/customers know that the product has an affiliate program. * * @author Leo Fajardo (@leorw) * @since 1.2.2.11 * * @return bool Returns true if the notice has been added. */ function _add_affiliate_program_notice() { if ( ! $this->is_user_admin() ) { return false; } if ( ! $this->is_user_in_admin() ) { return false; } // Check if the notice is already shown. if ( $this->_admin_notices->has_sticky( 'affiliate_program' ) ) { return false; } if ( // Product has no affiliate program. ! $this->has_affiliate_program() || // User has applied for an affiliate account. ! empty( $this->_storage->affiliate_application_data ) ) { return false; } if ( ! $this->apply_filters( 'show_affiliate_program_notice', true ) ) { // Developer explicitly asked not to show the notice about the affiliate program. return false; } if ( $this->is_activation_mode() || $this->is_pending_activation() ) { // If not yet opted in/skipped, or pending activation, don't show the notice. return false; } $last_time_notice_was_shown = $this->_storage->get( 'affiliate_program_notice_shown', false ); $was_notice_shown_before = ( false !== $last_time_notice_was_shown ); /** * Do not show the notice if it was already shown before or less than 30 days have passed since the initial * activation with FS. */ if ( $was_notice_shown_before || $this->_storage->install_timestamp > ( time() - ( WP_FS__TIME_24_HOURS_IN_SEC * 30 ) ) ) { return false; } if ( ! $this->is_paying() && FS_Plugin::AFFILIATE_MODERATION_CUSTOMERS == $this->_plugin->affiliate_moderation ) { // If the user is not a customer and the affiliate program is only for customers, don't show the notice. return false; } $message = sprintf( $this->get_text_inline( 'Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!', 'become-an-ambassador-admin-notice' ), sprintf( '%s', $this->get_plugin_name() ), $this->get_module_label( true ) ); // HTML code for the "Learn more..." button. $button = ' ' . sprintf( '', $this->_get_admin_page_url( 'affiliation' ), $this->get_text_inline( 'Learn more', 'learn-more' ) . '...' ); $this->_admin_notices->add_sticky( $this->apply_filters( 'affiliate_program_notice', "{$message} {$button}" ), 'affiliate_program', '', 'promotion' ); $this->_storage->affiliate_program_notice_shown = WP_FS__SCRIPT_START_TIME; return true; } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.5 */ function _enqueue_common_css() { if ( $this->has_paid_plan() && ! $this->is_paying() ) { // Add basic CSS for admin-notices and menu-item colors. fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); } } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 */ function _show_theme_activation_optin_dialog() { fs_enqueue_local_style( 'fs_connect', '/admin/connect.css' ); add_action( 'admin_footer', array( &$this, '_add_fs_theme_activation_dialog' ) ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 */ function _add_fs_theme_activation_dialog() { global $pagenow; if ( 'themes.php' !== $pagenow ) { return; } $vars = array( 'id' => $this->_module_id ); fs_require_once_template( 'connect.php', $vars ); } /* Action Links ------------------------------------------------------------------------------------------------------------------*/ private $_action_links_hooked = false; private $_action_links = array(); /** * Hook to plugin action links filter. * * @author Vova Feldman (@svovaf) * @since 1.0.0 */ private function hook_plugin_action_links() { $this->_logger->entrance(); $this->_action_links_hooked = true; $this->_logger->log( 'Adding action links hooks.' ); // Add action link to settings page. add_filter( 'plugin_action_links_' . $this->_plugin_basename, array( &$this, '_modify_plugin_action_links_hook' ), WP_FS__DEFAULT_PRIORITY, 2 ); add_filter( 'network_admin_plugin_action_links_' . $this->_plugin_basename, array( &$this, '_modify_plugin_action_links_hook' ), WP_FS__DEFAULT_PRIORITY, 2 ); } /** * Add plugin action link. * * @author Vova Feldman (@svovaf) * @since 1.0.0 * * @param $label * @param $url * @param bool $external * @param int $priority * @param bool $key */ function add_plugin_action_link( $label, $url, $external = false, $priority = WP_FS__DEFAULT_PRIORITY, $key = false ) { $this->_logger->entrance(); if ( ! isset( $this->_action_links[ $priority ] ) ) { $this->_action_links[ $priority ] = array(); } if ( false === $key ) { $key = preg_replace( "/[^A-Za-z0-9 ]/", '', strtolower( $label ) ); } $this->_action_links[ $priority ][] = array( 'label' => $label, 'href' => $url, 'key' => $key, 'external' => $external ); } /** * Adds Upgrade and Add-Ons links to the main Plugins page link actions collection. * * @author Vova Feldman (@svovaf) * @since 1.0.0 */ function _add_upgrade_action_link() { $this->_logger->entrance(); $is_activation_mode = $this->is_activation_mode(); $add_action_links = $this->should_add_submenu_or_action_links( $is_activation_mode ); /** * The following logic is based on the logic in `add_submenu_items()` method that decides when the "Upgrade" * and "Add-Ons" menus should be added. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $add_upgrade_link = ( $add_action_links || ( $is_activation_mode && $this->is_only_premium() ) ) && ! WP_FS__DEMO_MODE && ( ! $this->is_whitelabeled() ); $add_addons_link = ( $add_action_links && $this->has_addons() ); if ( ! $add_upgrade_link && ! $add_addons_link ) { return; } if ( $add_upgrade_link && $this->is_pricing_page_visible() && $this->is_submenu_item_visible( 'pricing' ) ) { $this->add_plugin_action_link( $this->get_text_inline( 'Upgrade', 'upgrade' ), $this->get_upgrade_url(), false, 7, 'upgrade' ); } if ( $add_addons_link && $this->has_addons() && $this->is_submenu_item_visible( 'addons' ) ) { $this->add_plugin_action_link( $this->get_text_inline( 'Add-Ons', 'add-ons' ), $this->_get_admin_page_url( 'addons' ), false, 9, 'addons' ); } } /** * Adds "Activate License" or "Change License" link to the main Plugins page link actions collection. * * @author Leo Fajardo (@leorw) * @since 1.1.9 */ function _add_license_action_link() { $this->_logger->entrance(); if ( ! self::is_ajax() ) { // Inject license activation dialog UI and client side code. add_action( 'admin_footer', array( &$this, '_add_license_activation_dialog_box' ) ); } $link_text = $this->is_free_plan() ? $this->get_text_inline( 'Activate License', 'activate-license' ) : $this->get_text_inline( 'Change License', 'change-license' ); $this->add_plugin_action_link( $link_text, '#', false, 11, ( 'activate-license ' . $this->get_unique_affix() ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.0.2 */ function _add_premium_version_upgrade_selection_action() { $this->_logger->entrance(); if ( ! self::is_ajax() ) { add_action( 'admin_footer', array( &$this, '_add_premium_version_upgrade_selection_dialog_box' ) ); } } /** * Adds "Opt In" or "Opt Out" link to the main "Plugins" page link actions collection. * * @author Leo Fajardo (@leorw) * @since 1.2.1.5 */ function _add_tracking_links() { if ( ! current_user_can( 'manage_options' ) ) { return; } $this->_logger->entrance(); if ( $this->is_only_premium() && $this->is_free_plan() ) { // Don't add tracking links for premium-only products that were opted-in by relation (add-on or a parent product) before activating any license. return; } if ( $this->is_addon() && ! $this->is_only_premium() ) { $parent = $this->get_parent_instance(); if ( is_object( $parent ) && $parent->is_anonymous() ) { return; } } if ( fs_is_network_admin() ) { if ( ! $this->_is_network_active ) { // Don't add tracking links when browsing the network WP Admin and the plugin is not network active. return; } else if ( $this->is_network_delegated_connection() ) { // Don't add tracking links when browsing the network WP Admin and the activation has been delegated to site admins. return; } } else { if ( $this->_is_network_active && ! $this->is_delegated_connection() ) { // Don't add tracking links when browsing the sub-site WP Admin, the plugin is network active, and the connection was not delegated. return; } } if ( fs_request_is_action_secure( $this->get_unique_affix() . '_reconnect' ) ) { if ( ! $this->is_registered() && $this->is_anonymous() ) { $this->connect_again(); return; } } if ( ( $this->is_plugin() && ! self::is_plugins_page() ) || ( $this->is_theme() && ! self::is_themes_page() ) ) { // Only show tracking links on the plugins and themes pages. return; } if ( $this->is_activation_mode() && $this->is_premium() && ! $this->is_registered() ) { // If not yet registered and running the premium code base, a license activation link will already be shown. return; } if ( $this->is_registered() && $this->is_tracking_allowed() ) { if ( ! $this->is_premium() && ! $this->is_enable_anonymous() ) { // If opted in and tracking is allowed, don't allow to opt out if not premium and anonymous mode is disabled. return; } } if ( $this->add_ajax_action( 'toggle_permission_tracking', array( &$this, '_toggle_permission_tracking_callback' ) ) ) { return; } $link_text_id = ''; $url = '#'; if ( $this->is_registered( true ) ) { if ( $this->is_registered() && $this->is_tracking_allowed() ) { $link_text_id = $this->get_text_inline( 'Opt Out', 'opt-out' ); } else { $link_text_id = $this->get_text_inline( 'Opt In', 'opt-in' ); } } else if ( $this->is_anonymous() || $this->is_activation_mode() ) { /** * Show opt-in link only if skipped or in activation mode. */ $link_text_id = $this->get_text_inline( 'Opt In', 'opt-in' ); $params = ! $this->is_anonymous() ? array() : array( 'nonce' => wp_create_nonce( $this->get_unique_affix() . '_reconnect' ), 'fs_action' => ( $this->get_unique_affix() . '_reconnect' ), ); $url = $this->get_activation_url( $params ); } add_action( 'admin_footer', array( &$this, '_add_optout_dialog' ) ); if ( ! empty( $link_text_id ) && $this->is_plugin() && self::is_plugins_page() ) { $this->add_plugin_action_link( $link_text_id, $url, false, 13, "opt-in-or-opt-out {$this->_slug}" ); } } /** * Get the URL of the page that should be loaded right after the plugin activation. * * @author Vova Feldman (@svovaf) * @since 1.1.7.4 * * @return string */ function get_after_plugin_activation_redirect_url() { $url = false; if ( ! $this->is_addon() || ! $this->has_free_plan() ) { $first_time_path = $this->_menu->get_first_time_path( fs_is_network_admin() && $this->_is_network_active ); if ( $this->is_activation_mode() ) { $url = $this->get_activation_url(); } else if ( ! empty( $first_time_path ) ) { $url = $first_time_path; } else { $page = ''; if ( ! empty( $this->_dynamically_added_top_level_page_hook_name ) ) { if ( $this->is_network_registered() ) { $page = 'account'; } else if ( $this->is_pending_activation() || $this->is_network_anonymous() ) { $this->maybe_set_slug_and_network_menu_exists_flag(); } } $url = $this->_get_admin_page_url( $page ); } } else { $plugin_fs = false; if ( $this->is_parent_plugin_installed() ) { $plugin_fs = self::get_parent_instance(); } if ( is_object( $plugin_fs ) ) { if ( ! $plugin_fs->is_registered() ) { // Forward to parent plugin connect when parent not registered. $url = $plugin_fs->get_activation_url(); } else { // Forward to account page. $url = $plugin_fs->_get_admin_page_url( 'account' ); } } } return $url; } /** * Forward page to activation page. * * @author Vova Feldman (@svovaf) * @since 1.0.3 */ function _redirect_on_activation_hook() { if ( $this->apply_filters( 'redirect_on_activation', true ) ) { $url = $this->get_after_plugin_activation_redirect_url(); if ( is_string( $url ) ) { fs_redirect( $url ); } } } /** * Modify plugin's page action links collection. * * @author Vova Feldman (@svovaf) * @since 1.0.0 * * @param array $links * @param $file * * @return array */ function _modify_plugin_action_links_hook( $links, $file ) { $this->_logger->entrance(); $passed_deactivate = false; $deactivate_link = ''; $before_deactivate = array(); $after_deactivate = array(); foreach ( $links as $key => $link ) { if ( 'deactivate' === $key ) { $deactivate_link = $link; $passed_deactivate = true; continue; } if ( ! $passed_deactivate ) { $before_deactivate[ $key ] = $link; } else { $after_deactivate[ $key ] = $link; } } ksort( $this->_action_links ); foreach ( $this->_action_links as $new_links ) { foreach ( $new_links as $link ) { $before_deactivate[ $link['key'] ] = '' . $link['label'] . ''; } } if ( ! empty( $deactivate_link ) ) { /** * This HTML element is used to identify the correct plugin when attaching an event to its Deactivate link. * * @since 1.2.1.6 Always show the deactivation feedback form since we added automatic free version deactivation upon premium code activation. */ $deactivate_link .= ''; // Append deactivation link. $before_deactivate['deactivate'] = $deactivate_link; } return array_merge( $before_deactivate, $after_deactivate ); } /** * Adds admin message. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param string $message * @param string $title * @param string $type */ function add_admin_message( $message, $title = '', $type = 'success' ) { $this->_admin_notices->add( $message, $title, $type ); } /** * Adds sticky admin message. * * @author Vova Feldman (@svovaf) * @since 1.1.0 * * @param string $message * @param string $id * @param string $title * @param string $type */ function add_sticky_admin_message( $message, $id, $title = '', $type = 'success' ) { $this->_admin_notices->add_sticky( $message, $id, $title, $type ); } /** * Check if the paid version of the module is installed. * * @author Vova Feldman (@svovaf) * @since 2.2.0 * * @return bool */ private function is_premium_version_installed() { $premium_plugin_basename = $this->premium_plugin_basename(); if ( $this->is_theme() ) { return $this->can_activate_theme( $this->get_premium_slug() ); } return file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $premium_plugin_basename ) ); } /** * Helper function that returns the final steps for the upgrade completion. * * If the module is already running the premium code, returns an empty string. * * @author Vova Feldman (@svovaf) * @since 1.2.1 * * @param string $plan_title * * @return string */ private function get_complete_upgrade_instructions( $plan_title = '' ) { $this->_logger->entrance(); $activate_license_string = $this->get_license_network_activation_notice(); if ( ! $this->has_premium_version() || $this->is_premium() ) { return '' . $activate_license_string; } if ( empty( $plan_title ) ) { $plan_title = $this->get_plan_title(); } if ( $this->is_premium_version_installed() ) { /** * If the premium version is already installed, instead of showing the installation instructions, * tell the current user to activate it. * * @author Leo Fajardo (@leorw) * @since 2.2.1 */ $premium_theme_slug_or_plugin_basename = $this->is_theme() ? $this->get_premium_slug() : $this->premium_plugin_basename(); return sprintf( /* translators: %1$s: Product title; %2$s: Plan title */ $this->get_text_inline( ' The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s', 'activate-premium-version' ), sprintf( '%s', esc_html( $this->get_plugin_title() ) ), $plan_title, sprintf( '', ( $this->is_theme() ? wp_nonce_url( 'themes.php?action=activate&stylesheet=' . $premium_theme_slug_or_plugin_basename, 'switch-theme_' . $premium_theme_slug_or_plugin_basename ) : wp_nonce_url( 'plugins.php?action=activate&plugin=' . $premium_theme_slug_or_plugin_basename, 'activate-plugin_' . $premium_theme_slug_or_plugin_basename ) ), esc_html( sprintf( /* translators: %s: Plan title */ $this->get_text_inline( 'Activate %s features', 'activate-x-features' ), $plan_title ) ) ) ); } else { // @since 1.2.1.5 The free version is auto deactivated. $deactivation_step = version_compare( $this->version, '1.2.1.5', '<' ) ? ( '
  • ' . $this->esc_html_inline( 'Deactivate the free version', 'deactivate-free-version' ) . '.
  • ' ) : ''; return sprintf( ' %s:
    1. %s.
    2. %s
    3. %s (%s).
    ', $this->get_text_inline( 'Please follow these steps to complete the upgrade', 'follow-steps-to-complete-upgrade' ), ( empty( $activate_license_string ) ? '' : $activate_license_string . '
  • ' ) . $this->get_latest_download_link( sprintf( /* translators: %s: Plan title */ $this->get_text_inline( 'Download the latest %s version', 'download-latest-x-version' ), $plan_title ) ), $deactivation_step, $this->get_text_inline( 'Upload and activate the downloaded version', 'upload-and-activate' ), $this->apply_filters( 'upload_and_install_video_url', '//bit.ly/wp-' . $this->_module_type . '-upload' ), $this->get_text_inline( 'How to upload and activate?', 'howto-upload-activate' ) ); } } /** * @author Leo Fajardo (@leorw) * @since 2.5.3 * * @param string $message_before_the_instructions * @param string $message_id * @param string $plan_title */ private function add_complete_upgrade_instructions_notice( $message_before_the_instructions, $message_id, $plan_title = '' ) { $this->_admin_notices->add_sticky( $message_before_the_instructions . $this->get_complete_upgrade_instructions( $plan_title ), $message_id, $this->get_text_x_inline( 'Yee-haw', 'interjection expressing joy or exuberance', 'yee-haw' ) . '!' ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.3 * * @param bool $is_upgrade */ private function add_after_plan_activation_or_upgrade_instructions_notice( $is_upgrade = true ) { $this->add_complete_upgrade_instructions_notice( $is_upgrade ? $this->get_text_inline( 'Your plan was successfully upgraded.', 'plan-upgraded-message' ) : $this->get_text_inline( 'Your plan was successfully activated.', 'plan-activated-message' ), 'plan_upgraded' ); } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 * * @param string $url * @param array $request */ private static function enrich_request_for_debug( &$url, &$request ) { if ( WP_FS__DEBUG_SDK || isset( $_COOKIE['XDEBUG_SESSION'] ) ) { $url = add_query_arg( 'XDEBUG_SESSION_START', rand( 0, 9999999 ), $url ); $url = add_query_arg( 'XDEBUG_SESSION', 'PHPSTORM', $url ); $request['cookies'] = array( new WP_Http_Cookie( array( 'name' => 'XDEBUG_SESSION', 'value' => 'PHPSTORM', ) ) ); } } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 * * @param string $url * @param array $request * @param int $success_cache_expiration * @param int $failure_cache_expiration * @param bool $maybe_enrich_request_for_debug * * @return WP_Error|array */ static function safe_remote_post( &$url, $request, $success_cache_expiration = 0, $failure_cache_expiration = 0, $maybe_enrich_request_for_debug = true ) { $should_cache = ($success_cache_expiration + $failure_cache_expiration > 0); $cache_key = $should_cache ? md5( fs_strip_url_protocol($url) . json_encode( $request ) ) : false; $response = (!WP_FS__DEBUG_SDK && ( false !== $cache_key )) ? get_transient( $cache_key ) : false; if ( false === $response ) { if ( $maybe_enrich_request_for_debug ) { self::enrich_request_for_debug( $url, $request ); } if ( ! isset( $request['method'] ) ) { $request['method'] = 'POST'; } $response = FS_Api::remote_request( $url, $request ); if ( 'https://' === substr( $url, 0, 8 ) && FS_Api::is_ssl_error_response( $response ) ) { // Failed due to old version of cURL or Open SSL (SSLv3 is not supported by CloudFlare). $url = 'http://' . substr( $url, 8 ); $request['timeout'] = 15; $response = FS_Api::remote_request( $url, $request ); } if ( false !== $cache_key ) { set_transient( $cache_key, $response, ( ( $response instanceof WP_Error ) ? $failure_cache_expiration : $success_cache_expiration ) ); } } return $response; } /** * This method is used to enrich the after upgrade notice instructions when the upgraded * license cannot be activated network wide (license quota isn't large enough). * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return string */ private function get_license_network_activation_notice() { if ( ! $this->_is_network_active ) { // Module isn't network level activated. return ''; } if ( ! fs_is_network_admin() ) { // Not network level admin. return ''; } if ( get_blog_count() == 1 ) { // There's only a single site in the network so if there's a context license it was already activated. return ''; } if ( ! is_object( $this->_license ) ) { // No context license. return ''; } if ( $this->_license->is_single_site() && 0 < $this->_license->activated ) { // License was already utilized (this is not 100% the case if all the network is localhost sites and the license can be utilized on unlimited localhost sites). return ''; } if ( $this->can_activate_license_on_network( $this->_license ) ) { // License can be activated on all the network, so probably, the license is already activate on all the network (that's how the after upgrade sync works). return ''; } return sprintf( $this->get_text_inline( '%sClick here%s to choose the sites where you\'d like to activate the license on.', 'network-choose-sites-for-license' ), '', '' ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param string $key * * @return string */ function get_text( $key ) { return fs_text( $key, $this->_slug ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * * @return string */ function get_text_inline( $text, $key = '' ) { return _fs_text_inline( $text, $key, $this->_slug ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $context Context information for the translators. * @param string $key String key for overrides. * * @return string */ function get_text_x_inline( $text, $context, $key ) { return _fs_text_x_inline( $text, $context, $key, $this->_slug ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * * @return string */ function esc_html_inline( $text, $key ) { return esc_html( _fs_text_inline( $text, $key, $this->_slug ) ); } #---------------------------------------------------------------------------------- #region Versioning #---------------------------------------------------------------------------------- /** * Check if Freemius in SDK upgrade mode. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_sdk_upgrade_mode() { return isset( $this->_storage->sdk_upgrade_mode ) ? $this->_storage->sdk_upgrade_mode : false; } /** * Turn SDK upgrade mode off. * * @author Vova Feldman (@svovaf) * @since 1.0.9 */ function set_sdk_upgrade_complete() { $this->_storage->sdk_upgrade_mode = false; } /** * Check if plugin upgrade mode. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_plugin_upgrade_mode() { return isset( $this->_storage->plugin_upgrade_mode ) ? $this->_storage->plugin_upgrade_mode : false; } /** * Turn plugin upgrade mode off. * * @author Vova Feldman (@svovaf) * @since 1.0.9 */ function set_plugin_upgrade_complete() { $this->_storage->plugin_upgrade_mode = false; $license_migration = ! empty( $this->_storage->license_migration ) ? $this->_storage->license_migration : array(); $license_migration['is_migrating'] = false; $this->_storage->license_migration = $license_migration; } #endregion #---------------------------------------------------------------------------------- #region Permissions #---------------------------------------------------------------------------------- /** * Check if specific permission requested. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string $permission * * @return bool */ function is_permission_requested( $permission ) { return isset( $this->_permissions[ $permission ] ) && ( true === $this->_permissions[ $permission ] ); } #endregion #---------------------------------------------------------------------------------- #region Auto Activation #---------------------------------------------------------------------------------- /** * Hints the SDK if running an auto-installation. * * @var bool */ private $_isAutoInstall = false; /** * After upgrade callback to install and auto activate a plugin. * This code will only be executed on explicit request from the user, * following the practice Jetpack are using with their theme installations. * * @link https://make.wordpress.org/plugins/2017/03/16/clarification-of-guideline-8-executable-code-and-installs/ * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 */ function _install_premium_version_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'install_premium_version' ); if ( ! $this->is_registered() ) { // Not registered. self::shoot_ajax_failure( array( 'message' => $this->get_text_inline( 'Auto installation only works for opted-in users.', 'auto-install-error-not-opted-in' ), 'code' => 'premium_installed', ) ); } $plugin_id = fs_request_get( 'target_module_id', $this->get_id() ); if ( ! FS_Plugin::is_valid_id( $plugin_id ) ) { // Invalid ID. self::shoot_ajax_failure( array( 'message' => $this->get_text_inline( 'Invalid module ID.', 'auto-install-error-invalid-id' ), 'code' => 'invalid_module_id', ) ); } if ( $plugin_id == $this->get_id() ) { if ( $this->is_premium() ) { // Already using the premium code version. self::shoot_ajax_failure( array( 'message' => $this->get_text_inline( 'Premium version already active.', 'auto-install-error-premium-activated' ), 'code' => 'premium_installed', ) ); } if ( ! $this->can_use_premium_code() ) { // Don't have access to the premium code. self::shoot_ajax_failure( array( 'message' => $this->get_text_inline( 'You do not have a valid license to access the premium version.', 'auto-install-error-invalid-license' ), 'code' => 'invalid_license', ) ); } if ( ! $this->has_release_on_freemius() ) { // Plugin is a serviceware, no premium code version. self::shoot_ajax_failure( array( 'message' => $this->get_text_inline( 'Plugin is a "Serviceware" which means it does not have a premium code version.', 'auto-install-error-serviceware' ), 'code' => 'premium_version_missing', ) ); } } else { $addon = $this->get_addon( $plugin_id ); if ( ! is_object( $addon ) ) { // Invalid add-on ID. self::shoot_ajax_failure( array( 'message' => $this->get_text_inline( 'Invalid module ID.', 'auto-install-error-invalid-id' ), 'code' => 'invalid_module_id', ) ); } if ( $this->is_addon_activated( $plugin_id, true ) ) { // Premium add-on version is already activated. self::shoot_ajax_failure( array( 'message' => $this->get_text_inline( 'Premium add-on version already installed.', 'auto-install-error-premium-addon-activated' ), 'code' => 'premium_installed', ) ); } } $this->_isAutoInstall = true; // Try to install and activate. $updater = FS_Plugin_Updater::instance( $this ); $result = $updater->install_and_activate_plugin( $plugin_id ); if ( is_array( $result ) && ! empty( $result['message'] ) ) { self::shoot_ajax_failure( array( 'message' => $result['message'], 'code' => $result['code'], ) ); } self::shoot_ajax_success( $result ); } /** * Displays module activation dialog box after a successful upgrade * where the user explicitly requested to auto download and install * the premium version. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 */ function _add_auto_installation_dialog_box() { $this->_logger->entrance(); if ( ! $this->is_registered() ) { // Not registered. return; } $plugin_id = fs_request_get( 'plugin_id', $this->get_id() ); if ( ! FS_Plugin::is_valid_id( $plugin_id ) ) { // Invalid module ID. return; } if ( $plugin_id == $this->get_id() ) { if ( $this->is_premium() ) { // Already using the premium code version. return; } if ( ! $this->can_use_premium_code() ) { // Don't have access to the premium code. return; } if ( ! $this->has_release_on_freemius() ) { // Plugin is a serviceware, no premium code version. return; } } else { $addon = $this->get_addon( $plugin_id ); if ( ! is_object( $addon ) ) { // Invalid add-on ID. return; } if ( $this->is_addon_activated( $plugin_id, true ) ) { // Premium add-on version is already activated. return; } } $vars = array( 'id' => $this->_module_id, 'target_module_id' => $plugin_id, 'slug' => $this->_slug, ); fs_require_template( 'auto-installation.php', $vars ); } #endregion #-------------------------------------------------------------------------------- #region Tabs Integration #-------------------------------------------------------------------------------- #region Module's Original Tabs /** * Inject a JavaScript logic to capture the theme tabs HTML. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 */ function _tabs_capture() { $this->_logger->entrance(); if ( ! $this->is_product_settings_page() || ! $this->should_page_include_tabs() || ! $this->is_matching_url( $this->main_menu_url() ) ) { return; } $params = array( 'id' => $this->_module_id, ); fs_require_once_template( 'tabs-capture-js.php', $params ); } /** * Cache theme's tabs HTML for a week. The cache will also be set as expired * after version and type (free/premium) changes, in addition to the week period. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 */ function _store_tabs_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'store_tabs' ); // Init filesystem if not yet initiated. WP_Filesystem(); // Get POST body HTML data. global $wp_filesystem; $tabs_html = $wp_filesystem->get_contents( "php://input" ); if ( is_string( $tabs_html ) ) { $tabs_html = trim( $tabs_html ); } if ( ! is_string( $tabs_html ) || empty( $tabs_html ) ) { self::shoot_ajax_failure(); } $this->_cache->set( 'tabs', $tabs_html, 7 * WP_FS__TIME_24_HOURS_IN_SEC ); self::shoot_ajax_success(); } /** * Cache theme's settings page custom styles. The cache will also be set as expired * after version and type (free/premium) changes, in addition to the week period. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 */ function _store_tabs_styles() { $this->_logger->entrance(); if ( ! $this->is_product_settings_page() || ! $this->should_page_include_tabs() || ! $this->is_matching_url( $this->main_menu_url() ) ) { return; } $wp_styles = wp_styles(); $theme_styles_url = get_template_directory_uri(); $stylesheets = array(); foreach ( $wp_styles->queue as $handler ) { if ( fs_starts_with( $handler, 'fs_' ) ) { // Assume that stylesheets that their handler starts with "fs_" belong to the SDK. continue; } /** * @var _WP_Dependency $stylesheet */ $stylesheet = $wp_styles->registered[ $handler ]; if ( fs_starts_with( $stylesheet->src, $theme_styles_url ) ) { $stylesheets[] = $stylesheet->src; } } if ( ! empty( $stylesheets ) ) { $this->_cache->set( 'tabs_stylesheets', $stylesheets, 7 * WP_FS__TIME_24_HOURS_IN_SEC ); } } /** * Check if module's original settings page has any tabs. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool */ private function has_tabs() { return $this->_cache->has( 'tabs' ); } /** * Get module's settings page HTML content, starting * from the beginning of the
    element, * until the tabs HTML (including). * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return string */ private function get_tabs_html() { $this->_logger->entrance(); return $this->_cache->get( 'tabs' ); } /** * Check if page should include tabs. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool */ private function should_page_include_tabs() { if ( ! $this->has_settings_menu() ) { // Don't add tabs if no settings at all. return false; } if ( self::NAVIGATION_TABS !== $this->_navigation ) { // Only add tabs to themes for now. return false; } if ( $this->is_theme() && ! $this->has_paid_plan() && ! $this->has_addons() ) { // Only add tabs to monetizing themes. return false; } if ( ! $this->is_product_settings_page() ) { // Only add tabs if browsing one of the product's setting pages. return false; } if ( $this->is_activation_mode() && $this->is_activation_page() ) { // Don't include tabs in the activation page. return false; } if ( $this->is_admin_page( 'pricing' ) && fs_request_get_bool( 'checkout' ) ) { // Don't add tabs on checkout page, we want to reduce distractions // as much as possible. return false; } return true; } /** * Add the tabs HTML before the setting's page content and * enqueue any required stylesheets. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool If tabs were included. */ function _add_tabs_before_content() { $this->_logger->entrance(); if ( ! $this->should_page_include_tabs() ) { return false; } /** * Enqueue the original stylesheets that are included in the * theme settings page. That way, if the theme settings has * some custom _styled_ content above the tabs UI, this * will make sure that the styling is preserved. */ $stylesheets = $this->_cache->get( 'tabs_stylesheets', array() ); if ( is_array( $stylesheets ) ) { for ( $i = 0, $len = count( $stylesheets ); $i < $len; $i ++ ) { wp_enqueue_style( "fs_{$this->_module_id}_tabs_{$i}", $stylesheets[ $i ] ); } } // Cut closing
    tag. echo substr( trim( $this->get_tabs_html() ), 0, - 6 ); return true; } /** * Add the tabs closing HTML after the setting's page content. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return bool If tabs closing HTML was included. */ function _add_tabs_after_content() { $this->_logger->entrance(); if ( ! $this->should_page_include_tabs() ) { return false; } echo '
  • '; return true; } #endregion /** * Add in-page JavaScript to inject the Freemius tabs into * the module's setting tabs section. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 */ function _add_freemius_tabs() { $this->_logger->entrance(); if ( ! $this->should_page_include_tabs() ) { return; } $params = array( 'id' => $this->_module_id ); fs_require_once_template( 'tabs.php', $params ); } #endregion #-------------------------------------------------------------------------------- #region Customizer Integration for Themes #-------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @param WP_Customize_Manager $customizer */ function _customizer_register( $customizer ) { $this->_logger->entrance(); if ( $this->is_pricing_page_visible() ) { require_once WP_FS__DIR_INCLUDES . '/customizer/class-fs-customizer-upsell-control.php'; $customizer->add_section( 'freemius_upsell', array( 'title' => '★ ' . $this->get_text_inline( 'View paid features', 'view-paid-features' ), 'priority' => 1, ) ); $customizer->add_setting( 'freemius_upsell', array( 'sanitize_callback' => 'esc_html', ) ); $customizer->add_control( new FS_Customizer_Upsell_Control( $customizer, 'freemius_upsell', array( 'fs' => $this, 'section' => 'freemius_upsell', 'priority' => 100, ) ) ); } if ( $this->is_page_visible( 'contact' ) || $this->is_page_visible( 'support' ) ) { require_once WP_FS__DIR_INCLUDES . '/customizer/class-fs-customizer-support-section.php'; // Main Documentation Link In Customizer Root. $customizer->add_section( new FS_Customizer_Support_Section( $customizer, 'freemius_support', array( 'fs' => $this, 'priority' => 1000, ) ) ); } } #endregion /** * If the theme has a paid version, add some custom * styling to the theme's premium version (if exists) * to highlight that it's the premium version of the * same theme, making it easier for identification * after the user upgrades and upload it to the site. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 */ function _style_premium_theme() { $this->_logger->entrance(); if ( ! self::is_themes_page() ) { // Only include in the themes page. return; } if ( ! $this->has_paid_plan() ) { // Only include if has any paid plans. return; } $params = null; fs_require_once_template( '/js/jquery.content-change.php', $params ); $params = array( 'slug' => $this->_slug, 'id' => $this->_module_id, ); fs_require_template( '/js/style-premium-theme.php', $params ); } /** * This method will return the absolute URL of the module's local icon. * * When you are running your plugin or theme on a **localhost** environment, if the icon * is not found in the local assets folder, try to fetch the icon URL from Freemius. If not set and * it's a plugin hosted on WordPress.org, try fetching the icon URL from wordpress.org. * If an icon is found, this method will automatically attempt to download the icon and store it * in /freemius/assets/img/{slug}.{png|jpg|gif|svg}. * * It's important to mention that this method is NOT phoning home since the developer will deploy * the product with the local icon in the assets folder. The download process just simplifies * the process for the developer. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return string */ function get_local_icon_url() { global $fs_active_plugins; /** * @since 1.1.7.5 */ $local_path = $this->apply_filters( 'plugin_icon', false ); if ( is_string( $local_path ) ) { $icons = array( $local_path ); } else { $img_dir = WP_FS__DIR_IMG; // Locate the main assets folder. if ( 1 < count( $fs_active_plugins->plugins ) ) { $plugin_or_theme_img_dir = ( $this->is_plugin() ? WP_PLUGIN_DIR : get_theme_root( get_stylesheet() ) ); foreach ( $fs_active_plugins->plugins as $sdk_path => &$data ) { if ( $data->plugin_path == $this->get_plugin_basename() ) { $img_dir = $plugin_or_theme_img_dir . '/' /** * The basename will be `themes` or the basename of a custom themes directory. * * @author Leo Fajardo (@leorw) * @since 2.2.3 */ . str_replace( '../' . basename( $plugin_or_theme_img_dir ) . '/', '', $sdk_path ) . '/assets/img'; break; } } } // Try to locate the icon in the assets folder. $icons = glob( fs_normalize_path( $img_dir . "/{$this->_slug}.*" ) ); if ( ! is_array( $icons ) || 0 === count( $icons ) ) { if ( ! WP_FS__IS_LOCALHOST && $this->is_theme() ) { $icons = array( fs_normalize_path( $img_dir . '/theme-icon.png' ) ); } else { $icon_found = false; $local_path = fs_normalize_path( "{$img_dir}/{$this->_slug}.png" ); if ( ! function_exists( 'get_filesystem_method' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } $have_write_permissions = ( 'direct' === get_filesystem_method( array(), fs_normalize_path( $img_dir ) ) ); /** * IMPORTANT: THIS CODE WILL NEVER RUN AFTER THE PLUGIN IS IN THE REPO. * * This code will only be executed once during the testing * of the plugin in a local environment. The plugin icon file WILL * already exist in the assets folder when the plugin is deployed to * the repository. */ if ( WP_FS__IS_LOCALHOST && $have_write_permissions ) { // Fetch icon from Freemius. $icon = $this->fetch_remote_icon_url(); // Fetch icon from WordPress.org. if ( empty( $icon ) && $this->is_plugin() && $this->is_org_repo_compliant() ) { if ( ! function_exists( 'plugins_api' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; } $plugin_information = plugins_api( 'plugin_information', array( 'slug' => $this->_slug, 'fields' => array( 'sections' => false, 'tags' => false, 'icons' => true ) ) ); if ( ! is_wp_error( $plugin_information ) && isset( $plugin_information->icons ) && ! empty( $plugin_information->icons ) ) { /** * Get the smallest icon. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ $icon = end( $plugin_information->icons ); } } if ( ! empty( $icon ) ) { if ( 0 !== strpos( $icon, 'http' ) ) { $icon = 'http:' . $icon; } /** * Get a clean file extension, e.g.: "jpg" and not "jpg?rev=1305765". * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ $ext = pathinfo( strtok( $icon, '?' ), PATHINFO_EXTENSION ); $local_path = fs_normalize_path( "{$img_dir}/{$this->_slug}.{$ext}" ); // Try to download the icon. $icon_found = fs_download_image( $icon, $local_path ); } } if ( ! $icon_found ) { // No icons found, fallback to default icon. if ( $have_write_permissions ) { // If have write permissions, copy default icon. copy( fs_normalize_path( $img_dir . "/{$this->_module_type}-icon.png" ), $local_path ); } else { // If doesn't have write permissions, use default icon path. $local_path = fs_normalize_path( $img_dir . "/{$this->_module_type}-icon.png" ); } } $icons = array( $local_path ); } } } $icon_dir = dirname( $icons[0] ); return fs_img_url( substr( $icons[0], strlen( $icon_dir ) ), $icon_dir ); } /** * Fetch module's extended info. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return object|mixed */ private function fetch_module_info() { return $this->get_api_plugin_scope()->get( 'info.json', false, WP_FS__TIME_WEEK_IN_SEC ); } /** * Fetch module's remote icon URL. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return string */ function fetch_remote_icon_url() { $info = $this->fetch_module_info(); return ( $this->is_api_result_object( $info, 'icon' ) && is_string( $info->icon ) ) ? $info->icon : ''; } #-------------------------------------------------------------------------------- #region GDPR #-------------------------------------------------------------------------------- /** * @author Leo Fajardo (@leorw) * @since 2.1.0 * * @param array $user_plugins * * @return string */ private function get_gdpr_admin_notice_string( $user_plugins ) { $this->_logger->entrance(); $addons = self::get_all_addons(); foreach ( $user_plugins as $user_plugin ) { $has_addons = isset( $addons[ $user_plugin->id ] ); if ( WP_FS__MODULE_TYPE_PLUGIN === $user_plugin->type && ! $has_addons ) { if ( $this->_module_id == $user_plugin->id ) { $addons = $this->get_addons(); $has_addons = ( ! empty( $addons ) ); } else { $plugin_api = FS_Api::instance( $user_plugin->id, 'plugin', $user_plugin->id, $user_plugin->public_key, ! $user_plugin->is_live, false, $this->get_sdk_version() ); $addons_result = $plugin_api->get( '/addons.json?enriched=true', true ); if ( $this->is_api_result_object( $addons_result, 'plugins' ) && is_array( $addons_result->plugins ) && ! empty( $addons_result->plugins ) ) { $has_addons = true; } } } $user_plugin->has_addons = $has_addons; } $is_single_parent_product = ( 1 === count( $user_plugins ) ); $multiple_products_text = ''; if ( $is_single_parent_product ) { $single_parent_product = reset( $user_plugins ); $thank_you = sprintf( "%s", $single_parent_product->id, sprintf( $single_parent_product->has_addons ? $this->get_text_inline( 'Thank you so much for using %s and its add-ons!', 'thank-you-for-using-product-and-its-addons' ) : $this->get_text_inline( 'Thank you so much for using %s!', 'thank-you-for-using-product' ), sprintf('%s', $single_parent_product->title) ) ); $already_opted_in = sprintf( $this->get_text_inline( "You've already opted-in to our usage-tracking, which helps us keep improving the %s.", 'already-opted-in-to-product-usage-tracking' ), ( WP_FS__MODULE_TYPE_THEME === $single_parent_product->type ) ? WP_FS__MODULE_TYPE_THEME : WP_FS__MODULE_TYPE_PLUGIN ); } else { $thank_you = $this->get_text_inline( 'Thank you so much for using our products!', 'thank-you-for-using-products' ); $already_opted_in = $this->get_text_inline( "You've already opted-in to our usage-tracking, which helps us keep improving them.", 'already-opted-in-to-products-usage-tracking' ); $products_and_add_ons = ''; foreach ( $user_plugins as $user_plugin ) { if ( ! empty( $products_and_add_ons ) ) { $products_and_add_ons .= ', '; } if ( ! $user_plugin->has_addons ) { $products_and_add_ons .= sprintf( "%s", $user_plugin->id, $user_plugin->title ); } else { $products_and_add_ons .= sprintf( "%s", $user_plugin->id, sprintf( $this->get_text_inline( '%s and its add-ons', 'product-and-its-addons' ), $user_plugin->title ) ); } } $multiple_products_text = sprintf( "%s: %s", $this->get_text_inline( 'Products', 'products' ), $products_and_add_ons ); } $actions = sprintf( '
    • %s - %s
    • %s - %s
    ', sprintf('', $this->get_text_inline( 'Yes', 'yes' ) ), $this->get_text_inline( 'send me security & feature updates, educational content and offers.', 'send-updates' ), sprintf('', $this->get_text_inline( 'No', 'no' ) ), sprintf( $this->get_text_inline( 'do %sNOT%s send me security & feature updates, educational content and offers.', 'do-not-send-updates' ), '', '' ) ); return sprintf( '%s %s %s', $thank_you, $already_opted_in, sprintf( $this->get_text_inline( 'Due to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)', 'due-to-gdpr-compliance-requirements' ), '', '' ) . '

    ' . '' . $this->get_text_inline( "Please let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:", 'contact-for-updates' ) . '' . $actions . ( $is_single_parent_product ? '' : $multiple_products_text ) ); } /** * This method is called for opted-in users to fetch the is_marketing_allowed flag of the user for all the * plugins and themes they've opted in to. * * @author Leo Fajardo (@leorw) * @since 2.1.0 * * @param string $user_email * @param string $license_key * @param array $plugin_ids * @param string|null $license_key * * @return array|false */ private function fetch_user_marketing_flag_status_by_plugins( $user_email, $license_key, $plugin_ids ) { $request = array( 'method' => 'POST', 'body' => array(), 'timeout' => WP_FS__DEBUG_SDK ? 60 : 30, ); if ( is_string( $user_email ) ) { $request['body']['email'] = $user_email; } else { $request['body']['license_key'] = $license_key; } $result = array(); $url = WP_FS__ADDRESS . '/action/service/user_plugin/'; $total_plugin_ids = count( $plugin_ids ); $plugin_ids_count_per_request = 10; for ( $i = 1; $i <= $total_plugin_ids; $i += $plugin_ids_count_per_request ) { $plugin_ids_set = array_slice( $plugin_ids, $i - 1, $plugin_ids_count_per_request ); $request['body']['plugin_ids'] = $plugin_ids_set; $response = self::safe_remote_post( $url, $request, WP_FS__TIME_24_HOURS_IN_SEC, WP_FS__TIME_12_HOURS_IN_SEC ); if ( ! is_wp_error( $response ) ) { $decoded = is_string( $response['body'] ) ? json_decode( $response['body'] ) : null; if ( !is_object($decoded) || !isset($decoded->success) || true !== $decoded->success || !isset( $decoded->data ) || !is_array( $decoded->data ) ) { return false; } $result = array_merge( $result, $decoded->data ); } } return $result; } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 */ function _maybe_show_gdpr_admin_notice() { if ( ! $this->is_user_in_admin() ) { return; } if ( ! $this->should_handle_gdpr_admin_notice() ) { return; } if ( ! $this->is_user_admin() ) { return; } require_once WP_FS__DIR_INCLUDES . '/class-fs-user-lock.php'; $lock = FS_User_Lock::instance(); /** * Try to acquire a 60-sec lock based on the WP user and thread/process ID. */ if ( ! $lock->try_lock( 60 ) ) { return; } /** * @var $current_wp_user WP_User */ $current_wp_user = self::_get_current_wp_user(); /** * @var FS_User $current_fs_user */ $current_fs_user = Freemius::_get_user_by_email( $current_wp_user->user_email ); $ten_years_in_sec = 10 * 365 * WP_FS__TIME_24_HOURS_IN_SEC; if ( ! is_object( $current_fs_user ) ) { // 10-year lock. $lock->lock( $ten_years_in_sec ); return; } $gdpr = FS_GDPR_Manager::instance(); if ( $gdpr->is_opt_in_notice_shown() ) { // 30-day lock. $lock->lock( 30 * WP_FS__TIME_24_HOURS_IN_SEC ); return; } if ( ! $gdpr->should_show_opt_in_notice() ) { // 10-year lock. $lock->lock( $ten_years_in_sec ); return; } $last_time_notice_shown = $gdpr->last_time_notice_was_shown(); $was_notice_shown_before = ( false !== $last_time_notice_shown ); if ( $was_notice_shown_before && 30 * WP_FS__TIME_24_HOURS_IN_SEC > time() - $last_time_notice_shown ) { // If the notice was shown before, show it again after 30 days from the last time it was shown. return; } /** * Find all plugin IDs that were installed by the current admin. */ $plugin_ids_map = self::get_user_opted_in_module_ids_map( $current_fs_user->id ); if ( empty( $plugin_ids_map )) { $lock->lock( $ten_years_in_sec ); return; } $user_plugins = $this->fetch_user_marketing_flag_status_by_plugins( $current_fs_user->email, null, array_keys( $plugin_ids_map ) ); if ( empty( $user_plugins ) ) { $lock->lock( is_array($user_plugins) ? $ten_years_in_sec : // Lock for 24-hours on errors. WP_FS__TIME_24_HOURS_IN_SEC ); return; } $has_unset_marketing_optin = false; foreach ( $user_plugins as $user_plugin ) { if ( true == $user_plugin->is_marketing_allowed ) { unset( $plugin_ids_map[ $user_plugin->plugin_id ] ); } if ( ! $has_unset_marketing_optin && is_null( $user_plugin->is_marketing_allowed ) ) { $has_unset_marketing_optin = true; } } if ( empty( $plugin_ids_map ) || ( $was_notice_shown_before && ! $has_unset_marketing_optin ) ) { $lock->lock( $ten_years_in_sec ); return; } $modules = array_merge( array_values( self::maybe_get_entities_account_option( 'plugins', array() ) ), array_values( self::maybe_get_entities_account_option( 'themes', array() ) ) ); foreach ( $modules as $module ) { if ( ! FS_Plugin::is_valid_id( $module->parent_plugin_id ) && isset( $plugin_ids_map[ $module->id ] ) ) { $plugin_ids_map[ $module->id ] = $module; } } $plugin_title = null; if ( 1 === count( $plugin_ids_map ) ) { $module = reset( $plugin_ids_map ); $plugin_title = $module->title; } $gdpr->add_opt_in_sticky_notice( $this->get_gdpr_admin_notice_string( $plugin_ids_map ), $plugin_title ); $this->add_gdpr_optin_ajax_handler_and_style(); $gdpr->notice_was_just_shown(); // 30-day lock. $lock->lock( 30 * WP_FS__TIME_24_HOURS_IN_SEC ); } /** * Prevents the GDPR opt-in admin notice from being added if the user has already chosen to allow or not allow * marketing. * * @author Leo Fajardo (@leorw) * @since 2.1.0 */ private function disable_opt_in_notice_and_lock_user() { FS_GDPR_Manager::instance()->disable_opt_in_notice(); require_once WP_FS__DIR_INCLUDES . '/class-fs-user-lock.php'; // 10-year lock. FS_User_Lock::instance()->lock( 10 * 365 * WP_FS__TIME_24_HOURS_IN_SEC ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.4 */ static function _add_api_connectivity_notice_handler_js() { fs_require_once_template( 'api-connectivity-message-js.php' ); } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 */ function _add_gdpr_optin_js() { $vars = array( 'id' => $this->_module_id ); fs_require_once_template( 'gdpr-optin-js.php', $vars ); } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 */ function enqueue_gdpr_optin_notice_style() { fs_enqueue_local_style( 'fs_gdpr_optin_notice', '/admin/gdpr-optin-notice.css' ); } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 */ function _maybe_add_gdpr_optin_ajax_handler() { $this->add_ajax_action( 'fetch_is_marketing_required_flag_value', array( &$this, '_fetch_is_marketing_required_flag_value_ajax_action' ) ); if ( FS_GDPR_Manager::instance()->is_opt_in_notice_shown() ) { $this->add_gdpr_optin_ajax_handler_and_style(); } } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 */ function _fetch_is_marketing_required_flag_value_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'fetch_is_marketing_required_flag_value' ); $license_key = fs_request_get( 'license_key' ); if ( empty($license_key) ) { self::shoot_ajax_failure( $this->get_text_inline( 'License key is empty.', 'empty-license-key' ) ); } $user_plugins = $this->fetch_user_marketing_flag_status_by_plugins( null, $license_key, array( $this->_module_id ) ); if ( ! is_array( $user_plugins ) || empty($user_plugins) || !isset($user_plugins[0]->plugin_id) || $user_plugins[0]->plugin_id != $this->_module_id ) { /** * If faced an error or if the module ID do not match to the current module, ask for GDPR opt-in. * * @author Vova Feldman (@svovaf) */ self::shoot_ajax_success( array( 'is_marketing_allowed' => null, 'license_owner_id' => null ) ); } self::shoot_ajax_success( array( 'is_marketing_allowed' => $user_plugins[0]->is_marketing_allowed, 'license_owner_id' => ( isset( $user_plugins[0]->license_owner_id ) ? $user_plugins[0]->license_owner_id : null ) ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.3.2 * * @param number[] $install_ids * * @return array { * An array of objects containing the installs' licenses owners data. * * @property number $id User ID. * @property string $email User email (can be masked email). * } */ private function fetch_installs_licenses_owners_data( $install_ids ) { $this->_logger->entrance(); $response = $this->get_api_user_scope()->get( '/licenses_owners.json?install_ids=' . implode( ',', $install_ids ) ); $license_owners = array(); if ( $this->is_api_result_object( $response, 'owners' ) ) { $license_owners = $response->owners; } return $license_owners; } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 */ private function add_gdpr_optin_ajax_handler_and_style() { // Add GDPR action AJAX callback. $this->add_ajax_action( 'gdpr_optin_action', array( &$this, '_gdpr_optin_ajax_action' ) ); add_action( 'admin_footer', array( &$this, '_add_gdpr_optin_js' ) ); add_action( 'admin_enqueue_scripts', array( &$this, 'enqueue_gdpr_optin_notice_style' ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 */ function _gdpr_optin_ajax_action() { $this->_logger->entrance(); $this->check_ajax_referer( 'gdpr_optin_action' ); if ( ! fs_request_has( 'is_marketing_allowed' ) || ! fs_request_has( 'plugin_ids' ) ) { self::shoot_ajax_failure(); } $current_wp_user = self::_get_current_wp_user(); $plugin_ids = fs_request_get( 'plugin_ids', array() ); if ( ! is_array( $plugin_ids ) || empty( $plugin_ids ) ) { self::shoot_ajax_failure(); } $modules = array_merge( array_values( self::maybe_get_entities_account_option( 'plugins', array() ) ), array_values( self::maybe_get_entities_account_option( 'themes', array() ) ) ); foreach ( $modules as $key => $module ) { if ( ! in_array( $module->id, $plugin_ids ) ) { unset( $modules[ $key ] ); } } if ( empty( $modules ) ) { self::shoot_ajax_failure(); } $user_api = $this->get_api_user_scope_by_user( Freemius::_get_user_by_email( $current_wp_user->user_email ) ); foreach ( $modules as $module ) { $user_api->call( "?plugin_id={$module->id}", 'put', array( 'is_marketing_allowed' => ( true == fs_request_get_bool( 'is_marketing_allowed' ) ) ) ); } FS_GDPR_Manager::instance()->remove_opt_in_notice(); require_once WP_FS__DIR_INCLUDES . '/class-fs-user-lock.php'; // 10-year lock. FS_User_Lock::instance()->lock( 10 * 365 * WP_FS__TIME_24_HOURS_IN_SEC ); self::shoot_ajax_success(); } /** * Checks if the GDPR admin notice should be handled. By default, this logic is off, unless the integrator adds the special 'handle_gdpr_admin_notice' filter. * * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @return bool */ private function should_handle_gdpr_admin_notice() { return $this->apply_filters( 'handle_gdpr_admin_notice', // Default to false. false ); } #endregion #---------------------------------------------------------------------------------- #region Marketing #---------------------------------------------------------------------------------- /** * Check if current user purchased any other plugins before. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function has_purchased_before() { // TODO: Implement has_purchased_before() method. throw new Exception( 'not implemented' ); } /** * Check if current user classified as an agency. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_agency() { // TODO: Implement is_agency() method. throw new Exception( 'not implemented' ); } /** * Check if current user classified as a developer. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_developer() { // TODO: Implement is_developer() method. throw new Exception( 'not implemented' ); } /** * Check if current user classified as a business. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @return bool */ function is_business() { // TODO: Implement is_business() method. throw new Exception( 'not implemented' ); } #endregion #---------------------------------------------------------------------------------- #region Helper #---------------------------------------------------------------------------------- /** * If running with a secret key, assume it's the developer and show pending plans as well. * * @author Vova Feldman (@svovaf) * @since 2.1.2 * * @param string $path * * @return string */ function add_show_pending( $path ) { if ( ! $this->has_secret_key() ) { return $path; } return $path . ( false !== strpos( $path, '?' ) ? '&' : '?' ) . 'show_pending=true'; } #endregion } freemius/includes/class-fs-storage.php000064400000055240146725417150014101 0ustar00_module_type = $module_type; $this->_module_slug = $slug; $this->_is_multisite = is_multisite(); if ( $this->_is_multisite ) { $this->_blog_id = get_current_blog_id(); $this->_network_storage = FS_Key_Value_Storage::instance( $module_type . '_data', $slug, true ); } $this->_storage = FS_Key_Value_Storage::instance( $module_type . '_data', $slug, $this->_blog_id ); } /** * Tells this storage wrapper class that the context plugin is network active. This flag will affect how values * are retrieved/stored from/into the storage. * * @author Leo Fajardo (@leorw) * * @param bool $is_network_active * @param bool $is_delegated_connection */ function set_network_active( $is_network_active = true, $is_delegated_connection = false ) { $this->_is_network_active = $is_network_active; $this->_is_delegated_connection = $is_delegated_connection; } /** * Switch the context of the site level storage manager. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id */ function set_site_blog_context( $blog_id ) { $this->_storage = $this->get_site_storage( $blog_id ); $this->_blog_id = $blog_id; } /** * @author Leo Fajardo (@leorw) * * @param string $key * @param mixed $value * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP). * @param int $option_level Since 2.5.1 * @param bool $flush */ function store( $key, $value, $network_level_or_blog_id = null, $option_level = self::OPTION_LEVEL_UNDEFINED, $flush = true ) { if ( $this->should_use_network_storage( $key, $network_level_or_blog_id, $option_level ) ) { $this->_network_storage->store( $key, $value, $flush ); } else { $storage = $this->get_site_storage( $network_level_or_blog_id ); $storage->store( $key, $value, $flush ); } } /** * @author Leo Fajardo (@leorw) * * @param bool $store * @param string[] $exceptions Set of keys to keep and not clear. * @param int|null|bool $network_level_or_blog_id */ function clear_all( $store = true, $exceptions = array(), $network_level_or_blog_id = null ) { if ( ! $this->_is_multisite || false === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) || is_numeric( $network_level_or_blog_id ) ) { $storage = $this->get_site_storage( $network_level_or_blog_id ); $storage->clear_all( $store, $exceptions ); } if ( $this->_is_multisite && ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) ) ) { $this->_network_storage->clear_all( $store, $exceptions ); } } /** * @author Leo Fajardo (@leorw) * * @param string $key * @param bool $store * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP). */ function remove( $key, $store = true, $network_level_or_blog_id = null ) { if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) { $this->_network_storage->remove( $key, $store ); } else { $storage = $this->get_site_storage( $network_level_or_blog_id ); $storage->remove( $key, $store ); } } /** * @author Leo Fajardo (@leorw) * * @param string $key * @param mixed $default * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP). * @param int $option_level Since 2.5.1 * * @return mixed */ function get( $key, $default = false, $network_level_or_blog_id = null, $option_level = self::OPTION_LEVEL_UNDEFINED ) { if ( $this->should_use_network_storage( $key, $network_level_or_blog_id, $option_level ) ) { return $this->_network_storage->get( $key, $default ); } else { $storage = $this->get_site_storage( $network_level_or_blog_id ); return $storage->get( $key, $default ); } } /** * Multisite activated: * true: Save network storage. * int: Save site specific storage. * false|0: Save current site storage. * null: Save network and current site storage. * Site level activated: * Save site storage. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param bool|int|null $network_level_or_blog_id */ function save( $network_level_or_blog_id = null ) { if ( $this->_is_network_active && ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) ) ) { $this->_network_storage->save(); } if ( ! $this->_is_network_active || true !== $network_level_or_blog_id ) { $storage = $this->get_site_storage( $network_level_or_blog_id ); $storage->save(); } } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return string */ function get_module_slug() { return $this->_module_slug; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return string */ function get_module_type() { return $this->_module_type; } /** * Migration script to the new storage data structure that is network compatible. * * IMPORTANT: * This method should be executed only after it is determined if this is a network * level compatible product activation. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function migrate_to_network() { if ( ! $this->_is_multisite ) { return; } $updated = false; if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) { self::load_network_options_map(); } foreach ( self::$_NETWORK_OPTIONS_MAP as $option => $storage_level ) { if ( ! $this->is_multisite_option( $option ) ) { continue; } if ( isset( $this->_storage->{$option} ) && ! isset( $this->_network_storage->{$option} ) ) { // Migrate option to the network storage. $this->_network_storage->store( $option, $this->_storage->{$option}, false ); $updated = true; } } if ( ! $updated ) { return; } // Update network level storage. $this->_network_storage->save(); // $this->_storage->save(); } #-------------------------------------------------------------------------------- #region Helper Methods #-------------------------------------------------------------------------------- /** * We don't want to load the map right away since it's not even needed in a non-MS environment. * * Example: * array( * 'option1' => 0, // Means that the option should always be stored on the network level. * 'option2' => 1, // Means that the option should be stored on the network level only when the module was network level activated. * 'option2' => 2, // Means that the option should be stored on the network level only when the module was network level activated AND the connection was NOT delegated. * 'option3' => 3, // Means that the option should always be stored on the site level. * ) * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ private static function load_network_options_map() { self::$_NETWORK_OPTIONS_MAP = array( // Network level options. 'affiliate_application_data' => self::OPTION_LEVEL_NETWORK, 'beta_data' => self::OPTION_LEVEL_NETWORK, 'connectivity_test' => self::OPTION_LEVEL_NETWORK, 'handle_gdpr_admin_notice' => self::OPTION_LEVEL_NETWORK, 'has_trial_plan' => self::OPTION_LEVEL_NETWORK, 'install_sync_timestamp' => self::OPTION_LEVEL_NETWORK, 'install_sync_cron' => self::OPTION_LEVEL_NETWORK, 'is_anonymous_ms' => self::OPTION_LEVEL_NETWORK, 'is_network_activated' => self::OPTION_LEVEL_NETWORK, 'is_on' => self::OPTION_LEVEL_NETWORK, 'is_plugin_new_install' => self::OPTION_LEVEL_NETWORK, 'network_install_blog_id' => self::OPTION_LEVEL_NETWORK, 'pending_sites_info' => self::OPTION_LEVEL_NETWORK, 'plugin_last_version' => self::OPTION_LEVEL_NETWORK, 'plugin_main_file' => self::OPTION_LEVEL_NETWORK, 'plugin_version' => self::OPTION_LEVEL_NETWORK, 'sdk_downgrade_mode' => self::OPTION_LEVEL_NETWORK, 'sdk_last_version' => self::OPTION_LEVEL_NETWORK, 'sdk_upgrade_mode' => self::OPTION_LEVEL_NETWORK, 'sdk_version' => self::OPTION_LEVEL_NETWORK, 'sticky_optin_added_ms' => self::OPTION_LEVEL_NETWORK, 'subscriptions' => self::OPTION_LEVEL_NETWORK, 'sync_timestamp' => self::OPTION_LEVEL_NETWORK, 'sync_cron' => self::OPTION_LEVEL_NETWORK, 'was_plugin_loaded' => self::OPTION_LEVEL_NETWORK, 'network_user_id' => self::OPTION_LEVEL_NETWORK, 'plugin_upgrade_mode' => self::OPTION_LEVEL_NETWORK, 'plugin_downgrade_mode' => self::OPTION_LEVEL_NETWORK, 'is_network_connected' => self::OPTION_LEVEL_NETWORK, /** * Special flag that is used when a super-admin upgrades to the new version of the SDK that supports network level integration, when the connection decision wasn't made for all the sites in the network. */ 'is_network_activation' => self::OPTION_LEVEL_NETWORK, 'license_migration' => self::OPTION_LEVEL_NETWORK, // When network activated, then network level. 'install_timestamp' => self::OPTION_LEVEL_NETWORK_ACTIVATED, 'prev_is_premium' => self::OPTION_LEVEL_NETWORK_ACTIVATED, 'require_license_activation' => self::OPTION_LEVEL_NETWORK_ACTIVATED, // If not network activated OR delegated, then site level. 'activation_timestamp' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, 'expired_license_notice_shown' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, 'is_whitelabeled' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, 'last_license_key' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, 'last_license_user_id' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, 'prev_user_id' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, 'sticky_optin_added' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, 'uninstall_reason' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, 'is_pending_activation' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, 'pending_license_key' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED, // Site level options. 'is_anonymous' => self::OPTION_LEVEL_SITE, 'clone_id' => self::OPTION_LEVEL_SITE, ); } /** * This method will and should only be executed when is_multisite() is true. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $key * @param int $option_level Since 2.5.1 * * @return bool */ private function is_multisite_option( $key, $option_level = self::OPTION_LEVEL_UNDEFINED ) { if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) { self::load_network_options_map(); } if ( self::OPTION_LEVEL_UNDEFINED === $option_level && isset( self::$_NETWORK_OPTIONS_MAP[ $key ] ) ) { $option_level = self::$_NETWORK_OPTIONS_MAP[ $key ]; } if ( self::OPTION_LEVEL_UNDEFINED === $option_level ) { // Option not found -> use site level storage. return false; } if ( self::OPTION_LEVEL_NETWORK === $option_level ) { // Option found and set to always use the network level storage on a multisite. return true; } if ( self::OPTION_LEVEL_SITE === $option_level ) { // Option found and set to always use the site level storage on a multisite. return false; } if ( ! $this->_is_network_active ) { return false; } if ( self::OPTION_LEVEL_NETWORK_ACTIVATED === $option_level ) { // Network activated. return true; } if ( self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED === $option_level && ! $this->_is_delegated_connection ) { // Network activated and not delegated. return true; } return false; } /** * @author Leo Fajardo * * @param string $key * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_BINARY_MAP). * @param int $option_level Since 2.5.1 * * @return bool */ private function should_use_network_storage( $key, $network_level_or_blog_id = null, $option_level = self::OPTION_LEVEL_UNDEFINED ) { if ( ! $this->_is_multisite ) { // Not a multisite environment. return false; } if ( is_numeric( $network_level_or_blog_id ) ) { // Explicitly asked to use a specified blog storage. return false; } if ( is_bool( $network_level_or_blog_id ) ) { // Explicitly specified whether it should use the network or blog level storage. return $network_level_or_blog_id; } // Determine which storage to use based on the option. return $this->is_multisite_option( $key, $option_level ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id * * @return \FS_Key_Value_Storage */ private function get_site_storage( $blog_id = 0 ) { if ( ! is_numeric( $blog_id ) || $blog_id == $this->_blog_id || 0 == $blog_id ) { return $this->_storage; } return FS_Key_Value_Storage::instance( $this->_module_type . '_data', $this->_storage->get_secondary_id(), $blog_id ); } #endregion #-------------------------------------------------------------------------------- #region Magic methods #-------------------------------------------------------------------------------- function __set( $k, $v ) { if ( $this->should_use_network_storage( $k ) ) { $this->_network_storage->{$k} = $v; } else { $this->_storage->{$k} = $v; } } function __isset( $k ) { return $this->should_use_network_storage( $k ) ? isset( $this->_network_storage->{$k} ) : isset( $this->_storage->{$k} ); } function __unset( $k ) { if ( $this->should_use_network_storage( $k ) ) { unset( $this->_network_storage->{$k} ); } else { unset( $this->_storage->{$k} ); } } function __get( $k ) { return $this->should_use_network_storage( $k ) ? $this->_network_storage->{$k} : $this->_storage->{$k}; } #endregion } freemius/includes/l10n.php000064400000002140146725417150011465 0ustar00_id = $id; $caller = $bt[2]; if ( false !== strpos( $caller['file'], 'plugins' ) ) { $this->_file_start = strpos( $caller['file'], 'plugins' ) + strlen( 'plugins/' ); } else { $this->_file_start = strpos( $caller['file'], 'themes' ) + strlen( 'themes/' ); } if ( $on ) { $this->on(); } if ( $echo ) { $this->echo_on(); } } /** * @param string $id * @param bool $on * @param bool $echo * * @return FS_Logger */ public static function get_logger( $id, $on = false, $echo = false ) { $id = strtolower( $id ); if ( ! isset( self::$_processID ) ) { self::init(); } if ( ! isset( self::$LOGGERS[ $id ] ) ) { self::$LOGGERS[ $id ] = new FS_Logger( $id, $on, $echo ); } return self::$LOGGERS[ $id ]; } /** * Initialize logging global info. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 */ private static function init() { self::$_ownerName = function_exists( 'get_current_user' ) ? get_current_user() : 'unknown'; self::$_isStorageLoggingOn = ( 1 == get_option( 'fs_storage_logger', 0 ) ); self::$_abspathLength = strlen( ABSPATH ); self::$_processID = mt_rand( 0, 32000 ); // Process ID may be `false` on errors. if ( ! is_numeric( self::$_processID ) ) { self::$_processID = 0; } } private static function hook_footer() { if ( self::$_HOOKED_FOOTER ) { return; } if ( is_admin() ) { add_action( 'admin_footer', 'FS_Logger::dump', 100 ); } else { add_action( 'wp_footer', 'FS_Logger::dump', 100 ); } } function is_on() { return $this->_on; } function on() { $this->_on = true; if ( ! function_exists( 'dbDelta' ) ) { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; } self::hook_footer(); } function echo_on() { $this->on(); $this->_echo = true; } function is_echo_on() { return $this->_echo; } function get_id() { return $this->_id; } function get_file() { return $this->_file_start; } private function _log( &$message, $type, $wrapper = false ) { if ( ! $this->is_on() ) { return; } $bt = debug_backtrace(); $depth = $wrapper ? 3 : 2; while ( $depth < count( $bt ) - 1 && 'eval' === $bt[ $depth ]['function'] ) { $depth ++; } $caller = $bt[ $depth ]; /** * Retrieve the correct call file & line number from backtrace * when logging from a wrapper method. * * @author Vova Feldman * @since 1.2.1.6 */ if ( empty( $caller['line'] ) ) { $depth --; while ( $depth >= 0 ) { if ( ! empty( $bt[ $depth ]['line'] ) ) { $caller['line'] = $bt[ $depth ]['line']; $caller['file'] = $bt[ $depth ]['file']; break; } } } $log = array_merge( $caller, array( 'cnt' => self::$CNT ++, 'logger' => $this, 'timestamp' => microtime( true ), 'log_type' => $type, 'msg' => $message, ) ); if ( self::$_isStorageLoggingOn ) { $this->db_log( $type, $message, self::$CNT, $caller ); } self::$LOG[] = $log; if ( $this->is_echo_on() && ! Freemius::is_ajax() ) { echo self::format_html( $log ) . "\n"; } } function log( $message, $wrapper = false ) { $this->_log( $message, 'log', $wrapper ); } function info( $message, $wrapper = false ) { $this->_log( $message, 'info', $wrapper ); } function warn( $message, $wrapper = false ) { $this->_log( $message, 'warn', $wrapper ); } function error( $message, $wrapper = false ) { $this->_log( $message, 'error', $wrapper ); } /** * Log API error. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param mixed $api_result * @param bool $wrapper */ function api_error( $api_result, $wrapper = false ) { $message = ''; if ( is_object( $api_result ) && ! empty( $api_result->error ) && ! empty( $api_result->error->message ) ) { $message = $api_result->error->message; } else if ( is_object( $api_result ) ) { $message = var_export( $api_result, true ); } else if ( is_string( $api_result ) ) { $message = $api_result; } else if ( empty( $api_result ) ) { $message = 'Empty API result.'; } $message = 'API Error: ' . $message; $this->_log( $message, 'error', $wrapper ); } function entrance( $message = '', $wrapper = false ) { $msg = 'Entrance' . ( empty( $message ) ? '' : ' > ' ) . $message; $this->_log( $msg, 'log', $wrapper ); } function departure( $message = '', $wrapper = false ) { $msg = 'Departure' . ( empty( $message ) ? '' : ' > ' ) . $message; $this->_log( $msg, 'log', $wrapper ); } #-------------------------------------------------------------------------------- #region Log Formatting #-------------------------------------------------------------------------------- private static function format( $log, $show_type = true ) { return '[' . str_pad( $log['cnt'], strlen( self::$CNT ), '0', STR_PAD_LEFT ) . '] [' . $log['logger']->_id . '] ' . ( $show_type ? '[' . $log['log_type'] . ']' : '' ) . ( ! empty( $log['class'] ) ? $log['class'] . $log['type'] : '' ) . $log['function'] . ' >> ' . $log['msg'] . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ') ' : '' ) . ' [' . $log['timestamp'] . ']'; } private static function format_html( $log ) { return '
    [' . $log['cnt'] . '] [' . $log['logger']->_id . '] [' . $log['log_type'] . '] ' . ( ! empty( $log['class'] ) ? $log['class'] . $log['type'] : '' ) . $log['function'] . ' >> ' . esc_html( $log['msg'] ) . '' . ( isset( $log['file'] ) ? ' (' . substr( $log['file'], $log['logger']->_file_start ) . ' ' . $log['line'] . ')' : '' ) . ' [' . $log['timestamp'] . ']
    '; } #endregion static function dump() { ?> prefix}fs_logger"; if ( $is_on ) { /** * Create logging table. * * NOTE: * dbDelta must use KEY and not INDEX for indexes. * * @link https://core.trac.wordpress.org/ticket/2695 */ $result = $wpdb->query( "CREATE TABLE {$table} ( `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, `process_id` INT UNSIGNED NOT NULL, `user_name` VARCHAR(64) NOT NULL, `logger` VARCHAR(128) NOT NULL, `log_order` INT UNSIGNED NOT NULL, `type` ENUM('log','info','warn','error') NOT NULL DEFAULT 'log', `message` TEXT NOT NULL, `file` VARCHAR(256) NOT NULL, `line` INT UNSIGNED NOT NULL, `function` VARCHAR(256) NOT NULL, `request_type` ENUM('call','ajax','cron') NOT NULL DEFAULT 'call', `request_url` VARCHAR(1024) NOT NULL, `created` DECIMAL(16, 6) NOT NULL, PRIMARY KEY (`id`), KEY `process_id` (`process_id` ASC), KEY `process_logger` (`process_id` ASC, `logger` ASC), KEY `function` (`function` ASC), KEY `type` (`type` ASC))" ); } else { /** * Drop logging table. */ $result = $wpdb->query( "DROP TABLE IF EXISTS $table;" ); } if ( false !== $result ) { update_option( 'fs_storage_logger', ( $is_on ? 1 : 0 ) ); } return ( false !== $result ); } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @param string $type * @param string $message * @param int $log_order * @param array $caller * * @return false|int */ private function db_log( &$type, &$message, &$log_order, &$caller ) { global $wpdb; $request_type = 'call'; if ( defined( 'DOING_CRON' ) && DOING_CRON ) { $request_type = 'cron'; } else if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { $request_type = 'ajax'; } $request_url = WP_FS__IS_HTTP_REQUEST ? $_SERVER['REQUEST_URI'] : ''; return $wpdb->insert( "{$wpdb->prefix}fs_logger", array( 'process_id' => self::$_processID, 'user_name' => self::$_ownerName, 'logger' => $this->_id, 'log_order' => $log_order, 'type' => $type, 'request_type' => $request_type, 'request_url' => $request_url, 'message' => $message, 'file' => isset( $caller['file'] ) ? substr( $caller['file'], self::$_abspathLength ) : '', 'line' => $caller['line'], 'function' => ( ! empty( $caller['class'] ) ? $caller['class'] . $caller['type'] : '' ) . $caller['function'], 'created' => microtime( true ), ) ); } /** * Persistent DB logger columns. * * @var array */ private static $_log_columns = array( 'id', 'process_id', 'user_name', 'logger', 'log_order', 'type', 'message', 'file', 'line', 'function', 'request_type', 'request_url', 'created', ); /** * Create DB logs query. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @param bool $filters * @param int $limit * @param int $offset * @param bool $order * @param bool $escape_eol * * @return string */ private static function build_db_logs_query( $filters = false, $limit = 200, $offset = 0, $order = false, $escape_eol = false ) { global $wpdb; $select = '*'; if ( $escape_eol ) { $select = ''; for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) { if ( $i > 0 ) { $select .= ', '; } if ( 'message' !== self::$_log_columns[ $i ] ) { $select .= self::$_log_columns[ $i ]; } else { $select .= 'REPLACE(message , \'\n\', \' \') AS message'; } } } $query = "SELECT {$select} FROM {$wpdb->prefix}fs_logger"; if ( is_array( $filters ) ) { $criteria = array(); if ( ! empty( $filters['type'] ) && 'all' !== $filters['type'] ) { $filters['type'] = strtolower( $filters['type'] ); switch ( $filters['type'] ) { case 'warn_error': $criteria[] = array( 'col' => 'type', 'val' => array( 'warn', 'error' ) ); break; case 'error': case 'warn': $criteria[] = array( 'col' => 'type', 'val' => $filters['type'] ); break; case 'info': default: $criteria[] = array( 'col' => 'type', 'val' => array( 'info', 'log' ) ); break; } } if ( ! empty( $filters['request_type'] ) ) { $filters['request_type'] = strtolower( $filters['request_type'] ); if ( in_array( $filters['request_type'], array( 'call', 'ajax', 'cron' ) ) ) { $criteria[] = array( 'col' => 'request_type', 'val' => $filters['request_type'] ); } } if ( ! empty( $filters['file'] ) ) { $criteria[] = array( 'col' => 'file', 'op' => 'LIKE', 'val' => '%' . esc_sql( $filters['file'] ), ); } if ( ! empty( $filters['function'] ) ) { $criteria[] = array( 'col' => 'function', 'op' => 'LIKE', 'val' => '%' . esc_sql( $filters['function'] ), ); } if ( ! empty( $filters['process_id'] ) && is_numeric( $filters['process_id'] ) ) { $criteria[] = array( 'col' => 'process_id', 'val' => $filters['process_id'] ); } if ( ! empty( $filters['logger'] ) ) { $criteria[] = array( 'col' => 'logger', 'op' => 'LIKE', 'val' => '%' . esc_sql( $filters['logger'] ) . '%', ); } if ( ! empty( $filters['message'] ) ) { $criteria[] = array( 'col' => 'message', 'op' => 'LIKE', 'val' => '%' . esc_sql( $filters['message'] ) . '%', ); } if ( 0 < count( $criteria ) ) { $query .= "\nWHERE\n"; $first = true; foreach ( $criteria as $c ) { if ( ! $first ) { $query .= "AND\n"; } if ( is_array( $c['val'] ) ) { $operator = 'IN'; for ( $i = 0, $len = count( $c['val'] ); $i < $len; $i ++ ) { $c['val'][ $i ] = "'" . esc_sql( $c['val'][ $i ] ) . "'"; } $val = '(' . implode( ',', $c['val'] ) . ')'; } else { $operator = ! empty( $c['op'] ) ? $c['op'] : '='; $val = "'" . esc_sql( $c['val'] ) . "'"; } $query .= "`{$c['col']}` {$operator} {$val}\n"; $first = false; } } } if ( ! is_array( $order ) ) { $order = array( 'col' => 'id', 'order' => 'desc' ); } $query .= " ORDER BY {$order['col']} {$order['order']} LIMIT {$offset},{$limit}"; return $query; } /** * Load logs from DB. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @param bool $filters * @param int $limit * @param int $offset * @param bool $order * * @return object[]|null */ public static function load_db_logs( $filters = false, $limit = 200, $offset = 0, $order = false ) { global $wpdb; $query = self::build_db_logs_query( $filters, $limit, $offset, $order ); return $wpdb->get_results( $query ); } /** * Load logs from DB. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @param bool $filters * @param string $filename * @param int $limit * @param int $offset * @param bool $order * * @return false|string File download URL or false on failure. */ public static function download_db_logs( $filters = false, $filename = '', $limit = 10000, $offset = 0, $order = false ) { global $wpdb; $query = self::build_db_logs_query( $filters, $limit, $offset, $order, true ); $upload_dir = wp_upload_dir(); if ( empty( $filename ) ) { $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv'; } $filepath = rtrim( $upload_dir['path'], '/' ) . "/{$filename}"; $query .= " INTO OUTFILE '{$filepath}' FIELDS TERMINATED BY '\t' ESCAPED BY '\\\\' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n'"; $columns = ''; for ( $i = 0, $len = count( self::$_log_columns ); $i < $len; $i ++ ) { if ( $i > 0 ) { $columns .= ', '; } $columns .= "'" . self::$_log_columns[ $i ] . "'"; } $query = "SELECT {$columns} UNION ALL " . $query; $result = $wpdb->query( $query ); if ( false === $result ) { return false; } return rtrim( $upload_dir['url'], '/' ) . '/' . $filename; } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @param string $filename * * @return string */ public static function get_logs_download_url( $filename = '' ) { $upload_dir = wp_upload_dir(); if ( empty( $filename ) ) { $filename = 'fs-logs-' . date( 'Y-m-d_H-i-s', WP_FS__SCRIPT_START_TIME ) . '.csv'; } return rtrim( $upload_dir['url'], '/' ) . $filename; } #endregion } freemius/includes/fs-plugin-info-dialog.php000064400000244121146725417150015014 0ustar00_fs = $fs; $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $fs->get_slug() . '_info', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); // Remove default plugin information action. remove_all_actions( 'install_plugins_pre_plugin-information' ); // Override action with custom plugins function for add-ons. add_action( 'install_plugins_pre_plugin-information', array( &$this, 'install_plugin_information' ) ); // Override request for plugin information for Add-ons. add_filter( 'fs_plugins_api', array( &$this, '_get_addon_info_filter' ), WP_FS__DEFAULT_PRIORITY, 3 ); } /** * Generate add-on plugin information. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param array $data * @param string $action * @param object|null $args * * @return array|null */ function _get_addon_info_filter( $data, $action = '', $args = null ) { $this->_logger->entrance(); $parent_plugin_id = fs_request_get( 'parent_plugin_id', $this->_fs->get_id() ); if ( $this->_fs->get_id() != $parent_plugin_id || ( 'plugin_information' !== $action ) || ! isset( $args->slug ) ) { return $data; } // Find add-on by slug. $selected_addon = $this->_fs->get_addon_by_slug( $args->slug, WP_FS__DEV_MODE ); if ( false === $selected_addon ) { return $data; } if ( ! isset( $selected_addon->info ) ) { // Setup some default info. $selected_addon->info = new stdClass(); $selected_addon->info->selling_point_0 = 'Selling Point 1'; $selected_addon->info->selling_point_1 = 'Selling Point 2'; $selected_addon->info->selling_point_2 = 'Selling Point 3'; $selected_addon->info->description = '

    Tell your users all about your add-on

    '; } fs_enqueue_local_style( 'fs_addons', '/admin/add-ons.css' ); $data = $args; $has_free_plan = false; $has_paid_plan = false; // Load add-on pricing. $has_pricing = false; $has_features = false; $plans = false; $result = $this->_fs->get_api_plugin_scope()->get( $this->_fs->add_show_pending( "/addons/{$selected_addon->id}/pricing.json?type=visible" ) ); if ( ! isset( $result->error ) ) { $plans = $result->plans; if ( is_array( $plans ) ) { for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { $pricing = isset( $plans[ $i ]->pricing ) ? $plans[ $i ]->pricing : null; $features = isset( $plans[ $i ]->features ) ? $plans[ $i ]->features : null; $plans[ $i ] = new FS_Plugin_Plan( $plans[ $i ] ); $plan = $plans[ $i ]; if ( 'free' == $plans[ $i ]->name || ! is_array( $pricing ) || 0 == count( $pricing ) ) { $has_free_plan = true; } if ( is_array( $pricing ) && 0 < count( $pricing ) ) { $filtered_pricing = array(); foreach ( $pricing as $prices ) { $prices = new FS_Pricing( $prices ); if ( ! $prices->is_usd() ) { /** * Skip non-USD pricing. * * @author Leo Fajardo (@leorw) * @since 2.3.1 */ continue; } if ( ( $prices->has_monthly() && $prices->monthly_price > 1.0 ) || ( $prices->has_annual() && $prices->annual_price > 1.0 ) || ( $prices->has_lifetime() && $prices->lifetime_price > 1.0 ) ) { $filtered_pricing[] = $prices; } } if ( ! empty( $filtered_pricing ) ) { $has_paid_plan = true; $plan->pricing = $filtered_pricing; $has_pricing = true; } } if ( is_array( $features ) && 0 < count( $features ) ) { $plan->features = $features; $has_features = true; } } } } $latest = null; if ( ! $has_paid_plan && $selected_addon->is_wp_org_compliant ) { $repo_data = FS_Plugin_Updater::_fetch_plugin_info_from_repository( 'plugin_information', (object) array( 'slug' => $selected_addon->slug, 'is_ssl' => is_ssl(), 'fields' => array( 'banners' => true, 'reviews' => true, 'downloaded' => false, 'active_installs' => true ) ) ); if ( ! empty( $repo_data ) ) { $data = $repo_data; $data->wp_org_missing = false; } else { // Couldn't find plugin on .org. $selected_addon->is_wp_org_compliant = false; // Plugin is missing, not on Freemius nor WP.org. $data->wp_org_missing = true; } $data->fs_missing = ( ! $has_free_plan || $data->wp_org_missing ); } else { $data->has_purchased_license = false; $data->wp_org_missing = false; $fs_addon = null; $current_addon_version = false; if ( $this->_fs->is_addon_activated( $selected_addon->id ) ) { $fs_addon = $this->_fs->get_addon_instance( $selected_addon->id ); $current_addon_version = $fs_addon->get_plugin_version(); } else if ( $this->_fs->is_addon_installed( $selected_addon->id ) ) { $addon_plugin_data = get_plugin_data( ( WP_PLUGIN_DIR . '/' . $this->_fs->get_addon_basename( $selected_addon->id ) ), false, false ); if ( ! empty( $addon_plugin_data ) ) { $current_addon_version = $addon_plugin_data['Version']; } } // Fetch latest version from Freemius. $latest = $this->_fs->_fetch_latest_version( $selected_addon->id, true, WP_FS__TIME_24_HOURS_IN_SEC, $current_addon_version ); if ( $has_paid_plan ) { $blog_id = fs_request_get( 'fs_blog_id' ); $has_valid_blog_id = is_numeric( $blog_id ); if ( $has_valid_blog_id ) { switch_to_blog( $blog_id ); } $data->checkout_link = $this->_fs->checkout_url( WP_FS__PERIOD_ANNUALLY, false, array(), ( $has_valid_blog_id ? false : null ) ); if ( $has_valid_blog_id ) { restore_current_blog(); } } /** * Check if there's a purchased license in case the add-on can only be installed/downloaded as part of a purchased bundle. * * @author Leo Fajardo (@leorw) * @since 2.4.1 */ if ( is_object( $fs_addon ) ) { $data->has_purchased_license = $fs_addon->has_active_valid_license(); } else { $account_addons = $this->_fs->get_account_addons(); if ( ! empty( $account_addons ) && in_array( $selected_addon->id, $account_addons ) ) { $data->has_purchased_license = true; } } if ( $has_free_plan || $data->has_purchased_license ) { $data->download_link = $this->_fs->_get_latest_download_local_url( $selected_addon->id ); } $data->fs_missing = ( false === $latest && ( empty( $selected_addon->premium_releases_count ) || ! ( $selected_addon->premium_releases_count > 0 ) ) ); // Fetch as much as possible info from local files. $plugin_local_data = $this->_fs->get_plugin_data(); $data->author = $plugin_local_data['Author']; if ( ! empty( $selected_addon->info->banner_url ) ) { $data->banners = array( 'low' => $selected_addon->info->banner_url, ); } if ( ! empty( $selected_addon->info->screenshots ) ) { $view_vars = array( 'screenshots' => $selected_addon->info->screenshots, 'plugin' => $selected_addon, ); $data->sections['screenshots'] = fs_get_template( '/plugin-info/screenshots.php', $view_vars ); } if ( is_object( $latest ) ) { $data->version = $latest->version; $data->last_updated = $latest->created; $data->requires = $latest->requires_platform_version; $data->requires_php = $latest->requires_programming_language_version; $data->tested = $latest->tested_up_to_version; } else if ( ! empty( $current_addon_version ) ) { $data->version = $current_addon_version; } else { // Add dummy version. $data->version = '1.0.0'; // Add message to developer to deploy the plugin through Freemius. } } $data->name = $selected_addon->title; $view_vars = array( 'plugin' => $selected_addon ); if ( is_object( $latest ) && isset( $latest->readme ) && is_object( $latest->readme ) ) { $latest_version_readme_data = $latest->readme; if ( isset( $latest_version_readme_data->sections ) ) { $data->sections = (array) $latest_version_readme_data->sections; } else { $data->sections = array(); } } $data->sections['description'] = fs_get_template( '/plugin-info/description.php', $view_vars ); if ( $has_pricing ) { // Add plans to data. $data->plans = $plans; if ( $has_features ) { $view_vars = array( 'plans' => $plans, 'plugin' => $selected_addon, ); $data->sections['features'] = fs_get_template( '/plugin-info/features.php', $view_vars ); } } $data->has_free_plan = $has_free_plan; $data->has_paid_plan = $has_paid_plan; $data->is_paid = $has_paid_plan; $data->is_wp_org_compliant = $selected_addon->is_wp_org_compliant; $data->premium_slug = $selected_addon->premium_slug; $data->addon_id = $selected_addon->id; if ( ! isset( $data->has_purchased_license ) ) { $data->has_purchased_license = false; } return $data; } /** * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @param FS_Plugin_Plan $plan * * @return string */ private function get_billing_cycle( FS_Plugin_Plan $plan ) { $billing_cycle = null; if ( 1 === count( $plan->pricing ) && 1 == $plan->pricing[0]->licenses ) { $pricing = $plan->pricing[0]; if ( isset( $pricing->annual_price ) ) { $billing_cycle = 'annual'; } else if ( isset( $pricing->monthly_price ) ) { $billing_cycle = 'monthly'; } else if ( isset( $pricing->lifetime_price ) ) { $billing_cycle = 'lifetime'; } } else { foreach ( $plan->pricing as $pricing ) { if ( isset( $pricing->annual_price ) ) { $billing_cycle = 'annual'; } else if ( isset( $pricing->monthly_price ) ) { $billing_cycle = 'monthly'; } else if ( isset( $pricing->lifetime_price ) ) { $billing_cycle = 'lifetime'; } if ( ! is_null( $billing_cycle ) ) { break; } } } return $billing_cycle; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param FS_Plugin_Plan $plan * @param FS_Pricing $pricing * * @return float|null|string */ private function get_price_tag( FS_Plugin_Plan $plan, FS_Pricing $pricing ) { $price_tag = ''; if ( isset( $pricing->annual_price ) ) { $price_tag = $pricing->annual_price . ( $plan->is_block_features ? ' / year' : '' ); } else if ( isset( $pricing->monthly_price ) ) { $price_tag = $pricing->monthly_price . ' / mo'; } else if ( isset( $pricing->lifetime_price ) ) { $price_tag = $pricing->lifetime_price; } return '$' . $price_tag; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param object $api * @param FS_Plugin_Plan $plan * * @return string */ private function get_actions_dropdown( $api, $plan = null ) { $this->actions = isset( $this->actions ) ? $this->actions : $this->get_plugin_actions( $api ); $actions = $this->actions; $checkout_cta = $this->get_checkout_cta( $api, $plan ); if ( ! empty( $checkout_cta ) ) { /** * If there's no license yet, make the checkout button the main CTA. Otherwise, make it the last item in * the actions dropdown. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ if ( ! $api->has_purchased_license ) { array_unshift( $actions, $checkout_cta ); } else { $actions[] = $checkout_cta; } } if ( empty( $actions ) ) { return ''; } $total_actions = count( $actions ); if ( 1 === $total_actions ) { return $actions[0]; } ob_start(); ?>
    checkout_link ) || ! isset( $api->plans ) || ! is_array( $api->plans ) || 0 == count( $api->plans ) ) { return ''; } if ( is_null( $plan ) ) { foreach ( $api->plans as $p ) { if ( ! empty( $p->pricing ) ) { $plan = $p; break; } } } $blog_id = fs_request_get( 'fs_blog_id' ); $has_valid_blog_id = is_numeric( $blog_id ); if ( $has_valid_blog_id ) { switch_to_blog( $blog_id ); } $addon_checkout_url = $this->_fs->addon_checkout_url( $plan->plugin_id, $plan->pricing[0]->id, $this->get_billing_cycle( $plan ), $plan->has_trial(), ( $has_valid_blog_id ? false : null ) ); if ( $has_valid_blog_id ) { restore_current_blog(); } return '' . esc_html( ! $plan->has_trial() ? ( $api->has_purchased_license ? fs_text_inline( 'Purchase More', 'purchase-more', $api->slug ) : fs_text_x_inline( 'Purchase', 'verb', 'purchase', $api->slug ) ) : sprintf( /* translators: %s: N-days trial */ fs_text_inline( 'Start my free %s', 'start-free-x', $api->slug ), $this->get_trial_period( $plan ) ) ) . ''; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param object $api * * @return string[] */ private function get_plugin_actions( $api ) { $this->status = isset( $this->status ) ? $this->status : install_plugin_install_status( $api ); $is_update_available = ( 'update_available' === $this->status['status'] ); if ( $is_update_available && empty( $this->status['url'] ) ) { return array(); } $blog_id = fs_request_get( 'fs_blog_id' ); $active_plugins_directories_map = Freemius::get_active_plugins_directories_map( $blog_id ); $actions = array(); $is_addon_activated = $this->_fs->is_addon_activated( $api->slug ); $fs_addon = null; $is_free_installed = null; $is_premium_installed = null; $has_installed_version = ( 'install' !== $this->status['status'] ); if ( ! $api->has_paid_plan && ! $api->has_purchased_license ) { /** * Free-only add-on. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $is_free_installed = $has_installed_version; $is_premium_installed = false; } else if ( ! $api->has_free_plan ) { /** * Premium-only add-on. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $is_free_installed = false; $is_premium_installed = $has_installed_version; } else { /** * Freemium add-on. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ if ( ! $has_installed_version ) { $is_free_installed = false; $is_premium_installed = false; } else { $fs_addon = $is_addon_activated ? $this->_fs->get_addon_instance( $api->slug ) : null; if ( is_object( $fs_addon ) ) { if ( $fs_addon->is_premium() ) { $is_premium_installed = true; } else { $is_free_installed = true; } } if ( is_null( $is_free_installed ) ) { $is_free_installed = file_exists( fs_normalize_path( WP_PLUGIN_DIR . "/{$api->slug}/{$api->slug}.php" ) ); if ( ! $is_free_installed ) { /** * Check if there's a plugin installed in a directory named `$api->slug`. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $installed_plugins = get_plugins( '/' . $api->slug ); $is_free_installed = ( ! empty( $installed_plugins ) ); } } if ( is_null( $is_premium_installed ) ) { $is_premium_installed = file_exists( fs_normalize_path( WP_PLUGIN_DIR . "/{$api->premium_slug}/{$api->slug}.php" ) ); if ( ! $is_premium_installed ) { /** * Check if there's a plugin installed in a directory named `$api->premium_slug`. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $installed_plugins = get_plugins( '/' . $api->premium_slug ); $is_premium_installed = ( ! empty( $installed_plugins ) ); } } } $has_installed_version = ( $is_free_installed || $is_premium_installed ); } $this->status['is_free_installed'] = $is_free_installed; $this->status['is_premium_installed'] = $is_premium_installed; $can_install_free_version = false; $can_install_free_version_update = false; $can_download_free_version = false; $can_activate_free_version = false; $can_install_premium_version = false; $can_install_premium_version_update = false; $can_download_premium_version = false; $can_activate_premium_version = false; if ( ! $api->has_purchased_license ) { if ( $api->has_free_plan ) { if ( $has_installed_version ) { if ( $is_update_available ) { $can_install_free_version_update = true; } else if ( ! $is_premium_installed && ! isset( $active_plugins_directories_map[ dirname( $this->status['file'] ) ] ) ) { $can_activate_free_version = true; } } else { if ( $this->_fs->is_premium() || ! $this->_fs->is_org_repo_compliant() || $api->is_wp_org_compliant ) { $can_install_free_version = true; } else { $can_download_free_version = true; } } } } else { if ( ! is_object( $fs_addon ) && $is_addon_activated ) { $fs_addon = $this->_fs->get_addon_instance( $api->slug ); } $can_download_premium_version = true; if ( ! isset( $active_plugins_directories_map[ dirname( $this->status['file'] ) ] ) ) { if ( $is_premium_installed ) { $can_activate_premium_version = ( ! $is_addon_activated || ! $fs_addon->is_premium() ); } else if ( $is_free_installed ) { $can_activate_free_version = ( ! $is_addon_activated ); } } if ( $this->_fs->is_premium() || ! $this->_fs->is_org_repo_compliant() ) { if ( $is_update_available ) { $can_install_premium_version_update = true; } else if ( ! $is_premium_installed ) { $can_install_premium_version = true; } } } if ( $can_install_premium_version || $can_install_premium_version_update ) { if ( is_numeric( $blog_id ) ) { /** * Replace the network status URL with a blog admin–based status URL if the `Add-Ons` page is loaded * from a specific blog admin page (when `fs_blog_id` is valid) in order for plugin installation/update * to work. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $this->status['url'] = self::get_blog_status_url( $blog_id, $this->status['url'], $this->status['status'] ); } /** * Add the `fs_allow_updater_and_dialog` param to the install/update URL so that the add-on can be * installed/updated. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $this->status['url'] = str_replace( '?', '?fs_allow_updater_and_dialog=true&', $this->status['url'] ); } if ( $can_install_free_version_update || $can_install_premium_version_update ) { $actions[] = $this->get_cta( ( $can_install_free_version_update ? fs_esc_html_inline( 'Install Free Version Update Now', 'install-free-version-update-now', $api->slug ) : fs_esc_html_inline( 'Install Update Now', 'install-update-now', $api->slug ) ), true, false, $this->status['url'], '_parent' ); } else if ( $can_install_free_version || $can_install_premium_version ) { $actions[] = $this->get_cta( ( $can_install_free_version ? fs_esc_html_inline( 'Install Free Version Now', 'install-free-version-now', $api->slug ) : fs_esc_html_inline( 'Install Now', 'install-now', $api->slug ) ), true, false, $this->status['url'], '_parent' ); } $download_latest_action = ''; if ( ! empty( $api->download_link ) && ( $can_download_free_version || $can_download_premium_version ) ) { $download_latest_action = $this->get_cta( ( $can_download_free_version ? fs_esc_html_x_inline( 'Download Latest Free Version', 'as download latest version', 'download-latest-free-version', $api->slug ) : fs_esc_html_x_inline( 'Download Latest', 'as download latest version', 'download-latest', $api->slug ) ), true, false, esc_url( $api->download_link ) ); } if ( ! $can_activate_free_version && ! $can_activate_premium_version ) { if ( ! empty( $download_latest_action ) ) { $actions[] = $download_latest_action; } } else { $activate_action = sprintf( '%s', wp_nonce_url( ( is_numeric( $blog_id ) ? trailingslashit( get_admin_url( $blog_id ) ) : '' ) . 'plugins.php?action=activate&plugin=' . $this->status['file'], 'activate-plugin_' . $this->status['file'] ), fs_esc_attr_inline( 'Activate this add-on', 'activate-this-addon', $api->slug ), $can_activate_free_version ? fs_text_inline( 'Activate Free Version', 'activate-free', $api->slug ) : fs_text_inline( 'Activate', 'activate', $api->slug ) ); if ( ! $can_download_premium_version && ! empty( $download_latest_action ) ) { $actions[] = $download_latest_action; $download_latest_action = ''; } if ( $can_install_premium_version || $can_install_premium_version_update ) { if ( $can_download_premium_version && ! empty( $download_latest_action ) ) { $actions[] = $download_latest_action; $download_latest_action = ''; } $actions[] = $activate_action; } else { array_unshift( $actions, $activate_action ); } if ( ! empty ($download_latest_action ) ) { $actions[] = $download_latest_action; } } return $actions; } /** * Rebuilds the status URL based on the admin URL. * * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param int $blog_id * @param string $network_status_url * @param string $status * * @return string */ private static function get_blog_status_url( $blog_id, $network_status_url, $status ) { if ( ! in_array( $status, array( 'install', 'update_available' ) ) ) { return $network_status_url; } $action = ( 'install' === $status ) ? 'install-plugin' : 'upgrade-plugin'; $query = parse_url( $network_status_url, PHP_URL_QUERY ); if ( empty( $query ) ) { return $network_status_url; } parse_str( html_entity_decode( $query ), $url_params ); if ( empty( $url_params ) || ! isset( $url_params['plugin'] ) ) { return $network_status_url; } $plugin = $url_params['plugin']; return wp_nonce_url( get_admin_url( $blog_id,"update.php?action={$action}&plugin={$plugin}"), "{$action}_{$plugin}"); } /** * Helper method to get a CTA button HTML. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $label * @param bool $is_primary * @param bool $is_disabled * @param string $href * @param string $target * * @return string */ private function get_cta( $label, $is_primary = true, $is_disabled = false, $href = '', $target = '_blank' ) { $classes = array(); if ( ! $is_primary ) { $classes[] = 'left'; } else { $classes[] = 'button-primary'; $classes[] = 'right'; } if ( $is_disabled ) { $classes[] = 'disabled'; } $rel = ( '_blank' === $target ) ? ' rel="noopener noreferrer"' : ''; return sprintf( '%s', empty( $href ) ? '' : 'href="' . $href . '" target="' . $target . '"' . $rel, implode( ' ', $classes ), $label ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.7 * * @param FS_Plugin_Plan $plan * * @return string */ private function get_trial_period( $plan ) { $trial_period = (int) $plan->trial_period; switch ( $trial_period ) { case 30: return 'month'; case 60: return '2 months'; default: return "{$plan->trial_period} days"; } } /** * Display plugin information in dialog box form. * * Based on core install_plugin_information() function. * * @author Vova Feldman (@svovaf) * @since 1.0.6 */ function install_plugin_information() { global $tab; if ( empty( $_REQUEST['plugin'] ) ) { return; } $args = array( 'slug' => wp_unslash( $_REQUEST['plugin'] ), 'is_ssl' => is_ssl(), 'fields' => array( 'banners' => true, 'reviews' => true, 'downloaded' => false, 'active_installs' => true ) ); if ( is_array( $args ) ) { $args = (object) $args; } if ( ! isset( $args->per_page ) ) { $args->per_page = 24; } if ( ! isset( $args->locale ) ) { $args->locale = get_locale(); } $api = apply_filters( 'fs_plugins_api', false, 'plugin_information', $args ); if ( is_wp_error( $api ) ) { wp_die( $api ); } $plugins_allowedtags = array( 'a' => array( 'href' => array(), 'title' => array(), 'target' => array(), // Add image style for screenshots. 'class' => array() ), 'style' => array(), 'abbr' => array( 'title' => array() ), 'acronym' => array( 'title' => array() ), 'code' => array(), 'pre' => array(), 'em' => array(), 'strong' => array(), 'div' => array( 'class' => array() ), 'span' => array( 'class' => array() ), 'p' => array(), 'ul' => array(), 'ol' => array(), 'li' => array( 'class' => array() ), 'i' => array( 'class' => array() ), 'h1' => array(), 'h2' => array(), 'h3' => array(), 'h4' => array(), 'h5' => array(), 'h6' => array(), 'img' => array( 'src' => array(), 'class' => array(), 'alt' => array() ), // 'table' => array(), // 'td' => array(), // 'tr' => array(), // 'th' => array(), // 'thead' => array(), // 'tbody' => array(), ); $plugins_section_titles = array( 'description' => fs_text_x_inline( 'Description', 'Plugin installer section title', 'description', $api->slug ), 'installation' => fs_text_x_inline( 'Installation', 'Plugin installer section title', 'installation', $api->slug ), 'faq' => fs_text_x_inline( 'FAQ', 'Plugin installer section title', 'faq', $api->slug ), 'screenshots' => fs_text_inline( 'Screenshots', 'screenshots', $api->slug ), 'changelog' => fs_text_x_inline( 'Changelog', 'Plugin installer section title', 'changelog', $api->slug ), 'reviews' => fs_text_x_inline( 'Reviews', 'Plugin installer section title', 'reviews', $api->slug ), 'other_notes' => fs_text_x_inline( 'Other Notes', 'Plugin installer section title', 'other-notes', $api->slug ), ); // Sanitize HTML // foreach ( (array) $api->sections as $section_name => $content ) { // $api->sections[$section_name] = wp_kses( $content, $plugins_allowedtags ); // } foreach ( array( 'version', 'author', 'requires', 'tested', 'homepage', 'downloaded', 'slug' ) as $key ) { if ( isset( $api->$key ) ) { $api->$key = wp_kses( $api->$key, $plugins_allowedtags ); } } // Add after $api->slug is ready. $plugins_section_titles['features'] = fs_text_x_inline( 'Features & Pricing', 'Plugin installer section title', 'features-and-pricing', $api->slug ); $_tab = esc_attr( $tab ); $section = isset( $_REQUEST['section'] ) ? wp_unslash( $_REQUEST['section'] ) : 'description'; // Default to the Description tab, Do not translate, API returns English. if ( empty( $section ) || ! isset( $api->sections[ $section ] ) ) { $section_titles = array_keys( (array) $api->sections ); $section = array_shift( $section_titles ); } iframe_header( fs_text_inline( 'Plugin Install', 'plugin-install', $api->slug ) ); $_with_banner = ''; // var_dump($api->banners); if ( ! empty( $api->banners ) && ( ! empty( $api->banners['low'] ) || ! empty( $api->banners['high'] ) ) ) { $_with_banner = 'with-banner'; $low = empty( $api->banners['low'] ) ? $api->banners['high'] : $api->banners['low']; $high = empty( $api->banners['high'] ) ? $api->banners['low'] : $api->banners['high']; ?> '; echo "

    {$api->name}

    "; echo "
    \n"; foreach ( (array) $api->sections as $section_name => $content ) { if ( 'reviews' === $section_name && ( empty( $api->ratings ) || 0 === array_sum( (array) $api->ratings ) ) ) { continue; } if ( isset( $plugins_section_titles[ $section_name ] ) ) { $title = $plugins_section_titles[ $section_name ]; } else { $title = ucwords( str_replace( '_', ' ', $section_name ) ); } $class = ( $section_name === $section ) ? ' class="current"' : ''; $href = add_query_arg( array( 'tab' => $tab, 'section' => $section_name ) ); $href = esc_url( $href ); $san_section = esc_attr( $section_name ); echo "\t" . esc_html( $title ) . "\n"; } echo "
    \n"; ?>
    is_paid ) : ?> plans ) ) : ?>
    plans as $plan ) : ?> pricing ) ) { continue; } /** * @var FS_Plugin_Plan $plan */ ?> pricing[0] ?> is_multi_cycle() ?>

    slug ), $plan->title ) ) ?>

    has_annual() ?> has_monthly() ?>
    pricing[0]->annual_discount_percentage() : 0 ?> 0 ) : ?> slug ), $annual_discount . '%' ) ?>
    get_actions_dropdown( $api, $plan ) ?>
    has_trial() ) : ?> get_trial_period( $plan ) ?>
    • slug ), $trial_period ) ) ?>
    • slug ) ), $trial_period, '' . $this->get_price_tag( $plan, $plan->pricing[0] ) . '' ) ?>

    slug ) ?>

      version ) ) { ?>
    • slug ); ?> : version; ?>
    • author ) ) { ?>
    • slug ); ?> : author, '_blank' ); ?>
    • last_updated ) ) { ?>
    • slug ); ?> : slug ), human_time_diff( strtotime( $api->last_updated ) ) ) ) ?>
    • requires ) ) { ?>
    • slug ) ?> : slug ), $api->requires ) ) ?>
    • tested ) ) { ?>
    • slug ); ?> : tested; ?>
    • requires_php ) ) { ?>
    • slug ); ?>: slug ), $api->requires_php ) ); ?>
    • downloaded ) ) { ?>
    • slug ) ?> : downloaded ) ? /* translators: %s: 1 or One (Number of times downloaded) */ fs_text_inline( '%s time', 'x-time', $api->slug ) : /* translators: %s: Number of times downloaded */ fs_text_inline( '%s times', 'x-times', $api->slug ) ), number_format_i18n( $api->downloaded ) ) ); ?>
    • slug ) && true == $api->is_wp_org_compliant ) { ?>
    • slug ) ?> »
    • homepage ) ) { ?>
    • slug ) ?> »
    • donate_link ) && empty( $api->contributors ) ) { ?>
    • slug ) ?> »
    rating ) ) { ?>

    slug ); ?>

    $api->rating, 'type' => 'percent', 'number' => $api->num_ratings ) ); ?> (slug ), sprintf( ( ( 1 == $api->num_ratings ) ? /* translators: %s: 1 or One */ fs_text_inline( '%s rating', 'x-rating', $api->slug ) : /* translators: %s: Number larger than 1 */ fs_text_inline( '%s ratings', 'x-ratings', $api->slug ) ), number_format_i18n( $api->num_ratings ) ) ) ) ?>) ratings ) && array_sum( (array) $api->ratings ) > 0 ) { foreach ( $api->ratings as $key => $ratecount ) { // Avoid div-by-zero. $_rating = $api->num_ratings ? ( $ratecount / $api->num_ratings ) : 0; $stars_label = sprintf( ( ( 1 == $key ) ? /* translators: %s: 1 or One */ fs_text_inline( '%s star', 'x-star', $api->slug ) : /* translators: %s: Number larger than 1 */ fs_text_inline( '%s stars', 'x-stars', $api->slug ) ), number_format_i18n( $key ) ); ?>
    contributors ) ) { ?>

    slug ); ?>

      contributors as $contrib_username => $contrib_profile ) { if ( empty( $contrib_username ) && empty( $contrib_profile ) ) { continue; } if ( empty( $contrib_username ) ) { $contrib_username = preg_replace( '/^.+\/(.+)\/?$/', '\1', $contrib_profile ); } $contrib_username = sanitize_user( $contrib_username ); if ( empty( $contrib_profile ) ) { echo "
    • {$contrib_username}
    • "; } else { echo "
    • {$contrib_username}
    • "; } } ?>
    donate_link ) ) { ?> slug ) ?> »
    requires_php ) ? $api->requires_php : null; $requires_wp = isset( $api->requires ) ? $api->requires : null; $compatible_php = empty( $requires_php ) || version_compare( PHP_VERSION, $requires_php, '>=' ); // Strip off any -alpha, -RC, -beta, -src suffixes. list( $wp_version ) = explode( '-', $GLOBALS['wp_version'] ); $compatible_wp = empty( $requires_wp ) || version_compare( $wp_version, $requires_wp, '>=' ); $tested_wp = ( empty( $api->tested ) || version_compare( $wp_version, $api->tested, '<=' ) ); if ( ! $compatible_php ) { echo '

    ' . fs_text_inline( 'Error', 'error', $api->slug ) . ': ' . fs_text_inline( 'This plugin requires a newer version of PHP.', 'newer-php-required-error', $api->slug ); if ( current_user_can( 'update_php' ) ) { $wp_get_update_php_url = function_exists( 'wp_get_update_php_url' ) ? wp_get_update_php_url() : 'https://wordpress.org/support/update-php/'; printf( /* translators: %s: URL to Update PHP page. */ ' ' . fs_text_inline( 'Click here to learn more about updating PHP.', 'php-update-learn-more-link', $api->slug ), esc_url( $wp_get_update_php_url ) ); if ( function_exists( 'wp_update_php_annotation' ) ) { wp_update_php_annotation( '

    ', '' ); } } else { echo '

    '; } echo '
    '; } if ( ! $tested_wp ) { echo '

    ' . '' . fs_text_inline( 'Warning', 'warning', $api->slug ) . ': ' . fs_text_inline( 'This plugin has not been tested with your current version of WordPress.', 'not-tested-warning', $api->slug ) . '

    '; } else if ( ! $compatible_wp ) { echo '

    ' . '' . fs_text_inline( 'Warning', 'warning', $api->slug ) . ': ' . fs_text_inline( 'This plugin has not been marked as compatible with your version of WordPress.', 'not-compatible-warning', $api->slug ) . '

    '; } foreach ( (array) $api->sections as $section_name => $content ) { $content = links_add_base_url( $content, 'https://wordpress.org/plugins/' . $api->slug . '/' ); $content = links_add_target( $content, '_blank' ); $san_section = esc_attr( $section_name ); $display = ( $section_name === $section ) ? 'block' : 'none'; if ( 'description' === $section_name && ( ( $api->is_wp_org_compliant && $api->wp_org_missing ) || ( ! $api->is_wp_org_compliant && $api->fs_missing ) ) ) { $missing_notice = array( 'type' => 'error', 'id' => md5( microtime() ), 'message' => $api->is_paid ? fs_text_inline( 'Paid add-on must be deployed to Freemius.', 'paid-addon-not-deployed', $api->slug ) : fs_text_inline( 'Add-on must be deployed to WordPress.org or Freemius.', 'free-addon-not-deployed', $api->slug ), ); fs_require_template( 'admin-notice.php', $missing_notice ); } echo "\t
    \n"; echo $content; echo "\t
    \n"; } echo "
    \n"; echo "
    \n"; echo "
    \n"; // #plugin-information-scrollable echo "\n"; ?> _id = $id; $this->_title = $title; $this->_module_unique_affix = $module_unique_affix; $this->_is_multisite = is_multisite(); if ( $this->_is_multisite ) { $this->_blog_id = get_current_blog_id(); $this->_network_notices = FS_Admin_Notice_Manager::instance( $id, $title, $module_unique_affix, $is_network_and_blog_admins, true ); } $this->_notices = FS_Admin_Notice_Manager::instance( $id, $title, $module_unique_affix, false, $this->_blog_id ); } /** * Add admin message to admin messages queue, and hook to admin_notices / all_admin_notices if not yet hooked. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param string $message * @param string $title * @param string $type * @param bool $is_sticky * @param string $id Message ID * @param bool $store_if_sticky * @param int|null $network_level_or_blog_id * * @uses add_action() */ function add( $message, $title = '', $type = 'success', $is_sticky = false, $id = '', $store_if_sticky = true, $network_level_or_blog_id = null, $is_dimissible = null ) { $notices = $this->get_site_or_network_notices( $id, $network_level_or_blog_id ); $notices->add( $message, $title, $type, $is_sticky, $id, $store_if_sticky, null, null, false, $is_dimissible ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param string|string[] $ids * @param int|null $network_level_or_blog_id * @param bool $store */ function remove_sticky( $ids, $network_level_or_blog_id = null, $store = true ) { if ( ! is_array( $ids ) ) { $ids = array( $ids ); } if ( $this->should_use_network_notices( $ids[0], $network_level_or_blog_id ) ) { $notices = $this->_network_notices; } else { $notices = $this->get_site_notices( $network_level_or_blog_id ); } return $notices->remove_sticky( $ids, $store ); } /** * Check if sticky message exists by id. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string $id * @param int|null $network_level_or_blog_id * * @return bool */ function has_sticky( $id, $network_level_or_blog_id = null ) { $notices = $this->get_site_or_network_notices( $id, $network_level_or_blog_id ); return $notices->has_sticky( $id ); } /** * Adds sticky admin notification. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param string $message * @param string $id Message ID * @param string $title * @param string $type * @param int|null $network_level_or_blog_id * @param number|null $wp_user_id * @param string|null $plugin_title * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network and * blog admin pages. * @param bool $is_dismissible */ function add_sticky( $message, $id, $title = '', $type = 'success', $network_level_or_blog_id = null, $wp_user_id = null, $plugin_title = null, $is_network_and_blog_admins = false, $is_dismissible = true, $data = array() ) { $notices = $this->get_site_or_network_notices( $id, $network_level_or_blog_id ); $notices->add_sticky( $message, $id, $title, $type, $wp_user_id, $plugin_title, $is_network_and_blog_admins, $is_dismissible, $data ); } /** * Retrieves the data of a sticky notice. * * @author Leo Fajardo (@leorw) * @since 2.4.3 * * @param string $id * @param int|null $network_level_or_blog_id * * @return array|null */ function get_sticky( $id, $network_level_or_blog_id ) { $notices = $this->get_site_or_network_notices( $id, $network_level_or_blog_id ); return $notices->get_sticky( $id ); } /** * Clear all sticky messages. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int|null $network_level_or_blog_id * @param bool $is_temporary */ function clear_all_sticky( $network_level_or_blog_id = null, $is_temporary = false ) { if ( ! $this->_is_multisite || false === $network_level_or_blog_id || 0 == $network_level_or_blog_id || is_null( $network_level_or_blog_id ) ) { $notices = $this->get_site_notices( $network_level_or_blog_id ); $notices->clear_all_sticky( $is_temporary ); } if ( $this->_is_multisite && ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) ) ) { $this->_network_notices->clear_all_sticky( $is_temporary ); } } /** * Add admin message to all admin messages queue, and hook to all_admin_notices if not yet hooked. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param string $message * @param string $title * @param string $type * @param bool $is_sticky * @param string $id Message ID */ function add_all( $message, $title = '', $type = 'success', $is_sticky = false, $id = '' ) { $this->add( $message, $title, $type, $is_sticky, true, $id ); } #-------------------------------------------------------------------------------- #region Helper Methods #-------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id * * @return FS_Admin_Notice_Manager */ private function get_site_notices( $blog_id = 0 ) { if ( 0 == $blog_id || $blog_id == $this->_blog_id ) { return $this->_notices; } return FS_Admin_Notice_Manager::instance( $this->_id, $this->_title, $this->_module_unique_affix, false, $blog_id ); } /** * Check if the network notices should be used. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $id * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite notices (if there's a network). When `false`, use the current context blog notices. When `null`, the decision which notices manager to use (MS vs. Current S) will be handled internally and determined based on the $id and the context admin (blog admin vs. network level admin). * * @return bool */ private function should_use_network_notices( $id = '', $network_level_or_blog_id = null ) { if ( ! $this->_is_multisite ) { // Not a multisite environment. return false; } if ( is_numeric( $network_level_or_blog_id ) ) { // Explicitly asked to use a specified blog storage. return false; } if ( is_bool( $network_level_or_blog_id ) ) { // Explicitly specified whether should use the network or blog level storage. return $network_level_or_blog_id; } return fs_is_network_admin(); } /** * Retrieves an instance of FS_Admin_Notice_Manager. * * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param string $id * @param int|null $network_level_or_blog_id * * @return FS_Admin_Notice_Manager */ private function get_site_or_network_notices( $id, $network_level_or_blog_id ) { return $this->should_use_network_notices( $id, $network_level_or_blog_id ) ? $this->_network_notices : $this->get_site_notices( $network_level_or_blog_id ); } #endregion }freemius/includes/class-fs-user-lock.php000064400000004423146725417150014336 0ustar00_lock = new FS_Lock( "locked_{$current_user_id}" ); } /** * Try to acquire lock. If the lock is already set or is being acquired by another locker, don't do anything. * * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @param int $expiration * * @return bool TRUE if successfully acquired lock. */ function try_lock( $expiration = 0 ) { return $this->_lock->try_lock( $expiration ); } /** * Acquire lock regardless if it's already acquired by another locker or not. * * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @param int $expiration */ function lock( $expiration = 0 ) { $this->_lock->lock( $expiration ); } /** * Unlock the lock. * * @author Vova Feldman (@svovaf) * @since 2.1.0 */ function unlock() { $this->_lock->unlock(); } }freemius/includes/class-fs-lock.php000064400000005451146725417150013364 0ustar00_lock_id = $lock_id; if ( ! isset( self::$_thread_id ) ) { self::$_thread_id = mt_rand( 0, 32000 ); } } /** * Try to acquire lock. If the lock is already set or is being acquired by another locker, don't do anything. * * @param int $expiration * * @return bool TRUE if successfully acquired lock. */ function try_lock( $expiration = 0 ) { if ( $this->is_locked() ) { // Already locked. return false; } set_site_transient( $this->_lock_id, self::$_thread_id, $expiration ); if ( $this->has_lock() ) { $this->lock($expiration); return true; } return false; } /** * Acquire lock regardless if it's already acquired by another locker or not. * * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @param int $expiration */ function lock( $expiration = 0 ) { set_site_transient( $this->_lock_id, true, $expiration ); } /** * Checks if lock is currently acquired. * * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @return bool */ function is_locked() { return ( false !== get_site_transient( $this->_lock_id ) ); } /** * Unlock the lock. * * @author Vova Feldman (@svovaf) * @since 2.1.0 */ function unlock() { delete_site_transient( $this->_lock_id ); } /** * Checks if lock is currently acquired by the current locker. * * @return bool */ protected function has_lock() { return ( self::$_thread_id == get_site_transient( $this->_lock_id ) ); } }freemius/includes/index.php000064400000000127146725417150012025 0ustar00 ' : '' ) . $title; if ( is_string( $confirmation ) ) { return sprintf( '
    %s%s
    ', freemius( $module_id )->_get_admin_page_url( $page, $params ), $method, $action, wp_nonce_field( $action, '_wpnonce', true, false ), 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ), $confirmation, $title ); } else if ( 'GET' !== strtoupper( $method ) ) { return sprintf( '
    %s%s
    ', freemius( $module_id )->_get_admin_page_url( $page, $params ), $method, $action, wp_nonce_field( $action, '_wpnonce', true, false ), 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ), $title ); } else { return sprintf( '%s', wp_nonce_url( freemius( $module_id )->_get_admin_page_url( $page, array_merge( $params, array( 'fs_action' => $action ) ) ), $action ), 'button' . ( ! empty( $button_class ) ? ' ' . $button_class : '' ) . ( $is_primary ? ' button-primary' : '' ) . ( $is_small ? ' button-small' : '' ), $title ); } } function fs_ui_action_link( $module_id, $page, $action, $title, $params = array() ) { ?> $entities_or_entity ) { if ( is_array( $entities_or_entity ) ) { $entities[ $key ] = fs_get_entities( $entities_or_entity, $class_name ); } else { $entities[ $key ] = fs_get_entity( $entities_or_entity, $class_name ); } } return $entities; } } if ( ! function_exists( 'fs_nonce_url' ) ) { /** * Retrieve URL with nonce added to URL query. * * Originally was using `wp_nonce_url()` but the new version * changed the return value to escaped URL, that's not the expected * behaviour. * * @author Vova Feldman (@svovaf) * @since ~1.1.3 * * @param string $actionurl URL to add nonce action. * @param int|string $action Optional. Nonce action name. Default -1. * @param string $name Optional. Nonce name. Default '_wpnonce'. * * @return string Escaped URL with nonce action added. */ function fs_nonce_url( $actionurl, $action = - 1, $name = '_wpnonce' ) { return add_query_arg( $name, wp_create_nonce( $action ), $actionurl ); } } if ( ! function_exists( 'fs_starts_with' ) ) { /** * Check if string starts with. * * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param string $haystack * @param string $needle * * @return bool */ function fs_starts_with( $haystack, $needle ) { $length = strlen( $needle ); return ( substr( $haystack, 0, $length ) === $needle ); } } if ( ! function_exists( 'fs_ends_with' ) ) { /** * Check if string ends with. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $haystack * @param string $needle * * @return bool */ function fs_ends_with( $haystack, $needle ) { $length = strlen( $needle ); $start = $length * - 1; // negative return ( substr( $haystack, $start ) === $needle ); } } if ( ! function_exists( 'fs_strip_url_protocol' ) ) { function fs_strip_url_protocol( $url ) { if ( ! fs_starts_with( $url, 'http' ) ) { return $url; } $protocol_pos = strpos( $url, '://' ); if ( $protocol_pos > 5 ) { return $url; } return substr( $url, $protocol_pos + 3 ); } } #region Url Canonization ------------------------------------------------------------------ if ( ! function_exists( 'fs_canonize_url' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param string $url * @param bool $omit_host * @param array $ignore_params * * @return string */ function fs_canonize_url( $url, $omit_host = false, $ignore_params = array() ) { $parsed_url = parse_url( strtolower( $url ) ); // if ( ! isset( $parsed_url['host'] ) ) { // return $url; // } $canonical = ( ( $omit_host || ! isset( $parsed_url['host'] ) ) ? '' : $parsed_url['host'] ) . $parsed_url['path']; if ( isset( $parsed_url['query'] ) ) { parse_str( $parsed_url['query'], $queryString ); $canonical .= '?' . fs_canonize_query_string( $queryString, $ignore_params ); } return $canonical; } } if ( ! function_exists( 'fs_canonize_query_string' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param array $params * @param array $ignore_params * @param bool $params_prefix * * @return string */ function fs_canonize_query_string( array $params, array &$ignore_params, $params_prefix = false ) { if ( ! is_array( $params ) || 0 === count( $params ) ) { return ''; } // Url encode both keys and values $keys = fs_urlencode_rfc3986( array_keys( $params ) ); $values = fs_urlencode_rfc3986( array_values( $params ) ); $params = array_combine( $keys, $values ); // Parameters are sorted by name, using lexicographical byte value ordering. // Ref: Spec: 9.1.1 (1) uksort( $params, 'strcmp' ); $pairs = array(); foreach ( $params as $parameter => $value ) { $lower_param = strtolower( $parameter ); // Skip ignore params. if ( in_array( $lower_param, $ignore_params ) || ( false !== $params_prefix && fs_starts_with( $lower_param, $params_prefix ) ) ) { continue; } if ( is_array( $value ) ) { // If two or more parameters share the same name, they are sorted by their value // Ref: Spec: 9.1.1 (1) natsort( $value ); foreach ( $value as $duplicate_value ) { $pairs[] = $lower_param . '=' . $duplicate_value; } } else { $pairs[] = $lower_param . '=' . $value; } } if ( 0 === count( $pairs ) ) { return ''; } return implode( "&", $pairs ); } } if ( ! function_exists( 'fs_urlencode_rfc3986' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param string|string[] $input * * @return array|mixed|string */ function fs_urlencode_rfc3986( $input ) { if ( is_array( $input ) ) { return array_map( 'fs_urlencode_rfc3986', $input ); } else if ( is_scalar( $input ) ) { return str_replace( '+', ' ', str_replace( '%7E', '~', rawurlencode( $input ) ) ); } return ''; } } #endregion Url Canonization ------------------------------------------------------------------ if ( ! function_exists( 'fs_download_image' ) ) { /** * @author Vova Feldman (@svovaf) * * @since 1.2.2 Changed to usage of WP_Filesystem_Direct. * * @param string $from URL * @param string $to File path. * * @return bool Is successfully downloaded. */ function fs_download_image( $from, $to ) { $dir = dirname( $to ); if ( 'direct' !== get_filesystem_method( array(), $dir ) ) { return false; } if ( ! class_exists( 'WP_Filesystem_Direct' ) ) { require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php'; require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php'; } $fs = new WP_Filesystem_Direct( '' ); $tmpfile = download_url( $from ); if ( $tmpfile instanceof WP_Error ) { // Issue downloading the file. return false; } $fs->copy( $tmpfile, $to ); $fs->delete( $tmpfile ); return true; } } /* General Utilities --------------------------------------------------------------------------------------------*/ if ( ! function_exists( 'fs_sort_by_priority' ) ) { /** * Sorts an array by the value of the priority key. * * @author Daniel Iser (@danieliser) * @since 1.1.7 * * @param $a * @param $b * * @return int */ function fs_sort_by_priority( $a, $b ) { // If b has a priority and a does not, b wins. if ( ! isset( $a['priority'] ) && isset( $b['priority'] ) ) { return 1; } // If b has a priority and a does not, b wins. elseif ( isset( $a['priority'] ) && ! isset( $b['priority'] ) ) { return - 1; } // If neither has a priority or both priorities are equal it's a tie. elseif ( ( ! isset( $a['priority'] ) && ! isset( $b['priority'] ) ) || $a['priority'] === $b['priority'] ) { return 0; } // If both have priority return the winner. return ( $a['priority'] < $b['priority'] ) ? - 1 : 1; } } #-------------------------------------------------------------------------------- #region Localization #-------------------------------------------------------------------------------- global $fs_text_overrides; if ( ! isset( $fs_text_overrides ) ) { $fs_text_overrides = array(); } if ( ! function_exists( 'fs_text' ) ) { /** * Retrieve a translated text by key. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param string $key * @param string $slug * * @return string * * @global $fs_text_overrides */ function fs_text( $key, $slug = 'freemius' ) { global $fs_text_overrides; if ( isset( $fs_text_overrides[ $slug ] ) ) { if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) { return $fs_text_overrides[ $slug ][ $key ]; } $lower_key = strtolower( $key ); if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) { return $fs_text_overrides[ $slug ][ $lower_key ]; } } return $key; } #region Private /** * Retrieve an inline translated text by key with a context. * * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $context Context information for the translators. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string * * @global $fs_text_overrides */ function _fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) { list( $text, $text_domain ) = fs_text_and_domain( $text, $key, $slug ); // Avoid misleading Theme Check warning. $fn = 'translate_with_gettext_context'; return $fn( $text, $context, $text_domain ); } #endregion /** * Retrieve an inline translated text by key with a context. * * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $context Context information for the translators. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string * * @global $fs_text_overrides */ function fs_text_x_inline( $text, $context, $key = '', $slug = 'freemius' ) { return _fs_text_x_inline( $text, $context, $key, $slug ); } /** * Output a translated text by key. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param string $key * @param string $slug */ function fs_echo( $key, $slug = 'freemius' ) { echo fs_text( $key, $slug ); } /** * Output an inline translated text. * * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. */ function fs_echo_inline( $text, $key = '', $slug = 'freemius' ) { echo _fs_text_inline( $text, $key, $slug ); } /** * Output an inline translated text with a context. * * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $context Context information for the translators. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. */ function fs_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) { echo _fs_text_x_inline( $text, $context, $key, $slug ); } } if ( ! function_exists( 'fs_text_override' ) ) { /** * Get a translatable text override if exists, or `false`. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string|false */ function fs_text_override( $text, $key, $slug ) { global $fs_text_overrides; /** * Check if string is overridden. */ if ( ! isset( $fs_text_overrides[ $slug ] ) ) { return false; } if ( empty( $key ) ) { $key = strtolower( str_replace( ' ', '-', $text ) ); } if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) { return $fs_text_overrides[ $slug ][ $key ]; } $lower_key = strtolower( $key ); if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) { return $fs_text_overrides[ $slug ][ $lower_key ]; } return false; } } if ( ! function_exists( 'fs_text_and_domain' ) ) { /** * Get a translatable text and its text domain. * * When the text is overridden by the module, returns the overridden text and the text domain of the module. Otherwise, returns the original text and 'freemius' as the text domain. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string[] */ function fs_text_and_domain( $text, $key, $slug ) { $override = fs_text_override( $text, $key, $slug ); if ( false === $override ) { // No override, use FS text domain. $text_domain = 'freemius'; } else { // Found an override. $text = $override; // Use the module's text domain. $text_domain = $slug; } return array( $text, $text_domain ); } } if ( ! function_exists( '_fs_text_inline' ) ) { /** * Retrieve an inline translated text by key. * * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string * * @global $fs_text_overrides */ function _fs_text_inline( $text, $key = '', $slug = 'freemius' ) { list( $text, $text_domain ) = fs_text_and_domain( $text, $key, $slug ); // Avoid misleading Theme Check warning. $fn = 'translate'; return $fn( $text, $text_domain ); } } if ( ! function_exists( 'fs_text_inline' ) ) { /** * Retrieve an inline translated text by key. * * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string * * @global $fs_text_overrides */ function fs_text_inline( $text, $key = '', $slug = 'freemius' ) { return _fs_text_inline( $text, $key, $slug ); } } if ( ! function_exists( 'fs_esc_attr' ) ) { /** * @author Vova Feldman * @since 1.2.1.6 * * @param string $key * @param string $slug * * @return string */ function fs_esc_attr( $key, $slug ) { return esc_attr( fs_text( $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_attr_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string */ function fs_esc_attr_inline( $text, $key = '', $slug = 'freemius' ) { return esc_attr( _fs_text_inline( $text, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_attr_x_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $context Context information for the translators. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string */ function fs_esc_attr_x_inline( $text, $context, $key = '', $slug = 'freemius' ) { return esc_attr( _fs_text_x_inline( $text, $context, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_attr_echo' ) ) { /** * @author Vova Feldman * @since 1.2.1.6 * * @param string $key * @param string $slug */ function fs_esc_attr_echo( $key, $slug ) { echo esc_attr( fs_text( $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_attr_echo_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. */ function fs_esc_attr_echo_inline( $text, $key = '', $slug = 'freemius' ) { echo esc_attr( _fs_text_inline( $text, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_js' ) ) { /** * @author Vova Feldman * @since 1.2.1.6 * * @param string $key * @param string $slug * * @return string */ function fs_esc_js( $key, $slug ) { return esc_js( fs_text( $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_js_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string */ function fs_esc_js_inline( $text, $key = '', $slug = 'freemius' ) { return esc_js( _fs_text_inline( $text, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_js_x_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $context Context information for the translators. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string */ function fs_esc_js_x_inline( $text, $context, $key = '', $slug = 'freemius' ) { return esc_js( _fs_text_x_inline( $text, $context, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_js_echo_x_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $context Context information for the translators. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string */ function fs_esc_js_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) { echo esc_js( _fs_text_x_inline( $text, $context, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_js_echo' ) ) { /** * @author Vova Feldman * @since 1.2.1.6 * * @param string $key * @param string $slug */ function fs_esc_js_echo( $key, $slug ) { echo esc_js( fs_text( $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_js_echo_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. */ function fs_esc_js_echo_inline( $text, $key = '', $slug = 'freemius' ) { echo esc_js( _fs_text_inline( $text, $key, $slug ) ); } } if ( ! function_exists( 'fs_json_encode_echo' ) ) { /** * @author Vova Feldman * @since 1.2.1.6 * * @param string $key * @param string $slug */ function fs_json_encode_echo( $key, $slug ) { echo json_encode( fs_text( $key, $slug ) ); } } if ( ! function_exists( 'fs_json_encode_echo_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. */ function fs_json_encode_echo_inline( $text, $key = '', $slug = 'freemius' ) { echo json_encode( _fs_text_inline( $text, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_html' ) ) { /** * @author Vova Feldman * @since 1.2.1.6 * * @param string $key * @param string $slug * * @return string */ function fs_esc_html( $key, $slug ) { return esc_html( fs_text( $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_html_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string */ function fs_esc_html_inline( $text, $key = '', $slug = 'freemius' ) { return esc_html( _fs_text_inline( $text, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_html_x_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $context Context information for the translators. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. * * @return string */ function fs_esc_html_x_inline( $text, $context, $key = '', $slug = 'freemius' ) { return esc_html( _fs_text_x_inline( $text, $context, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_html_echo_x_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $context Context information for the translators. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. */ function fs_esc_html_echo_x_inline( $text, $context, $key = '', $slug = 'freemius' ) { echo esc_html( _fs_text_x_inline( $text, $context, $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_html_echo' ) ) { /** * @author Vova Feldman * @since 1.2.1.6 * * @param string $key * @param string $slug */ function fs_esc_html_echo( $key, $slug ) { echo esc_html( fs_text( $key, $slug ) ); } } if ( ! function_exists( 'fs_esc_html_echo_inline' ) ) { /** * @author Vova Feldman (@svovaf) * @since 1.2.3 * * @param string $text Translatable string. * @param string $key String key for overrides. * @param string $slug Module slug for overrides. */ function fs_esc_html_echo_inline( $text, $key = '', $slug = 'freemius' ) { echo esc_html( _fs_text_inline( $text, $key, $slug ) ); } } if ( ! function_exists( 'fs_override_i18n' ) ) { /** * Override default i18n text phrases. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param array[string]string $key_value * @param string $slug * * @global $fs_text_overrides */ function fs_override_i18n( array $key_value, $slug = 'freemius' ) { global $fs_text_overrides; if ( ! isset( $fs_text_overrides[ $slug ] ) ) { $fs_text_overrides[ $slug ] = array(); } foreach ( $key_value as $key => $value ) { $fs_text_overrides[ $slug ][ $key ] = $value; } } } #endregion #-------------------------------------------------------------------------------- #region Multisite Network #-------------------------------------------------------------------------------- if ( ! function_exists( 'fs_is_plugin_uninstall' ) ) { /** * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function fs_is_plugin_uninstall() { return ( defined( 'WP_UNINSTALL_PLUGIN' ) || ( 0 < did_action( 'pre_uninstall_plugin' ) ) ); } } if ( ! function_exists( 'fs_is_network_admin' ) ) { /** * Unlike is_network_admin(), this one will also work properly when * the context execution is WP AJAX handler, and during plugin * uninstall. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function fs_is_network_admin() { return ( WP_FS__IS_NETWORK_ADMIN || ( is_multisite() && fs_is_plugin_uninstall() ) ); } } if ( ! function_exists( 'fs_is_blog_admin' ) ) { /** * Unlike is_blog_admin(), this one will also work properly when * the context execution is WP AJAX handler, and during plugin * uninstall. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function fs_is_blog_admin() { return ( WP_FS__IS_BLOG_ADMIN || ( ! is_multisite() && fs_is_plugin_uninstall() ) ); } } #endregion if ( ! function_exists( 'fs_apply_filter' ) ) { /** * Apply filter for specific plugin. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param string $module_unique_affix Module's unique affix. * @param string $tag The name of the filter hook. * @param mixed $value The value on which the filters hooked to `$tag` are applied on. * * @return mixed The filtered value after all hooked functions are applied to it. * * @uses apply_filters() */ function fs_apply_filter( $module_unique_affix, $tag, $value ) { $args = func_get_args(); return call_user_func_array( 'apply_filters', array_merge( array( "fs_{$tag}_{$module_unique_affix}" ), array_slice( $args, 2 ) ) ); } }freemius/includes/class-fs-security.php000064400000003347146725417150014305 0ustar00id . $entity->secret_key . $entity->public_key . $action ); } /** * @param \FS_Scope_Entity $entity * @param int|bool $timestamp * @param string $action * * @return array */ function get_context_params( FS_Scope_Entity $entity, $timestamp = false, $action = '' ) { if ( false === $timestamp ) { $timestamp = time(); } return array( 's_ctx_type' => $entity->get_type(), 's_ctx_id' => $entity->id, 's_ctx_ts' => $timestamp, 's_ctx_secure' => $this->get_secure_token( $entity, $timestamp, $action ), ); } } freemius/includes/debug/debug-bar-start.php000064400000002470146725417150014772 0ustar00title( 'Freemius' ); } static function requests_count() { if ( class_exists( 'Freemius_Api_WordPress' ) ) { $logger = Freemius_Api_WordPress::GetLogger(); } else { $logger = array(); } return number_format( count( $logger ) ); } static function total_time() { if ( class_exists( 'Freemius_Api_WordPress' ) ) { $logger = Freemius_Api_WordPress::GetLogger(); } else { $logger = array(); } $total_time = .0; foreach ( $logger as $l ) { $total_time += $l['total']; } return number_format( 100 * $total_time, 2 ) . ' ' . fs_text_x_inline( 'ms', 'milliseconds' ); } function render() { ?>



    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {description} Copyright (C) {year} {fullname} This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. {signature of Ty Coon}, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. freemius/includes/sdk/Exceptions/ArgumentNotExistException.php000064400000000467146725417150020766 0ustar00_result = $result; $code = 0; $message = 'Unknown error, please check GetResult().'; $type = ''; if ( isset( $result['error'] ) && is_array( $result['error'] ) ) { if ( isset( $result['error']['code'] ) ) { $code = $result['error']['code']; } if ( isset( $result['error']['message'] ) ) { $message = $result['error']['message']; } if ( isset( $result['error']['type'] ) ) { $type = $result['error']['type']; } } $this->_type = $type; $this->_code = $code; parent::__construct( $message, is_numeric( $code ) ? $code : 0 ); } /** * Return the associated result object returned by the API server. * * @return array The result from the API server */ public function getResult() { return $this->_result; } public function getStringCode() { return $this->_code; } public function getType() { return $this->_type; } /** * To make debugging easier. * * @return string The string representation of the error */ public function __toString() { $str = $this->getType() . ': '; if ( $this->code != 0 ) { $str .= $this->getStringCode() . ': '; } return $str . $this->getMessage(); } } } freemius/includes/sdk/Exceptions/EmptyArgumentException.php000064400000000461146725417150020301 0ustar00_id = $pID; $this->_public = $pPublic; $this->_secret = $pSecret; $this->_scope = $pScope; $this->_isSandbox = $pIsSandbox; } public function IsSandbox() { return $this->_isSandbox; } function CanonizePath( $pPath ) { $pPath = trim( $pPath, '/' ); $query_pos = strpos( $pPath, '?' ); $query = ''; if ( false !== $query_pos ) { $query = substr( $pPath, $query_pos ); $pPath = substr( $pPath, 0, $query_pos ); } // Trim '.json' suffix. $format_length = strlen( '.' . self::FORMAT ); $start = $format_length * ( - 1 ); //negative if ( substr( strtolower( $pPath ), $start ) === ( '.' . self::FORMAT ) ) { $pPath = substr( $pPath, 0, strlen( $pPath ) - $format_length ); } switch ( $this->_scope ) { case 'app': $base = '/apps/' . $this->_id; break; case 'developer': $base = '/developers/' . $this->_id; break; case 'user': $base = '/users/' . $this->_id; break; case 'plugin': $base = '/plugins/' . $this->_id; break; case 'install': $base = '/installs/' . $this->_id; break; default: throw new Freemius_Exception( 'Scope not implemented.' ); } return '/v' . FS_API__VERSION . $base . ( ! empty( $pPath ) ? '/' : '' ) . $pPath . ( ( false === strpos( $pPath, '.' ) ) ? '.' . self::FORMAT : '' ) . $query; } abstract function MakeRequest( $pCanonizedPath, $pMethod = 'GET', $pParams = array() ); /** * @param string $pPath * @param string $pMethod * @param array $pParams * * @return object[]|object|null */ private function _Api( $pPath, $pMethod = 'GET', $pParams = array() ) { $pMethod = strtoupper( $pMethod ); try { $result = $this->MakeRequest( $pPath, $pMethod, $pParams ); } catch ( Freemius_Exception $e ) { // Map to error object. $result = (object) $e->getResult(); } catch ( Exception $e ) { // Map to error object. $result = (object) array( 'error' => (object) array( 'type' => 'Unknown', 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')', 'code' => 'unknown', 'http' => 402 ) ); } return $result; } public function Api( $pPath, $pMethod = 'GET', $pParams = array() ) { return $this->_Api( $this->CanonizePath( $pPath ), $pMethod, $pParams ); } /** * Base64 decoding that does not need to be urldecode()-ed. * * Exactly the same as PHP base64 encode except it uses * `-` instead of `+` * `_` instead of `/` * No padded = * * @param string $input Base64UrlEncoded() string * * @return string */ protected static function Base64UrlDecode( $input ) { /** * IMPORTANT NOTE: * This is a hack suggested by @otto42 and @greenshady from * the theme's review team. The usage of base64 for API * signature encoding was approved in a Slack meeting * held on Tue (10/25 2016). * * @todo Remove this hack once the base64 error is removed from the Theme Check. * * @since 1.2.2 * @author Vova Feldman (@svovaf) */ $fn = 'base64' . '_decode'; return $fn( strtr( $input, '-_', '+/' ) ); } /** * Base64 encoding that does not need to be urlencode()ed. * * Exactly the same as base64 encode except it uses * `-` instead of `+ * `_` instead of `/` * * @param string $input string * * @return string Base64 encoded string */ protected static function Base64UrlEncode( $input ) { /** * IMPORTANT NOTE: * This is a hack suggested by @otto42 and @greenshady from * the theme's review team. The usage of base64 for API * signature encoding was approved in a Slack meeting * held on Tue (10/25 2016). * * @todo Remove this hack once the base64 error is removed from the Theme Check. * * @since 1.2.2 * @author Vova Feldman (@svovaf) */ $fn = 'base64' . '_encode'; $str = strtr( $fn( $input ), '+/', '-_' ); $str = str_replace( '=', '', $str ); return $str; } } }freemius/includes/sdk/FreemiusWordPress.php000064400000053413146725417150015135 0ustar00 '7.37' ); if ( ! defined( 'FS_API__PROTOCOL' ) ) { define( 'FS_API__PROTOCOL', version_compare( $curl_version['version'], '7.37', '>=' ) ? 'https' : 'http' ); } if ( ! defined( 'FS_API__LOGGER_ON' ) ) { define( 'FS_API__LOGGER_ON', false ); } if ( ! defined( 'FS_API__ADDRESS' ) ) { define( 'FS_API__ADDRESS', '://api.freemius.com' ); } if ( ! defined( 'FS_API__SANDBOX_ADDRESS' ) ) { define( 'FS_API__SANDBOX_ADDRESS', '://sandbox-api.freemius.com' ); } if ( ! class_exists( 'Freemius_Api_WordPress' ) ) { class Freemius_Api_WordPress extends Freemius_Api_Base { private static $_logger = array(); /** * @param string $pScope 'app', 'developer', 'user' or 'install'. * @param number $pID Element's id. * @param string $pPublic Public key. * @param string|bool $pSecret Element's secret key. * @param bool $pSandbox Whether or not to run API in sandbox mode. */ public function __construct( $pScope, $pID, $pPublic, $pSecret = false, $pSandbox = false ) { // If secret key not provided, use public key encryption. if ( is_bool( $pSecret ) ) { $pSecret = $pPublic; } parent::Init( $pScope, $pID, $pPublic, $pSecret, $pSandbox ); } public static function GetUrl( $pCanonizedPath = '', $pIsSandbox = false ) { $address = ( $pIsSandbox ? FS_API__SANDBOX_ADDRESS : FS_API__ADDRESS ); if ( ':' === $address[0] ) { $address = self::$_protocol . $address; } return $address . $pCanonizedPath; } #---------------------------------------------------------------------------------- #region Servers Clock Diff #---------------------------------------------------------------------------------- /** * @var int Clock diff in seconds between current server to API server. */ private static $_clock_diff = 0; /** * Set clock diff for all API calls. * * @since 1.0.3 * * @param $pSeconds */ public static function SetClockDiff( $pSeconds ) { self::$_clock_diff = $pSeconds; } /** * Find clock diff between current server to API server. * * @since 1.0.2 * @return int Clock diff in seconds. */ public static function FindClockDiff() { $time = time(); $pong = self::Ping(); return ( $time - strtotime( $pong->timestamp ) ); } #endregion /** * @var string http or https */ private static $_protocol = FS_API__PROTOCOL; /** * Set API connection protocol. * * @since 1.0.4 */ public static function SetHttp() { self::$_protocol = 'http'; } /** * Sets API connection protocol to HTTPS. * * @since 2.5.4 */ public static function SetHttps() { self::$_protocol = 'https'; } /** * @since 1.0.4 * * @return bool */ public static function IsHttps() { return ( 'https' === self::$_protocol ); } /** * Sign request with the following HTTP headers: * Content-MD5: MD5(HTTP Request body) * Date: Current date (i.e Sat, 14 Feb 2016 20:24:46 +0000) * Authorization: FS {scope_entity_id}:{scope_entity_public_key}:base64encode(sha256(string_to_sign, * {scope_entity_secret_key})) * * @param string $pResourceUrl * @param array $pWPRemoteArgs * * @return array */ function SignRequest( $pResourceUrl, $pWPRemoteArgs ) { $auth = $this->GenerateAuthorizationParams( $pResourceUrl, $pWPRemoteArgs['method'], ! empty( $pWPRemoteArgs['body'] ) ? $pWPRemoteArgs['body'] : '' ); $pWPRemoteArgs['headers']['Date'] = $auth['date']; $pWPRemoteArgs['headers']['Authorization'] = $auth['authorization']; if ( ! empty( $auth['content_md5'] ) ) { $pWPRemoteArgs['headers']['Content-MD5'] = $auth['content_md5']; } return $pWPRemoteArgs; } /** * Generate Authorization request headers: * * Content-MD5: MD5(HTTP Request body) * Date: Current date (i.e Sat, 14 Feb 2016 20:24:46 +0000) * Authorization: FS {scope_entity_id}:{scope_entity_public_key}:base64encode(sha256(string_to_sign, * {scope_entity_secret_key})) * * @author Vova Feldman * * @param string $pResourceUrl * @param string $pMethod * @param string $pPostParams * * @return array * @throws Freemius_Exception */ function GenerateAuthorizationParams( $pResourceUrl, $pMethod = 'GET', $pPostParams = '' ) { $pMethod = strtoupper( $pMethod ); $eol = "\n"; $content_md5 = ''; $content_type = ''; $now = ( time() - self::$_clock_diff ); $date = date( 'r', $now ); if ( in_array( $pMethod, array( 'POST', 'PUT' ) ) ) { $content_type = 'application/json'; if ( ! empty( $pPostParams ) ) { $content_md5 = md5( $pPostParams ); } } $string_to_sign = implode( $eol, array( $pMethod, $content_md5, $content_type, $date, $pResourceUrl ) ); // If secret and public keys are identical, it means that // the signature uses public key hash encoding. $auth_type = ( $this->_secret !== $this->_public ) ? 'FS' : 'FSP'; $auth = array( 'date' => $date, 'authorization' => $auth_type . ' ' . $this->_id . ':' . $this->_public . ':' . self::Base64UrlEncode( hash_hmac( 'sha256', $string_to_sign, $this->_secret ) ) ); if ( ! empty( $content_md5 ) ) { $auth['content_md5'] = $content_md5; } return $auth; } /** * Get API request URL signed via query string. * * @since 1.2.3 Stopped using http_build_query(). Instead, use urlencode(). In some environments the encoding of http_build_query() can generate a URL that once used with a redirect, the `&` querystring separator is escaped to `&` which breaks the URL (Added by @svovaf). * * @param string $pPath * * @throws Freemius_Exception * * @return string */ function GetSignedUrl( $pPath ) { $resource = explode( '?', $this->CanonizePath( $pPath ) ); $pResourceUrl = $resource[0]; $auth = $this->GenerateAuthorizationParams( $pResourceUrl ); return Freemius_Api_WordPress::GetUrl( $pResourceUrl . '?' . ( 1 < count( $resource ) && ! empty( $resource[1] ) ? $resource[1] . '&' : '' ) . 'authorization=' . urlencode( $auth['authorization'] ) . '&auth_date=' . urlencode( $auth['date'] ) , $this->_isSandbox ); } /** * @author Vova Feldman * * @param string $pUrl * @param array $pWPRemoteArgs * * @return mixed */ private static function ExecuteRequest( $pUrl, &$pWPRemoteArgs ) { $bt = debug_backtrace(); $start = microtime( true ); $response = self::RemoteRequest( $pUrl, $pWPRemoteArgs ); if ( FS_API__LOGGER_ON ) { $end = microtime( true ); $has_body = ( isset( $pWPRemoteArgs['body'] ) && ! empty( $pWPRemoteArgs['body'] ) ); $is_http_error = is_wp_error( $response ); self::$_logger[] = array( 'id' => count( self::$_logger ), 'start' => $start, 'end' => $end, 'total' => ( $end - $start ), 'method' => $pWPRemoteArgs['method'], 'path' => $pUrl, 'body' => $has_body ? $pWPRemoteArgs['body'] : null, 'result' => ! $is_http_error ? $response['body'] : json_encode( $response->get_error_messages() ), 'code' => ! $is_http_error ? $response['response']['code'] : null, 'backtrace' => $bt, ); } return $response; } /** * @author Leo Fajardo (@leorw) * * @param string $pUrl * @param array $pWPRemoteArgs * * @return array|WP_Error The response array or a WP_Error on failure. */ static function RemoteRequest( $pUrl, $pWPRemoteArgs ) { $response = wp_remote_request( $pUrl, $pWPRemoteArgs ); if ( is_array( $response ) && ( empty( $response['headers'] ) || empty( $response['headers']['x-api-server'] ) ) ) { // API is considered blocked if the response doesn't include the `x-api-server` header. When there's no error but this header doesn't exist, the response is usually not in the expected form (e.g., cannot be JSON-decoded). $response = new WP_Error( 'api_blocked', htmlentities( $response['body'] ) ); } return $response; } /** * @return array */ static function GetLogger() { return self::$_logger; } /** * @param string $pCanonizedPath * @param string $pMethod * @param array $pParams * @param null|array $pWPRemoteArgs * @param bool $pIsSandbox * @param null|callable $pBeforeExecutionFunction * * @return object[]|object|null * * @throws \Freemius_Exception */ private static function MakeStaticRequest( $pCanonizedPath, $pMethod = 'GET', $pParams = array(), $pWPRemoteArgs = null, $pIsSandbox = false, $pBeforeExecutionFunction = null ) { // Connectivity errors simulation. if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_CLOUDFLARE ) { self::ThrowCloudFlareDDoSException(); } else if ( FS_SDK__SIMULATE_NO_API_CONNECTIVITY_SQUID_ACL ) { self::ThrowSquidAclException(); } if ( empty( $pWPRemoteArgs ) ) { $user_agent = 'Freemius/WordPress-SDK/' . Freemius_Api_Base::VERSION . '; ' . home_url(); $pWPRemoteArgs = array( 'method' => strtoupper( $pMethod ), 'connect_timeout' => 10, 'timeout' => 60, 'follow_redirects' => true, 'redirection' => 5, 'user-agent' => $user_agent, 'blocking' => true, ); } if ( ! isset( $pWPRemoteArgs['headers'] ) || ! is_array( $pWPRemoteArgs['headers'] ) ) { $pWPRemoteArgs['headers'] = array(); } if ( in_array( $pMethod, array( 'POST', 'PUT' ) ) ) { $pWPRemoteArgs['headers']['Content-type'] = 'application/json'; if ( is_array( $pParams ) && 0 < count( $pParams ) ) { $pWPRemoteArgs['body'] = json_encode( $pParams ); } } $request_url = self::GetUrl( $pCanonizedPath, $pIsSandbox ); $resource = explode( '?', $pCanonizedPath ); if ( FS_SDK__HAS_CURL ) { // Disable the 'Expect: 100-continue' behaviour. This causes cURL to wait // for 2 seconds if the server does not support this header. $pWPRemoteArgs['headers']['Expect'] = ''; } if ( 'https' === substr( strtolower( $request_url ), 0, 5 ) ) { $pWPRemoteArgs['sslverify'] = FS_SDK__SSLVERIFY; } if ( false !== $pBeforeExecutionFunction && is_callable( $pBeforeExecutionFunction ) ) { $pWPRemoteArgs = call_user_func( $pBeforeExecutionFunction, $resource[0], $pWPRemoteArgs ); } $result = self::ExecuteRequest( $request_url, $pWPRemoteArgs ); if ( is_wp_error( $result ) ) { /** * @var WP_Error $result */ if ( self::IsCurlError( $result ) ) { /** * With dual stacked DNS responses, it's possible for a server to * have IPv6 enabled but not have IPv6 connectivity. If this is * the case, cURL will try IPv4 first and if that fails, then it will * fall back to IPv6 and the error EHOSTUNREACH is returned by the * operating system. */ $matches = array(); $regex = '/Failed to connect to ([^:].*): Network is unreachable/'; if ( preg_match( $regex, $result->get_error_message( 'http_request_failed' ), $matches ) ) { /** * Validate IP before calling `inet_pton()` to avoid PHP un-catchable warning. * @author Vova Feldman (@svovaf) */ if ( filter_var( $matches[1], FILTER_VALIDATE_IP ) ) { if ( strlen( inet_pton( $matches[1] ) ) === 16 ) { // error_log('Invalid IPv6 configuration on server, Please disable or get native IPv6 on your server.'); // Hook to an action triggered just before cURL is executed to resolve the IP version to v4. add_action( 'http_api_curl', 'Freemius_Api_WordPress::CurlResolveToIPv4', 10, 1 ); // Re-run request. $result = self::ExecuteRequest( $request_url, $pWPRemoteArgs ); } } } } if ( is_wp_error( $result ) ) { self::ThrowWPRemoteException( $result ); } } $response_body = $result['body']; if ( empty( $response_body ) ) { return null; } $decoded = json_decode( $response_body ); if ( is_null( $decoded ) ) { if ( preg_match( '/Please turn JavaScript on/i', $response_body ) && preg_match( '/text\/javascript/', $response_body ) ) { self::ThrowCloudFlareDDoSException( $response_body ); } else if ( preg_match( '/Access control configuration prevents your request from being allowed at this time. Please contact your service provider if you feel this is incorrect./', $response_body ) && preg_match( '/squid/', $response_body ) ) { self::ThrowSquidAclException( $response_body ); } else { $decoded = (object) array( 'error' => (object) array( 'type' => 'Unknown', 'message' => $response_body, 'code' => 'unknown', 'http' => 402 ) ); } } return $decoded; } /** * Makes an HTTP request. This method can be overridden by subclasses if * developers want to do fancier things or use something other than wp_remote_request() * to make the request. * * @param string $pCanonizedPath The URL to make the request to * @param string $pMethod HTTP method * @param array $pParams The parameters to use for the POST body * @param null|array $pWPRemoteArgs wp_remote_request options. * * @return object[]|object|null * * @throws Freemius_Exception */ public function MakeRequest( $pCanonizedPath, $pMethod = 'GET', $pParams = array(), $pWPRemoteArgs = null ) { $resource = explode( '?', $pCanonizedPath ); // Only sign request if not ping.json connectivity test. $sign_request = ( '/v1/ping.json' !== strtolower( substr( $resource[0], - strlen( '/v1/ping.json' ) ) ) ); return self::MakeStaticRequest( $pCanonizedPath, $pMethod, $pParams, $pWPRemoteArgs, $this->_isSandbox, $sign_request ? array( &$this, 'SignRequest' ) : null ); } /** * Sets CURLOPT_IPRESOLVE to CURL_IPRESOLVE_V4 for cURL-Handle provided as parameter * * @param resource $handle A cURL handle returned by curl_init() * * @return resource $handle A cURL handle returned by curl_init() with CURLOPT_IPRESOLVE set to * CURL_IPRESOLVE_V4 * * @link https://gist.github.com/golderweb/3a2aaec2d56125cc004e */ static function CurlResolveToIPv4( $handle ) { curl_setopt( $handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); return $handle; } #---------------------------------------------------------------------------------- #region Connectivity Test #---------------------------------------------------------------------------------- /** * This method exists only for backward compatibility to prevent a fatal error from happening when called from an outdated piece of code. * * @param mixed $pPong * * @return bool */ public static function Test( $pPong = null ) { return ( is_object( $pPong ) && isset( $pPong->api ) && 'pong' === $pPong->api ); } /** * Ping API to test connectivity. * * @return object */ public static function Ping() { try { $result = self::MakeStaticRequest( '/v' . FS_API__VERSION . '/ping.json' ); } catch ( Freemius_Exception $e ) { // Map to error object. $result = (object) $e->getResult(); } catch ( Exception $e ) { // Map to error object. $result = (object) array( 'error' => (object) array( 'type' => 'Unknown', 'message' => $e->getMessage() . ' (' . $e->getFile() . ': ' . $e->getLine() . ')', 'code' => 'unknown', 'http' => 402 ) ); } return $result; } #endregion #---------------------------------------------------------------------------------- #region Connectivity Exceptions #---------------------------------------------------------------------------------- /** * @param \WP_Error $pError * * @return bool */ private static function IsCurlError( WP_Error $pError ) { $message = $pError->get_error_message( 'http_request_failed' ); return ( 0 === strpos( $message, 'cURL' ) ); } /** * @param WP_Error $pError * * @throws Freemius_Exception */ private static function ThrowWPRemoteException( WP_Error $pError ) { if ( self::IsCurlError( $pError ) ) { $message = $pError->get_error_message( 'http_request_failed' ); #region Check if there are any missing cURL methods. $curl_required_methods = array( 'curl_version', 'curl_exec', 'curl_init', 'curl_close', 'curl_setopt', 'curl_setopt_array', 'curl_error', ); // Find all missing methods. $missing_methods = array(); foreach ( $curl_required_methods as $m ) { if ( ! function_exists( $m ) ) { $missing_methods[] = $m; } } if ( ! empty( $missing_methods ) ) { throw new Freemius_Exception( array( 'error' => (object) array( 'type' => 'cUrlMissing', 'message' => $message, 'code' => 'curl_missing', 'http' => 402 ), 'missing_methods' => $missing_methods, ) ); } #endregion // cURL error - "cURL error {{errno}}: {{error}}". $parts = explode( ':', substr( $message, strlen( 'cURL error ' ) ), 2 ); $code = ( 0 < count( $parts ) ) ? $parts[0] : 'http_request_failed'; $message = ( 1 < count( $parts ) ) ? $parts[1] : $message; $e = new Freemius_Exception( array( 'error' => (object) array( 'code' => $code, 'message' => $message, 'type' => 'CurlException', ), ) ); } else { $e = new Freemius_Exception( array( 'error' => (object) array( 'code' => $pError->get_error_code(), 'message' => $pError->get_error_message(), 'type' => 'WPRemoteException', ), ) ); } throw $e; } /** * @param string $pResult * * @throws Freemius_Exception */ private static function ThrowCloudFlareDDoSException( $pResult = '' ) { throw new Freemius_Exception( array( 'error' => (object) array( 'type' => 'CloudFlareDDoSProtection', 'message' => $pResult, 'code' => 'cloudflare_ddos_protection', 'http' => 402 ) ) ); } /** * @param string $pResult * * @throws Freemius_Exception */ private static function ThrowSquidAclException( $pResult = '' ) { throw new Freemius_Exception( array( 'error' => (object) array( 'type' => 'SquidCacheBlock', 'message' => $pResult, 'code' => 'squid_cache_block', 'http' => 402 ) ) ); } #endregion } } freemius/includes/class-fs-plugin-updater.php000064400000176376146725417150015413 0ustar00get_id(); if ( ! isset( self::$_INSTANCES[ $key ] ) ) { self::$_INSTANCES[ $key ] = new self( $freemius ); } return self::$_INSTANCES[ $key ]; } #endregion private function __construct( Freemius $freemius ) { $this->_fs = $freemius; $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $freemius->get_slug() . '_updater', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); $this->filters(); } /** * Initiate required filters. * * @author Vova Feldman (@svovaf) * @since 1.0.4 */ private function filters() { // Override request for plugin information add_filter( 'plugins_api', array( &$this, 'plugins_api_filter' ), 10, 3 ); $this->add_transient_filters(); /** * If user has the premium plugin's code but do NOT have an active license, * encourage him to upgrade by showing that there's a new release, but instead * of showing an update link, show upgrade link to the pricing page. * * @since 1.1.6 * */ // WP 2.9+ add_action( "after_plugin_row_{$this->_fs->get_plugin_basename()}", array( &$this, 'catch_plugin_update_row' ), 9 ); add_action( "after_plugin_row_{$this->_fs->get_plugin_basename()}", array( &$this, 'edit_and_echo_plugin_update_row' ), 11, 2 ); if ( ! $this->_fs->has_any_active_valid_license() ) { add_action( 'admin_head', array( &$this, 'catch_plugin_information_dialog_contents' ) ); } if ( ! WP_FS__IS_PRODUCTION_MODE ) { add_filter( 'http_request_host_is_external', array( $this, 'http_request_host_is_external_filter' ), 10, 3 ); } if ( $this->_fs->is_premium() ) { if ( ! $this->is_correct_folder_name() ) { add_filter( 'upgrader_post_install', array( &$this, '_maybe_update_folder_name' ), 10, 3 ); } add_filter( 'upgrader_pre_install', array( 'FS_Plugin_Updater', '_store_basename_for_source_adjustment' ), 1, 2 ); add_filter( 'upgrader_source_selection', array( 'FS_Plugin_Updater', '_maybe_adjust_source_dir' ), 1, 3 ); if ( ! $this->_fs->has_any_active_valid_license() ) { add_filter( 'wp_prepare_themes_for_js', array( &$this, 'change_theme_update_info_html' ), 10, 1 ); } } } /** * @author Leo Fajardo (@leorw) * @since 2.1.4 */ function catch_plugin_information_dialog_contents() { if ( 'plugin-information' !== fs_request_get( 'tab', false ) || $this->_fs->get_slug() !== fs_request_get( 'plugin', false ) ) { return; } add_action( 'admin_footer', array( &$this, 'edit_and_echo_plugin_information_dialog_contents' ), 0, 1 ); ob_start(); } /** * @author Leo Fajardo (@leorw) * @since 2.1.4 * * @param string $hook_suffix */ function edit_and_echo_plugin_information_dialog_contents( $hook_suffix ) { if ( 'plugin-information' !== fs_request_get( 'tab', false ) || $this->_fs->get_slug() !== fs_request_get( 'plugin', false ) ) { return; } $license = $this->_fs->_get_license(); $subscription = ( is_object( $license ) && ! $license->is_lifetime() ) ? $this->_fs->_get_subscription( $license->id ) : null; $contents = ob_get_clean(); $install_or_update_button_id_attribute_pos = strpos( $contents, 'id="plugin_install_from_iframe"' ); if ( false === $install_or_update_button_id_attribute_pos ) { $install_or_update_button_id_attribute_pos = strpos( $contents, 'id="plugin_update_from_iframe"' ); } if ( false !== $install_or_update_button_id_attribute_pos ) { $install_or_update_button_start_pos = strrpos( substr( $contents, 0, $install_or_update_button_id_attribute_pos ), '', $install_or_update_button_id_attribute_pos ) + strlen( '' ) ); /** * The part of the contents without the update button. * * @author Leo Fajardo (@leorw) * @since 2.2.5 */ $modified_contents = substr( $contents, 0, $install_or_update_button_start_pos ); $install_or_update_button = substr( $contents, $install_or_update_button_start_pos, ( $install_or_update_button_end_pos - $install_or_update_button_start_pos ) ); /** * Replace the plugin information dialog's "Install Update Now" button's text and URL. If there's a license, * the text will be "Renew license" and will link to the checkout page with the license's billing cycle * and quota. If there's no license, the text will be "Buy license" and will link to the pricing page. */ $install_or_update_button = preg_replace( '/(\)(.+)(\<\/a>)/is', is_object( $license ) ? sprintf( '$1$4%s$6%s$8', $this->_fs->checkout_url( is_object( $subscription ) ? ( 1 == $subscription->billing_cycle ? WP_FS__PERIOD_MONTHLY : WP_FS__PERIOD_ANNUALLY ) : WP_FS__PERIOD_LIFETIME, false, array( 'licenses' => $license->quota ) ), fs_text_inline( 'Renew license', 'renew-license', $this->_fs->get_slug() ) ) : sprintf( '$1$4%s$6%s$8', $this->_fs->pricing_url(), fs_text_inline( 'Buy license', 'buy-license', $this->_fs->get_slug() ) ), $install_or_update_button ); /** * Append the modified button. * * @author Leo Fajardo (@leorw) * @since 2.2.5 */ $modified_contents .= $install_or_update_button; /** * Append the remaining part of the contents after the update button. * * @author Leo Fajardo (@leorw) * @since 2.2.5 */ $modified_contents .= substr( $contents, $install_or_update_button_end_pos ); $contents = $modified_contents; } echo $contents; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 */ private function add_transient_filters() { if ( $this->_fs->is_premium() && $this->_fs->is_registered() && ! FS_Permission_Manager::instance( $this->_fs )->is_essentials_tracking_allowed() ) { $this->_logger->log( 'Opted out sites cannot receive automatic software updates.' ); return; } add_filter( 'pre_set_site_transient_update_plugins', array( &$this, 'pre_set_site_transient_update_plugins_filter' ) ); add_filter( 'pre_set_site_transient_update_themes', array( &$this, 'pre_set_site_transient_update_plugins_filter' ) ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 */ private function remove_transient_filters() { remove_filter( 'pre_set_site_transient_update_plugins', array( &$this, 'pre_set_site_transient_update_plugins_filter' ) ); remove_filter( 'pre_set_site_transient_update_themes', array( &$this, 'pre_set_site_transient_update_plugins_filter' ) ); } /** * Capture plugin update row by turning output buffering. * * @author Vova Feldman (@svovaf) * @since 1.1.6 */ function catch_plugin_update_row() { ob_start(); } /** * Overrides default update message format with "renew your license" message. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string $file * @param array $plugin_data */ function edit_and_echo_plugin_update_row( $file, $plugin_data ) { $plugin_update_row = ob_get_clean(); $current = get_site_transient( 'update_plugins' ); if ( ! isset( $current->response[ $file ] ) ) { echo $plugin_update_row; return; } $r = $current->response[ $file ]; $has_beta_update = $this->_fs->has_beta_update(); if ( $this->_fs->has_any_active_valid_license() ) { if ( $has_beta_update ) { /** * Turn the "new version" text into "new Beta version". * * Sample input: * There is a new version of Awesome Plugin available. update now. * Output: * There is a new Beta version of Awesome Plugin available. update now. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ $plugin_update_row = preg_replace( '/(\)(.+)(\.+\)/is', ( '$1' . sprintf( fs_text_inline( 'There is a %s of %s available.', 'new-version-available', $this->_fs->get_slug() ), $has_beta_update ? fs_text_inline( 'new Beta version', 'new-beta-version', $this->_fs->get_slug() ) : fs_text_inline( 'new version', 'new-version', $this->_fs->get_slug() ), $this->_fs->get_plugin_title() ) . ' ' . '$3' . '$6' ), $plugin_update_row ); } } else { /** * Turn the "new version" text into a link that opens the plugin information dialog when clicked and * make the "View version x details" text link to the checkout page instead of opening the plugin * information dialog when clicked. * * Sample input: * There is a new version of Awesome Plugin available. update now. * Output: * There is a Buy a license now to access version x.y.z security & feature updates, and support. * OR * There is a Buy a license now to access version x.y.z security & feature updates, and support. * * @author Leo Fajardo (@leorw) */ $plugin_update_row = preg_replace( '/(\)(.+)(\.+\)/is', ( '$1' . sprintf( fs_text_inline( 'There is a %s of %s available.', 'new-version-available', $this->_fs->get_slug() ), sprintf( '%s', '$5', $has_beta_update ? fs_text_inline( 'new Beta version', 'new-beta-version', $this->_fs->get_slug() ) : fs_text_inline( 'new version', 'new-version', $this->_fs->get_slug() ) ), $this->_fs->get_plugin_title() ) . ' ' . $this->_fs->version_upgrade_checkout_link( $r->new_version ) . '$6' ), $plugin_update_row ); } if ( $this->_fs->is_plugin() && isset( $r->upgrade_notice ) && strlen( trim( $r->upgrade_notice ) ) > 0 ) { $slug = $this->_fs->get_slug(); $upgrade_notice_html = sprintf( '

    %3$s %4$s

    ', $slug, $this->_fs->get_module_type(), fs_text_inline( 'Important Upgrade Notice:', 'upgrade_notice', $slug ), esc_html( $r->upgrade_notice ) ); $plugin_update_row = str_replace( '
    ', '
    ' . $upgrade_notice_html, $plugin_update_row ); } echo $plugin_update_row; } /** * @author Leo Fajardo (@leorw) * @since 2.0.2 * * @param array $prepared_themes * * @return array */ function change_theme_update_info_html( $prepared_themes ) { $theme_basename = $this->_fs->get_plugin_basename(); if ( ! isset( $prepared_themes[ $theme_basename ] ) ) { return $prepared_themes; } $themes_update = get_site_transient( 'update_themes' ); if ( ! isset( $themes_update->response[ $theme_basename ] ) || empty( $themes_update->response[ $theme_basename ]['package'] ) ) { return $prepared_themes; } $prepared_themes[ $theme_basename ]['update'] = preg_replace( '/(\)(.+)(\)/is', '$1 $2 ' . $this->_fs->version_upgrade_checkout_link( $themes_update->response[ $theme_basename ]['new_version'] ) . '$4', $prepared_themes[ $theme_basename ]['update'] ); // Set to false to prevent the "Update now" link for the context theme from being shown on the "Themes" page. $prepared_themes[ $theme_basename ]['hasPackage'] = false; return $prepared_themes; } /** * Since WP version 3.6, a new security feature was added that denies access to repository with a local ip. * During development mode we want to be able updating plugin versions via our localhost repository. This * filter white-list all domains including "api.freemius". * * @link http://www.emanueletessore.com/wordpress-download-failed-valid-url-provided/ * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param bool $allow * @param string $host * @param string $url * * @return bool */ function http_request_host_is_external_filter( $allow, $host, $url ) { return ( false !== strpos( $host, 'freemius' ) ) ? true : $allow; } /** * Check for Updates at the defined API endpoint and modify the update array. * * This function dives into the update api just when WordPress creates its update array, * then adds a custom API call and injects the custom plugin data retrieved from the API. * It is reassembled from parts of the native WordPress plugin update code. * See wp-includes/update.php line 121 for the original wp_update_plugins() function. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @uses FS_Api * * @param object $transient_data Update array build by WordPress. * * @return object Modified update array with custom plugin data. */ function pre_set_site_transient_update_plugins_filter( $transient_data ) { $this->_logger->entrance(); /** * "plugins" or "themes". * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ $module_type = $this->_fs->get_module_type() . 's'; /** * Ensure that we don't mix plugins update info with themes update info. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ if ( "pre_set_site_transient_update_{$module_type}" !== current_filter() ) { return $transient_data; } if ( empty( $transient_data ) || defined( 'WP_FS__UNINSTALL_MODE' ) ) { return $transient_data; } global $wp_current_filter; $current_plugin_version = $this->_fs->get_plugin_version(); if ( ! empty( $wp_current_filter ) && 'upgrader_process_complete' === $wp_current_filter[0] ) { if ( is_null( $this->_update_details ) || ( is_object( $this->_update_details ) && $this->_update_details->new_version !== $current_plugin_version ) ) { /** * After an update, clear the stored update details and reparse the plugin's main file in order to get * the updated version's information and prevent the previous update information from showing up on the * updates page. * * @author Leo Fajardo (@leorw) * @since 2.3.1 */ $this->_update_details = null; $current_plugin_version = $this->_fs->get_plugin_version( true ); } } if ( ! isset( $this->_update_details ) ) { // Get plugin's newest update. $new_version = $this->_fs->get_update( false, fs_request_get_bool( 'force-check' ), WP_FS__TIME_24_HOURS_IN_SEC / 24, $current_plugin_version ); $this->_update_details = false; if ( is_object( $new_version ) && $this->is_new_version_premium( $new_version ) ) { $this->_logger->log( 'Found newer plugin version ' . $new_version->version ); /** * Cache plugin details locally since set_site_transient( 'update_plugins' ) * called multiple times and the non wp.org plugins are filtered after the * call to .org. * * @since 1.1.8.1 */ $this->_update_details = $this->get_update_details( $new_version ); } } // Alias. $basename = $this->_fs->premium_plugin_basename(); if ( is_object( $this->_update_details ) ) { if ( isset( $transient_data->no_update ) ) { unset( $transient_data->no_update[ $basename ] ); } if ( ! isset( $transient_data->response ) ) { $transient_data->response = array(); } // Add plugin to transient data. $transient_data->response[ $basename ] = $this->_fs->is_plugin() ? $this->_update_details : (array) $this->_update_details; } else { if ( isset( $transient_data->response ) ) { /** * Ensure that there's no update data for the plugin to prevent upgrading the premium version to the latest free version. * * @author Leo Fajardo (@leorw) * @since 2.3.0 */ unset( $transient_data->response[ $basename ] ); } if ( ! isset( $transient_data->no_update ) ) { $transient_data->no_update = array(); } /** * Add product to no_update transient data to properly integrate with WP 5.5 auto-updates UI. * * @since 2.4.1 * @link https://make.wordpress.org/core/2020/07/30/recommended-usage-of-the-updates-api-to-support-the-auto-updates-ui-for-plugins-and-themes-in-wordpress-5-5/ */ $transient_data->no_update[ $basename ] = $this->_fs->is_plugin() ? (object) array( 'id' => $basename, 'slug' => $this->_fs->get_slug(), 'plugin' => $basename, 'new_version' => $this->_fs->get_plugin_version(), 'url' => '', 'package' => '', 'icons' => array(), 'banners' => array(), 'banners_rtl' => array(), 'tested' => '', 'requires_php' => '', 'compatibility' => new stdClass(), ) : array( 'theme' => $basename, 'new_version' => $this->_fs->get_plugin_version(), 'url' => '', 'package' => '', 'requires' => '', 'requires_php' => '', ); } $slug = $this->_fs->get_slug(); if ( $this->_fs->is_org_repo_compliant() && $this->_fs->is_freemium() ) { if ( ! isset( $this->_translation_updates ) ) { $this->_translation_updates = array(); $translation_updates = $this->fetch_wp_org_module_translation_updates( $module_type, $slug ); if ( ! empty( $translation_updates ) ) { $this->_translation_updates = $translation_updates; } } if ( ! empty( $this->_translation_updates ) ) { $all_translation_updates = ( isset( $transient_data->translations ) && is_array( $transient_data->translations ) ) ? $transient_data->translations : array(); $current_plugin_translation_updates_map = array(); foreach ( $all_translation_updates as $key => $translation_update ) { if ( $module_type === ( $translation_update['type'] . 's' ) && $slug === $translation_update['slug'] ) { $current_plugin_translation_updates_map[ $translation_update['language'] ] = $translation_update; unset( $all_translation_updates[ $key ] ); } } foreach ( $this->_translation_updates as $translation_update ) { $lang = $translation_update['language']; if ( ! isset( $current_plugin_translation_updates_map[ $lang ] ) || version_compare( $translation_update['version'], $current_plugin_translation_updates_map[ $lang ]['version'], '>' ) ) { $current_plugin_translation_updates_map[ $lang ] = $translation_update; } } $transient_data->translations = array_merge( $all_translation_updates, array_values( $current_plugin_translation_updates_map ) ); } } return $transient_data; } /** * Get module's required data for the updates' mechanism. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_Plugin_Tag $new_version * * @return object */ function get_update_details( FS_Plugin_Tag $new_version ) { $update = new stdClass(); $update->slug = $this->_fs->get_slug(); $update->new_version = $new_version->version; $update->url = WP_FS__ADDRESS; $update->package = $new_version->url; $update->tested = self::get_tested_wp_version( $new_version->tested_up_to_version ); $update->requires = $new_version->requires_platform_version; $update->requires_php = $new_version->requires_programming_language_version; $icon = $this->_fs->get_local_icon_url(); if ( ! empty( $icon ) ) { $update->icons = array( // '1x' => $icon, // '2x' => $icon, 'default' => $icon, ); } if ( $this->_fs->is_premium() ) { $latest_tag = $this->_fs->_fetch_latest_version( $this->_fs->get_id(), false ); if ( isset( $latest_tag->readme ) && isset( $latest_tag->readme->upgrade_notice ) && ! empty( $latest_tag->readme->upgrade_notice ) ) { $update->upgrade_notice = $latest_tag->readme->upgrade_notice; } } $update->{$this->_fs->get_module_type()} = $this->_fs->get_plugin_basename(); return $update; } /** * @author Leo Fajardo (@leorw) * @since 2.3.0 * * @param FS_Plugin_Tag $new_version * * @return bool */ private function is_new_version_premium( FS_Plugin_Tag $new_version ) { $query_str = parse_url( $new_version->url, PHP_URL_QUERY ); if ( empty( $query_str ) ) { return false; } parse_str( $query_str, $params ); return ( isset( $params['is_premium'] ) && 'true' == $params['is_premium'] ); } /** * Update the updates transient with the module's update information. * * This method is required for multisite environment. * If a module is site activated (not network) and not on the main site, * the module will NOT be executed on the network level, therefore, the * custom updates logic will not be executed as well, so unless we force * the injection of the update into the updates transient, premium updates * will not work. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param \FS_Plugin_Tag $new_version */ function set_update_data( FS_Plugin_Tag $new_version ) { $this->_logger->entrance(); if ( ! $this->is_new_version_premium( $new_version ) ) { return; } $transient_key = "update_{$this->_fs->get_module_type()}s"; $transient_data = get_site_transient( $transient_key ); $transient_data = is_object( $transient_data ) ? $transient_data : new stdClass(); // Alias. $basename = $this->_fs->get_plugin_basename(); $is_plugin = $this->_fs->is_plugin(); if ( ! isset( $transient_data->response ) || ! is_array( $transient_data->response ) ) { $transient_data->response = array(); } else if ( ! empty( $transient_data->response[ $basename ] ) ) { $version = $is_plugin ? ( ! empty( $transient_data->response[ $basename ]->new_version ) ? $transient_data->response[ $basename ]->new_version : null ) : ( ! empty( $transient_data->response[ $basename ]['new_version'] ) ? $transient_data->response[ $basename ]['new_version'] : null ); if ( $version == $new_version->version ) { // The update data is already set. return; } } // Remove the added filters. $this->remove_transient_filters(); $this->_update_details = $this->get_update_details( $new_version ); // Set update data in transient. $transient_data->response[ $basename ] = $is_plugin ? $this->_update_details : (array) $this->_update_details; if ( ! isset( $transient_data->checked ) || ! is_array( $transient_data->checked ) ) { $transient_data->checked = array(); } // Flag the module as if it was already checked. $transient_data->checked[ $basename ] = $this->_fs->get_plugin_version(); $transient_data->last_checked = time(); set_site_transient( $transient_key, $transient_data ); $this->add_transient_filters(); } /** * @author Leo Fajardo (@leorw) * @since 2.0.2 */ function delete_update_data() { $this->_logger->entrance(); $transient_key = "update_{$this->_fs->get_module_type()}s"; $transient_data = get_site_transient( $transient_key ); // Alias $basename = $this->_fs->get_plugin_basename(); if ( ! is_object( $transient_data ) || ! isset( $transient_data->response ) || ! is_array( $transient_data->response ) || empty( $transient_data->response[ $basename ] ) ) { return; } unset( $transient_data->response[ $basename ] ); // Remove the added filters. $this->remove_transient_filters(); set_site_transient( $transient_key, $transient_data ); $this->add_transient_filters(); } /** * Try to fetch plugin's info from .org repository. * * @author Vova Feldman (@svovaf) * @since 1.0.5 * * @param string $action * @param object $args * * @return bool|mixed */ static function _fetch_plugin_info_from_repository( $action, $args ) { $url = $http_url = 'http://api.wordpress.org/plugins/info/1.2/'; $url = add_query_arg( array( 'action' => $action, 'request' => $args, ), $url ); if ( wp_http_supports( array( 'ssl' ) ) ) { $url = set_url_scheme( $url, 'https' ); } // The new endpoint version serves only GET requests. $request = wp_remote_get( $url, array( 'timeout' => 15 ) ); if ( is_wp_error( $request ) ) { return false; } $res = json_decode( wp_remote_retrieve_body( $request ), true ); if ( is_array( $res ) ) { // Object casting is required in order to match the info/1.0 format. We are not decoding directly into an object as we need some fields to remain an array (e.g., $res->sections). $res = (object) $res; } if ( ! is_object( $res ) || isset( $res->error ) ) { return false; } return $res; } /** * Fetches module translation updates from wordpress.org. * * @author Leo Fajardo (@leorw) * @since 2.1.2 * * @param string $module_type * @param string $slug * * @return array|null */ private function fetch_wp_org_module_translation_updates( $module_type, $slug ) { $plugin_data = $this->_fs->get_plugin_data(); $locales = array_values( get_available_languages() ); $locales = apply_filters( "{$module_type}_update_check_locales", $locales ); $locales = array_unique( $locales ); $plugin_basename = $this->_fs->get_plugin_basename(); if ( 'themes' === $module_type ) { $plugin_basename = $slug; } global $wp_version; $request_args = array( 'timeout' => 15, 'body' => array( "{$module_type}" => json_encode( array( "{$module_type}" => array( $plugin_basename => array( 'Name' => trim( str_replace( $this->_fs->get_plugin()->premium_suffix, '', $plugin_data['Name'] ) ), 'Author' => $plugin_data['Author'], ) ) ) ), 'translations' => json_encode( $this->get_installed_translations( $module_type, $slug ) ), 'locale' => json_encode( $locales ) ), 'user-agent' => ( 'WordPress/' . $wp_version . '; ' . home_url( '/' ) ) ); $url = "http://api.wordpress.org/{$module_type}/update-check/1.1/"; if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) { $url = set_url_scheme( $url, 'https' ); } $raw_response = Freemius::safe_remote_post( $url, $request_args, WP_FS__TIME_24_HOURS_IN_SEC, WP_FS__TIME_12_HOURS_IN_SEC, false ); if ( is_wp_error( $raw_response ) ) { return null; } $response = json_decode( wp_remote_retrieve_body( $raw_response ), true ); if ( ! is_array( $response ) ) { return null; } if ( ! isset( $response['translations'] ) || empty( $response['translations'] ) ) { return null; } return $response['translations']; } /** * @author Leo Fajardo (@leorw) * @since 2.1.2 * * @param string $module_type * @param string $slug * * @return array */ private function get_installed_translations( $module_type, $slug ) { if ( function_exists( 'wp_get_installed_translations' ) ) { return wp_get_installed_translations( $module_type ); } $dir = "/{$module_type}"; if ( ! is_dir( WP_LANG_DIR . $dir ) ) return array(); $files = scandir( WP_LANG_DIR . $dir ); if ( ! $files ) return array(); $language_data = array(); foreach ( $files as $file ) { if ( 0 !== strpos( $file, $slug ) ) { continue; } if ( '.' === $file[0] || is_dir( WP_LANG_DIR . "{$dir}/{$file}" ) ) { continue; } if ( substr( $file, -3 ) !== '.po' ) { continue; } if ( ! preg_match( '/(?:(.+)-)?([a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?).po/', $file, $match ) ) { continue; } if ( ! in_array( substr( $file, 0, -3 ) . '.mo', $files ) ) { continue; } list( , $textdomain, $language ) = $match; if ( '' === $textdomain ) { $textdomain = 'default'; } $language_data[ $textdomain ][ $language ] = wp_get_pomo_file_data( WP_LANG_DIR . "{$dir}/{$file}" ); } return $language_data; } /** * Updates information on the "View version x.x details" page with custom data. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @uses FS_Api * * @param object $data * @param string $action * @param mixed $args * * @return object */ function plugins_api_filter( $data, $action = '', $args = null ) { $this->_logger->entrance(); if ( ( 'plugin_information' !== $action ) || ! isset( $args->slug ) ) { return $data; } $addon = false; $is_addon = false; $addon_version = false; if ( $this->_fs->get_slug() !== $args->slug ) { $addon = $this->_fs->get_addon_by_slug( $args->slug ); if ( ! is_object( $addon ) ) { return $data; } if ( $this->_fs->is_addon_activated( $addon->id ) ) { $addon_version = $this->_fs->get_addon_instance( $addon->id )->get_plugin_version(); } else if ( $this->_fs->is_addon_installed( $addon->id ) ) { $addon_plugin_data = get_plugin_data( ( WP_PLUGIN_DIR . '/' . $this->_fs->get_addon_basename( $addon->id ) ), false, false ); if ( ! empty( $addon_plugin_data ) ) { $addon_version = $addon_plugin_data['Version']; } } $is_addon = true; } $plugin_in_repo = false; if ( ! $is_addon ) { // Try to fetch info from .org repository. $data = self::_fetch_plugin_info_from_repository( $action, $args ); $plugin_in_repo = ( false !== $data ); } if ( ! $plugin_in_repo ) { $data = $args; // Fetch as much as possible info from local files. $plugin_local_data = $this->_fs->get_plugin_data(); $data->name = $plugin_local_data['Name']; $data->author = $plugin_local_data['Author']; $data->sections = array( 'description' => 'Upgrade ' . $plugin_local_data['Name'] . ' to latest.', ); // @todo Store extra plugin info on Freemius or parse readme.txt markup. /*$info = $this->_fs->get_api_site_scope()->call('/information.json'); if ( !isset($info->error) ) { $data = $info; }*/ } $plugin_version = $is_addon ? $addon_version : $this->_fs->get_plugin_version(); // Get plugin's newest update. $new_version = $this->get_latest_download_details( $is_addon ? $addon->id : false, $plugin_version ); if ( ! is_object( $new_version ) || empty( $new_version->version ) ) { $data->version = $plugin_version; } else { if ( $is_addon ) { $data->name = $addon->title . ' ' . $this->_fs->get_text_inline( 'Add-On', 'addon' ); $data->slug = $addon->slug; $data->url = WP_FS__ADDRESS; $data->package = $new_version->url; } if ( ! $plugin_in_repo ) { $data->last_updated = ! is_null( $new_version->updated ) ? $new_version->updated : $new_version->created; $data->requires = $new_version->requires_platform_version; $data->requires_php = $new_version->requires_programming_language_version; $data->tested = $new_version->tested_up_to_version; } $data->version = $new_version->version; $data->download_link = $new_version->url; if ( isset( $new_version->readme ) && is_object( $new_version->readme ) ) { $new_version_readme_data = $new_version->readme; if ( isset( $new_version_readme_data->sections ) ) { $new_version_readme_data->sections = (array) $new_version_readme_data->sections; } else { $new_version_readme_data->sections = array(); } if ( isset( $data->sections ) ) { if ( isset( $data->sections['screenshots'] ) ) { $new_version_readme_data->sections['screenshots'] = $data->sections['screenshots']; } if ( isset( $data->sections['reviews'] ) ) { $new_version_readme_data->sections['reviews'] = $data->sections['reviews']; } } if ( isset( $new_version_readme_data->banners ) ) { $new_version_readme_data->banners = (array) $new_version_readme_data->banners; } else if ( isset( $data->banners ) ) { $new_version_readme_data->banners = $data->banners; } $wp_org_sections = array( 'author', 'author_profile', 'rating', 'ratings', 'num_ratings', 'support_threads', 'support_threads_resolved', 'active_installs', 'added', 'homepage' ); foreach ( $wp_org_sections as $wp_org_section ) { if ( isset( $data->{$wp_org_section} ) ) { $new_version_readme_data->{$wp_org_section} = $data->{$wp_org_section}; } } $data = $new_version_readme_data; } } if ( ! empty( $data->tested ) ) { $data->tested = self::get_tested_wp_version( $data->tested ); } return $data; } /** * @since 2.5.3 If the current WordPress version is a patch of the tested version (e.g., 6.1.2 is a patch of 6.1), then override the tested version with the patch so developers won't need to release a new version just to bump the latest supported WP version. * * @param string|null $tested_up_to * * @return string|null */ private static function get_tested_wp_version( $tested_up_to ) { $current_wp_version = get_bloginfo( 'version' ); return ( ! empty($tested_up_to) && fs_starts_with( $current_wp_version, $tested_up_to . '.' ) ) ? $current_wp_version : $tested_up_to; } /** * @author Vova Feldman (@svovaf) * @since 1.2.1.7 * * @param number|bool $addon_id * @param bool|string $newer_than Since 2.2.1 * @param bool|string $fetch_readme Since 2.2.1 * * @return object */ private function get_latest_download_details( $addon_id = false, $newer_than = false, $fetch_readme = true ) { return $this->_fs->_fetch_latest_version( $addon_id, true, WP_FS__TIME_24_HOURS_IN_SEC, $newer_than, $fetch_readme ); } /** * Checks if a given basename has a matching folder name * with the current context plugin. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @return bool */ private function is_correct_folder_name() { return ( $this->_fs->get_target_folder_name() == trim( dirname( $this->_fs->get_plugin_basename() ), '/\\' ) ); } /** * This is a special after upgrade handler for migrating modules * that didn't use the '-premium' suffix folder structure before * the migration. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @param bool $response Install response. * @param array $hook_extra Extra arguments passed to hooked filters. * @param array $result Installation result data. * * @return bool */ function _maybe_update_folder_name( $response, $hook_extra, $result ) { $basename = $this->_fs->get_plugin_basename(); if ( true !== $response || empty( $hook_extra ) || empty( $hook_extra['plugin'] ) || $basename !== $hook_extra['plugin'] ) { return $response; } $active_plugins_basenames = get_option( 'active_plugins' ); foreach ( $active_plugins_basenames as $key => $active_plugin_basename ) { if ( $basename === $active_plugin_basename ) { // Get filename including extension. $filename = basename( $basename ); $new_basename = plugin_basename( trailingslashit( $this->_fs->is_premium() ? $this->_fs->get_premium_slug() : $this->_fs->get_slug() ) . $filename ); // Verify that the expected correct path exists. if ( file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $new_basename ) ) ) { // Override active plugin name. $active_plugins_basenames[ $key ] = $new_basename; update_option( 'active_plugins', $active_plugins_basenames ); } break; } } return $response; } #---------------------------------------------------------------------------------- #region Auto Activation #---------------------------------------------------------------------------------- /** * Installs and active a plugin when explicitly requested that from a 3rd party service. * * This logic was inspired by the TGMPA GPL licensed library by Thomas Griffin. * * @link http://tgmpluginactivation.com/ * * @author Vova Feldman * @since 1.2.1.7 * * @link https://make.wordpress.org/plugins/2017/03/16/clarification-of-guideline-8-executable-code-and-installs/ * * @uses WP_Filesystem * @uses WP_Error * @uses WP_Upgrader * @uses Plugin_Upgrader * @uses Plugin_Installer_Skin * @uses Plugin_Upgrader_Skin * * @param number|bool $plugin_id * * @return array */ function install_and_activate_plugin( $plugin_id = false ) { if ( ! empty( $plugin_id ) && ! FS_Plugin::is_valid_id( $plugin_id ) ) { // Invalid plugin ID. return array( 'message' => $this->_fs->get_text_inline( 'Invalid module ID.', 'auto-install-error-invalid-id' ), 'code' => 'invalid_module_id', ); } $is_addon = false; if ( FS_Plugin::is_valid_id( $plugin_id ) && $plugin_id != $this->_fs->get_id() ) { $addon = $this->_fs->get_addon( $plugin_id ); if ( ! is_object( $addon ) ) { // Invalid add-on ID. return array( 'message' => $this->_fs->get_text_inline( 'Invalid module ID.', 'auto-install-error-invalid-id' ), 'code' => 'invalid_module_id', ); } $slug = $addon->slug; $premium_slug = $addon->premium_slug; $title = $addon->title . ' ' . $this->_fs->get_text_inline( 'Add-On', 'addon' ); $is_addon = true; } else { $slug = $this->_fs->get_slug(); $premium_slug = $this->_fs->get_premium_slug(); $title = $this->_fs->get_plugin_title() . ( $this->_fs->is_addon() ? ' ' . $this->_fs->get_text_inline( 'Add-On', 'addon' ) : '' ); } if ( $this->is_premium_plugin_active( $plugin_id ) ) { // Premium version already activated. return array( 'message' => $is_addon ? $this->_fs->get_text_inline( 'Premium add-on version already installed.', 'auto-install-error-premium-addon-activated' ) : $this->_fs->get_text_inline( 'Premium version already active.', 'auto-install-error-premium-activated' ), 'code' => 'premium_installed', ); } $latest_version = $this->get_latest_download_details( $plugin_id, false, false ); $target_folder = $premium_slug; // Prep variables for Plugin_Installer_Skin class. $extra = array(); $extra['slug'] = $target_folder; $source = $latest_version->url; $api = null; $install_url = add_query_arg( array( 'action' => 'install-plugin', 'plugin' => urlencode( $slug ), ), 'update.php' ); if ( ! class_exists( 'Plugin_Upgrader', false ) ) { // Include required resources for the installation. require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; } $skin_args = array( 'type' => 'web', 'title' => sprintf( $this->_fs->get_text_inline( 'Installing plugin: %s', 'installing-plugin-x' ), $title ), 'url' => esc_url_raw( $install_url ), 'nonce' => 'install-plugin_' . $slug, 'plugin' => '', 'api' => $api, 'extra' => $extra, ); // $skin = new Automatic_Upgrader_Skin( $skin_args ); // $skin = new Plugin_Installer_Skin( $skin_args ); $skin = new WP_Ajax_Upgrader_Skin( $skin_args ); // Create a new instance of Plugin_Upgrader. $upgrader = new Plugin_Upgrader( $skin ); // Perform the action and install the plugin from the $source urldecode(). add_filter( 'upgrader_source_selection', array( 'FS_Plugin_Updater', '_maybe_adjust_source_dir' ), 1, 3 ); $install_result = $upgrader->install( $source ); remove_filter( 'upgrader_source_selection', array( 'FS_Plugin_Updater', '_maybe_adjust_source_dir' ), 1 ); if ( is_wp_error( $install_result ) ) { return array( 'message' => $install_result->get_error_message(), 'code' => $install_result->get_error_code(), ); } elseif ( is_wp_error( $skin->result ) ) { return array( 'message' => $skin->result->get_error_message(), 'code' => $skin->result->get_error_code(), ); } elseif ( $skin->get_errors()->get_error_code() ) { return array( 'message' => $skin->get_error_messages(), 'code' => 'unknown', ); } elseif ( is_null( $install_result ) ) { global $wp_filesystem; $error_code = 'unable_to_connect_to_filesystem'; $error_message = $this->_fs->get_text_inline( 'Unable to connect to the filesystem. Please confirm your credentials.' ); // Pass through the error from WP_Filesystem if one was raised. if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) { $error_message = $wp_filesystem->errors->get_error_message(); } return array( 'message' => $error_message, 'code' => $error_code, ); } // Grab the full path to the main plugin's file. $plugin_activate = $upgrader->plugin_info(); // Try to activate the plugin. $activation_result = $this->try_activate_plugin( $plugin_activate ); if ( is_wp_error( $activation_result ) ) { return array( 'message' => $activation_result->get_error_message(), 'code' => $activation_result->get_error_code(), ); } return $skin->get_upgrade_messages(); } /** * Tries to activate a plugin. If fails, returns the error. * * @author Vova Feldman * @since 1.2.1.7 * * @param string $file_path Path within wp-plugins/ to main plugin file. * This determines the styling of the output messages. * * @return bool|WP_Error */ protected function try_activate_plugin( $file_path ) { $activate = activate_plugin( $file_path, '', $this->_fs->is_network_active() ); return is_wp_error( $activate ) ? $activate : true; } /** * Check if a premium module version is already active. * * @author Vova Feldman * @since 1.2.1.7 * * @param number|bool $plugin_id * * @return bool */ private function is_premium_plugin_active( $plugin_id = false ) { if ( $plugin_id != $this->_fs->get_id() ) { return $this->_fs->is_addon_activated( $plugin_id, true ); } return is_plugin_active( $this->_fs->premium_plugin_basename() ); } /** * Store the basename since it's not always available in the `_maybe_adjust_source_dir` method below. * * @author Leo Fajardo (@leorw) * @since 2.2.1 * * @param bool|WP_Error $response Response. * @param array $hook_extra Extra arguments passed to hooked filters. * * @return bool|WP_Error */ static function _store_basename_for_source_adjustment( $response, $hook_extra ) { if ( isset( $hook_extra['plugin'] ) ) { self::$_upgrade_basename = $hook_extra['plugin']; } else if ( isset( $hook_extra['theme'] ) ) { self::$_upgrade_basename = $hook_extra['theme']; } else { self::$_upgrade_basename = null; } return $response; } /** * Adjust the plugin directory name if necessary. * Assumes plugin has a folder (not a single file plugin). * * The final destination directory of a plugin is based on the subdirectory name found in the * (un)zipped source. In some cases this subdirectory name is not the same as the expected * slug and the plugin will not be recognized as installed. This is fixed by adjusting * the temporary unzipped source subdirectory name to the expected plugin slug. * * @author Vova Feldman * @since 1.2.1.7 * @since 2.2.1 The method was converted to static since when the admin update bulk products via the Updates section, the logic applies the `upgrader_source_selection` filter for every product that is being updated. * * @param string $source Path to upgrade/zip-file-name.tmp/subdirectory/. * @param string $remote_source Path to upgrade/zip-file-name.tmp. * @param \WP_Upgrader $upgrader Instance of the upgrader which installs the plugin. * * @return string|WP_Error */ static function _maybe_adjust_source_dir( $source, $remote_source, $upgrader ) { if ( ! is_object( $GLOBALS['wp_filesystem'] ) ) { return $source; } $basename = self::$_upgrade_basename; $is_theme = false; // Figure out what the slug is supposed to be. if ( isset( $upgrader->skin->options['extra'] ) ) { // Set by the auto-install logic. $desired_slug = $upgrader->skin->options['extra']['slug']; } else if ( ! empty( $basename ) ) { /** * If it doesn't end with ".php", it's a theme. * * @author Leo Fajardo (@leorw) * @since 2.2.1 */ $is_theme = ( ! fs_ends_with( $basename, '.php' ) ); $desired_slug = ( ! $is_theme ) ? dirname( $basename ) : // Theme slug $basename; } else { // Can't figure out the desired slug, stop the execution. return $source; } if ( is_multisite() ) { /** * If we are running in a multisite environment and the product is not network activated, * the instance will not exist anyway. Therefore, try to update the source if necessary * regardless if the Freemius instance of the product exists or not. * * @author Vova Feldman */ } else if ( ! empty( $basename ) ) { $fs = Freemius::get_instance_by_file( $basename, $is_theme ? WP_FS__MODULE_TYPE_THEME : WP_FS__MODULE_TYPE_PLUGIN ); if ( ! is_object( $fs ) ) { /** * If the Freemius instance does not exist on a non-multisite network environment, it means that: * 1. The product is not powered by Freemius; OR * 2. The product is not activated, therefore, we don't mind if after the update the folder name will change. * * @author Leo Fajardo (@leorw) * @since 2.2.1 */ return $source; } } $subdir_name = untrailingslashit( str_replace( trailingslashit( $remote_source ), '', $source ) ); if ( ! empty( $subdir_name ) && $subdir_name !== $desired_slug ) { $from_path = untrailingslashit( $source ); $to_path = trailingslashit( $remote_source ) . $desired_slug; if ( true === $GLOBALS['wp_filesystem']->move( $from_path, $to_path ) ) { return trailingslashit( $to_path ); } return new WP_Error( 'rename_failed', fs_text_inline( 'The remote plugin package does not contain a folder with the desired slug and renaming did not work.', 'module-package-rename-failure' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) ); } return $source; } #endregion } freemius/includes/class-fs-options.php000064400000041105146725417150014123 0ustar00_id = $id; $this->_is_multisite = is_multisite(); if ( $this->_is_multisite ) { $this->_blog_id = get_current_blog_id(); $this->_network_options = FS_Option_Manager::get_manager( $id, $load, true ); } $this->_options = FS_Option_Manager::get_manager( $id, $load, $this->_blog_id ); } /** * Switch the context of the site level options manager. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param $blog_id */ function set_site_blog_context( $blog_id ) { $this->_blog_id = $blog_id; $this->_options = FS_Option_Manager::get_manager( $this->_id, false, $this->_blog_id ); } /** * @author Leo Fajardo (@leorw) * * @param string $option * @param mixed $default * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS). * * @return mixed */ function get_option( $option, $default = null, $network_level_or_blog_id = null ) { if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) { return $this->_network_options->get_option( $option, $default ); } $site_options = $this->get_site_options( $network_level_or_blog_id ); return $site_options->get_option( $option, $default ); } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param string $option * @param mixed $value * @param bool $flush * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS). */ function set_option( $option, $value, $flush = false, $network_level_or_blog_id = null ) { if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) { $this->_network_options->set_option( $option, $value, $flush ); } else { $site_options = $this->get_site_options( $network_level_or_blog_id ); $site_options->set_option( $option, $value, $flush ); } } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $option * @param bool $flush * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS). */ function unset_option( $option, $flush = false, $network_level_or_blog_id = null ) { if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) { $this->_network_options->unset_option( $option, $flush ); } else { $site_options = $this->get_site_options( $network_level_or_blog_id ); $site_options->unset_option( $option, $flush ); } } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param bool $flush * @param bool $network_level */ function load( $flush = false, $network_level = true ) { if ( $this->_is_multisite && $network_level ) { $this->_network_options->load( $flush ); } else { $this->_options->load( $flush ); } } /** * @author Leo Fajardo (@leorw) * @since 2.0.0 * * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, store both network storage and the current context blog storage. */ function store( $network_level_or_blog_id = null ) { if ( ! $this->_is_multisite || false === $network_level_or_blog_id || 0 == $network_level_or_blog_id || is_null( $network_level_or_blog_id ) ) { $site_options = $this->get_site_options( $network_level_or_blog_id ); $site_options->store(); } if ( $this->_is_multisite && ( is_null( $network_level_or_blog_id ) || true === $network_level_or_blog_id ) ) { $this->_network_options->store(); } } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int|null|bool $network_level_or_blog_id * @param bool $flush */ function clear( $network_level_or_blog_id = null, $flush = false ) { if ( ! $this->_is_multisite || false === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) || is_numeric( $network_level_or_blog_id ) ) { $site_options = $this->get_site_options( $network_level_or_blog_id ); $site_options->clear( $flush ); } if ( $this->_is_multisite && ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) ) ) { $this->_network_options->clear( $flush ); } } /** * Migration script to the new storage data structure that is network compatible. * * IMPORTANT: * This method should be executed only after it is determined if this is a network * level compatible product activation. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id */ function migrate_to_network( $blog_id = 0 ) { if ( ! $this->_is_multisite ) { return; } $updated = false; $site_options = $this->get_site_options( $blog_id ); $keys = $site_options->get_options_keys(); foreach ( $keys as $option ) { if ( $this->is_site_option( $option ) || // Don't move admin notices to the network storage. in_array($option, array( // Don't move admin notices to the network storage. 'admin_notices', // Don't migrate the module specific data, it will be migrated by the FS_Storage. 'plugin_data', 'theme_data', )) ) { continue; } $option_updated = false; // Migrate option to the network storage. $site_option = $site_options->get_option( $option ); if ( ! $this->_network_options->has_option( $option ) ) { // Option not set on the network level, so just set it. $this->_network_options->set_option( $option, $site_option, false ); $option_updated = true; } else { // Option already set on the network level, so we need to merge it inelegantly. $network_option = $this->_network_options->get_option( $option ); if ( is_array( $network_option ) && is_array( $site_option ) ) { // Option is an array. foreach ( $site_option as $key => $value ) { if ( ! isset( $network_option[ $key ] ) ) { $network_option[ $key ] = $value; $option_updated = true; } else if ( is_array( $network_option[ $key ] ) && is_array( $value ) ) { if ( empty( $network_option[ $key ] ) ) { $network_option[ $key ] = $value; $option_updated = true; } else if ( empty( $value ) ) { // Do nothing. } else { reset($value); $first_key = key($value); if ( $value[$first_key] instanceof FS_Entity ) { // Merge entities by IDs. $network_entities_ids = array(); foreach ( $network_option[ $key ] as $entity ) { $network_entities_ids[ $entity->id ] = true; } foreach ( $value as $entity ) { if ( ! isset( $network_entities_ids[ $entity->id ] ) ) { $network_option[ $key ][] = $entity; $option_updated = true; } } } } } } } if ( $option_updated ) { $this->_network_options->set_option( $option, $network_option, false ); } } /** * Remove the option from site level storage. * * IMPORTANT: * The line below is intentionally commented since we want to preserve the option * on the site storage level for "downgrade compatibility". Basically, if the user * will downgrade to an older version of the plugin with the prev storage structure, * it will continue working. * * @todo After a few releases we can remove this. */ // $site_options->unset_option($option, false); if ( $option_updated ) { $updated = true; } } if ( ! $updated ) { return; } // Update network level storage. $this->_network_options->store(); // $site_options->store(); } #-------------------------------------------------------------------------------- #region Helper Methods #-------------------------------------------------------------------------------- /** * We don't want to load the map right away since it's not even needed in a non-MS environment. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ private static function load_site_options_map() { self::$_SITE_OPTIONS_MAP = array( 'sites' => true, 'theme_sites' => true, 'unique_id' => true, 'active_plugins' => true, ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $option * * @return bool */ private function is_site_option( $option ) { if ( WP_FS__ACCOUNTS_OPTION_NAME != $this->_id ) { return false; } if ( ! isset( self::$_SITE_OPTIONS_MAP ) ) { self::load_site_options_map(); } return isset( self::$_SITE_OPTIONS_MAP[ $option ] ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param int $blog_id * * @return FS_Option_Manager */ private function get_site_options( $blog_id = 0 ) { if ( 0 == $blog_id || $blog_id == $this->_blog_id ) { return $this->_options; } return FS_Option_Manager::get_manager( $this->_id, true, $blog_id ); } /** * Check if an option should be stored on the MS network storage. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $option * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS). * * @return bool */ private function should_use_network_storage( $option, $network_level_or_blog_id = null ) { if ( ! $this->_is_multisite ) { // Not a multisite environment. return false; } if ( is_numeric( $network_level_or_blog_id ) ) { // Explicitly asked to use a specified blog storage. return false; } if ( is_bool( $network_level_or_blog_id ) ) { // Explicitly specified whether should use the network or blog level storage. return $network_level_or_blog_id; } // Determine which storage to use based on the option. return ! $this->is_site_option( $option ); } #endregion }freemius/includes/customizer/class-fs-customizer-upsell-control.php000064400000012154146725417150022022 0ustar00register_control_type( 'FS_Customizer_Upsell_Control' ); parent::__construct( $manager, $id, $args ); } /** * Enqueue resources for the control. */ public function enqueue() { fs_enqueue_local_style( 'fs_customizer', 'customizer.css' ); } /** * Json conversion */ public function to_json() { $pricing_cta = esc_html( $this->fs->get_pricing_cta_label() ) . '  ' . ( is_rtl() ? '←' : '➤' ); parent::to_json(); $this->json['button_text'] = $pricing_cta; $this->json['button_url'] = $this->fs->is_in_trial_promotion() ? $this->fs->get_trial_url() : $this->fs->get_upgrade_url(); $api = FS_Plugin::is_valid_id( $this->fs->get_bundle_id() ) ? $this->fs->get_api_bundle_scope() : $this->fs->get_api_plugin_scope(); // Load features. $pricing = $api->get( $this->fs->add_show_pending( "pricing.json" ) ); if ( $this->fs->is_api_result_object( $pricing, 'plans' ) ) { // Add support features. if ( is_array( $pricing->plans ) && 0 < count( $pricing->plans ) ) { $support_features = array( 'kb' => 'Help Center', 'forum' => 'Support Forum', 'email' => 'Priority Email Support', 'phone' => 'Phone Support', 'skype' => 'Skype Support', 'is_success_manager' => 'Personal Success Manager', ); for ( $i = 0, $len = count( $pricing->plans ); $i < $len; $i ++ ) { if ( 'free' == $pricing->plans[$i]->name ) { continue; } if ( ! isset( $pricing->plans[ $i ]->features ) || ! is_array( $pricing->plans[ $i ]->features ) ) { $pricing->plans[$i]->features = array(); } foreach ( $support_features as $key => $label ) { $key = ( 'is_success_manager' !== $key ) ? "support_{$key}" : $key; if ( ! empty( $pricing->plans[ $i ]->{$key} ) ) { $support_feature = new stdClass(); $support_feature->title = $label; $pricing->plans[ $i ]->features[] = $support_feature; } } } $this->json['plans'] = $pricing->plans; } } $this->json['strings'] = array( 'plan' => $this->fs->get_text_x_inline( 'Plan', 'as product pricing plan', 'plan' ), ); } /** * Control content */ public function content_template() { ?>
    <# if ( data.plans ) { #>
      <# for (i in data.plans) { #> <# if ( 'free' != data.plans[i].name && (null != data.plans[i].features && 0 < data.plans[i].features.length) ) { #>
    • <# if ( data.plans[i].description ) { #>

      {{ data.plans[i].description }}

      <# } #> <# if ( data.plans[i].features ) { #>
        <# for ( j in data.plans[i].features ) { #>
      • <# if ( data.plans[i].features[j].value ) { #>{{ data.plans[i].features[j].value }} <# } #>{{ data.plans[i].features[j].title }} <# if ( data.plans[i].features[j].description ) { #> {{ data.plans[i].features[j].description }} <# } #>
      • <# } #>
      <# } #> <# if ( 'free' != data.plans[i].name ) { #> {{{ data.button_text }}} <# } #>
    • <# } #> <# } #>
    <# } #>
    register_section_type( 'FS_Customizer_Support_Section' ); parent::__construct( $manager, $id, $args ); } /** * The type of customize section being rendered. * * @since 1.0.0 * @access public * @var string */ public $type = 'freemius-support-section'; /** * @var Freemius */ public $fs = null; /** * Add custom parameters to pass to the JS via JSON. * * @since 1.0.0 */ public function json() { $json = parent::json(); $is_contact_visible = $this->fs->is_page_visible( 'contact' ); $is_support_visible = $this->fs->is_page_visible( 'support' ); $json['theme_title'] = $this->fs->get_plugin_name(); if ( $is_contact_visible && $is_support_visible ) { $json['theme_title'] .= ' ' . $this->fs->get_text_inline( 'Support', 'support' ); } if ( $is_contact_visible ) { $json['contact'] = array( 'label' => $this->fs->get_text_inline( 'Contact Us', 'contact-us' ), 'url' => $this->fs->contact_url(), ); } if ( $is_support_visible ) { $json['support'] = array( 'label' => $this->fs->get_text_inline( 'Support Forum', 'support-forum' ), 'url' => $this->fs->get_support_forum_url() ); } return $json; } /** * Outputs the Underscore.js template. * * @since 1.0.0 */ protected function render_template() { ?>
  • {{ data.theme_title }} <# if ( data.contact && data.support ) { #>
    <# } #> <# if ( data.contact ) { #> {{ data.contact.label }} <# } #> <# if ( data.support ) { #> {{ data.support.label }} <# } #> <# if ( data.contact && data.support ) { #>
    <# } #>

  • _logger = FS_Logger::get_logger( WP_FS__SLUG . '_cach_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); $this->_logger->entrance(); $this->_logger->log( 'id = ' . $id ); $this->_options = FS_Option_Manager::get_manager( $id, true, true, false ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param $id * * @return FS_Cache_Manager */ static function get_manager( $id ) { $id = strtolower( $id ); if ( ! isset( self::$_MANAGERS[ $id ] ) ) { self::$_MANAGERS[ $id ] = new FS_Cache_Manager( $id ); } return self::$_MANAGERS[ $id ]; } /** * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @return bool */ function is_empty() { $this->_logger->entrance(); return $this->_options->is_empty(); } /** * @author Vova Feldman (@svovaf) * @since 1.1.6 */ function clear() { $this->_logger->entrance(); $this->_options->clear( true ); } /** * Delete cache manager from DB. * * @author Vova Feldman (@svovaf) * @since 1.0.9 */ function delete() { $this->_options->delete(); } /** * Check if there's a cached item. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string $key * * @return bool */ function has( $key ) { $cache_entry = $this->_options->get_option( $key, false ); return ( is_object( $cache_entry ) && isset( $cache_entry->timestamp ) && is_numeric( $cache_entry->timestamp ) ); } /** * Check if there's a valid cached item. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string $key * @param null|int $expiration Since 1.2.2.7 * * @return bool */ function has_valid( $key, $expiration = null ) { $cache_entry = $this->_options->get_option( $key, false ); $is_valid = ( is_object( $cache_entry ) && isset( $cache_entry->timestamp ) && is_numeric( $cache_entry->timestamp ) && $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME ); if ( $is_valid && is_numeric( $expiration ) && isset( $cache_entry->created ) && is_numeric( $cache_entry->created ) && $cache_entry->created + $expiration < WP_FS__SCRIPT_START_TIME ) { /** * Even if the cache is still valid, since we are checking for validity * with an explicit expiration period, if the period has past, return * `false` as if the cache is invalid. * * @since 1.2.2.7 */ $is_valid = false; } return $is_valid; } /** * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string $key * @param mixed $default * * @return mixed */ function get( $key, $default = null ) { $this->_logger->entrance( 'key = ' . $key ); $cache_entry = $this->_options->get_option( $key, false ); if ( is_object( $cache_entry ) && isset( $cache_entry->timestamp ) && is_numeric( $cache_entry->timestamp ) ) { return $cache_entry->result; } return is_object( $default ) ? clone $default : $default; } /** * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string $key * @param mixed $default * * @return mixed */ function get_valid( $key, $default = null ) { $this->_logger->entrance( 'key = ' . $key ); $cache_entry = $this->_options->get_option( $key, false ); if ( is_object( $cache_entry ) && isset( $cache_entry->timestamp ) && is_numeric( $cache_entry->timestamp ) && $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME ) { return $cache_entry->result; } return is_object( $default ) ? clone $default : $default; } /** * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string $key * @param mixed $value * @param int $expiration * @param int $created Since 2.0.0 Cache creation date. */ function set( $key, $value, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $created = WP_FS__SCRIPT_START_TIME ) { $this->_logger->entrance( 'key = ' . $key ); $cache_entry = new stdClass(); $cache_entry->result = $value; $cache_entry->created = $created; $cache_entry->timestamp = $created + $expiration; $this->_options->set_option( $key, $cache_entry, true ); } /** * Get cached record expiration, or false if not cached or expired. * * @author Vova Feldman (@svovaf) * @since 1.1.7.3 * * @param string $key * * @return bool|int */ function get_record_expiration( $key ) { $this->_logger->entrance( 'key = ' . $key ); $cache_entry = $this->_options->get_option( $key, false ); if ( is_object( $cache_entry ) && isset( $cache_entry->timestamp ) && is_numeric( $cache_entry->timestamp ) && $cache_entry->timestamp > WP_FS__SCRIPT_START_TIME ) { return $cache_entry->timestamp; } return false; } /** * Purge cached item. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string $key */ function purge( $key ) { $this->_logger->entrance( 'key = ' . $key ); $this->_options->unset_option( $key, true ); } /** * Extend cached item caching period. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $key * @param int $expiration * * @return bool */ function update_expiration( $key, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) { $this->_logger->entrance( 'key = ' . $key ); $cache_entry = $this->_options->get_option( $key, false ); if ( ! is_object( $cache_entry ) || ! isset( $cache_entry->timestamp ) || ! is_numeric( $cache_entry->timestamp ) ) { return false; } $this->set( $key, $cache_entry->result, $expiration, $cache_entry->created ); return true; } /** * Set cached item as expired. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @param string $key */ function expire( $key ) { $this->_logger->entrance( 'key = ' . $key ); $cache_entry = $this->_options->get_option( $key, false ); if ( is_object( $cache_entry ) && isset( $cache_entry->timestamp ) && is_numeric( $cache_entry->timestamp ) ) { // Set to expired. $cache_entry->timestamp = WP_FS__SCRIPT_START_TIME; $this->_options->set_option( $key, $cache_entry, true ); } } #-------------------------------------------------------------------------------- #region Migration #-------------------------------------------------------------------------------- /** * Migrate options from site level. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function migrate_to_network() { $this->_options->migrate_to_network(); } #endregion }freemius/includes/managers/class-fs-admin-menu-manager.php000064400000063232146725417150017674 0ustar00 */ private $_default_submenu_items; /** * @since 1.1.3 * * @var string */ private $_first_time_path; /** * @since 1.2.2 * * @var bool */ private $_menu_exists; /** * @since 2.0.0 * * @var bool */ private $_network_menu_exists; #endregion Properties /** * @var FS_Logger */ protected $_logger; #region Singleton /** * @var FS_Admin_Menu_Manager[] */ private static $_instances = array(); /** * @param number $module_id * @param string $module_type * @param string $module_unique_affix * * @return FS_Admin_Menu_Manager */ static function instance( $module_id, $module_type, $module_unique_affix ) { $key = 'm_' . $module_id; if ( ! isset( self::$_instances[ $key ] ) ) { self::$_instances[ $key ] = new FS_Admin_Menu_Manager( $module_id, $module_type, $module_unique_affix ); } return self::$_instances[ $key ]; } protected function __construct( $module_id, $module_type, $module_unique_affix ) { $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $module_id . '_admin_menu', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); $this->_module_id = $module_id; $this->_module_type = $module_type; $this->_module_unique_affix = $module_unique_affix; } #endregion Singleton #region Helpers private function get_option( &$options, $key, $default = false ) { return ! empty( $options[ $key ] ) ? $options[ $key ] : $default; } private function get_bool_option( &$options, $key, $default = false ) { return isset( $options[ $key ] ) && is_bool( $options[ $key ] ) ? $options[ $key ] : $default; } #endregion Helpers /** * @param array $menu * @param bool $is_addon */ function init( $menu, $is_addon = false ) { $this->_menu_exists = ( isset( $menu['slug'] ) && ! empty( $menu['slug'] ) ); $this->_network_menu_exists = ( ! empty( $menu['network'] ) && true === $menu['network'] ); $this->_menu_slug = ( $this->_menu_exists ? $menu['slug'] : $this->_module_unique_affix ); $this->_default_submenu_items = array(); // @deprecated $this->_type = 'page'; $this->_is_top_level = true; $this->_is_override_exact = false; $this->_parent_slug = false; // @deprecated $this->_parent_type = 'page'; if ( isset( $menu ) ) { if ( ! $is_addon ) { $this->_default_submenu_items = array( 'contact' => $this->get_bool_option( $menu, 'contact', true ), 'support' => $this->get_bool_option( $menu, 'support', true ), 'affiliation' => $this->get_bool_option( $menu, 'affiliation', true ), 'account' => $this->get_bool_option( $menu, 'account', true ), 'pricing' => $this->get_bool_option( $menu, 'pricing', true ), 'addons' => $this->get_bool_option( $menu, 'addons', true ), ); // @deprecated $this->_type = $this->get_option( $menu, 'type', 'page' ); } $this->_is_override_exact = $this->get_bool_option( $menu, 'override_exact' ); if ( isset( $menu['parent'] ) ) { $this->_parent_slug = $this->get_option( $menu['parent'], 'slug' ); // @deprecated $this->_parent_type = $this->get_option( $menu['parent'], 'type', 'page' ); // If parent's slug is different, then it's NOT a top level menu item. $this->_is_top_level = ( $this->_parent_slug === $this->_menu_slug ); } else { /** * If no parent then top level if: * - Has custom admin menu ('page') * - CPT menu type ('cpt') */ // $this->_is_top_level = in_array( $this->_type, array( // 'cpt', // 'page' // ) ); } $first_path = $this->get_option( $menu, 'first-path', false ); if ( ! empty( $first_path ) && is_string( $first_path ) ) { $this->_first_time_path = $first_path; } } } /** * Check if top level menu. * * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return bool False if submenu item. */ function is_top_level() { return $this->_is_top_level; } /** * Check if the page should be override on exact URL match. * * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return bool False if submenu item. */ function is_override_exact() { return $this->_is_override_exact; } /** * Get the path of the page the user should be forwarded to after first activation. * * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param bool $is_network Since 2.4.5 * * @return string */ function get_first_time_path( $is_network = false ) { if ( empty ( $this->_first_time_path ) ) { return $this->_first_time_path; } if ( $is_network ) { return network_admin_url( $this->_first_time_path ); } else { return admin_url( $this->_first_time_path ); } } /** * Check if plugin's menu item is part of a custom top level menu. * * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return bool */ function has_custom_parent() { return ! $this->_is_top_level && is_string( $this->_parent_slug ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @return bool */ function has_menu() { return $this->_menu_exists; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return bool */ function has_network_menu() { return $this->_network_menu_exists; } /** * @author Leo Fajardo (@leorw) * * @param string $menu_slug * * @since 2.1.3 */ function set_slug_and_network_menu_exists_flag($menu_slug ) { $this->_menu_slug = $menu_slug; $this->_network_menu_exists = false; } /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param string $id * @param bool $default * @param bool $ignore_menu_existence Since 1.2.2.7 If true, check if the submenu item visible even if there's no parent menu. * * @return bool */ function is_submenu_item_visible( $id, $default = true, $ignore_menu_existence = false ) { if ( ! $ignore_menu_existence && ! $this->has_menu() ) { return false; } return fs_apply_filter( $this->_module_unique_affix, 'is_submenu_visible', $this->get_bool_option( $this->_default_submenu_items, $id, $default ), $id ); } /** * Calculates admin settings menu slug. * If plugin's menu slug is a file (e.g. CPT), uses plugin's slug as the menu slug. * * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @param string $page * * @return string */ function get_slug( $page = '' ) { return ( ( false === strpos( $this->_menu_slug, '.php?' ) ) ? $this->_menu_slug : $this->_module_unique_affix ) . ( empty( $page ) ? '' : ( '-' . $page ) ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return string */ function get_parent_slug() { return $this->_parent_slug; } /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return string */ function get_type() { return $this->_type; } /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return bool */ function is_cpt() { return ( 0 === strpos( $this->_menu_slug, 'edit.php?post_type=' ) || // Back compatibility. 'cpt' === $this->_type ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return string */ function get_parent_type() { return $this->_parent_type; } /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return string */ function get_raw_slug() { return $this->_menu_slug; } /** * Get plugin's original menu slug. * * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return string */ function get_original_menu_slug() { if ( 'cpt' === $this->_type ) { return add_query_arg( array( 'post_type' => $this->_menu_slug ), 'edit.php' ); } if ( false === strpos( $this->_menu_slug, '.php?' ) ) { return $this->_menu_slug; } else { return $this->_module_unique_affix; } } /** * @author Vova Feldman (@svovaf) * @since 1.1.3 * * @return string */ function get_top_level_menu_slug() { return $this->has_custom_parent() ? $this->get_parent_slug() : $this->get_raw_slug(); } /** * Is user on plugin's admin activation page. * * @author Vova Feldman (@svovaf) * @since 1.0.8 * * @param bool $show_opt_in_on_themes_page Since 2.3.1 * * @return bool * * @deprecated Please use is_activation_page() instead. */ function is_main_settings_page( $show_opt_in_on_themes_page = false ) { return $this->is_activation_page( $show_opt_in_on_themes_page ); } /** * Is user on product's admin activation page. * * @author Vova Feldman (@svovaf) * @since 2.3.1 * * @param bool $show_opt_in_on_themes_page Since 2.3.1 * * @return bool */ function is_activation_page( $show_opt_in_on_themes_page = false ) { if ( $show_opt_in_on_themes_page ) { /** * In activation only when show_optin query string param is given. * * @since 1.2.2 */ return ( ( WP_FS__MODULE_TYPE_THEME === $this->_module_type ) && Freemius::is_themes_page() && fs_request_get_bool( $this->_module_unique_affix . '_show_optin' ) ); } if ( $this->_menu_exists && ( fs_is_plugin_page( $this->_menu_slug ) || fs_is_plugin_page( $this->_module_unique_affix ) ) ) { /** * Module has a settings menu and the context page is the main settings page, so assume it's in * activation (doesn't really check if already opted-in/skipped or not). * * @since 1.2.2 */ return true; } return false; } #region Submenu Override /** * Override submenu's action. * * @author Vova Feldman (@svovaf) * @since 1.1.0 * * @param string $parent_slug * @param string $menu_slug * @param callable $function * * @return false|string If submenu exist, will return the hook name. */ function override_submenu_action( $parent_slug, $menu_slug, $function ) { global $submenu; $menu_slug = plugin_basename( $menu_slug ); $parent_slug = plugin_basename( $parent_slug ); if ( ! isset( $submenu[ $parent_slug ] ) ) { // Parent menu not exist. return false; } $found_submenu_item = false; foreach ( $submenu[ $parent_slug ] as $submenu_item ) { if ( $menu_slug === $submenu_item[2] ) { $found_submenu_item = $submenu_item; break; } } if ( false === $found_submenu_item ) { // Submenu item not found. return false; } // Remove current function. $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug ); remove_all_actions( $hookname ); // Attach new action. add_action( $hookname, $function ); return $hookname; } #endregion Submenu Override #region Top level menu Override /** * Find plugin's admin dashboard main menu item. * * @author Vova Feldman (@svovaf) * @since 1.0.2 * * @return string[]|false */ private function find_top_level_menu() { global $menu; $position = - 1; $found_menu = false; $menu_slug = $this->get_raw_slug(); $hook_name = get_plugin_page_hookname( $menu_slug, '' ); foreach ( $menu as $pos => $m ) { if ( $menu_slug === $m[2] ) { $position = $pos; $found_menu = $m; break; } } if ( false === $found_menu ) { return false; } return array( 'menu' => $found_menu, 'position' => $position, 'hook_name' => $hook_name ); } /** * Find plugin's admin dashboard main submenu item. * * @author Vova Feldman (@svovaf) * @since 1.2.1.6 * * @return array|false */ private function find_main_submenu() { global $submenu; $top_level_menu_slug = $this->get_top_level_menu_slug(); if ( ! isset( $submenu[ $top_level_menu_slug ] ) ) { return false; } $submenu_slug = $this->get_raw_slug(); $position = - 1; $found_submenu = false; $hook_name = get_plugin_page_hookname( $submenu_slug, '' ); foreach ( $submenu[ $top_level_menu_slug ] as $pos => $sub ) { if ( $submenu_slug === $sub[2] ) { $position = $pos; $found_submenu = $sub; } } if ( false === $found_submenu ) { return false; } return array( 'menu' => $found_submenu, 'parent_slug' => $top_level_menu_slug, 'position' => $position, 'hook_name' => $hook_name ); } /** * Remove all sub-menu items. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @return bool If submenu with plugin's menu slug was found. */ private function remove_all_submenu_items() { global $submenu; $menu_slug = $this->get_raw_slug(); if ( ! isset( $submenu[ $menu_slug ] ) ) { return false; } /** * This method is NOT executed for WordPress.org themes. * Since we maintain only one version of the SDK we added this small * hack to avoid the error from Theme Check since it's a false-positive. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 */ $submenu_ref = &$submenu; $submenu_ref[ $menu_slug ] = array(); return true; } /** * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param bool $remove_top_level_menu * * @return false|array[string]mixed */ function remove_menu_item( $remove_top_level_menu = false ) { $this->_logger->entrance(); // Find main menu item. $top_level_menu = $this->find_top_level_menu(); if ( false === $top_level_menu ) { return false; } // Remove it with its actions. remove_all_actions( $top_level_menu['hook_name'] ); // Remove all submenu items. $this->remove_all_submenu_items(); if ( $remove_top_level_menu ) { global $menu; unset( $menu[ $top_level_menu['position'] ] ); } return $top_level_menu; } /** * Get module's main admin setting page URL. * * @todo This method was only tested for wp.org compliant themes with a submenu item. Need to test for plugins with top level, submenu, and CPT top level, menu items. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 * * @return string */ function main_menu_url() { $this->_logger->entrance(); if ( $this->_is_top_level ) { $menu = $this->find_top_level_menu(); } else { $menu = $this->find_main_submenu(); } $parent_slug = isset( $menu['parent_slug'] ) ? $menu['parent_slug'] : 'admin.php'; return admin_url( $parent_slug . ( false === strpos( $parent_slug, '?' ) ? '?' : '&' ) . 'page=' . $menu['menu'][2] ); } /** * @author Vova Feldman (@svovaf) * @since 1.1.4 * * @param callable $function * * @return false|array[string]mixed */ function override_menu_item( $function ) { $found_menu = $this->remove_menu_item(); if ( false === $found_menu ) { return false; } if ( ! $this->is_top_level() || ! $this->is_cpt() ) { $menu_slug = plugin_basename( $this->get_slug() ); $hookname = get_plugin_page_hookname( $menu_slug, '' ); // Override menu action. add_action( $hookname, $function ); } else { global $menu; // Remove original CPT menu. unset( $menu[ $found_menu['position'] ] ); // Create new top-level menu action. $hookname = self::add_page( $found_menu['menu'][3], $found_menu['menu'][0], 'manage_options', $this->get_slug(), $function, $found_menu['menu'][6], $found_menu['position'] ); } return $hookname; } /** * Adds a counter to the module's top level menu item. * * @author Vova Feldman (@svovaf) * @since 1.2.1.5 * * @param int $counter * @param string $class */ function add_counter_to_menu_item( $counter = 1, $class = '' ) { global $menu, $submenu; $mask = '%s '; /** * This method is NOT executed for WordPress.org themes. * Since we maintain only one version of the SDK we added this small * hack to avoid the error from Theme Check since it's a false-positive. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 */ $menu_ref = &$menu; $submenu_ref = &$submenu; if ( $this->_is_top_level ) { // Find main menu item. $found_menu = $this->find_top_level_menu(); if ( false !== $found_menu ) { // Override menu label. $menu_ref[ $found_menu['position'] ][0] = sprintf( $mask, $found_menu['menu'][0], $class, $counter ); } } else { $found_submenu = $this->find_main_submenu(); if ( false !== $found_submenu ) { // Override menu label. $submenu_ref[ $found_submenu['parent_slug'] ][ $found_submenu['position'] ][0] = sprintf( $mask, $found_submenu['menu'][0], $class, $counter ); } } } #endregion Top level menu Override /** * Add a top-level menu page. * * Note for WordPress.org Theme/Plugin reviewer: * * This is a replication of `add_menu_page()` to avoid Theme Check warning. * * Why? * ==== * Freemius is an SDK for plugin and theme developers. Since the core * of the SDK is relevant both for plugins and themes, for obvious reasons, * we only develop and maintain one code base. * * This method will not run for wp.org themes (only plugins) since theme * admin settings/options are now only allowed in the customizer. * * If you have any questions or need clarifications, please don't hesitate * pinging me on slack, my username is @svovaf. * * @author Vova Feldman (@svovaf) * @since 1.2.2 * * @param string $page_title The text to be displayed in the title tags of the page when the menu is * selected. * @param string $menu_title The text to be used for the menu. * @param string $capability The capability required for this menu to be displayed to the user. * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). * @param callable|string $function The function to be called to output the content for this page. * @param string $icon_url The URL to the icon to be used for this menu. * * Pass a base64-encoded SVG using a data URI, which will be colored to * match the color scheme. This should begin with * 'data:image/svg+xml;base64,'. * * Pass the name of a Dashicons helper class to use a font icon, * e.g. 'dashicons-chart-pie'. * * Pass 'none' to leave div.wp-menu-image empty so an icon can be added * via CSS. * @param int $position The position in the menu order this one should appear. * * @return string The resulting page's hook_suffix. */ static function add_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) { $fn = 'add_menu' . '_page'; return $fn( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position ); } /** * Add page and update menu instance settings. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $page_title * @param string $menu_title * @param string $capability * @param string $menu_slug * @param callable|string $function * @param string $icon_url * @param int|null $position * * @return string */ function add_page_and_update( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) { $this->_menu_slug = $menu_slug; $this->_is_top_level = true; $this->_menu_exists = true; $this->_network_menu_exists = true; return self::add_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position ); } /** * Add a submenu page. * * Note for WordPress.org Theme/Plugin reviewer: * * This is a replication of `add_submenu_page()` to avoid Theme Check warning. * * Why? * ==== * Freemius is an SDK for plugin and theme developers. Since the core * of the SDK is relevant both for plugins and themes, for obvious reasons, * we only develop and maintain one code base. * * This method will not run for wp.org themes (only plugins) since theme * admin settings/options are now only allowed in the customizer. * * If you have any questions or need clarifications, please don't hesitate * pinging me on slack, my username is @svovaf. * * @author Vova Feldman (@svovaf) * @since 1.2.2 * * @param string $parent_slug The slug name for the parent menu (or the file name of a standard * WordPress admin page). * @param string $page_title The text to be displayed in the title tags of the page when the menu is * selected. * @param string $menu_title The text to be used for the menu. * @param string $capability The capability required for this menu to be displayed to the user. * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu). * @param callable|string $function The function to be called to output the content for this page. * * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability * required. */ static function add_subpage( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { $fn = 'add_submenu' . '_page'; return $fn( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function ); } /** * Add sub page and update menu instance settings. * * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @param string $parent_slug * @param string $page_title * @param string $menu_title * @param string $capability * @param string $menu_slug * @param callable|string $function * * @return string */ function add_subpage_and_update( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '' ) { $this->_menu_slug = $menu_slug; $this->_parent_slug = $parent_slug; $this->_is_top_level = false; $this->_menu_exists = true; $this->_network_menu_exists = true; return self::add_subpage( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function ); } }freemius/includes/managers/class-fs-option-manager.php000064400000034211146725417150017145 0ustar00_logger = FS_Logger::get_logger( WP_FS__SLUG . '_opt_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); $this->_logger->entrance(); $this->_logger->log( 'id = ' . $id ); $this->_id = $id; $this->_autoload = $autoload; if ( is_multisite() ) { $this->_is_network_storage = ( true === $network_level_or_blog_id ); if ( is_numeric( $network_level_or_blog_id ) ) { $this->_blog_id = $network_level_or_blog_id; } } else { $this->_is_network_storage = false; } if ( $load ) { $this->load(); } } /** * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @param string $id * @param bool $load * @param bool|int $network_level_or_blog_id Since 2.0.0 * @param bool|null $autoload * * @return \FS_Option_Manager */ static function get_manager( $id, $load = false, $network_level_or_blog_id = false, $autoload = null ) { $key = strtolower( $id ); if ( is_multisite() ) { if ( true === $network_level_or_blog_id ) { $key .= ':ms'; } else if ( is_numeric( $network_level_or_blog_id ) && $network_level_or_blog_id > 0 ) { $key .= ":{$network_level_or_blog_id}"; } else { $network_level_or_blog_id = get_current_blog_id(); $key .= ":{$network_level_or_blog_id}"; } } if ( ! isset( self::$_MANAGERS[ $key ] ) ) { self::$_MANAGERS[ $key ] = new FS_Option_Manager( $id, $load, $network_level_or_blog_id, $autoload ); } // If load required but not yet loaded, load. else if ( $load && ! self::$_MANAGERS[ $key ]->is_loaded() ) { self::$_MANAGERS[ $key ]->load(); } return self::$_MANAGERS[ $key ]; } /** * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @param bool $flush */ function load( $flush = false ) { $this->_logger->entrance(); if ( ! $flush && isset( $this->_options ) ) { return; } if ( isset( $this->_options ) ) { // Clear prev options. $this->clear(); } $option_name = $this->get_option_manager_name(); if ( $this->_is_network_storage ) { $this->_options = get_site_option( $option_name ); } else if ( $this->_blog_id > 0 ) { $this->_options = get_blog_option( $this->_blog_id, $option_name ); } else { $this->_options = get_option( $option_name ); } if ( is_string( $this->_options ) ) { $this->_options = json_decode( $this->_options ); } // $this->_logger->info('get_option = ' . var_export($this->_options, true)); if ( false === $this->_options ) { $this->clear(); } } /** * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @return bool */ function is_loaded() { return isset( $this->_options ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @return bool */ function is_empty() { return ( $this->is_loaded() && false === $this->_options ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param bool $flush */ function clear( $flush = false ) { $this->_logger->entrance(); $this->_options = array(); if ( $flush ) { $this->store(); } } /** * Delete options manager from DB. * * @author Vova Feldman (@svovaf) * @since 1.0.9 */ function delete() { $option_name = $this->get_option_manager_name(); if ( $this->_is_network_storage ) { delete_site_option( $option_name ); } else if ( $this->_blog_id > 0 ) { delete_blog_option( $this->_blog_id, $option_name ); } else { delete_option( $option_name ); } } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param string $option * @param bool $flush * * @return bool */ function has_option( $option, $flush = false ) { if ( ! $this->is_loaded() || $flush ) { $this->load( $flush ); } return array_key_exists( $option, $this->_options ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @param string $option * @param mixed $default * @param bool $flush * * @return mixed */ function get_option( $option, $default = null, $flush = false ) { $this->_logger->entrance( 'option = ' . $option ); if ( ! $this->is_loaded() || $flush ) { $this->load( $flush ); } if ( is_array( $this->_options ) ) { $value = isset( $this->_options[ $option ] ) ? $this->_options[ $option ] : $default; } else if ( is_object( $this->_options ) ) { $value = isset( $this->_options->{$option} ) ? $this->_options->{$option} : $default; } else { $value = $default; } /** * If it's an object, return a clone of the object, otherwise, * external changes of the object will actually change the value * of the object in the option manager which may lead to an unexpected * behaviour and data integrity when a store() call is triggered. * * Example: * $object1 = $options->get_option( 'object1' ); * $object1->x = 123; * * $object2 = $options->get_option( 'object2' ); * $object2->y = 'dummy'; * * $options->set_option( 'object2', $object2, true ); * * If we don't return a clone of option 'object1', setting 'object2' * will also store the updated value of 'object1' which is quite not * an expected behaviour. * * @author Vova Feldman */ return is_object( $value ) ? clone $value : $value; } /** * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @param string $option * @param mixed $value * @param bool $flush */ function set_option( $option, $value, $flush = false ) { $this->_logger->entrance( 'option = ' . $option ); if ( ! $this->is_loaded() ) { $this->clear(); } /** * If it's an object, store a clone of the object, otherwise, * external changes of the object will actually change the value * of the object in the options manager which may lead to an unexpected * behaviour and data integrity when a store() call is triggered. * * Example: * $object1 = new stdClass(); * $object1->x = 123; * * $options->set_option( 'object1', $object1 ); * * $object1->x = 456; * * $options->set_option( 'object2', $object2, true ); * * If we don't set the option as a clone of option 'object1', setting 'object2' * will also store the updated value of 'object1' ($object1->x = 456 instead of * $object1->x = 123) which is quite not an expected behaviour. * * @author Vova Feldman */ $copy = is_object( $value ) ? clone $value : $value; if ( is_array( $this->_options ) ) { $this->_options[ $option ] = $copy; } else if ( is_object( $this->_options ) ) { $this->_options->{$option} = $copy; } if ( $flush ) { $this->store(); } } /** * Unset option. * * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @param string $option * @param bool $flush */ function unset_option( $option, $flush = false ) { $this->_logger->entrance( 'option = ' . $option ); if ( is_array( $this->_options ) ) { if ( ! isset( $this->_options[ $option ] ) ) { return; } unset( $this->_options[ $option ] ); } else if ( is_object( $this->_options ) ) { if ( ! isset( $this->_options->{$option} ) ) { return; } unset( $this->_options->{$option} ); } if ( $flush ) { $this->store(); } } /** * Dump options to database. * * @author Vova Feldman (@svovaf) * @since 1.0.3 */ function store() { $this->_logger->entrance(); $option_name = $this->get_option_manager_name(); if ( $this->_logger->is_on() ) { $this->_logger->info( $option_name . ' = ' . var_export( $this->_options, true ) ); } // Update DB. if ( $this->_is_network_storage ) { update_site_option( $option_name, $this->_options ); } else if ( $this->_blog_id > 0 ) { update_blog_option( $this->_blog_id, $option_name, $this->_options ); } else { update_option( $option_name, $this->_options, $this->_autoload ); } } /** * Get options keys. * * @author Vova Feldman (@svovaf) * @since 1.0.3 * * @return string[] */ function get_options_keys() { if ( is_array( $this->_options ) ) { return array_keys( $this->_options ); } else if ( is_object( $this->_options ) ) { return array_keys( get_object_vars( $this->_options ) ); } return array(); } #-------------------------------------------------------------------------------- #region Migration #-------------------------------------------------------------------------------- /** * Migrate options from site level. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function migrate_to_network() { $site_options = FS_Option_Manager::get_manager($this->_id, true, false); $options = is_object( $site_options->_options ) ? get_object_vars( $site_options->_options ) : $site_options->_options; if ( ! empty( $options ) ) { foreach ( $options as $key => $val ) { $this->set_option( $key, $val, false ); } $this->store(); } } #endregion #-------------------------------------------------------------------------------- #region Helper Methods #-------------------------------------------------------------------------------- /** * @return string */ private function get_option_manager_name() { return $this->_id; } #endregion } freemius/includes/managers/class-fs-license-manager.php000064400000004226146725417150017262 0ustar00get_slug() ); // // if ( ! isset( self::$_instances[ $slug ] ) ) { // self::$_instances[ $slug ] = new FS_License_Manager( $slug, $fs ); // } // // return self::$_instances[ $slug ]; // } // //// private function __construct($slug) { //// parent::__construct($slug); //// } // // function entry_id() { // return 'licenses'; // } // // function sync( $id ) { // // } // // /** // * @author Vova Feldman (@svovaf) // * @since 1.0.5 // * @uses FS_Api // * // * @param number|bool $plugin_id // * // * @return FS_Plugin_License[]|stdClass Licenses or API error. // */ // function api_get_user_plugin_licenses( $plugin_id = false ) { // $api = $this->_fs->get_api_user_scope(); // // if ( ! is_numeric( $plugin_id ) ) { // $plugin_id = $this->_fs->get_id(); // } // // $result = $api->call( "/plugins/{$plugin_id}/licenses.json" ); // // if ( ! isset( $result->error ) ) { // for ( $i = 0, $len = count( $result->licenses ); $i < $len; $i ++ ) { // $result->licenses[ $i ] = new FS_Plugin_License( $result->licenses[ $i ] ); // } // // $result = $result->licenses; // } // // return $result; // } // // function api_get_many() { // // } // // function api_activate( $id ) { // // } // // function api_deactivate( $id ) { // // } /** * @param FS_Plugin_License[] $licenses * * @return bool */ static function has_premium_license( $licenses ) { if ( is_array( $licenses ) ) { foreach ( $licenses as $license ) { /** * @var FS_Plugin_License $license */ if ( ! $license->is_utilized() && $license->is_features_enabled() ) { return true; } } } return false; } }freemius/includes/managers/class-fs-permission-manager.php000064400000062170146725417150020032 0ustar00 */ private static $_instances = array(); const PERMISSION_USER = 'user'; const PERMISSION_SITE = 'site'; const PERMISSION_EVENTS = 'events'; const PERMISSION_ESSENTIALS = 'essentials'; const PERMISSION_DIAGNOSTIC = 'diagnostic'; const PERMISSION_EXTENSIONS = 'extensions'; const PERMISSION_NEWSLETTER = 'newsletter'; /** * @param Freemius $fs * * @return self */ static function instance( Freemius $fs ) { $id = $fs->get_id(); if ( ! isset( self::$_instances[ $id ] ) ) { self::$_instances[ $id ] = new self( $fs ); } return self::$_instances[ $id ]; } /** * @param Freemius $fs */ protected function __construct( Freemius $fs ) { $this->_fs = $fs; $this->_storage = FS_Storage::instance( $fs->get_module_type(), $fs->get_slug() ); } /** * @return string[] */ static function get_all_permission_ids() { return array( self::PERMISSION_USER, self::PERMISSION_SITE, self::PERMISSION_EVENTS, self::PERMISSION_ESSENTIALS, self::PERMISSION_DIAGNOSTIC, self::PERMISSION_EXTENSIONS, self::PERMISSION_NEWSLETTER, ); } /** * @return string[] */ static function get_api_managed_permission_ids() { return array( self::PERMISSION_USER, self::PERMISSION_SITE, self::PERMISSION_EXTENSIONS, ); } /** * @param string $permission * * @return bool */ static function is_supported_permission( $permission ) { return in_array( $permission, self::get_all_permission_ids() ); } /** * @since 2.5.3 * * @return bool */ function is_premium_context() { return ( $this->_fs->is_premium() || $this->_fs->can_use_premium_code() ); } /** * @param bool $is_license_activation * @param array[] $extra_permissions * * @return array[] */ function get_permissions( $is_license_activation, array $extra_permissions = array() ) { return $is_license_activation ? $this->get_license_activation_permissions( $extra_permissions ) : $this->get_opt_in_permissions( $extra_permissions ); } #-------------------------------------------------------------------------------- #region Opt-In Permissions #-------------------------------------------------------------------------------- /** * @param array[] $extra_permissions * * @return array[] */ function get_opt_in_permissions( array $extra_permissions = array(), $load_default_from_storage = false, $is_optional = false ) { $permissions = array_merge( $this->get_opt_in_required_permissions( $load_default_from_storage ), $this->get_opt_in_optional_permissions( $load_default_from_storage, $is_optional ), $extra_permissions ); return $this->get_sorted_permissions_by_priority( $permissions ); } /** * @param bool $load_default_from_storage * * @return array[] */ function get_opt_in_required_permissions( $load_default_from_storage = false ) { return array( $this->get_user_permission( $load_default_from_storage ) ); } /** * @param bool $load_default_from_storage * @param bool $is_optional * * @return array[] */ function get_opt_in_optional_permissions( $load_default_from_storage = false, $is_optional = false ) { return array_merge( $this->get_opt_in_diagnostic_permissions( $load_default_from_storage, $is_optional ), array( $this->get_extensions_permission( false, false, $load_default_from_storage ) ) ); } /** * @param bool $load_default_from_storage * @param bool $is_optional * * @return array[] */ function get_opt_in_diagnostic_permissions( $load_default_from_storage = false, $is_optional = false ) { // Alias. $fs = $this->_fs; $permissions = array(); $permissions[] = $this->get_permission( self::PERMISSION_SITE, 'admin-links', $fs->get_text_inline( 'View Basic Website Info', 'permissions-site' ), $fs->get_text_inline( 'Homepage URL & title, WP & PHP versions, and site language', 'permissions-site_desc' ), sprintf( /* translators: %s: 'Plugin' or 'Theme' */ $fs->get_text_inline( 'To provide additional functionality that\'s relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.', 'permissions-site_tooltip' ), $fs->get_module_label( true ) ), 10, $is_optional, true, $load_default_from_storage ); $permissions[] = $this->get_permission( self::PERMISSION_EVENTS, 'admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ), sprintf( $fs->get_text_inline( 'View Basic %s Info', 'permissions-events' ), $fs->get_module_label() ), sprintf( /* translators: %s: 'Plugin' or 'Theme' */ $fs->get_text_inline( 'Current %s & SDK versions, and if active or uninstalled', 'permissions-events_desc' ), $fs->get_module_label( true ) ), '', 20, $is_optional, true, $load_default_from_storage ); return $permissions; } #endregion #-------------------------------------------------------------------------------- #region License Activation Permissions #-------------------------------------------------------------------------------- /** * @param array[] $extra_permissions * * @return array[] */ function get_license_activation_permissions( array $extra_permissions = array(), $include_optional_label = true ) { $permissions = array_merge( $this->get_license_required_permissions(), $this->get_license_optional_permissions( $include_optional_label ), $extra_permissions ); return $this->get_sorted_permissions_by_priority( $permissions ); } /** * @param bool $load_default_from_storage * * @return array[] */ function get_license_required_permissions( $load_default_from_storage = false ) { // Alias. $fs = $this->_fs; $permissions = array(); $permissions[] = $this->get_permission( self::PERMISSION_ESSENTIALS, 'admin-links', $fs->get_text_inline( 'View License Essentials', 'permissions-essentials' ), $fs->get_text_inline( sprintf( /* translators: %s: 'Plugin' or 'Theme' */ 'Homepage URL, %s version, SDK version', $fs->get_module_label() ), 'permissions-essentials_desc' ), sprintf( /* translators: %s: 'Plugin' or 'Theme' */ $fs->get_text_inline( 'To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.', 'permissions-essentials_tooltip' ), $fs->get_module_label( true ) ), 10, false, true, $load_default_from_storage ); $permissions[] = $this->get_permission( self::PERMISSION_EVENTS, 'admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ), sprintf( $fs->get_text_inline( 'View %s State', 'permissions-events' ), $fs->get_module_label() ), sprintf( /* translators: %s: 'Plugin' or 'Theme' */ $fs->get_text_inline( 'Is active, deactivated, or uninstalled', 'permissions-events_desc-paid' ), $fs->get_module_label( true ) ), sprintf( $fs->get_text_inline( 'So you can reuse the license when the %s is no longer active.', 'permissions-events_tooltip' ), $fs->get_module_label( true ) ), 20, false, true, $load_default_from_storage ); return $permissions; } /** * @return array[] */ function get_license_optional_permissions( $include_optional_label = false, $load_default_from_storage = false ) { return array( $this->get_diagnostic_permission( $include_optional_label, $load_default_from_storage ), $this->get_extensions_permission( true, $include_optional_label, $load_default_from_storage ), ); } /** * @param bool $include_optional_label * @param bool $load_default_from_storage * * @return array */ function get_diagnostic_permission( $include_optional_label = false, $load_default_from_storage = false ) { return $this->get_permission( self::PERMISSION_DIAGNOSTIC, 'wordpress-alt', $this->_fs->get_text_inline( 'View Diagnostic Info', 'permissions-diagnostic' ) . ( $include_optional_label ? ' (' . $this->_fs->get_text_inline( 'optional' ) . ')' : '' ), $this->_fs->get_text_inline( 'WordPress & PHP versions, site language & title', 'permissions-diagnostic_desc' ), sprintf( /* translators: %s: 'Plugin' or 'Theme' */ $this->_fs->get_text_inline( 'To avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.', 'permissions-diagnostic_tooltip' ), $this->_fs->get_module_label( true ) ), 25, true, true, $load_default_from_storage ); } #endregion #-------------------------------------------------------------------------------- #region Common Permissions #-------------------------------------------------------------------------------- /** * @param bool $is_license_activation * @param bool $include_optional_label * @param bool $load_default_from_storage * * @return array */ function get_extensions_permission( $is_license_activation, $include_optional_label = false, $load_default_from_storage = false ) { $is_on_by_default = ! $is_license_activation; return $this->get_permission( self::PERMISSION_EXTENSIONS, 'block-default', $this->_fs->get_text_inline( 'View Plugins & Themes List', 'permissions-extensions' ) . ( $is_license_activation ? ( $include_optional_label ? ' (' . $this->_fs->get_text_inline( 'optional' ) . ')' : '' ) : '' ), $this->_fs->get_text_inline( 'Names, slugs, versions, and if active or not', 'permissions-extensions_desc' ), $this->_fs->get_text_inline( 'To ensure compatibility and avoid conflicts with your installed plugins and themes.', 'permissions-events_tooltip' ), 25, true, $is_on_by_default, $load_default_from_storage ); } /** * @param bool $load_default_from_storage * * @return array */ function get_user_permission( $load_default_from_storage = false ) { return $this->get_permission( self::PERMISSION_USER, 'admin-users', $this->_fs->get_text_inline( 'View Basic Profile Info', 'permissions-profile' ), $this->_fs->get_text_inline( 'Your WordPress user\'s: first & last name, and email address', 'permissions-profile_desc' ), $this->_fs->get_text_inline( 'Never miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.', 'permissions-profile_tooltip' ), 5, false, true, $load_default_from_storage ); } #endregion #-------------------------------------------------------------------------------- #region Optional Permissions #-------------------------------------------------------------------------------- /** * @return array[] */ function get_newsletter_permission() { return $this->get_permission( self::PERMISSION_NEWSLETTER, 'email-alt', $this->_fs->get_text_inline( 'Newsletter', 'permissions-newsletter' ), $this->_fs->get_text_inline( 'Updates, announcements, marketing, no spam', 'permissions-newsletter_desc' ), '', 15 ); } #endregion #-------------------------------------------------------------------------------- #region Permissions Storage #-------------------------------------------------------------------------------- /** * @param int|null $blog_id * * @return bool */ function is_extensions_tracking_allowed( $blog_id = null ) { return $this->is_permission_allowed( self::PERMISSION_EXTENSIONS, ! $this->_fs->is_premium(), $blog_id ); } /** * @param int|null $blog_id * * @return bool */ function is_essentials_tracking_allowed( $blog_id = null ) { return $this->is_permission_allowed( self::PERMISSION_ESSENTIALS, true, $blog_id ); } /** * @param bool $default * * @return bool */ function is_diagnostic_tracking_allowed( $default = true ) { return $this->is_premium_context() ? $this->is_permission_allowed( self::PERMISSION_DIAGNOSTIC, $default ) : $this->is_permission_allowed( self::PERMISSION_SITE, $default ); } /** * @param int|null $blog_id * * @return bool */ function is_homepage_url_tracking_allowed( $blog_id = null ) { return $this->is_permission_allowed( $this->get_site_permission_name(), true, $blog_id ); } /** * @param int|null $blog_id * * @return bool */ function update_site_tracking( $is_enabled, $blog_id = null, $only_if_not_set = false ) { $permissions = $this->get_site_tracking_permission_names(); $result = true; foreach ( $permissions as $permission ) { if ( ! $only_if_not_set || ! $this->is_permission_set( $permission, $blog_id ) ) { $result = ( $result && $this->update_permission_tracking_flag( $permission, $is_enabled, $blog_id ) ); } } return $result; } /** * @param string $permission * @param bool $default * @param int|null $blog_id * * @return bool */ function is_permission_allowed( $permission, $default = false, $blog_id = null ) { if ( ! self::is_supported_permission( $permission ) ) { return $default; } return $this->is_permission( $permission, true, $blog_id ); } /** * @param string $permission * @param bool $is_allowed * @param int|null $blog_id * * @return bool */ function is_permission( $permission, $is_allowed, $blog_id = null ) { if ( ! self::is_supported_permission( $permission ) ) { return false; } $tag = "is_{$permission}_tracking_allowed"; return ( $is_allowed === $this->_fs->apply_filters( $tag, $this->_storage->get( $tag, $this->get_permission_default( $permission ), $blog_id, FS_Storage::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED ) ) ); } /** * @param string $permission * @param int|null $blog_id * * @return bool */ function is_permission_set( $permission, $blog_id = null ) { $tag = "is_{$permission}_tracking_allowed"; $permission = $this->_storage->get( $tag, null, $blog_id, FS_Storage::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED ); return is_bool( $permission ); } /** * @param string[] $permissions * @param bool $is_allowed * * @return bool `true` if all given permissions are in sync with `$is_allowed`. */ function are_permissions( $permissions, $is_allowed, $blog_id = null ) { foreach ( $permissions as $permission ) { if ( ! $this->is_permission( $permission, $is_allowed, $blog_id ) ) { return false; } } return true; } /** * @param string $permission * @param bool $is_enabled * @param int|null $blog_id * * @return bool `false` if permission not supported or `$is_enabled` is not a boolean. */ function update_permission_tracking_flag( $permission, $is_enabled, $blog_id = null ) { if ( is_bool( $is_enabled ) && self::is_supported_permission( $permission ) ) { $this->_storage->store( "is_{$permission}_tracking_allowed", $is_enabled, $blog_id, FS_Storage::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED ); return true; } return false; } /** * @param array $permissions */ function update_permissions_tracking_flag( $permissions ) { foreach ( $permissions as $permission => $is_enabled ) { $this->update_permission_tracking_flag( $permission, $is_enabled ); } } #endregion /** * @param string $permission * * @return bool */ function get_permission_default( $permission ) { if ( $this->_fs->is_premium() && self::PERMISSION_EXTENSIONS === $permission ) { return false; } // All permissions except for the extensions in paid version are on by default when the user opts in to usage tracking. return true; } /** * @return string */ function get_site_permission_name() { return $this->is_premium_context() ? self::PERMISSION_ESSENTIALS : self::PERMISSION_SITE; } /** * @return string[] */ function get_site_tracking_permission_names() { return $this->is_premium_context() ? array( FS_Permission_Manager::PERMISSION_ESSENTIALS, FS_Permission_Manager::PERMISSION_EVENTS, ) : array( FS_Permission_Manager::PERMISSION_SITE ); } #-------------------------------------------------------------------------------- #region Rendering #-------------------------------------------------------------------------------- /** * @param array $permission */ function render_permission( array $permission ) { fs_require_template( 'connect/permission.php', $permission ); } /** * @param array $permissions_group */ function render_permissions_group( array $permissions_group ) { $permissions_group[ 'fs' ] = $this->_fs; fs_require_template( 'connect/permissions-group.php', $permissions_group ); } function require_permissions_js() { fs_require_once_template( 'js/permissions.php', $params ); } #endregion #-------------------------------------------------------------------------------- #region Helper Methods #-------------------------------------------------------------------------------- /** * @param string $id * @param string $dashicon * @param string $label * @param string $desc * @param string $tooltip * @param int $priority * @param bool $is_optional * @param bool $is_on_by_default * @param bool $load_from_storage * * @return array */ private function get_permission( $id, $dashicon, $label, $desc, $tooltip = '', $priority = 10, $is_optional = false, $is_on_by_default = true, $load_from_storage = false ) { $is_on = $load_from_storage ? $this->is_permission_allowed( $id, $is_on_by_default ) : $is_on_by_default; return array( 'id' => $id, 'icon-class' => $this->_fs->apply_filters( "permission_{$id}_icon", "dashicons dashicons-{$dashicon}" ), 'label' => $this->_fs->apply_filters( "permission_{$id}_label", $label ), 'tooltip' => $this->_fs->apply_filters( "permission_{$id}_tooltip", $tooltip ), 'desc' => $this->_fs->apply_filters( "permission_{$id}_desc", $desc ), 'priority' => $this->_fs->apply_filters( "permission_{$id}_priority", $priority ), 'optional' => $is_optional, 'default' => $this->_fs->apply_filters( "permission_{$id}_default", $is_on ), ); } /** * @param array $permissions * * @return array[] */ private function get_sorted_permissions_by_priority( array $permissions ) { // Allow filtering of the permissions list. $permissions = $this->_fs->apply_filters( 'permission_list', $permissions ); // Sort by priority. uasort( $permissions, 'fs_sort_by_priority' ); return $permissions; } #endregion }freemius/includes/managers/index.php000064400000000127146725417150013622 0ustar00_storage = FS_Option_Manager::get_manager( WP_FS___OPTION_PREFIX . self::OPTION_MANAGER_NAME, true ); $this->_network_storage = FS_Option_Manager::get_manager( WP_FS___OPTION_PREFIX . self::OPTION_MANAGER_NAME, true, true ); $this->maybe_migrate_options(); $this->_notices = FS_Admin_Notices::instance( 'global_clone_resolution_notices', '', '', true ); $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . '_clone_manager', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); } /** * Migrate clone resolution options from 2.5.0 array-based structure, to a new flat structure. * * The reason this logic is not in a separate migration script is that we want to be 100% sure data is migrated before any execution of clone logic. * * @todo Delete this one in the future. */ private function maybe_migrate_options() { $storages = array( $this->_storage, $this->_network_storage ); foreach ( $storages as $storage ) { $clone_data = $storage->get_option( self::OPTION_NAME ); if ( is_array( $clone_data ) && ! empty( $clone_data ) ) { foreach ( $clone_data as $key => $val ) { if ( ! is_null( $val ) ) { $storage->set_option( $key, $val ); } } $storage->unset_option( self::OPTION_NAME, true ); } } } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function _init() { if ( is_admin() ) { if ( Freemius::is_admin_post() ) { add_action( 'admin_post_fs_clone_resolution', array( $this, '_handle_clone_resolution' ) ); } if ( Freemius::is_ajax() ) { Freemius::add_ajax_action_static( 'handle_clone_resolution', array( $this, '_clone_resolution_action_ajax_handler' ) ); } else { if ( empty( $this->get_clone_identification_timestamp() ) && ( ! fs_is_network_admin() || ! ( $this->is_clone_resolution_options_notice_shown() || $this->is_temporary_duplicate_notice_shown() ) ) ) { $this->hide_clone_admin_notices(); } else if ( ! Freemius::is_cron() && ! Freemius::is_admin_post() ) { $this->try_resolve_clone_automatically(); $this->maybe_show_clone_admin_notice(); add_action( 'admin_footer', array( $this, '_add_clone_resolution_javascript' ) ); } } } } /** * Retrieves the timestamp that was stored when a clone was identified. * * @return int|null */ function get_clone_identification_timestamp() { return $this->get_option( 'clone_identification_timestamp', true ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.1 * * @param string $sdk_last_version */ function maybe_update_clone_resolution_support_flag( $sdk_last_version ) { if ( null !== $this->hide_manual_resolution ) { return; } $this->hide_manual_resolution = ( ! empty( $sdk_last_version ) && version_compare( $sdk_last_version, '2.5.0', '<' ) ); } /** * Stores the time when a clone was identified. */ function store_clone_identification_timestamp() { $this->clone_identification_timestamp = time(); } /** * Retrieves the timestamp for the temporary duplicate mode's expiration. * * @return int */ function get_temporary_duplicate_expiration_timestamp() { $temporary_duplicate_mode_start_timestamp = $this->was_temporary_duplicate_mode_selected() ? $this->temporary_duplicate_mode_selection_timestamp : $this->get_clone_identification_timestamp(); return ( $temporary_duplicate_mode_start_timestamp + self::TEMPORARY_DUPLICATE_PERIOD ); } /** * Determines if the SDK should handle clones. The SDK handles clones only up to 3 times with 3 min interval. * * @return bool */ private function should_handle_clones() { if ( ! isset( $this->request_handler_timestamp ) ) { return true; } if ( $this->request_handler_retries_count >= self::CLONE_RESOLUTION_MAX_RETRIES ) { return false; } // Give the logic that handles clones enough time to finish (it is given 3 minutes for now). return ( time() > ( $this->request_handler_timestamp + self::CLONE_RESOLUTION_MAX_EXECUTION_TIME ) ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.1 * * @return bool */ function should_hide_manual_resolution() { return ( true === $this->hide_manual_resolution ); } /** * Executes the clones handler logic if it should be executed, i.e., based on the return value of the should_handle_clones() method. * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function maybe_run_clone_resolution() { if ( ! $this->should_handle_clones() ) { return; } $this->request_handler_retries_count = isset( $this->request_handler_retries_count ) ? ( $this->request_handler_retries_count + 1 ) : 1; $this->request_handler_timestamp = time(); $handler_id = ( rand() . microtime() ); $this->request_handler_id = $handler_id; // Add cookies to trigger request with the same user access permissions. $cookies = array(); foreach ( $_COOKIE as $name => $value ) { $cookies[] = new WP_Http_Cookie( array( 'name' => $name, 'value' => $value, ) ); } wp_remote_post( admin_url( 'admin-post.php' ), array( 'method' => 'POST', 'body' => array( 'action' => 'fs_clone_resolution', 'handler_id' => $handler_id, ), 'timeout' => 0.01, 'blocking' => false, 'sslverify' => false, 'cookies' => $cookies, ) ); } /** * Executes the clones handler logic. * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function _handle_clone_resolution() { $handler_id = fs_request_get( 'handler_id' ); if ( empty( $handler_id ) ) { return; } if ( ! isset( $this->request_handler_id ) || $this->request_handler_id !== $handler_id ) { return; } if ( ! $this->try_automatic_resolution() ) { $this->clear_temporary_duplicate_notice_shown_timestamp(); } } #-------------------------------------------------------------------------------- #region Automatic Clone Resolution #-------------------------------------------------------------------------------- /** * @var array All installs cache. */ private $all_installs; /** * Checks if a given instance's install is a clone of another subsite in the network. * * @author Vova Feldman (@svovaf) * * @return FS_Site */ private function find_network_subsite_clone_install( Freemius $instance ) { if ( ! is_multisite() ) { // Not a multi-site network. return null; } if ( ! isset( $this->all_installs ) ) { $this->all_installs = Freemius::get_all_modules_sites(); } // Check if there's another blog that has the same site. $module_type = $instance->get_module_type(); $sites_by_module_type = ! empty( $this->all_installs[ $module_type ] ) ? $this->all_installs[ $module_type ] : array(); $slug = $instance->get_slug(); $sites_by_slug = ! empty( $sites_by_module_type[ $slug ] ) ? $sites_by_module_type[ $slug ] : array(); $current_blog_id = get_current_blog_id(); $current_install = $instance->get_site(); foreach ( $sites_by_slug as $site ) { if ( $current_install->id == $site->id && $current_blog_id != $site->blog_id ) { // Clone is identical to an install on another subsite in the network. return $site; } } return null; } /** * Tries to find a different install of the context product that is associated with the current URL and loads it. * * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param Freemius $instance * @param string $url * * @return object */ private function find_other_install_by_url( Freemius $instance, $url ) { $result = $instance->get_api_user_scope()->get( "/plugins/{$instance->get_id()}/installs.json?url=" . urlencode( $url ) . "&all=true", true ); $current_install = $instance->get_site(); if ( $instance->is_api_result_object( $result, 'installs' ) ) { foreach ( $result->installs as $install ) { if ( $install->id == $current_install->id ) { continue; } if ( $instance->is_only_premium() && ! FS_Plugin_License::is_valid_id( $install->license_id ) ) { continue; } // When searching for installs by a URL, the API will first strip any paths and search for any matching installs by the subdomain. Therefore, we need to test if there's a match between the current URL and the install's URL before continuing. if ( $url !== fs_strip_url_protocol( untrailingslashit( $install->url ) ) ) { continue; } // Found a different install that is associated with the current URL, load it and replace the current install with it if no updated install is found. return $install; } } return null; } /** * Delete the current install associated with a given instance and opt-in/activate-license to create a fresh install. * * @author Vova Feldman (@svovaf) * @since 2.5.0 * * @param Freemius $instance * @param string|false $license_key * * @return bool TRUE if successfully connected. FALSE if failed and had to restore install from backup. */ private function delete_install_and_connect( Freemius $instance, $license_key = false ) { $user = Freemius::_get_user_by_id( $instance->get_site()->user_id ); $instance->delete_current_install( true ); if ( ! is_object( $user ) ) { // Get logged-in WordPress user. $current_user = Freemius::_get_current_wp_user(); // Find the relevant FS user by email address. $user = Freemius::_get_user_by_email( $current_user->user_email ); } if ( is_object( $user ) ) { // When a clone is found, we prefer to use the same user of the original install for the opt-in. $instance->install_with_user( $user, $license_key, false, false ); } else { // If no user is found, activate with the license. $instance->opt_in( false, false, false, $license_key ); } if ( is_object( $instance->get_site() ) ) { // Install successfully created. return true; } // Restore from backup. $instance->restore_backup_site(); return false; } /** * Try to resolve the clone situation automatically. * * @param Freemius $instance * @param string $current_url * @param bool $is_localhost * @param bool|null $is_clone_of_network_subsite * * @return bool If managed to automatically resolve the clone. */ private function try_resolve_clone_automatically_by_instance( Freemius $instance, $current_url, $is_localhost, $is_clone_of_network_subsite = null ) { // Try to find a different install of the context product that is associated with the current URL. $associated_install = $this->find_other_install_by_url( $instance, $current_url ); if ( is_object( $associated_install ) ) { // Replace the current install with a different install that is associated with the current URL. $instance->store_site( new FS_Site( clone $associated_install ) ); $instance->sync_install( array( 'is_new_site' => true ), true ); return true; } if ( ! $instance->is_premium() ) { // For free products, opt-in with the context user to create new install. return $this->delete_install_and_connect( $instance ); } $license = $instance->_get_license(); $can_activate_license = ( is_object( $license ) && ! $license->is_utilized( $is_localhost ) ); if ( ! $can_activate_license ) { // License can't be activated, therefore, can't be automatically resolved. return false; } if ( ! WP_FS__IS_LOCALHOST_FOR_SERVER && ! $is_localhost ) { $is_clone_of_network_subsite = ( ! is_null( $is_clone_of_network_subsite ) ) ? $is_clone_of_network_subsite : is_object( $this->find_network_subsite_clone_install( $instance ) ); if ( ! $is_clone_of_network_subsite ) { return false; } } // If the site is a clone of another subsite in the network, or a localhost one, try to auto activate the license. return $this->delete_install_and_connect( $instance, $license->secret_key ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ private function try_resolve_clone_automatically() { $clone_action = $this->get_clone_resolution_action_from_config(); if ( ! empty( $clone_action ) ) { $this->try_resolve_clone_automatically_by_config( $clone_action ); return; } $this->try_automatic_resolution(); } /** * Tries to resolve the clone situation automatically based on the config in the wp-config.php file. * * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param string $clone_action */ private function try_resolve_clone_automatically_by_config( $clone_action ) { $fs_instances = array(); if ( self::OPTION_LONG_TERM_DUPLICATE === $clone_action ) { $instances = Freemius::_get_all_instances(); foreach ( $instances as $instance ) { if ( ! $instance->is_registered() ) { continue; } if ( ! $instance->is_clone() ) { continue; } $license = $instance->has_features_enabled_license() ? $instance->_get_license() : null; if ( is_object( $license ) && ! $license->is_utilized( ( WP_FS__IS_LOCALHOST_FOR_SERVER || FS_Site::is_localhost_by_address( Freemius::get_unfiltered_site_url() ) ) ) ) { $fs_instances[] = $instance; } } if ( empty( $fs_instances ) ) { return; } } $this->resolve_cloned_sites( $clone_action, $fs_instances ); } /** * @author Leo Fajard (@leorw) * @since 2.5.0 * * @return string|null */ private function get_clone_resolution_action_from_config() { if ( ! defined( 'FS__RESOLVE_CLONE_AS' ) ) { return null; } if ( ! in_array( FS__RESOLVE_CLONE_AS, array( self::OPTION_NEW_HOME, self::OPTION_TEMPORARY_DUPLICATE, self::OPTION_LONG_TERM_DUPLICATE, ) ) ) { return null; } return FS__RESOLVE_CLONE_AS; } /** * Tries to recover the install of a newly created subsite or resolve it if it's a clone. * * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param Freemius $instance */ function maybe_resolve_new_subsite_install_automatically( Freemius $instance ) { if ( ! $instance->is_user_in_admin() ) { // Try to recover an install or resolve a clone only when there's a user in admin to prevent doing it prematurely (e.g., the install can get replaced with clone data again). return; } if ( ! is_multisite() ) { return; } $new_blog_install_map = $this->new_blog_install_map; if ( empty( $new_blog_install_map ) || ! is_array( $new_blog_install_map ) ) { return; } $is_network_admin = fs_is_network_admin(); if ( ! $is_network_admin ) { // If not in network admin, handle the current site. $blog_id = get_current_blog_id(); } else { // If in network admin, handle only the first site. $blog_ids = array_keys( $new_blog_install_map ); $blog_id = $blog_ids[0]; } if ( ! isset( $new_blog_install_map[ $blog_id ] ) ) { // There's no site to handle. return; } $expected_install_id = $new_blog_install_map[ $blog_id ]['install_id']; $current_install = $instance->get_install_by_blog_id( $blog_id ); $current_install_id = is_object( $current_install ) ? $current_install->id : null; if ( $expected_install_id == $current_install_id ) { // Remove the current site's information from the map to prevent handling it again. $this->remove_new_blog_install_info_from_storage( $blog_id ); return; } require_once WP_FS__DIR_INCLUDES . '/class-fs-lock.php'; $lock = new FS_Lock( self::OPTION_NAME . '_subsite' ); if ( ! $lock->try_lock(60) ) { return; } $instance->switch_to_blog( $blog_id ); $current_url = untrailingslashit( Freemius::get_unfiltered_site_url( null, true ) ); $current_install_url = is_object( $current_install ) ? fs_strip_url_protocol( untrailingslashit( $current_install->url ) ) : null; // This can be `false` even if the install is a clone as the URL can be updated as part of the cloning process. $is_clone = ( ! is_null( $current_install_url ) && $current_url !== $current_install_url ); if ( ! FS_Site::is_valid_id( $expected_install_id ) ) { $expected_install = null; } else { $expected_install = $instance->fetch_install_by_id( $expected_install_id ); } if ( FS_Api::is_api_result_entity( $expected_install ) ) { // Replace the current install with the expected install. $instance->store_site( new FS_Site( clone $expected_install ) ); $instance->sync_install( array( 'is_new_site' => true ), true ); } else { $network_subsite_clone_install = null; if ( ! $is_clone ) { // It is possible that `$is_clone` is `false` but the install is actually a clone as the following call checks the install ID and not the URL. $network_subsite_clone_install = $this->find_network_subsite_clone_install( $instance ); } if ( $is_clone || is_object( $network_subsite_clone_install ) ) { // If there's no expected install (or it couldn't be fetched) and the current install is a clone, try to resolve the clone automatically. $is_localhost = FS_Site::is_localhost_by_address( $current_url ); $resolved = $this->try_resolve_clone_automatically_by_instance( $instance, $current_url, $is_localhost, is_object( $network_subsite_clone_install ) ); if ( ! $resolved && is_object( $network_subsite_clone_install ) ) { if ( empty( $this->get_clone_identification_timestamp() ) ) { $this->store_clone_identification_timestamp(); } // Since the clone couldn't be identified based on the URL, replace the stored install with the cloned install so that the manual clone resolution notice will appear. $instance->store_site( clone $network_subsite_clone_install ); } } } $instance->restore_current_blog(); // Remove the current site's information from the map to prevent handling it again. $this->remove_new_blog_install_info_from_storage( $blog_id ); $lock->unlock(); } /** * If a new install was created after creating a new subsite, its ID is stored in the blog-install map so that it can be recovered in case it's replaced with a clone install (e.g., when the newly created subsite is a clone). The IDs of the clone subsites that were created while not running this version of the SDK or a higher version will also be stored in the said map so that the clone manager can also try to resolve them later on. * * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param int $blog_id * @param FS_Site $site */ function store_blog_install_info( $blog_id, $site = null ) { $new_blog_install_map = $this->new_blog_install_map; if ( empty( $new_blog_install_map ) || ! is_array( $new_blog_install_map ) ) { $new_blog_install_map = array(); } $install_id = null; if ( is_object( $site ) ) { $install_id = $site->id; } $new_blog_install_map[ $blog_id ] = array( 'install_id' => $install_id ); $this->new_blog_install_map = $new_blog_install_map; } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param int $blog_id */ private function remove_new_blog_install_info_from_storage( $blog_id ) { $new_blog_install_map = $this->new_blog_install_map; unset( $new_blog_install_map[ $blog_id ] ); $this->new_blog_install_map = $new_blog_install_map; } /** * Tries to resolve all clones automatically. * * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @return bool If managed to automatically resolve all clones. */ private function try_automatic_resolution() { $this->_logger->entrance(); require_once WP_FS__DIR_INCLUDES . '/class-fs-lock.php'; $lock = new FS_Lock( self::OPTION_NAME ); /** * Try to acquire lock for the next 60 sec based on the thread ID. */ if ( ! $lock->try_lock( 60 ) ) { return false; } $current_url = untrailingslashit( Freemius::get_unfiltered_site_url( null, true ) ); $is_localhost = FS_Site::is_localhost_by_address( $current_url ); $require_manual_resolution = false; $instances = Freemius::_get_all_instances(); foreach ( $instances as $instance ) { if ( ! $instance->is_registered() ) { continue; } if ( ! $instance->is_clone() ) { continue; } if ( ! $this->try_resolve_clone_automatically_by_instance( $instance, $current_url, $is_localhost ) ) { $require_manual_resolution = true; } } // Create a 1-day lock. $lock->lock( WP_FS__TIME_24_HOURS_IN_SEC ); return ( ! $require_manual_resolution ); } #endregion #-------------------------------------------------------------------------------- #region Manual Clone Resolution #-------------------------------------------------------------------------------- /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function _add_clone_resolution_javascript() { $vars = array( 'ajax_action' => Freemius::get_ajax_action_static( 'handle_clone_resolution' ) ); fs_require_once_template( 'clone-resolution-js.php', $vars ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function _clone_resolution_action_ajax_handler() { $this->_logger->entrance(); check_ajax_referer( Freemius::get_ajax_action_static( 'handle_clone_resolution' ), 'security' ); $clone_action = fs_request_get( 'clone_action' ); $blog_id = is_multisite() ? fs_request_get( 'blog_id' ) : 0; if ( is_multisite() && $blog_id == get_current_blog_id() ) { $blog_id = 0; } if ( empty( $clone_action ) ) { Freemius::shoot_ajax_failure( array( 'message' => fs_text_inline( 'Invalid clone resolution action.', 'invalid-clone-resolution-action-error' ), 'redirect_url' => '', ) ); } $result = $this->resolve_cloned_sites( $clone_action, array(), $blog_id ); Freemius::shoot_ajax_success( $result ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @param string $clone_action * @param Freemius[] $fs_instances * @param int $blog_id * * @return array */ private function resolve_cloned_sites( $clone_action, $fs_instances = array(), $blog_id = 0 ) { $this->_logger->entrance(); $result = array(); $instances_with_clone = array(); $instances_with_clone_count = 0; $install_by_instance_id = array(); $instances = ( ! empty( $fs_instances ) ) ? $fs_instances : Freemius::_get_all_instances(); $should_switch_to_blog = ( $blog_id > 0 ); foreach ( $instances as $instance ) { if ( $should_switch_to_blog ) { $instance->switch_to_blog( $blog_id ); } if ( $instance->is_registered() && $instance->is_clone() ) { $instances_with_clone[] = $instance; $instances_with_clone_count ++; $install_by_instance_id[ $instance->get_id() ] = $instance->get_site(); } } if ( self::OPTION_TEMPORARY_DUPLICATE === $clone_action ) { $this->store_temporary_duplicate_timestamp(); } else { $redirect_url = ''; foreach ( $instances_with_clone as $instance ) { if ( $should_switch_to_blog ) { $instance->switch_to_blog( $blog_id ); } $has_error = false; if ( self::OPTION_NEW_HOME === $clone_action ) { $instance->sync_install( array( 'is_new_site' => true ), true ); if ( $instance->is_clone() ) { $has_error = true; } } else { $instance->_handle_long_term_duplicate(); if ( ! is_object( $instance->get_site() ) ) { $has_error = true; } } if ( $has_error && 1 === $instances_with_clone_count ) { $redirect_url = $instance->get_activation_url(); } } $result = ( array( 'redirect_url' => $redirect_url ) ); } foreach ( $instances_with_clone as $instance ) { if ( $should_switch_to_blog ) { $instance->switch_to_blog( $blog_id ); } // No longer a clone, send an update. if ( ! $instance->is_clone() ) { $instance->send_clone_resolution_update( $clone_action, $install_by_instance_id[ $instance->get_id() ] ); } } if ( 'temporary_duplicate_license_activation' !== $clone_action ) { $this->remove_clone_resolution_options_notice(); } else { $this->remove_temporary_duplicate_notice(); } if ( $should_switch_to_blog ) { foreach ( $instances as $instance ) { $instance->restore_current_blog(); } } return $result; } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ private function hide_clone_admin_notices() { $this->remove_clone_resolution_options_notice( false ); $this->remove_temporary_duplicate_notice( false ); } /** * @author Leo Fajardo (@leorw) * @since 2.5.0 */ function maybe_show_clone_admin_notice() { $this->_logger->entrance(); if ( fs_is_network_admin() ) { $existing_notice_ids = $this->maybe_remove_notices(); if ( ! empty( $existing_notice_ids ) ) { fs_enqueue_local_style( 'fs_clone_resolution_notice', '/admin/clone-resolution.css' ); } return; } $first_instance_with_clone = null; $site_urls = array(); $sites_with_license_urls = array(); $sites_with_premium_version_count = 0; $product_ids = array(); $product_titles = array(); $instances = Freemius::_get_all_instances(); foreach ( $instances as $instance ) { if ( ! $instance->is_registered() ) { continue; } if ( ! $instance->is_clone( true ) ) { continue; } $install = $instance->get_site(); $site_urls[] = $install->url; $product_ids[] = $instance->get_id(); $product_titles[] = $instance->get_plugin_title(); if ( is_null( $first_instance_with_clone ) ) { $first_instance_with_clone = $instance; } if ( is_object( $instance->_get_license() ) ) { $sites_with_license_urls[] = $install->url; } if ( $instance->is_premium() ) { $sites_with_premium_version_count ++; } } if ( empty( $site_urls ) && empty( $sites_with_license_urls ) ) { $this->hide_clone_admin_notices(); return; } $site_urls = array_unique( $site_urls ); $sites_with_license_urls = array_unique( $sites_with_license_urls ); $module_label = fs_text_inline( 'products', 'products' ); $admin_notice_module_title = null; $has_temporary_duplicate_mode_expired = $this->has_temporary_duplicate_mode_expired(); if ( ! $this->was_temporary_duplicate_mode_selected() || $has_temporary_duplicate_mode_expired ) { if ( ! empty( $site_urls ) ) { fs_enqueue_local_style( 'fs_clone_resolution_notice', '/admin/clone-resolution.css' ); $doc_url = 'https://freemius.com/help/documentation/wordpress-sdk/safe-mode-clone-resolution-duplicate-website/'; if ( 1 === count( $instances ) ) { $doc_url = fs_apply_filter( $first_instance_with_clone->get_unique_affix(), 'clone_resolution_documentation_url', $doc_url ); } $this->add_manual_clone_resolution_admin_notice( $product_ids, $product_titles, $site_urls, Freemius::get_unfiltered_site_url(), ( count( $site_urls ) === count( $sites_with_license_urls ) ), ( count( $site_urls ) === $sites_with_premium_version_count ), $doc_url ); } return; } if ( empty( $sites_with_license_urls ) ) { return; } if ( ! $this->is_temporary_duplicate_notice_shown() ) { $last_time_temporary_duplicate_notice_shown = $this->temporary_duplicate_notice_shown_timestamp; $was_temporary_duplicate_notice_shown_before = is_numeric( $last_time_temporary_duplicate_notice_shown ); if ( $was_temporary_duplicate_notice_shown_before ) { $temporary_duplicate_mode_expiration_timestamp = $this->get_temporary_duplicate_expiration_timestamp(); $current_time = time(); if ( $current_time > $temporary_duplicate_mode_expiration_timestamp || $current_time < ( $temporary_duplicate_mode_expiration_timestamp - ( 2 * WP_FS__TIME_24_HOURS_IN_SEC ) ) ) { // Do not show the notice if the temporary duplicate mode has already expired or it will expire more than 2 days from now. return; } } } if ( 1 === count( $sites_with_license_urls ) ) { $module_label = $first_instance_with_clone->get_module_label( true ); $admin_notice_module_title = $first_instance_with_clone->get_plugin_title(); } fs_enqueue_local_style( 'fs_clone_resolution_notice', '/admin/clone-resolution.css' ); $this->add_temporary_duplicate_sticky_notice( $product_ids, $this->get_temporary_duplicate_admin_notice_string( $sites_with_license_urls, $product_titles, $module_label ), $admin_notice_module_title ); } /** * Removes the notices from the storage if the context product is either no longer active on the context subsite or it's active but there's no longer any clone. This prevents the notices from being shown on the network-level admin page when they are no longer relevant. * * @author Leo Fajardo (@leorw) * @since 2.5.1 * * @return string[] */ private function maybe_remove_notices() { $notices = array( 'clone_resolution_options_notice' => $this->_notices->get_sticky( 'clone_resolution_options_notice', true ), 'temporary_duplicate_notice' => $this->_notices->get_sticky( 'temporary_duplicate_notice', true ), ); $instances = Freemius::_get_all_instances(); foreach ( $notices as $id => $notice ) { if ( ! is_array( $notice ) ) { unset( $notices[ $id ] ); continue; } if ( empty( $notice['data'] ) || ! is_array( $notice['data'] ) ) { continue; } if ( empty( $notice['data']['product_ids'] ) || empty( $notice['data']['blog_id'] ) ) { continue; } $product_ids = $notice['data']['product_ids']; $blog_id = $notice['data']['blog_id']; $has_clone = false; if ( ! is_null( get_site( $blog_id ) ) ) { foreach ( $product_ids as $product_id ) { if ( ! isset( $instances[ 'm_' . $product_id ] ) ) { continue; } $instance = $instances[ 'm_' . $product_id ]; $plugin_basename = $instance->get_plugin_basename(); $is_plugin_active = is_plugin_active_for_network( $plugin_basename ); if ( ! $is_plugin_active ) { switch_to_blog( $blog_id ); $is_plugin_active = is_plugin_active( $plugin_basename ); restore_current_blog(); } if ( ! $is_plugin_active ) { continue; } $install = $instance->get_install_by_blog_id( $blog_id ); if ( ! is_object( $install ) ) { continue; } $subsite_url = Freemius::get_unfiltered_site_url( $blog_id, true, true ); $has_clone = ( fs_strip_url_protocol( trailingslashit( $install->url ) ) !== $subsite_url ); } } if ( ! $has_clone ) { $this->_notices->remove_sticky( $id, true, false ); unset( $notices[ $id ] ); } } return array_keys( $notices ); } /** * Adds a notice that provides the logged-in WordPress user with manual clone resolution options. * * @param number[] $product_ids * @param string[] $site_urls * @param string $current_url * @param bool $has_license * @param bool $is_premium * @param string $doc_url */ private function add_manual_clone_resolution_admin_notice( $product_ids, $product_titles, $site_urls, $current_url, $has_license, $is_premium, $doc_url ) { $this->_logger->entrance(); $total_sites = count( $site_urls ); $sites_list = ''; $total_products = count( $product_titles ); $products_list = ''; if ( 1 === $total_products ) { $notice_header = sprintf( '

    %s

    ', fs_esc_html_inline( '%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.', 'single-cloned-site-safe-mode-message' ) ); } else { $notice_header = sprintf( '

    %s

    ', ( 1 === $total_sites ) ? fs_esc_html_inline( 'The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$s', 'multiple-products-cloned-site-safe-mode-message' ) : fs_esc_html_inline( 'The products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$s', 'multiple-products-multiple-cloned-sites-safe-mode-message' ) ); foreach ( $product_titles as $product_title ) { $products_list .= sprintf( '
  • %s
  • ', $product_title ); } $products_list = '
      ' . $products_list . '
    '; foreach ( $site_urls as $site_url ) { $sites_list .= sprintf( '
  • %s
  • ', $site_url, fs_strip_url_protocol( $site_url ) ); } $sites_list = '
      ' . $sites_list . '
    '; } $remote_site_link = '' . (1 === $total_sites ? sprintf( '%s', $site_urls[0], fs_strip_url_protocol( $site_urls[0] ) ) : fs_text_inline( 'the above-mentioned sites', 'above-mentioned-sites' )) . ''; $current_site_link = sprintf( '%s', $current_url, fs_strip_url_protocol( $current_url ) ); $button_template = ''; $option_template = '
    %s

    %s

    %s
    '; $duplicate_option = sprintf( $option_template, fs_esc_html_inline( 'Is %2$s a duplicate of %4$s?', 'duplicate-site-confirmation-message' ), fs_esc_html_inline( 'Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.', 'duplicate-site-message' ), ( $this->has_temporary_duplicate_mode_expired() ? sprintf( $button_template, 'long_term_duplicate', fs_text_inline( 'Long-Term Duplicate', 'long-term-duplicate' ) ) : sprintf( $button_template, 'temporary_duplicate', fs_text_inline( 'Duplicate Website', 'duplicate-site' ) ) ) ); $migration_option = sprintf( $option_template, fs_esc_html_inline( 'Is %2$s the new home of %4$s?', 'migrate-site-confirmation-message' ), sprintf( fs_esc_html_inline( 'Yes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s.', 'migrate-site-message' ), ( $has_license ? fs_text_inline( 'license', 'license' ) : fs_text_inline( 'data', 'data' ) ) ), sprintf( $button_template, 'new_home', $has_license ? fs_text_inline( 'Migrate License', 'migrate-product-license' ) : fs_text_inline( 'Migrate', 'migrate-product-data' ) ) ); $new_website = sprintf( $option_template, fs_esc_html_inline( 'Is %2$s a new website?', 'new-site-confirmation-message' ), fs_esc_html_inline( 'Yes, %2$s is a new and different website that is separate from %4$s.', 'new-site-message' ) . ($is_premium ? ' ' . fs_text_inline( 'It requires license activation.', 'new-site-requires-license-activation-message' ) : '' ), sprintf( $button_template, 'new_website', ( ! $is_premium || ! $has_license ) ? fs_text_inline( 'New Website', 'new-website' ) : fs_text_inline( 'Activate License', 'activate-license' ) ) ); $blog_id = get_current_blog_id(); /** * %1$s - single product's title or product titles list. * %2$s - site's URL. * %3$s - single install's URL or install URLs list. * %4$s - Clone site's link or "the above-mentioned sites" if there are multiple clone sites. */ $message = sprintf( $notice_header . '
    ' . $duplicate_option . $migration_option . $new_website . '
    ' . sprintf( '
    Unsure what to do? Read more here.
    ', $doc_url ), // %1$s ( 1 === $total_products ? sprintf( '%s', $product_titles[0] ) : ( 1 === $total_sites ? sprintf( '
    %s
    ', $products_list ) : sprintf( '

    %s:

    %s
    ', fs_esc_html_x_inline( 'Products', 'Clone resolution admin notice products list label', 'products' ), $products_list ) ) ), // %2$s $current_site_link, // %3$s ( 1 === $total_sites ? $remote_site_link : $sites_list ), // %4$s $remote_site_link ); $this->_notices->add_sticky( $message, 'clone_resolution_options_notice', '', 'warn', true, null, null, true, // Intentionally not dismissible. false, array( 'product_ids' => $product_ids, 'blog_id' => $blog_id ) ); } #endregion #-------------------------------------------------------------------------------- #region Temporary Duplicate (Short Term) #-------------------------------------------------------------------------------- /** * @author Leo Fajardo (@leorw) * @since 2.5.0 * * @return string */ private function get_temporary_duplicate_admin_notice_string( $site_urls, $product_titles, $module_label ) { $this->_logger->entrance(); $temporary_duplicate_end_date = $this->get_temporary_duplicate_expiration_timestamp(); $temporary_duplicate_end_date = date( 'M j, Y', $temporary_duplicate_end_date ); $current_url = Freemius::get_unfiltered_site_url(); $current_site_link = sprintf( '%s', $current_url, fs_strip_url_protocol( $current_url ) ); $total_sites = count( $site_urls ); $sites_list = ''; $total_products = count( $product_titles ); $products_list = ''; if ( $total_sites > 1 ) { foreach ( $site_urls as $site_url ) { $sites_list .= sprintf( '
  • %s
  • ', $site_url, fs_strip_url_protocol( $site_url ) ); } $sites_list = '
      ' . $sites_list . '
    '; } if ( $total_products > 1 ) { foreach ( $product_titles as $product_title ) { $products_list .= sprintf( '
  • %s
  • ', $product_title ); } $products_list = '
      ' . $products_list . '
    '; } return sprintf( sprintf( '
    %s
    ', ( 1 === $total_sites ? sprintf( '

    %s

    ', fs_esc_html_inline( 'You marked this website, %s, as a temporary duplicate of %s.', 'temporary-duplicate-message' ) ) : sprintf( '

    %s:

    ', fs_esc_html_inline( 'You marked this website, %s, as a temporary duplicate of these sites', 'temporary-duplicate-of-sites-message' ) ) . '%s' ) ) . '%s', $current_site_link, ( 1 === $total_sites ? sprintf( '%s', $site_urls[0], fs_strip_url_protocol( $site_urls[0] ) ) : $sites_list ), sprintf( '

    %s

    %s

    %s

    ', esc_attr( admin_url( 'admin-ajax.php?_fs_network_admin=false', 'relative' ) ), sprintf( fs_esc_html_inline( "%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).", 'duplicate-site-confirmation-message' ), ( 1 === $total_products ? sprintf( fs_esc_html_x_inline( "The %s's", '"The ", e.g.: "The plugin"', 'the-product-x'), "{$module_label}" ) : fs_esc_html_inline( "The following products'", 'the-following-products' ) ), sprintf( '%s', $temporary_duplicate_end_date ) ), ( 1 === $total_products ? '' : sprintf( '
    %s
    ', $products_list ) ), sprintf( fs_esc_html_inline( 'If this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.', 'duplicate-site-message' ), sprintf( '%s', $temporary_duplicate_end_date), sprintf( '%s', fs_esc_html_inline( 'activate a license here', 'activate-license-here' ) ) ) ) ); } /** * Determines if the temporary duplicate mode has already expired. * * @return bool */ function has_temporary_duplicate_mode_expired() { $temporary_duplicate_mode_start_timestamp = $this->was_temporary_duplicate_mode_selected() ? $this->get_option( 'temporary_duplicate_mode_selection_timestamp', true ) : $this->get_clone_identification_timestamp(); if ( ! is_numeric( $temporary_duplicate_mode_start_timestamp ) ) { return false; } return ( time() > ( $temporary_duplicate_mode_start_timestamp + self::TEMPORARY_DUPLICATE_PERIOD ) ); } /** * Determines if the logged-in WordPress user manually selected the temporary duplicate mode for the site. * * @return bool */ function was_temporary_duplicate_mode_selected() { return is_numeric( $this->temporary_duplicate_mode_selection_timestamp ); } /** * Stores the time when the logged-in WordPress user selected the temporary duplicate mode for the site. */ private function store_temporary_duplicate_timestamp() { $this->temporary_duplicate_mode_selection_timestamp = time(); } /** * Removes the notice that is shown when the logged-in WordPress user has selected the temporary duplicate mode for the site. * * @param bool $store */ function remove_clone_resolution_options_notice( $store = true ) { $this->_notices->remove_sticky( 'clone_resolution_options_notice', true, $store ); } /** * Removes the notice that is shown when the logged-in WordPress user has selected the temporary duplicate mode for the site. * * @param bool $store */ function remove_temporary_duplicate_notice( $store = true ) { $this->_notices->remove_sticky( 'temporary_duplicate_notice', true, $store ); } /** * Determines if the manual clone resolution options notice is currently being shown. * * @return bool */ function is_clone_resolution_options_notice_shown() { return $this->_notices->has_sticky( 'clone_resolution_options_notice', true ); } /** * Determines if the temporary duplicate notice is currently being shown. * * @return bool */ function is_temporary_duplicate_notice_shown() { return $this->_notices->has_sticky( 'temporary_duplicate_notice', true ); } /** * Determines if a site was marked as a temporary duplicate and if it's still a temporary duplicate. * * @return bool */ function is_temporary_duplicate_by_blog_id( $blog_id ) { $timestamp = $this->get_option( 'temporary_duplicate_mode_selection_timestamp', false, $blog_id ); return ( is_numeric( $timestamp ) && time() < ( $timestamp + self::TEMPORARY_DUPLICATE_PERIOD ) ); } /** * Determines the last time the temporary duplicate notice was shown. * * @return int|null */ function last_time_temporary_duplicate_notice_was_shown() { return $this->temporary_duplicate_notice_shown_timestamp; } /** * Clears the time that has been stored when the temporary duplicate notice was shown. */ function clear_temporary_duplicate_notice_shown_timestamp() { unset( $this->temporary_duplicate_notice_shown_timestamp ); } /** * Adds a temporary duplicate notice that provides the logged-in WordPress user with an option to activate a license for the site. * * @param number[] $product_ids * @param string $message * @param string|null $plugin_title */ function add_temporary_duplicate_sticky_notice( $product_ids, $message, $plugin_title = null ) { $this->_logger->entrance(); $this->_notices->add_sticky( $message, 'temporary_duplicate_notice', '', 'promotion', true, null, $plugin_title, true, true, array( 'product_ids' => $product_ids, 'blog_id' => get_current_blog_id() ) ); $this->temporary_duplicate_notice_shown_timestamp = time(); } #endregion /** * @author Leo Fajardo * @since 2.5.0 * * @param string $key * * @return bool */ private function should_use_network_storage( $key ) { return ( 'new_blog_install_map' === $key ); } /** * @param string $key * @param number|null $blog_id * * @return FS_Option_Manager */ private function get_storage( $key, $blog_id = null ) { if ( is_numeric( $blog_id ) ){ return FS_Option_Manager::get_manager( WP_FS___OPTION_PREFIX . self::OPTION_MANAGER_NAME, true, $blog_id ); } return $this->should_use_network_storage( $key ) ? $this->_network_storage : $this->_storage; } /** * @param string $name * @param bool $flush * @param number|null $blog_id * * @return mixed */ private function get_option( $name, $flush = false, $blog_id = null ) { return $this->get_storage( $name, $blog_id )->get_option( $name, null, $flush ); } #-------------------------------------------------------------------------------- #region Magic methods #-------------------------------------------------------------------------------- /** * @param string $name * @param int|string $value */ function __set( $name, $value ) { $this->get_storage( $name )->set_option( $name, $value, true ); } /** * @param string $name * * @return bool */ function __isset( $name ) { return $this->get_storage( $name )->has_option( $name, true ); } /** * @param string $name */ function __unset( $name ) { $this->get_storage( $name )->unset_option( $name, true ); } /** * @param string $name * * @return null|int|string */ function __get( $name ) { return $this->get_option( $name, // Reload storage from DB when accessing request_handler_* options to avoid race conditions. fs_starts_with( $name, 'request_handler' ) ); } #endregion } freemius/includes/managers/class-fs-plan-manager.php000064400000006036146725417150016573 0ustar00is_utilized() && $license->is_features_enabled() ) { return true; } } } return false; } /** * Check if plugin has any paid plans. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param FS_Plugin_Plan[] $plans * * @return bool */ function has_paid_plan( $plans ) { if ( ! is_array( $plans ) || 0 === count( $plans ) ) { return false; } /** * @var FS_Plugin_Plan[] $plans */ for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { if ( ! $plans[ $i ]->is_free() ) { return true; } } return false; } /** * Check if plugin has any free plan, or is it premium only. * * Note: If no plans configured, assume plugin is free. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param FS_Plugin_Plan[] $plans * * @return bool */ function has_free_plan( $plans ) { if ( ! is_array( $plans ) || 0 === count( $plans ) ) { return true; } /** * @var FS_Plugin_Plan[] $plans */ for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { if ( $plans[ $i ]->is_free() ) { return true; } } return false; } /** * Find all plans that have trial. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param FS_Plugin_Plan[] $plans * * @return FS_Plugin_Plan[] */ function get_trial_plans( $plans ) { $trial_plans = array(); if ( is_array( $plans ) && 0 < count( $plans ) ) { /** * @var FS_Plugin_Plan[] $plans */ for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { if ( $plans[ $i ]->has_trial() ) { $trial_plans[] = $plans[ $i ]; } } } return $trial_plans; } /** * Check if plugin has any trial plan. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param FS_Plugin_Plan[] $plans * * @return bool */ function has_trial_plan( $plans ) { if ( ! is_array( $plans ) || 0 === count( $plans ) ) { return true; } /** * @var FS_Plugin_Plan[] $plans */ for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) { if ( $plans[ $i ]->has_trial() ) { return true; } } return false; } }freemius/includes/managers/class-fs-key-value-storage.php000064400000024374146725417150017602 0ustar00 0 ) { $key .= ":{$network_level_or_blog_id}"; } else { $network_level_or_blog_id = get_current_blog_id(); $key .= ":{$network_level_or_blog_id}"; } } if ( ! isset( self::$_instances[ $key ] ) ) { self::$_instances[ $key ] = new FS_Key_Value_Storage( $id, $secondary_id, $network_level_or_blog_id ); } return self::$_instances[ $key ]; } protected function __construct( $id, $secondary_id, $network_level_or_blog_id = false ) { $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $secondary_id . '_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); $this->_id = $id; $this->_secondary_id = $secondary_id; if ( is_multisite() ) { $this->_is_multisite_storage = ( true === $network_level_or_blog_id ); if ( is_numeric( $network_level_or_blog_id ) ) { $this->_blog_id = $network_level_or_blog_id; } } else { $this->_is_multisite_storage = false; } $this->load(); } protected function get_option_manager() { return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true, $this->_is_multisite_storage ? true : ( $this->_blog_id > 0 ? $this->_blog_id : false ) ); } protected function get_all_data() { return $this->get_option_manager()->get_option( $this->_id, array() ); } /** * Load plugin data from local DB. * * @author Vova Feldman (@svovaf) * @since 1.0.7 */ function load() { $all_plugins_data = $this->get_all_data(); $this->_data = isset( $all_plugins_data[ $this->_secondary_id ] ) ? $all_plugins_data[ $this->_secondary_id ] : array(); } /** * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param string $key * @param mixed $value * @param bool $flush */ function store( $key, $value, $flush = true ) { if ( $this->_logger->is_on() ) { $this->_logger->entrance( $key . ' = ' . var_export( $value, true ) ); } if ( array_key_exists( $key, $this->_data ) && $value === $this->_data[ $key ] ) { // No need to store data if the value wasn't changed. return; } $all_data = $this->get_all_data(); $this->_data[ $key ] = $value; $all_data[ $this->_secondary_id ] = $this->_data; $options_manager = $this->get_option_manager(); $options_manager->set_option( $this->_id, $all_data, $flush ); } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 */ function save() { $this->get_option_manager()->store(); } /** * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param bool $store * @param string[] $exceptions Set of keys to keep and not clear. */ function clear_all( $store = true, $exceptions = array() ) { $new_data = array(); foreach ( $exceptions as $key ) { if ( isset( $this->_data[ $key ] ) ) { $new_data[ $key ] = $this->_data[ $key ]; } } $this->_data = $new_data; if ( $store ) { $all_data = $this->get_all_data(); $all_data[ $this->_secondary_id ] = $this->_data; $options_manager = $this->get_option_manager(); $options_manager->set_option( $this->_id, $all_data, true ); } } /** * Delete key-value storage. * * @author Vova Feldman (@svovaf) * @since 1.0.9 */ function delete() { $this->_data = array(); $all_data = $this->get_all_data(); unset( $all_data[ $this->_secondary_id ] ); $options_manager = $this->get_option_manager(); $options_manager->set_option( $this->_id, $all_data, true ); } /** * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param string $key * @param bool $store */ function remove( $key, $store = true ) { if ( ! array_key_exists( $key, $this->_data ) ) { return; } unset( $this->_data[ $key ] ); if ( $store ) { $all_data = $this->get_all_data(); $all_data[ $this->_secondary_id ] = $this->_data; $options_manager = $this->get_option_manager(); $options_manager->set_option( $this->_id, $all_data, true ); } } /** * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param string $key * @param mixed $default * * @return bool|\FS_Plugin */ function get( $key, $default = false ) { return array_key_exists( $key, $this->_data ) ? $this->_data[ $key ] : $default; } /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return string */ function get_secondary_id() { return $this->_secondary_id; } /* ArrayAccess + Magic Access (better for refactoring) -----------------------------------------------------------------------------------*/ function __set( $k, $v ) { $this->store( $k, $v ); } function __isset( $k ) { return array_key_exists( $k, $this->_data ); } function __unset( $k ) { $this->remove( $k ); } function __get( $k ) { return $this->get( $k, null ); } #[ReturnTypeWillChange] function offsetSet( $k, $v ) { if ( is_null( $k ) ) { throw new Exception( 'Can\'t append value to request params.' ); } else { $this->{$k} = $v; } } #[ReturnTypeWillChange] function offsetExists( $k ) { return array_key_exists( $k, $this->_data ); } #[ReturnTypeWillChange] function offsetUnset( $k ) { unset( $this->$k ); } #[ReturnTypeWillChange] function offsetGet( $k ) { return $this->get( $k, null ); } /** * (PHP 5 >= 5.0.0)
    * Return the current element * * @link http://php.net/manual/en/iterator.current.php * @return mixed Can return any type. */ #[ReturnTypeWillChange] public function current() { return current( $this->_data ); } /** * (PHP 5 >= 5.0.0)
    * Move forward to next element * * @link http://php.net/manual/en/iterator.next.php * @return void Any returned value is ignored. */ #[ReturnTypeWillChange] public function next() { next( $this->_data ); } /** * (PHP 5 >= 5.0.0)
    * Return the key of the current element * * @link http://php.net/manual/en/iterator.key.php * @return mixed scalar on success, or null on failure. */ #[ReturnTypeWillChange] public function key() { return key( $this->_data ); } /** * (PHP 5 >= 5.0.0)
    * Checks if current position is valid * * @link http://php.net/manual/en/iterator.valid.php * @return boolean The return value will be casted to boolean and then evaluated. * Returns true on success or false on failure. */ #[ReturnTypeWillChange] public function valid() { $key = key( $this->_data ); return ( $key !== null && $key !== false ); } /** * (PHP 5 >= 5.0.0)
    * Rewind the Iterator to the first element * * @link http://php.net/manual/en/iterator.rewind.php * @return void Any returned value is ignored. */ #[ReturnTypeWillChange] public function rewind() { reset( $this->_data ); } /** * (PHP 5 >= 5.1.0)
    * Count elements of an object * * @link http://php.net/manual/en/countable.count.php * @return int The custom count as an integer. *

    *

    * The return value is cast to an integer. */ #[ReturnTypeWillChange] public function count() { return count( $this->_data ); } }freemius/includes/managers/class-fs-gdpr-manager.php000064400000013145146725417150016574 0ustar00_storage = FS_Option_Manager::get_manager( WP_FS__GDPR_OPTION_NAME, true, true ); $this->_wp_user_id = Freemius::get_current_wp_user_id(); $this->_option_name = "u{$this->_wp_user_id}"; $this->_data = $this->_storage->get_option( $this->_option_name, array() ); $this->_notices = FS_Admin_Notices::instance( 'all_admins', '', '', true ); if ( ! is_array( $this->_data ) ) { $this->_data = array(); } } /** * Update a GDPR option for the current admin and store it. * * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @param string $name * @param mixed $value */ private function update_option( $name, $value ) { $this->_data[ $name ] = $value; $this->_storage->set_option( $this->_option_name, $this->_data, true ); } /** * @author Leo Fajardo (@leorw) * @since 2.1.0 * * @param bool $is_required */ public function store_is_required( $is_required ) { $this->update_option( 'required', $is_required ); } /** * Checks if the GDPR opt-in sticky notice is currently shown. * * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @return bool */ public function is_opt_in_notice_shown() { return $this->_notices->has_sticky( "gdpr_optin_actions_{$this->_wp_user_id}", true ); } /** * Remove the GDPR opt-in sticky notice. * * @author Vova Feldman (@svovaf) * @since 2.1.0 */ public function remove_opt_in_notice() { $this->_notices->remove_sticky( "gdpr_optin_actions_{$this->_wp_user_id}", true ); $this->disable_opt_in_notice(); } /** * Prevents the opt-in message from being added/shown. * * @author Leo Fajardo (@leorw) * @since 2.1.0 */ public function disable_opt_in_notice() { $this->update_option( 'show_opt_in_notice', false ); } /** * Checks if a GDPR opt-in message needs to be shown to the current admin. * * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @return bool */ public function should_show_opt_in_notice() { return ( ! isset( $this->_data['show_opt_in_notice'] ) || true === $this->_data['show_opt_in_notice'] ); } /** * Get the last time the GDPR opt-in notice was shown. * * @author Vova Feldman (@svovaf) * @since 2.1.0 * * @return false|int */ public function last_time_notice_was_shown() { return isset( $this->_data['notice_shown_at'] ) ? $this->_data['notice_shown_at'] : false; } /** * Update the timestamp of the last time the GDPR opt-in message was shown to now. * * @author Vova Feldman (@svovaf) * @since 2.1.0 */ public function notice_was_just_shown() { $this->update_option( 'notice_shown_at', WP_FS__SCRIPT_START_TIME ); } /** * @param string $message * @param string|null $plugin_title * * @author Vova Feldman (@svovaf) * @since 2.1.0 */ public function add_opt_in_sticky_notice( $message, $plugin_title = null ) { $this->_notices->add_sticky( $message, "gdpr_optin_actions_{$this->_wp_user_id}", '', 'promotion', true, $this->_wp_user_id, $plugin_title, true ); } }freemius/includes/managers/class-fs-plugin-manager.php000064400000013766146725417150017147 0ustar00_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $module_id . '_' . 'plugins', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); $this->_module_id = $module_id; $this->load(); } protected function get_option_manager() { return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true, true ); } /** * @author Leo Fajardo (@leorw) * @since 1.2.2 * * @param string|bool $module_type "plugin", "theme", or "false" for all modules. * * @return array */ protected function get_all_modules( $module_type = false ) { $option_manager = $this->get_option_manager(); if ( false !== $module_type ) { return fs_get_entities( $option_manager->get_option( $module_type . 's', array() ), FS_Plugin::get_class_name() ); } return array( self::OPTION_NAME_PLUGINS => fs_get_entities( $option_manager->get_option( self::OPTION_NAME_PLUGINS, array() ), FS_Plugin::get_class_name() ), self::OPTION_NAME_THEMES => fs_get_entities( $option_manager->get_option( self::OPTION_NAME_THEMES, array() ), FS_Plugin::get_class_name() ), ); } /** * Load plugin data from local DB. * * @author Vova Feldman (@svovaf) * @since 1.0.6 */ function load() { $all_modules = $this->get_all_modules(); if ( ! is_numeric( $this->_module_id ) ) { unset( $all_modules[ self::OPTION_NAME_THEMES ] ); } foreach ( $all_modules as $modules ) { /** * @since 1.2.2 * * @var $modules FS_Plugin[] */ foreach ( $modules as $module ) { $found_module = false; /** * If module ID is not numeric, it must be a plugin's slug. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ if ( ! is_numeric( $this->_module_id ) ) { if ( $this->_module_id === $module->slug ) { $this->_module_id = $module->id; $found_module = true; } } else if ( $this->_module_id == $module->id ) { $found_module = true; } if ( $found_module ) { $this->_module = $module; break; } } } } /** * Store plugin on local DB. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param bool|FS_Plugin $module * @param bool $flush * * @return bool|\FS_Plugin */ function store( $module = false, $flush = true ) { if ( false !== $module ) { $this->_module = $module; } $all_modules = $this->get_all_modules( $this->_module->type ); $all_modules[ $this->_module->slug ] = $this->_module; $options_manager = $this->get_option_manager(); $options_manager->set_option( $this->_module->type . 's', $all_modules, $flush ); return $this->_module; } /** * Update local plugin data if different. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param \FS_Plugin $plugin * @param bool $store * * @return bool True if plugin was updated. */ function update( FS_Plugin $plugin, $store = true ) { if ( ! ($this->_module instanceof FS_Plugin ) || $this->_module->slug != $plugin->slug || $this->_module->public_key != $plugin->public_key || $this->_module->secret_key != $plugin->secret_key || $this->_module->parent_plugin_id != $plugin->parent_plugin_id || $this->_module->title != $plugin->title ) { $this->store( $plugin, $store ); return true; } return false; } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @param FS_Plugin $plugin * @param bool $store */ function set( FS_Plugin $plugin, $store = false ) { $this->_module = $plugin; if ( $store ) { $this->store(); } } /** * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return bool|\FS_Plugin */ function get() { if ( isset( $this->_module ) ) { return $this->_module; } if ( empty( $this->_module_id ) ) { return false; } /** * Return an FS_Plugin entity that has its `id` and `is_live` properties set (`is_live` is initialized in the FS_Plugin constructor) to avoid triggering an error that is relevant to these properties when the FS_Plugin entity is used before the `parse_settings()` method is called. This can happen when creating a regular WordPress site by cloning a subsite of a multisite network and the data that is stored in the network-level storage is not cloned. * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ $plugin = new FS_Plugin(); $plugin->id = $this->_module_id; return $plugin; } }freemius/includes/managers/class-fs-admin-notice-manager.php000064400000045124146725417150020211 0ustar00 0 ) { $key .= ":{$network_level_or_blog_id}"; } else { $network_level_or_blog_id = get_current_blog_id(); $key .= ":{$network_level_or_blog_id}"; } } if ( ! isset( self::$_instances[ $key ] ) ) { self::$_instances[ $key ] = new FS_Admin_Notice_Manager( $id, $title, $module_unique_affix, $is_network_and_blog_admins, $network_level_or_blog_id ); } return self::$_instances[ $key ]; } /** * @param string $id * @param string $title * @param string $module_unique_affix * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network and * blog admin pages. * @param bool|int $network_level_or_blog_id */ protected function __construct( $id, $title = '', $module_unique_affix = '', $is_network_and_blog_admins = false, $network_level_or_blog_id = false ) { $this->_id = $id; $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $this->_id . '_data', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK ); $this->_title = ! empty( $title ) ? $title : ''; $this->_module_unique_affix = $module_unique_affix; $this->_sticky_storage = FS_Key_Value_Storage::instance( 'admin_notices', $this->_id, $network_level_or_blog_id ); if ( is_multisite() ) { $this->_is_network_notices = ( true === $network_level_or_blog_id ); if ( is_numeric( $network_level_or_blog_id ) ) { $this->_blog_id = $network_level_or_blog_id; } } else { $this->_is_network_notices = false; } $is_network_admin = fs_is_network_admin(); $is_blog_admin = fs_is_blog_admin(); if ( ( $this->_is_network_notices && $is_network_admin ) || ( ! $this->_is_network_notices && $is_blog_admin ) || ( $is_network_and_blog_admins && ( $is_network_admin || $is_blog_admin ) ) ) { if ( 0 < count( $this->_sticky_storage ) ) { $ajax_action_suffix = str_replace( ':', '-', $this->_id ); // If there are sticky notices for the current slug, add a callback // to the AJAX action that handles message dismiss. add_action( "wp_ajax_fs_dismiss_notice_action_{$ajax_action_suffix}", array( &$this, 'dismiss_notice_ajax_callback' ) ); foreach ( $this->_sticky_storage as $msg ) { // Add admin notice. $this->add( $msg['message'], $msg['title'], $msg['type'], true, $msg['id'], false, isset( $msg['wp_user_id'] ) ? $msg['wp_user_id'] : null, ! empty( $msg['plugin'] ) ? $msg['plugin'] : null, $is_network_and_blog_admins, isset( $msg['dismissible'] ) ? $msg['dismissible'] : null ); } } } } /** * Remove sticky message by ID. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * */ function dismiss_notice_ajax_callback() { check_admin_referer( 'fs_dismiss_notice_action' ); if ( ! is_numeric( $_POST['message_id'] ) ) { $this->_sticky_storage->remove( $_POST['message_id'] ); } wp_die(); } /** * Rendered sticky message dismiss JavaScript. * * @author Vova Feldman (@svovaf) * @since 1.0.7 */ static function _add_sticky_dismiss_javascript() { $params = array(); fs_require_once_template( 'sticky-admin-notice-js.php', $params ); } private static $_added_sticky_javascript = false; /** * Hook to the admin_footer to add sticky message dismiss JavaScript handler. * * @author Vova Feldman (@svovaf) * @since 1.0.7 */ private static function has_sticky_messages() { if ( ! self::$_added_sticky_javascript ) { add_action( 'admin_footer', array( 'FS_Admin_Notice_Manager', '_add_sticky_dismiss_javascript' ) ); } } /** * Handle admin_notices by printing the admin messages stacked in the queue. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * */ function _admin_notices_hook() { if ( function_exists( 'current_user_can' ) && ! current_user_can( 'manage_options' ) ) { // Only show messages to admins. return; } foreach ( $this->_notices as $id => $msg ) { if ( isset( $msg['wp_user_id'] ) && is_numeric( $msg['wp_user_id'] ) ) { if ( get_current_user_id() != $msg['wp_user_id'] ) { continue; } } /** * Added a filter to control the visibility of admin notices. * * Usage example: * * /** * * @param bool $show * * @param array $msg { * * @var string $message The actual message. * * @var string $title An optional message title. * * @var string $type The type of the message ('success', 'update', 'warning', 'promotion'). * * @var string $id The unique identifier of the message. * * @var string $manager_id The unique identifier of the notices manager. For plugins it would be the plugin's slug, for themes - `-theme`. * * @var string $plugin The product's title. * * @var string $wp_user_id An optional WP user ID that this admin notice is for. * * } * * * * @return bool * *\/ * function my_custom_show_admin_notice( $show, $msg ) { * if ('trial_promotion' != $msg['id']) { * return false; * } * * return $show; * } * * my_fs()->add_filter( 'show_admin_notice', 'my_custom_show_admin_notice', 10, 2 ); * * @author Vova Feldman * @since 2.2.0 */ $show_notice = call_user_func_array( 'fs_apply_filter', array( $this->_module_unique_affix, 'show_admin_notice', $this->show_admin_notices(), $msg ) ); if ( true !== $show_notice ) { continue; } fs_require_template( 'admin-notice.php', $msg ); if ( $msg['sticky'] ) { self::has_sticky_messages(); } } } /** * Enqueue common stylesheet to style admin notice. * * @author Vova Feldman (@svovaf) * @since 1.0.7 */ function _enqueue_styles() { fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); } /** * Check if the current page is the Gutenberg block editor. * * @author Vova Feldman (@svovaf) * @since 2.2.3 * * @return bool */ function is_gutenberg_page() { if ( function_exists( 'is_gutenberg_page' ) && is_gutenberg_page() ) { // The Gutenberg plugin is on. return true; } $current_screen = get_current_screen(); if ( method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() ) { // Gutenberg page on 5+. return true; } return false; } /** * Check if admin notices should be shown on page. E.g., we don't want to show notices in the Visual Editor. * * @author Xiaheng Chen (@xhchen) * @since 2.4.2 * * @return bool */ function show_admin_notices() { global $pagenow; if ( 'about.php' === $pagenow ) { // Don't show admin notices on the About page. return false; } if ( $this->is_gutenberg_page() ) { // Don't show admin notices in Gutenberg (visual editor). return false; } return true; } /** * Add admin message to admin messages queue, and hook to admin_notices / all_admin_notices if not yet hooked. * * @author Vova Feldman (@svovaf) * @since 1.0.4 * * @param string $message * @param string $title * @param string $type * @param bool $is_sticky * @param string $id Message ID * @param bool $store_if_sticky * @param number|null $wp_user_id * @param string|null $plugin_title * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network * and blog admin pages. * @param bool|null $is_dismissible * @param array $data * * @uses add_action() */ function add( $message, $title = '', $type = 'success', $is_sticky = false, $id = '', $store_if_sticky = true, $wp_user_id = null, $plugin_title = null, $is_network_and_blog_admins = false, $is_dismissible = null, $data = array() ) { $notices_type = $this->get_notices_type(); if ( empty( $this->_notices ) ) { if ( ! $is_network_and_blog_admins ) { add_action( $notices_type, array( &$this, "_admin_notices_hook" ) ); } else { add_action( 'network_admin_notices', array( &$this, "_admin_notices_hook" ) ); add_action( 'admin_notices', array( &$this, "_admin_notices_hook" ) ); } add_action( 'admin_enqueue_scripts', array( &$this, '_enqueue_styles' ) ); } if ( '' === $id ) { $id = md5( $title . ' ' . $message . ' ' . $type ); } $message_object = array( 'message' => $message, 'title' => $title, 'type' => $type, 'sticky' => $is_sticky, 'id' => $id, 'manager_id' => $this->_id, 'plugin' => ( ! is_null( $plugin_title ) ? $plugin_title : $this->_title ), 'wp_user_id' => $wp_user_id, 'dismissible' => $is_dismissible, 'data' => $data ); if ( $is_sticky && $store_if_sticky ) { $this->_sticky_storage->{$id} = $message_object; } $this->_notices[ $id ] = $message_object; } /** * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param string|string[] $ids * @param bool $store */ function remove_sticky( $ids, $store = true ) { if ( ! is_array( $ids ) ) { $ids = array( $ids ); } foreach ( $ids as $id ) { // Remove from sticky storage. $this->_sticky_storage->remove( $id, $store ); if ( isset( $this->_notices[ $id ] ) ) { unset( $this->_notices[ $id ] ); } } } /** * Check if sticky message exists by id. * * @author Vova Feldman (@svovaf) * @since 1.0.9 * * @param $id * * @return bool */ function has_sticky( $id ) { return isset( $this->_sticky_storage[ $id ] ); } /** * Adds sticky admin notification. * * @author Vova Feldman (@svovaf) * @since 1.0.7 * * @param string $message * @param string $id Message ID * @param string $title * @param string $type * @param number|null $wp_user_id * @param string|null $plugin_title * @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network * and blog admin pages. * @param bool $is_dimissible * @param array $data */ function add_sticky( $message, $id, $title = '', $type = 'success', $wp_user_id = null, $plugin_title = null, $is_network_and_blog_admins = false, $is_dimissible = true, $data = array() ) { if ( ! empty( $this->_module_unique_affix ) ) { $message = fs_apply_filter( $this->_module_unique_affix, "sticky_message_{$id}", $message ); $title = fs_apply_filter( $this->_module_unique_affix, "sticky_title_{$id}", $title ); } $this->add( $message, $title, $type, true, $id, true, $wp_user_id, $plugin_title, $is_network_and_blog_admins, $is_dimissible, $data ); } /** * Retrieves the data of an sticky notice. * * @author Leo Fajardo (@leorw) * @since 2.4.3 * * @param string $id Message ID. * * @return array|null */ function get_sticky( $id ) { return isset( $this->_sticky_storage->{$id} ) ? $this->_sticky_storage->{$id} : null; } /** * Clear all sticky messages. * * @author Vova Feldman (@svovaf) * @since 1.0.8 * * @param bool $is_temporary @since 2.5.1 */ function clear_all_sticky( $is_temporary = false ) { if ( $is_temporary ) { $this->_notices = array(); } else { $this->_sticky_storage->clear_all(); } } #-------------------------------------------------------------------------------- #region Helper Method #-------------------------------------------------------------------------------- /** * @author Vova Feldman (@svovaf) * @since 2.0.0 * * @return string */ private function get_notices_type() { return $this->_is_network_notices ? 'network_admin_notices' : 'admin_notices'; } #endregion } freemius/includes/fs-essential-functions.php000064400000031726146725417150015332 0ustar00add( "Freemius failed to redirect the page because the headers have been already sent from line {$line} in file {$file}. If it's unexpected, it usually happens due to invalid space and/or EOL character(s).", 'Oops...', 'error' ); } return false; } if ( defined( 'DOING_AJAX' ) ) { // Don't redirect on AJAX calls. return false; } if ( ! $location ) // allows the wp_redirect filter to cancel a redirect { return false; } $location = fs_sanitize_redirect( $location ); if ( $is_IIS ) { header( "Refresh: 0;url=$location" ); } else { if ( php_sapi_name() != 'cgi-fcgi' ) { status_header( $status ); } // This causes problems on IIS and some FastCGI setups header( "Location: $location" ); } if ( $exit ) { exit(); } return true; } if ( ! function_exists( 'fs_sanitize_redirect' ) ) { /** * Sanitizes a URL for use in a redirect. * * @since 2.3 * * @param string $location * * @return string redirect-sanitized URL */ function fs_sanitize_redirect( $location ) { $location = preg_replace( '|[^a-z0-9-~+_.?#=&;,/:%!]|i', '', $location ); $location = fs_kses_no_null( $location ); // remove %0d and %0a from location $strip = array( '%0d', '%0a' ); $found = true; while ( $found ) { $found = false; foreach ( (array) $strip as $val ) { while ( strpos( $location, $val ) !== false ) { $found = true; $location = str_replace( $val, '', $location ); } } } return $location; } } if ( ! function_exists( 'fs_kses_no_null' ) ) { /** * Removes any NULL characters in $string. * * @since 1.0.0 * * @param string $string * * @return string */ function fs_kses_no_null( $string ) { $string = preg_replace( '/\0+/', '', $string ); $string = preg_replace( '/(\\\\0)+/', '', $string ); return $string; } } } #endregion Core Redirect (copied from BuddyPress) ----------------------------------------- if ( ! function_exists( 'fs_get_ip' ) ) { /** * Get server IP. * * @since 2.5.1 This method returns the server IP. * * @author Vova Feldman (@svovaf) * @since 1.1.2 * * @return string|null */ function fs_get_ip() { return empty( $_SERVER[ 'SERVER_ADDR' ] ) ? null : $_SERVER[ 'SERVER_ADDR' ]; } } /** * Leverage backtrace to find caller plugin main file path. * * @author Vova Feldman (@svovaf) * @since 1.0.6 * * @return string */ function fs_find_caller_plugin_file() { /** * All the code below will be executed once on activation. * If the user changes the main plugin's file name, the file_exists() * will catch it. */ if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $all_plugins = fs_get_plugins( true ); $all_plugins_paths = array(); // Get active plugin's main files real full names (might be symlinks). foreach ( $all_plugins as $relative_path => $data ) { $all_plugins_paths[] = fs_normalize_path( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) ); } $plugin_file = null; for ( $i = 1, $bt = debug_backtrace(), $len = count( $bt ); $i < $len; $i ++ ) { if ( empty( $bt[ $i ]['file'] ) ) { continue; } if ( in_array( fs_normalize_path( $bt[ $i ]['file'] ), $all_plugins_paths ) ) { $plugin_file = $bt[ $i ]['file']; break; } } if ( is_null( $plugin_file ) ) { // Throw an error to the developer in case of some edge case dev environment. wp_die( 'Freemius SDK couldn\'t find the plugin\'s main file. Please contact sdk@freemius.com with the current error.', 'Error', array( 'back_link' => true ) ); } return $plugin_file; } require_once dirname( __FILE__ ) . '/supplements/fs-essential-functions-1.1.7.1.php'; /** * Update SDK newest version reference. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @param string $sdk_relative_path * @param string|bool $plugin_file * * @global $fs_active_plugins */ function fs_update_sdk_newest_version( $sdk_relative_path, $plugin_file = false ) { /** * If there is a plugin running an older version of FS (1.2.1 or below), the `fs_update_sdk_newest_version()` * function in the older version will be used instead of this one. But since the older version is using * the `is_plugin_active` function to check if a plugin is active, passing the theme's `plugin_path` to the * `is_plugin_active` function will return false since the path is not a plugin path, so `in_activation` will be * `true` for theme modules and the upgrading of the SDK version to 1.2.2 or newer version will work fine. * * Future versions that will call this function will use the proper logic here instead of just relying on the * `is_plugin_active` function to fail for themes. * * @author Leo Fajardo (@leorw) * @since 1.2.2 */ global $fs_active_plugins; $newest_sdk = $fs_active_plugins->plugins[ $sdk_relative_path ]; if ( ! is_string( $plugin_file ) ) { $plugin_file = plugin_basename( fs_find_caller_plugin_file() ); } if ( ! isset( $newest_sdk->type ) || 'theme' !== $newest_sdk->type ) { if ( ! function_exists( 'is_plugin_active' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $in_activation = ( ! is_plugin_active( $plugin_file ) ); } else { $theme = wp_get_theme(); $in_activation = ( $newest_sdk->plugin_path == $theme->stylesheet ); } $fs_active_plugins->newest = (object) array( 'plugin_path' => $plugin_file, 'sdk_path' => $sdk_relative_path, 'version' => $newest_sdk->version, 'in_activation' => $in_activation, 'timestamp' => time(), ); // Update DB with latest SDK version and path. update_option( 'fs_active_plugins', $fs_active_plugins ); } /** * Reorder the plugins load order so the plugin with the newest Freemius SDK is loaded first. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @return bool Was plugin order changed. Return false if plugin was loaded first anyways. * * @global $fs_active_plugins */ function fs_newest_sdk_plugin_first() { global $fs_active_plugins; /** * @todo Multi-site network activated plugin are always loaded prior to site plugins so if there's a plugin activated in the network mode that has an older version of the SDK of another plugin which is site activated that has new SDK version, the fs-essential-functions.php will be loaded from the older SDK. Same thing about MU plugins (loaded even before network activated plugins). * * @link https://github.com/Freemius/wordpress-sdk/issues/26 */ $newest_sdk_plugin_path = $fs_active_plugins->newest->plugin_path; $active_plugins = get_option( 'active_plugins', array() ); $updated_active_plugins = array( $newest_sdk_plugin_path ); $plugin_found = false; $is_first_path = true; foreach ( $active_plugins as $key => $plugin_path ) { if ( $plugin_path === $newest_sdk_plugin_path ) { if ( $is_first_path ) { // if it's the first plugin already, no need to continue return false; } $plugin_found = true; // Skip the plugin (it is already added as the 1st item of $updated_active_plugins). continue; } $updated_active_plugins[] = $plugin_path; if ( $is_first_path ) { $is_first_path = false; } } if ( $plugin_found ) { update_option( 'active_plugins', $updated_active_plugins ); return true; } if ( is_multisite() ) { // Plugin is network active. $network_active_plugins = get_site_option( 'active_sitewide_plugins', array() ); if ( isset( $network_active_plugins[ $newest_sdk_plugin_path ] ) ) { reset( $network_active_plugins ); if ( $newest_sdk_plugin_path === key( $network_active_plugins ) ) { // Plugin is already activated first on the network level. return false; } else { $time = $network_active_plugins[ $newest_sdk_plugin_path ]; // Remove plugin from its current position. unset( $network_active_plugins[ $newest_sdk_plugin_path ] ); // Set it to be included first. $network_active_plugins = array( $newest_sdk_plugin_path => $time ) + $network_active_plugins; update_site_option( 'active_sitewide_plugins', $network_active_plugins ); return true; } } } return false; } /** * Go over all Freemius SDKs in the system and find and "remember" * the newest SDK which is associated with an active plugin. * * @author Vova Feldman (@svovaf) * @since 1.1.6 * * @global $fs_active_plugins */ function fs_fallback_to_newest_active_sdk() { global $fs_active_plugins; /** * @var object $newest_sdk_data */ $newest_sdk_data = null; $newest_sdk_path = null; foreach ( $fs_active_plugins->plugins as $sdk_relative_path => $data ) { if ( is_null( $newest_sdk_data ) || version_compare( $data->version, $newest_sdk_data->version, '>' ) ) { // If plugin inactive or SDK starter file doesn't exist, remove SDK reference. if ( 'plugin' === $data->type ) { $is_module_active = is_plugin_active( $data->plugin_path ); } else { $active_theme = wp_get_theme(); $is_module_active = ( $data->plugin_path === $active_theme->get_template() ); } $is_sdk_exists = file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $sdk_relative_path . '/start.php' ) ); if ( ! $is_module_active || ! $is_sdk_exists ) { unset( $fs_active_plugins->plugins[ $sdk_relative_path ] ); // No need to store the data since it will be stored in fs_update_sdk_newest_version() // or explicitly with update_option(). } else { $newest_sdk_data = $data; $newest_sdk_path = $sdk_relative_path; } } } if ( is_null( $newest_sdk_data ) ) { // Couldn't find any SDK reference. $fs_active_plugins = new stdClass(); update_option( 'fs_active_plugins', $fs_active_plugins ); } else { fs_update_sdk_newest_version( $newest_sdk_path, $newest_sdk_data->plugin_path ); } }freemius/includes/supplements/fs-essential-functions-2.2.1.php000064400000002513146725417150020337 0ustar00 $install ) { if ( true === $install->is_disconnected ) { $permission_manager->update_site_tracking( false, ( 0 == $blog_id ) ? null : $blog_id, // Update only if permissions are not yet set. true ); } } } }freemius/includes/supplements/index.php000064400000000127146725417150014404 0ustar00 $data ) { if ( 0 === strpos( $file_real_path, fs_normalize_path( dirname( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) ) . '/' ) ) ) { if ( '.' !== dirname( trailingslashit( $relative_path ) ) ) { return $relative_path; } } } return null; } freemius/languages/freemius-hu_HU.mo000064400000064207146725417150013540 0ustar00Þ•{ô ýÌÀnÁS0 „ _ ð ú ! !!!'!+!J!j!r!‚!Š! “!Ÿ!°!Å!Û!&ì!-"A" V"`"s"z"‚"Š" š"¦" ¿" Ì"Ö"ç"î" # #2=#!p#’#©#¸#À#È#Û#ä#ì# ñ#ÿ# $$:$A$U$ i$ v$€$‘$­$¼$ Í$ Ù$å$î$ó$% %('%:P%‹%%¡%©% ¹% Ä%Ñ%ç%ï% ô%ÿ%x&”‹& ' -'7'K'S'm'ƒ'™'¢'¶'Ì' è'ó' ù'a(i(o(( —( ¥(³(¸(¿( Ä( Ï( Ü(é(jø(5c) ™)£)¬)À)Ü))÷)-!*O*c*'{*£*7¦*Þ*ø* ++0+F+ N+•X+1î+. ,O,AÏ,-1-G-BK-,Ž-»- À-Í-ë- .... 0. ;.G. W.c.y. ‚.Œ.”. ›.§.Á.Æ.Ê. à.ë.ð.ó.ù.///$/@/ F/R/ [/ f/t/‘/š/Ÿ/§/-¾/Uì/B0a0h0 x0‚0(‘0*º0"å011+:1*f1&‘1¸1À1Ö1.Þ1 22=2E2 T2 _2j2s2 |2‡2 ˜2¦2µ2»2 Ô2â2ù233$3(313 93E3 W3b3q3‚3–3ž3 ¤3®3 ³3¿3 Å3 Ñ3Þ3 æ3ô3 44 (4 34>4S4f4C…4É4ß4-ÿ4-5 35@5'G5 o5y55…5Š55•5¨5º5É5Ð5*ß5 6*6^=6œ6«6³6¹6¿6 È6 Õ6â6õ6"ý66 7=W7•7 ª7¸7-É7÷78+8*E8p8t8†8¦8&½8-ä899<L9U‰9Kß9(+:GT:#œ:%À:)æ:$;)5;_;q;>†;Å;å;$û; <:<V<r<&<*·<7â<=1=O=3h=œ=±=Ç=ß=ó=*>1;>m>‰>#>Á>Ý>ï>ÿ>?6? K?X?w?•?°?À?Ñ?â?1ý?/@7@K@ \@ h@ u@ €@@–@C®@ò@Q÷@IA YA fApAvA ‰A•A ¤A ®A ¸A ÄA ÑA ßA éA óA ÿA» B~ÈE(GF pFu{FñFG G G'G*G-G1G:GCGIG ]G hGtG„G›GµGÓG;èG3$HXHtHˆH £H±HÀHÅHÍH$ÞHI I I >IIIZI rI*“I¾I×IïI J J J *J5J=JBJKJeJzJšJ¢J¸JÏJ äJîJþJK+KDKYK uKK†K'£K ËKCØK L&L+L P…TPCÚP Q*Q3Q'HQpQ#ŠQ2®QáQôQR2R5R!QR"sR–R§RÅRãRëRÓòR.ÆS2õS¢(T<ËTUU6UY;÷+h~Wõ1HÛ–KˆsèfcYicãue+õZ(Äa´:OÏ]gt=A’1Üÿ—”#°Ñ_# „o& ª/?[†5Þìüv¿@}¥GF'‰×ùúû©t24ôÉL"yþ!åk_ÔZr[³·dêóNCy.nr@ÀEEïz X>«øBœPI=k9M¨Ÿä¼ÕBÇÂjR$)•<D^âA0qSÙ9š™m2ÝUð6ÁFî^ž$7-£0“‹»LXo "òd&x½¶5VQÍ l The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Licenses%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s rating%s ratings%s star%s stars%s time%s timesAPIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd another domainAdd-OnAdd-OnsAddressAddress Line %dAffiliationAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAmountAn unknown error has occurred.Anonymous feedbackApply to become an affiliateAre you sure you want to delete all Freemius data?Are you sure you want to proceed?Automatic InstallationAverage RatingAwesomeBillingBilling & InvoicesBlockingBlog IDBodyBusiness nameBuy a license nowBuy licenseCan't find your license key?CancelCancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %s...Cancelling the subscriptionChange LicenseChange OwnershipChange PlanChange UserCheckoutCityClear API CacheClear Updates TransientsClick hereClick here to use the plugin anonymouslyClone resolution admin notice products list labelProductsCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDelete All AccountsDetailsDon't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload Paid VersionDownload the latest versionDownloadedEmailEmail addressEnter the email address you've used for the upgrade below and we will resend you the license key.ErrorError received from the server:ExpiredExpires in %sExtra DomainsFileFilterFreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius is our licensing and software updates engineFull nameFunctionHave a license key?How to upload and activate?I can't pay for it anymoreI couldn't understand how to make it workI don't like to share my information with youI found a better %sI no longer need the %sI only needed the %s for a short periodIDIf you have a moment, please let us know why you are %sImportant Upgrade Notice:Install Free Version NowInstall NowInstall Update NowInstalling plugin: %sInvoiceIs ActiveIs this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.It looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It's not what I was looking forJoin the Beta programKeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense IDLicense KeyLicense issues?License keyLicense key is empty.LifetimeLocalhostMessageMethodModule PathMore information about %sNameNewNew Version AvailableNewsletterNextNoNo IDNo credit card requiredO.KOpt InOpt OutOpt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPayPal account email addressPaymentsPlanPlan IDPlease contact us herePlease contact us with the following message:Please enter the license key that you received in the email right after the purchase:Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium versionPremium version already active.PricingPrivacy PolicyProcess IDProcessingProductsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackQuotaRe-send activation emailRenew licenseRenew your license nowRequestsRequires WordPress VersionResultSDKSDK PathSave %sScreenshotsSearch by addressSecret KeySelect CountrySend License KeySingle Site LicenseSite IDSitesSkip & %sSlugStart TrialStateSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you!Thanks %s!The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a new version of %s available.TimestampTitleTotalTownTrialTypeUnlimited LicensesUnlimited UpdatesUp to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser DashboardUser IDUsersValueVerifiedVerify EmailView detailsView paid featuresWarningWe made a few tweaks to the %s, %sWebsite, email, and social media statistics (optional)Welcome to %s! To get started, please enter your license key:What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?WordPress.org Plugin PageWould you like to proceed with the update?YesYou are all good!You are just one step away - %sYou have a %s license.You have successfully updated your %s.Your %s license was successfully deactivated.Your account was successfully activated with the %s plan.Your email has been successfully verified - you are AWESOME!Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your trial has been successfully started.ZIP / Postal Codeactive add-onActiveadvance notice of something that will need attention.Heads upas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOncall to actionStart free trialclose a windowDismissclose windowDismissdeactivatinge.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,installed add-onInstalledinterjection expressing joy or exuberanceYee-hawlicenselike websitesSitesnew Beta versionnew versionnot verifiednounPricenounPricingoptionalproduct versionVersionsend me security & feature updates, educational content and offers.skipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialsubscriptionswitchingtrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradeProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Peter Ambrus, 2018-2019,2021 Language-Team: Hungarian (Hungary) (http://www.transifex.com/freemius/wordpress-sdk/language/hu_HU/) Language: hu_HU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js A(z) %1$s fizetÅ‘s verziója sikeresen telepítve. Kérlek aktiváld, hogy a(z) %2$s minden funkciója elérhetÅ‘ legyen. %3$s"%s" aktiválásának a befejezése most%s licenszA(z) %s egy prémium kiegészítÅ‘. A bÅ‘vítmény aktiválásához elÅ‘bb egy érvényes licenszt kell vásárolnod.%s értékelés%s értékelés%s csillag%s csillag%s%sAPI←➤FiókFiók információkEseményekAktiválás%s aktiválása%s csomag aktiválása%s funkciók aktiválásaIngyenes verzió aktiválásaLicensz aktiválásaLicensz aktiválása a hálózat minden függÅ‘ aloldalán.Licensz aktiválása a hálózat minden aloldalán.KiegészítÅ‘ bekapcsolásaSikeres aktiválásMásik domain hozzáadásaKiegészítÅ‘KiegészítÅ‘kCímCím %dAjánlórendszerLicensz elfogadása és aktiválásaMinden kérésMinden típusEngedélyezés és folytatásMennyiségIsmeretlen hiba.Névtelen visszajelzésJelentkezés ajánló partnernekBiztosan törölsz minden Freemius adatot?Biztosan ezt szeretnéd?Automatikus telepítésÃtlagos értékelésNagyszerűSzámlázásSzámlázásBlokkolásBlog IDBodyCégnévVásárolj licenszet mostLicensz vásárlásaNem találod a licensz kulcsod?MégsemTelepítés törléseElÅ‘fizetés törlésePróbaidÅ‘ törléseTörölve%s törlése...ElÅ‘fizetés törléseLicensz módosításaTulajdonos módosításaCsomag módosításaFelhasználó módosításaPénztárVárosAPI gyorsítótár törléseÃtmeneti frissítési adatok törléseKattints ideKattints ide, ha névtelenül szeretnéd használni a bÅ‘vítménytTermékekKódKompatibilitás:KapcsolatÃrás az ügyfélszolgálatraKapcsolatKözreműködÅ‘kA(z) %s aktiválása nem sikerült.OrszágDátumDeaktiválásLicensz deaktiválásaA(z) %s deaktiválása vagy törlése automatikusan törli az oldalhoz tartozó licenszed is, amit így másik weboldalon tudsz újra aktiválni.A licensz deaktiválása után a prémium funkciók használata nem elérhetÅ‘, de így tudod másik weboldalon aktiválni ugyanezt a licenszt. Folytatod a deaktiválást?DeaktiválásHibakeresési naplóMinden fiók törléseRészletekNincs még licensz kulcsod?BÅ‘vítmény támogatásaElÅ‘fizetés módosítása kisebbreLetöltés%s verzió letöltéseFizetÅ‘s verzió letöltéseTöltsd le a legfrissebb verziótLetöltések száma:EmailEmail címAdd meg az email címet, amit a vásárlás során használtál és újraküldjük a licensz kulcsot.HibaHiba érkezett a szervertÅ‘l.LejártHátralévÅ‘ idÅ‘: %sTovábbi domainekFájlSzűrÅ‘IngyenesIngyenes próbaidÅ‘Ingyenes verzióFreemius APIFreemius hibakeresésA Freemius SDK nem találja a bÅ‘vítmény fÅ‘ fájlját. Kérlek írj az sdk@freemius.com email címre a problémával kapcsolatban.A licenszkezelést és szoftver frissítést a Freemius biztosítjaTeljes névFunkcióVan licensz kulcsod?Hogyan kell feltölteni és aktiválni?Nem tudom tovább fizetniNem értettem, hogy kell használniNem szeretném megosztani veletek az információtJobb %st találtamNincs tovább szükségem ráCsak egy kis idÅ‘re használtamIDKérlek mondd el, miért %sFontos frissítési információ:Ingyenes verzió telepítése mostTelepítés mostFrissítés telepítése mostBÅ‘vítmény telepítése: %sSzámlaAktívEz egy ügyfélnek készült weboldal? %s ha szeretnéd inkább elrejteni az admin felületrÅ‘l az érzékeny információkat, mint például email cím, licensz kulcs, árak, számlázási adatok és számlák.Úgy tűnik, hogy a licensz nem aktiválható.Úgy tűnik a licensz kikapcsolása nem sikerült.Úgy tűnik, hogy még mindig a %s csomagban vagy. Ha biztosan elÅ‘fizettél vagy csomagot váltottál, akkor valószínű a hiba a mi oldalunkon van. Elnézést!Úgy tűnik, hogy a weboldalhoz nem tartozik aktív licensz.Nem ezt kerestemJelentkezz a Béta programbaKulcsHa elmondod mi nem működött, ki tudjuk javítani a leendÅ‘ felhasználók számára...Ha elmondod az okát, tudunk fejlÅ‘dni.UtolsóUtolsó frissítésLegfrissebb ingyenes verzió telepítveLegfrissebb verzió telepítveBÅ‘vebbenHosszLicenszLicensz szerzÅ‘désLicensz IDLicensz kulcsLicensszel kapcsolatos problémák?Licensz kulcsA licensz kulcs üres.ÖrökLocalhostÃœzenetMódModul útvonalTovábbi információNévÚjÚj verzió érhetÅ‘ elHírlevélKövetkezÅ‘NemNincs IDBankkártya megadása nem kötelezÅ‘RendbenFeliratkozásLeiratkozásIratkozz fel, hogy a(z) %s még jobb lehessen!EgyébTulajdonos email címeTulajdonos IDTulajdonos nevePCI megfelelésPayPal fiók email címeFizetési módokCsomagCsomag IDÃrj nekünk ittKérlek írj nekünk a következÅ‘ üzenettel:Kérlek add meg a licensz kulcsot, amit emailben kaptál a vásárlásod után:Kérlek add meg a teljes neved!BÅ‘vítményBÅ‘vítmény oldalaBÅ‘vítmény IDBÅ‘vítmény telepítéseVáltoztatásokLeírásGYIKFunkciók & ÃrakTelepítésEgyéb megjegyzésekVéleményekBÅ‘vítményekBÅ‘vítmények és sablonok szinkronizálásaPrémium%s prémium verziója sikeresen aktiválva.Prémium verzióA prémium verzió már aktív.ÃrakAdatkezelési tájékoztatóMűvelet IDFeldolgozás alattTermékekTartományPublikus kulcsLicensz vásárlásaVásárlás folytatásaGyors visszajelzésRendelkezésre állAktivációs email újraküldéseLicensz megújításaLicensz kulcs megújításaKérésekA következÅ‘ WordPress verzió szükséges:EredménySDKSDK útvonal%s mentéseKépernyÅ‘fotókKeresés cím alapjánTitkos kulcsVálaszz országotLicensz kulcs küldéseEgy weboldalas licenszWeboldal IDWeboldalakKihagyás & %sKözvetlen hivatkozásPróbaidÅ‘ indításaMegyeKüldés & %sElÅ‘fizetésÃœgyfélszolgálatTámogató fórumAdatok szinkronizálása a szerverrÅ‘lKözösségi adószámSzolgáltatási feltételekKöszönjük!Köszönjük %s!A(z) %s hibát generált az oldalonA(z) %s nem működöttA %s nem az elvárásoknak megfelelÅ‘en működöttA(z) %s nagyszerű, de nekem olyan funkcióra van szükségem, amit nem tudA(z) %s nem működikA(z) %s egyszer csak nem működöttA(z) %s frissítése sikeres volt.SablonSablon váltásSablonokA(z) %s új verziója érhetÅ‘ el.IdÅ‘bélyegCímÖsszesenTelepülésPróbaidÅ‘TípusKorlátlan licenszKorlátlan frissítésWeboldalak száma: %sFrissítésLicensz frissítéseFrissítések, közlemények, marketing, de semmi SPAM!ElÅ‘fizetésTöltsd fel és aktiváld a letöltött verziótFantasztikusFelhasználó vezérlÅ‘pultFelhasználó IDFelhasználókÉrtékEllenÅ‘rzöttEmail ellenÅ‘rzéseRészletek megtekintéseFizetÅ‘s funkciók megtekintéseFigyelmeztetésNéhány frissítést kapott a %s. %sWeboldal, email és közösségi média statisztikák (opcionális)Köszönjük, hogy a(z) %s szoftverünket választottad! Kérlek add meg a licensz kulcsod: Mire számítottál?Melyik funkcióra van szükséged?Mi a te %s?Mi lenne az elfogadható ár, amit tudnál fizetni?Pontosan mit kerestél?Mi a %s neve?WordPress.org bÅ‘vítmény oldalSzeretnéd folytatni a frissítést?IgenMinden rendben!Már csak egy lépés van hátra - %sLicensz típusa: %sA(z) %s sikeresen frissítve.A(z) %s licensz kikapcsolása sikerült.A fiókodat sikeresen aktiváltuk a következÅ‘ csomaggal: %sAz email címedet sikerült ellenÅ‘rizni - ez nagyszerű!A licensz kikapcsolásra került. Ha úgy gondolod, hogy ez tévedés volt, kérlek írj az ügyfélszolgálatra!A licensz lejárt. A(z) %s ingyenes verziója továbbra is használható korlátlanul.A licensz sikeresen aktiválva.A licenszedet sikeresen deaktiváltuk, az aktuális csomagod: %sA neved sikeresen frissítettük.Az elÅ‘fizetés sikeresen aktiválva.Az elÅ‘fizetés sikeresen módosítva: %s.Az elÅ‘fizetés sikeresen frissítve.A próbaidÅ‘szakodat sikeresen aktiváltuk.IrányítószámAktívFigyelemAktiválásévAPIMégsemHibakeresésGratulálunkBlokkolvaKapcsolódvaLegfrissebb verzió letöltéseA legfrissebb ingyenes verzió letöltéseHaviLejáratÚtvonalEmail küldésehóÉvesÉvesEgyszeriCsomagNincs titkos kulcsSDK verziókLicenszSzinkronizálásLicensz szinkronizálásaSzerzÅ‘KiBeIngyenes próbaidÅ‘szak indításaMégsemMégsemdeaktiválod%s csomag%s számlázásLegjobbÃœdvHoppáÜdv %s!TelepítveJuhuuulicenszWeboldalakúj Béta verzióúj verziónem ellenÅ‘rzöttÃrÃrakválaszthatóVerziókérek biztonsági és funkcionális frissítéseket, használati ismertetÅ‘ket és ajánlatokat.ugrásHmmpróbaidÅ‘ indításaelÅ‘fizetésváltaszpróbaidÅ‘PróbaidÅ‘TörlésVáltás kisebb csomagraSzerkesztésElrejtFeliratkozásLeiratkozásVásárlásMutasdUgrásFrissítésVáltás nagyobb csomagrafreemius/languages/freemius-en.mo000064400000205647146725417150013137 0ustar00Þ•¡$‹,*X8AY8¢›8n>92­9Zà9h;:d¤:S ;%]; ƒ; ;›;¢;¥µ;6[<´’<_G=§=Ç=#Þ=>%> B> O> Y>d>k>s>|>„>@>HÎ>?O*?Mz?jÈ?›3@Ï@Ó@ò@AAŒ*A·A¿A ÈAÔAåAúAB&!B-HBvB ‹B•B¤B¹BÌBÓB5ÛBCC )C 3C'?CgC €C C—Co¨CDžDG¾DTE[E©zE$F7F"SFvF(“F2¼F!ïF>GaPG+²G0ÞGH!H8HGHOHcHhHpHƒHŒH”H™H  H ¬HºH ÌHEØHyI˜IµI¼I’ÐI cJnJ‚J –J £J ­J»JÌJYèJBKQK bK nKzKƒKˆK˜K ±K(¼K1åK%L:=LxL }L‹LœL¤L ´L ¿LÌLâL êL7ôL,M 1M*]mi]g×]p?^°^Ê^yÐ^J_c_ ƒ__¢_ ¸_Ù_%ì_ `3`;`X`o` `&—`•¾`1Ta.†aOµabA…bÇbyçb2ac”c´caÊc ,d9dPdBTd,—dÄd Éd Ödãde e%e,e4e Fe Qe]e meyee4˜eÍe Üeæeêeñef fff,f GfSf Zf ffrfŒf,‘f ¾f ËfØf¡÷f™gg ³g!¿gág þg hhh%&hLh%Rh+xh¤h ¼h Êh/×him i~yiøiÿiujÛ}j¡Ykûkmm %m1m :m Em)Sm}mšm4£mØm5Ým(nê)‘ @‘&a‘<ˆ‘DÅ‘Z ’€e’Tæ’R;“.Ž“.½“ì“-þ”;,•9h•Z¢•3ý•<1–bn–PÑ–U"—_x—šØ—Ks˜(¿˜Gè˜#0™%T™)z™$¤™ŠÉ™UTš)ªšÔšæš››;0›6l›>£›â›è›œ#œ$9œ^œxœ”œ°œ&Îœ*õœ7 Xo3¦Úïžž1ž*Nž1yž«žÇž#ÛžÿžŸ-Ÿ =ŸIŸiŸ€Ÿ•Ÿ©Ÿ®Ÿ ³ŸÀŸNÉŸ 7 U p € ‘ ¢ § ­ 1È ú ¡¡&¡ 7¡ C¡ P¡ [¡h¡q¡‰¡ ’¡  ¡9¬¡Cæ¡*¢Q/¢¢ ‘¢ ž¢¨¢¢Ý¢㢠ö¢£ £ £ %£ 1£ >£ L£ V£ `£ l£ y£o†£Aö¦¢8§nÛ§J¨ZS¨h®¨d©|©%™© ¿© Ë©שÞ©¥ñ©6—ª´Îª_ƒ«ã«¬#¬>¬%X¬ ~¬ ‹¬ •¬ ¬§¬¯¬¸¬À¬@ɬH ­S­Of­M¶­j®›o® ¯¯¯!¯)¯Œ9¯Ưί ׯã¯ô¯ °°&0°-W°…° š°¤°³°È°Û°â°5ê° ±(± 8± B±'N±v± ± œ±¦±o·±'²ž.²GͲT³j³©‰³3´F´"b´…´(¢´2Ë´!þ´> µa_µ+Áµ0íµ¶0¶G¶V¶^¶r¶w¶¶’¶›¶£¶¨¶ ¯¶ »¶ɶ Û¶Eç¶y-·§·Ä·Ë·’ß· r¸}¸‘¸ ¥¸ ²¸ ¼¸ʸÛ¸Y÷¸Q¹`¹ q¹ }¹‰¹’¹—¹§¹ À¹(˹1ô¹%&ºLºUº Zºhºyºº ‘º œº©º¿º Ǻ7Ѻ » »»x,»”¥» :¼ G¼”Q¼æ¼þ¼½½5*½`½X{½tÔ½I¾c¾y¾¾˜¾¬¾¾á¾ ý¾¹¿—¿ZÀ[lÀfÈÀ/Á 5ÁCÁXÁrÁvÁYŠÁ_äÁaD¦ÂÂÂÈÂè ð þ Ã;ÃSÃXÃþ_ÃO^Ä®Ä ³Ä ¾Ä ËÄØÄjçÄRÅ5aÅ —Å¡Å3ªÅ2ÞÅAÆSÇ~gÇ:æÇU!ÈwȓȬÈÂÈ)ÝÈ8É-@ÉnÉS‚ÉÖÉ'îÉÊgÊMÊ7ÏÊ>ËmFËg´ËpÌ̧Ìy­Ì'Í@Í `ÍlÍÍ •Í¶Í%ÉÍ ïÍÎÎ5ÎLÎ jÎ&tΕ›Î11Ï.cÏO’ÏâÏAbФÐyÄÐ2>ÑqÑ‘Ña§Ñ ÒÒ-ÒB1Ò,tÒ¡Ò ¦Ò ³ÒÀÒÞÒ ÷ÒÓ ÓÓ #Ó .Ó:Ó JÓVÓlÓ4uÓªÓ ¹ÓÃÓÇÓÎÓâÓêÓñÓùÓ Ô $Ô0Ô 7Ô CÔOÔiÔ,nÔ ›Ô ¨ÔµÔ¡ÔÔvÕzÕ Õ!œÕ¾Õ ÛÕæÕëÕîÕ%Ö)Ö%/Ö+UÖÖ ™Ö §Ö/´ÖäÖmèÖ~V×Õ×Ü×uä×ÛZØ¡6ÙØÙàÚüÚ ÛÛ Û "Û)0ÛZÛwÛ4€ÛµÛ5ºÛ(ðÛÜ!Ü-8ÜfÜUzÜ6ÐÜÈÝ1ÐÝ~ÞÞ[žßúßà à 0à:à Ià Sà_àcà và ƒààN—àæàîàá. á);áeáuá•áá¬á ´á ¿áÊáÓáãáõá þá â â(â7â=âWVâ ®â¼âÓâÜâñâ ã(ã/ã3ã<ãDãJã Zãfã xã5ƒãs¹ãl-ä&šäÁäÐä áä ïäûåæ-æAæIæeæ kæuæ zæ=†æ&ÄæLëæf8çŸç ¥ç ±ç½çÎçÔç ãçîç õç èè è$è :èGè¯Xè•é–žé%5ê/[ê‹ê)«ê Õê àê\ëê˜Hëáëöë ìC(ìlì‚ì¢ì…ºìm@íx®íd'î-Œîºî ÀîÍîÔî'óî¬ïMÈïGð,^ð‹ð ¡ð«ð¦±ðSXñ ¬ñ‘MòçßòÇóÍóÒóØóEÝó#ô6ôHô_ônôuô*„ô¯ô*·ôâôçôöôþôõ õdõxõ õŽõ §õµõÈõàõøõ ö%ö @öMö`öihöWÒön*÷¤™÷">øƒaøBåø6(ù=_ùù ²ùÀù-Ñùÿùú&3ú/ZúŠú#¤ú*Èúóú÷úûû/2ûQbûU´ûD ü$OüMtüÂü/Ôüýo$ý>”ýÓý êý& þ<2þDoþZ´þ€ÿTÿRåÿ.8.g–-¨;Ö9ZL3§<ÛbP{UÌ_"š‚K(iG’#Ú%þ)$$NŠsUþ)T~™±¸!Òôý  '1: BL\y Œ ‘Ÿ¢©²· ¼ ÆÓÛ àíôø û   ( < A  F S N\ «  ³ ½  Æ Ë Ó Ø  Þ è ð ø þ      + 1 9 B J  S a 9e CŸ ã è ì  ü   - H N T  [ e j o v ~ ‡ Œ ‘ ˜   ŒÖ¼¾wk|{ &¥~ð2Œk”dûÁ(‘d+.¦ŠÛÜg"¡"¡õ„KæÇ{¨!Þ9’‹XÛ(݈C4sÞgü\\€J±xorËu9vEšjz½J±1ž ŸNs%’n,W¦e…^ù÷6»* ×>Ãtg@ÌÀ—e+°Ó/_^Ãiƒç#ø6=Ù”4®èBù¤Šÿx7—i·÷Ÿyœ¤HZ*fŽ„Ú¢ä20c«RUÎA¶ÌìVp4Žé¾1ÐåIh‘òêJ†zï×ö à b:~'Í8Ôy? ƒ5Y¯ßj†¹n»m[-û…œ¸}Ò\)š,m?–j3$uÖ¥!S.;ZN5ôÚCËlNë‰':ÆHŽtºÅr$o ç>Ķñ›tLw@{˜ŒzDC‡µ:!€£ ³Mæ6œü‡á<õú]yDî£öB©¯²ˆQKBK2þ_pPE²u 3ªOYžÐpHø«ìÜ‚ÑQXf=ã#§#ʬ[S˜|8R©s0a‹EI¨Õl9}áe¼Ø߬¿mƒ"SMÝ.Wé(›¡_ÿ~ë)•–Ál þPŠ]q/Xvâ›FÏnžÙÉ8’Íý]óµñ^OÓ­Àê‘èkôLW¸§$†7šUP% Yò„whÈíäðÊo¿bâ…aÇ3‰Òà<1=@Î[‡å—Zr%c? ØŸ}`ó˜G‹ªÅ-bQ¹;“<v'`îdF‚ÂÄV|qIM‰·A*T)íÕ,´>〴a™&q ®0 ï“DˆÉ ;G¢•RÆc–úÈ G°T/ ™F+½U‚T•7 V”xhO-i `&“Ô­ ýAÑL³Ϻ™f5 %s to access version %s security & feature updates, and support. The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"The ", e.g.: "The plugin"The %s's%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is my client's email address%s is my email address%s is the new owner of the account.%s minimum payout amount.%s opt-in was successfully completed.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.Click here to learn more about updating PHP.A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.APIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsAccount is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.ActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.An unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred while trying to toggle the license's white-label mode.An unknown error has occurred.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre both %s and %s your email addresses?Are you sure you want to delete all Freemius data?Are you sure you want to proceed?Are you sure you would like to proceed with the disconnection?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Associate with the license owner's account.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBetaBillingBilling & InvoicesBlockingBlog IDBodyBundleBundle PlanBusiness nameBuy a license nowBuy licenseBy changing the user, you agree to transfer the account ownership to:By disconnecting the website, previously shared diagnostic data about %1$s will be deleted and no longer visible to %2$s.Can't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanChange UserCheckoutCityClear API CacheClear Updates TransientsClick hereClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCommunicationCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeCurrent %s & SDK versions, and if active or uninstalledDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDebug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.Delegate to Site AdminsDelete All AccountsDetailsDiagnostic InfoDiagnostic data will no longer be sent from %s to %s.Disabling white-label modeDisconnecting the website will permanently remove %s from your User Dashboard's account.Don't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload Paid VersionDownload the latest %s versionDownload the latest versionDownloadedDue to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.Duplicate WebsiteDuring the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEmail address updateEnabling white-label modeEndEnter email addressEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used during the purchase and we will resend you the license key.Enter the email address you've used for the upgrade below and we will resend you the license key.Enter the new email addressErrorError received from the server:ExpiredExpires in %sExtensionsExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.For delivery of security & feature updates, and license management, %s needs toFreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFreemius is our licensing and software updates engineFull nameFunctionGet commission for automated subscription renewals.Get updates for bleeding edge Beta versions of %s.Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!Homepage URL & title, WP & PHP versions, and site languageHow do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I Agree - Change UserI can't pay for it anymoreI couldn't understand how to make it workI don't know what is cURL or how to install it, help me!I don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.If you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you skip this, that's okay! %1$s will still work just fine.If you wish to cancel your %1$s plan's subscription instead, please navigate to the %2$s and cancel it there.If you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid clone resolution action.Invalid module ID.Invalid new user ID or email address.Invalid site details collection.InvoiceIs %2$s a duplicate of %4$s?Is %2$s a new website?Is %2$s the new home of %4$s?Is ActiveIs active, deactivated, or uninstalledIs this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.It looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It requires license activation.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's a temporary %s - I'm troubleshooting an issueIt's not what I was looking forJoin the Beta programJust letting you know that the add-ons information of %s is being pulled from an external server.Keep SharingKeep automatic updatesKeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense IDLicense KeyLicense issues?License keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerLong-Term DuplicateMessageMethodMigrateMigrate LicenseMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNames, slugs, versions, and if active or notNetwork BlogNetwork UserNever miss an important updateNever miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.NewNew Version AvailableNew WebsiteNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo - just deactivateNo - only move this site's data to %sNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to get email notifications for security & feature updates, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please enter the license key to enable the debug mode:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires PHP VersionRequires WordPress VersionReset Deactivation SnoozingResultSDKSDK PathSave %sSavedScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSharing diagnostic data with %s helps to provide functionality that's more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to.Simulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSnooze & %sSo you can reuse the license when the %s is no longer active.Social media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart DebugStart TrialStart my free %sStateStay ConnectedStop DebugSubmitSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience.Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you for updating to %1$s v%2$s!Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe following products'The installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$sThe products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$sThe remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn't work, contact the %s's author with the following:This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.This plugin requires a newer version of PHP.This will allow %s toTimestampTitleTo avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.To ensure compatibility and avoid conflicts with your installed plugins and themes.To enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.To provide additional functionality that's relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.TotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser DashboardUser IDUser keyUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View %s StateView Basic %s InfoView Basic Profile InfoView Basic Website InfoView Diagnostic InfoView License EssentialsView Plugins & Themes ListView detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We couldn't load the add-ons list. It's probably an issue on our side, please try to come back in few minutes.We have introduced this opt-in so you never miss an important update and help us make the %s more compatible with your site and better at doing what you need it to.We made a few tweaks to the %s, %sWe'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.We're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)Welcome to %s! To get started, please enter your license key:What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress & PHP versions, site language & titleWordPress.org Plugin PageWould you like to merge %s into %s?Would you like to proceed with the update?YesYes - %sYes - both addresses are mineYes - do your thingYes - move all my data and assets from %s to %sYes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s.Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.Yes, %2$s is a new and different website that is separate from %4$s.You already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have purchased a %s license.You have successfully updated your %s.You marked this website, %s, as a temporary duplicate of %s.You marked this website, %s, as a temporary duplicate of these sitesYou might have missed it, but you don't have to share any data and can just %s the opt-in.You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s.Your %s license was successfully deactivated.Your WordPress user's: first & last name, and email addressYour account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$sYour subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onactivate a license hereactive add-onActiveaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismisscomplete the opt-indatadaysdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,hourhoursinstalled add-onInstalledinterjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew Beta versionnew versionnot verifiednounPricenounPricingoptionalproduct versionVersionproductsrevert it nowsecondssecseems like the key you entered doesn't match our records.send me security & feature updates, educational content and offers.skipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialsubscriptionswitchingthe above-mentioned sitesthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: freemius Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: Last-Translator: Vova Feldman Language-Team: Freemius Team Language: en MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js %s to access version %s security & feature updates, and support. The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$sThe %s's%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.Complete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is my client's email address%s is my email address%s is the new owner of the account.%s minimum payout amount.%s opt-in was successfully completed.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.Click here to learn more about updating PHP.A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.API←➤AccountAccount DetailsAccount is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.ActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.An unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred while trying to toggle the license's white-label mode.An unknown error has occurred.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre both %s and %s your email addresses?Are you sure you want to delete all Freemius data?Are you sure you want to proceed?Are you sure you would like to proceed with the disconnection?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Associate with the license owner's account.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBetaBillingBilling & InvoicesBlockingBlog IDBodyBundleBundle PlanBusiness nameBuy a license nowBuy licenseBy changing the user, you agree to transfer the account ownership to:By disconnecting the website, previously shared diagnostic data about %1$s will be deleted and no longer visible to %2$s.Can't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanChange UserCheckoutCityClear API CacheClear Updates TransientsClick hereClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dProductsCodeCommunicationCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeCurrent %s & SDK versions, and if active or uninstalledDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDebug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.Delegate to Site AdminsDelete All AccountsDetailsDiagnostic InfoDiagnostic data will no longer be sent from %s to %s.Disabling white-label modeDisconnecting the website will permanently remove %s from your User Dashboard's account.Don't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload Paid VersionDownload the latest %s versionDownload the latest versionDownloadedDue to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.Duplicate WebsiteDuring the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEmail address updateEnabling white-label modeEndEnter email addressEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used during the purchase and we will resend you the license key.Enter the email address you've used for the upgrade below and we will resend you the license key.Enter the new email addressErrorError received from the server:ExpiredExpires in %sExtensionsExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.For delivery of security & feature updates, and license management, %s needs toFreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFreemius is our licensing and software updates engineFull nameFunctionGet commission for automated subscription renewals.Get updates for bleeding edge Beta versions of %s.Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!Homepage URL & title, WP & PHP versions, and site languageHow do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I Agree - Change UserI can't pay for it anymoreI couldn't understand how to make it workI don't know what is cURL or how to install it, help me!I don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.If you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you skip this, that's okay! %1$s will still work just fine.If you wish to cancel your %1$s plan's subscription instead, please navigate to the %2$s and cancel it there.If you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid clone resolution action.Invalid module ID.Invalid new user ID or email address.Invalid site details collection.InvoiceIs %2$s a duplicate of %4$s?Is %2$s a new website?Is %2$s the new home of %4$s?Is ActiveIs active, deactivated, or uninstalledIs this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.It looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It requires license activation.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's a temporary %s - I'm troubleshooting an issueIt's not what I was looking forJoin the Beta programJust letting you know that the add-ons information of %s is being pulled from an external server.Keep SharingKeep automatic updatesKeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense IDLicense KeyLicense issues?License keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerLong-Term DuplicateMessageMethodMigrateMigrate LicenseMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNames, slugs, versions, and if active or notNetwork BlogNetwork UserNever miss an important updateNever miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.NewNew Version AvailableNew WebsiteNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo - just deactivateNo - only move this site's data to %sNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to get email notifications for security & feature updates, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please enter the license key to enable the debug mode:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallChangelogDescriptionFAQFeatures & PricingInstallationOther NotesReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires PHP VersionRequires WordPress VersionReset Deactivation SnoozingResultSDKSDK PathSave %sSavedScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSharing diagnostic data with %s helps to provide functionality that's more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to.Simulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSnooze & %sSo you can reuse the license when the %s is no longer active.Social media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart DebugStart TrialStart my free %sStateStay ConnectedStop DebugSubmitSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience.Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you for updating to %1$s v%2$s!Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe following products'The installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$sThe products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$sThe remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn't work, contact the %s's author with the following:This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.This plugin requires a newer version of PHP.This will allow %s toTimestampTitleTo avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.To ensure compatibility and avoid conflicts with your installed plugins and themes.To enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.To provide additional functionality that's relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.TotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionW00tUser DashboardUser IDUser keyUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View %s StateView Basic %s InfoView Basic Profile InfoView Basic Website InfoView Diagnostic InfoView License EssentialsView Plugins & Themes ListView detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We couldn't load the add-ons list. It's probably an issue on our side, please try to come back in few minutes.We have introduced this opt-in so you never miss an important update and help us make the %s more compatible with your site and better at doing what you need it to.We made a few tweaks to the %s, %sWe'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.We're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)Welcome to %s! To get started, please enter your license key:What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress & PHP versions, site language & titleWordPress.org Plugin PageWould you like to merge %s into %s?Would you like to proceed with the update?YesYes - %sYes - both addresses are mineYes - do your thingYes - move all my data and assets from %s to %sYes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s.Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.Yes, %2$s is a new and different website that is separate from %4$s.You already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have purchased a %s license.You have successfully updated your %s.You marked this website, %s, as a temporary duplicate of %s.You marked this website, %s, as a temporary duplicate of these sitesYou might have missed it, but you don't have to share any data and can just %s the opt-in.You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s.Your %s license was successfully deactivated.Your WordPress user's: first & last name, and email addressYour account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$sYour subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal CodeRight onactivate a license hereActive%s cannot run without %s.%s cannot run without the plugin.Heads upallow%s leftActivatingyearAPIDismissDebuggingCongratsBlockedConnectedDownload LatestDownload Latest Free VersionMonthlyExpirationPathSending emailmoAnnualAnnuallyOncePlanNo SecretSDK VersionsLicenseSyncSync LicenseAuthorOffOnbased on %sStart free trialDismissDismisscomplete the opt-indatadaysdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.%s PlanBilled %sBestHeyOopsHey %s,hourhoursInstalledYee-hawlicenseSitesmsnew Beta versionnew versionnot verifiedPricePricingoptionalVersionproductsrevert it nowsecseems like the key you entered doesn't match our records.send me security & feature updates, educational content and offers.skipHmmstart the trialsubscriptionswitchingthe above-mentioned sitesthe latest %s version heretrialTrialDeleteDowngradeEditHideOpt InOpt OutPurchaseShowSkipUpdateUpgrade%s agofreemius/languages/freemius-cs_CZ.mo000064400000107323146725417150013526 0ustar00Þ•»ô QÌ%A%nS%hÂ%d+&S&%ä& ' '"')'6<'´s'_((#ˆ(¬( Æ( Ó( Ý(è(ï(÷())@)R)V)u)•))­)µ) ¾)Ê)Û)ð)** ,*6*E*L*5T*Š* ’*'œ*Ä* Ý*ç*ø*Gÿ*G+©f+,2#,!V,x,Š,™,¡,µ,½,Ð,Ù,á, æ,ô, --/-6-J- ^- k- u-ƒ-”-Y°- .. *.6.?.D.T.(m.%–.:¼.÷.ü. // %/ 0/=/S/[/ `/k/ ~/ ‹/•//·/Í/ã/ì/00 ;0F0 L0Z0a^0À0Æ0æ0 î0 ü0 11þ12 2 %2 22?2jN2¹2 È2Ò2AÛ24U14‡4£4¼4)×485-:5h5|5'”5¼57¿5p÷5h6n6 ‡6“6¦6¼6%Ï6õ6 ý617.97Oh7¸7Ø7î7Bò7,58b8 g8 t88Ÿ8 ¸8Ã8Ê8Ò8 ä8ð8 9 9"9 +95999@9H9O9 V9 b9n9ˆ99‘9!§9É9 æ9ñ9ö9ù9:: ,:::>:E:M:i: o:{: „: :):Ç:ä:4í:";5';(];†;Ž;-¥;Ó;Uç;6=<1t<~¦<%=D=K= [=e=(t=*="È=1ë=+>&I>p>x>Ž>–>¦>Æ>Î>Ý>å>î> ÷>? ?!?0? I?W?n?w?’?™??¦?®? ¾?Ê? Ü?5ç?l@&Š@±@À@Ñ@å@í@ ó@ý@LAfOA¶A ¼AÈAÙA ßA ëAøA BB $B1B BB MB\XBµBÊBÝBCüB@CVC…vCdüC-aDD •D¢D'©D ÑDÛD áD‚EˆEE“EE˜EÞEñEFFF*(FSF*[F^†FåFôFüFGdGmG vGƒG œG©G¼GWÄG"Hƒ?HBÃH6I==I{I IžI-¯IÝIûIJ*+JVJZJcJ$wJœJ>¼JûJ K&3K9ZK<”KbÑKP4LU…L_ÛLš;MKÖM("NGKN#“N%·N)ÝN$OŠ,OU·O) P7P;IP6…P¼PÂPÝPýP$Q8QRQnQŠQ&¨Q*ÏQ7úQ2RIRgR3€R´RÉRßR÷R S*(S1SS…S¡S#µSÙSõST T#T:T OT\TNeT´TÓTñT UU-U1>UpUxUŒUœU ­U ¹U ÆU ÑUÞU öUCVFVQKVV ­V ºVÄVßVåV øVW W W 'W 3W @W NW XW bW nW {W,ˆWXµ[b\eq\f×\>],Z] ‡] •]¡]ª]4½]Ùò]bÌ^/_!M_o_ €_ Ž_œ_ ¡_ ¬_¶_¿_WÈ_ `$`-`6`=`L` Q` [`h`{``ª`¼` Ù`å`ú`aD aQaXa `aa “a¡a·aOÀab´+bàb.ùb(cDcac xc‚c  cªc ½cÉcÑc ×cäcùc*d3d;dWdld…d Žd ™d§dt¼d1eAe Vedemete"ˆe8«e=äe"f+f0fEfMfafifyff“f ™f¥f ¹f ÄfÑfÙfôfg ,g6g Igjgˆg‘g—g¨go®gh$h @hJhYhihphvh”i›i ³i ÀiÍijÜi Gj UjbjTij¾km×kEl0^l$l´l9Ól% m3mJm!_mm.„mw³m+n1n KnVnon„n.™nÈn Ðn!Ün+þnC*onoŠožo]¥oGp KpUpkp)}p"§pÊpßpæpîpqq)q;q [q gqqqyq€qˆqq•q ¤q¯qÅqÌqÒq+êq$r ;rFrUrXr mr"yrœr«r®r ½r/Êrúrs s s2s1Fsxs˜s=ŸsÝsAís(/t Xtft3ƒt·tXÑt<*u6gu«žu%Jvpvwv v›v­v¼vÂvÆv Úvävõvývw&w"7wZw!aw ƒww˜wžw¯w¾wÏwæwxx /x9x Sx]x ax mxxxŠxœx °x>¾x…ýx*ƒy ®y»yÕy ñyýyzzyzu•z { {#{>{ C{ P{]{e{t{“{˜{ ª{ µ{qÃ{5| H|!V|@x| ¹|Æ|zâ|^]}+¼}è}ñ}~ ~ )~6~˜=~Ö~Ý~ä~í~Oñ~ Aby Š—1¬Þ$æ €€ +€ 9€E€|M€ Ê€Ô€ä€û€ )b4)—•ÁRW‚=ª‚>è‚'ƒ <ƒJƒ%_ƒ…ƒ–ƒ©ƒ!Ƀëƒïƒ øƒ,„F„9_„™„±„"Ì„/ï„6…‰V…€à…_a†gÁ†»)‡Jå‡+0ˆF\ˆ-£ˆ+ш4ýˆ*2‰¤]‰QŠ2TŠ‡Š¢Š$»ŠàŠ èŠóŠ‹ ‹‹ ‹ ‹ +‹ 8‹C‹,_‹ Œ‹˜‹¡‹©‹È‹Ë‹Ó‹ Û‹æ‹ö‹ ŒŒŒ,ŒCŒIŒQŒYŒiŒpŒ wŒ „ŒYŽŒèŒñŒ +19>A R^nsz€W‚ Úæê Ž ŽŽ 7ŽBŽHŽOŽjŽrŽyŽ ˆŽ•ŽžŽ §Ž ³Ž ÀŽÊŽ²!§é‰w+k‚ <‡nõ¼p’¦C1:t?«‘(Ì Yø ™JÔcyi&¶AQŒ_¤›4iZrDÿô$æ¶Uª= xš`¦;?U¢^— ÞR|­XÓ¨ë.¤W)XÈ jk@=§Ž#džE2ù6ÙvÚ'טV…ˆ¡~ ˜*Ø÷!dVš™”nè¥Nz}±rçÛ¡g¢oû`%@Bó5©‹€äpH¸cvasjœ†ŸŒS²«•It9Å·ú´Ç“4ÜÏ7³½‡h/W»ý¹K{T¾ö0„u‰ l^¿Õ–~3eåfo6€YŽªIáÊÁG-´y—>†ÎHm[ï+ì{L ¬ |Ã28z±#NbAòŸ&M.;:FS e’s£g„fî Ò¯ƒMDþ¯°h©­ •–‚) ZàTCµ¥Ý»<Ш]Eu,®ºL_“8‹íqP*ml£}\…wËÖK(”'>]"ÄO9êOQŠ¹aÉb›ž7ƒ¬µ1%\°®Jâ,xq/"Rº$ã5ü¸ñ0ˆ3·ŠÑÆßPð-À³Bœ[‘FGÍ %s to access version %s security & feature updates, and support. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is the new owner of the account.%s minimum payout amount.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.APIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate this add-onActivatedAdd Ons for %sAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAffiliateAfter your free %s, pay as little as %sAgree & Activate LicenseAll TypesAllow & ContinueAmountAn unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonymous feedbackAre you sure you want to delete all Freemius data?Are you sure you want to proceed?Auto renews in %sAverage RatingAwesomeBecome an affiliateBillingBilling & InvoicesBlockingBlog IDBodyBusiness nameBuy a license nowBuy licenseCan't find your license key?CancelCancel %s & ProceedCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanCheckoutCityClear API CacheClear Updates TransientsClick here to use the plugin anonymouslyClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryDateDeactivateDeactivate LicenseDeactivationDebug LogDetailsDon't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload the latest %s versionDownload the latest versionDownloadedEmailEmail addressEndEnter the email address you've used for the upgrade below and we will resend you the license key.ErrorError received from the server:ExpiredExpires in %sExtra DomainsFileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.FreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFull nameFunctionGreat, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again.Have a license key?How do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I can't pay for it anymoreI couldn't understand how to make it workI don't know what is cURL or how to install it, help me!I don't like to share my information with youI found a better %sI no longer need the %sI only needed the %s for a short periodIDIf you have a moment, please let us know why you are %sIf you'd like to use the %s on those sites, please enter your license key below and click the activation button.In %sInstall Free Version NowInstall NowInstall Update NowInstalling plugin: %sInvalid module ID.Invalid new user ID or email address.InvoiceIs ActiveIt looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It's not what I was looking forJoin the Beta programKeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense KeyLicense issues?License keyLicense key is empty.LifetimeLocalhostLogLoggerMessageMethodModuleModule PathModule TypeMore information about %sNameNewNew Version AvailableNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo - just deactivateNo IDNo credit card requiredNo expirationO.KOpt InOpt OutOpt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please enter the license key to enable the debug mode:Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleReviewsPluginsPlugins & Themes SyncPremiumPremium versionPremium version already active.PricingPrivacy PolicyProceedProductsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackRe-send activation emailRenew licenseRenew your license nowRequestsRequires WordPress VersionResultSDKSDK PathSave %sScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySingle Site LicenseSite IDSitesSkip & %sSlugSorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart TrialStart my free %sStateSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a new version of %s available.TimestampTitleTo enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:TotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUp to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser DashboardUser IDUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View detailsView paid featuresWarningWe couldn't find your email address in the system, are you sure it's the right address?We made a few tweaks to the %s, %sWe'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.We're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)Welcome to %s! To get started, please enter your license key:What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?WordPress.org Plugin PageWould you like to proceed with the update?YesYes - %sYes - do your thingYou already utilized a trial before.You are just one step away - %sYou do not have a valid license to access the premium version.You have a %s license.You have purchased a %s license.You have successfully updated your %s.Your account was successfully activated with the %s plan.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$sYour subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal CodeaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.allowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %sclose a windowDismissclose windowDismissdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,interjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew Beta versionnew versionnot verifiednounPricenounPricingproduct versionVersionsecondssecsend me security & feature updates, educational content and offers.skipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialsubscriptionswitchingthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Karolína VyskoÄilová , 2019-2022 Language-Team: Czech (Czech Republic) (http://www.transifex.com/freemius/wordpress-sdk/language/cs_CZ/) Language: cs_CZ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3; X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js %s pro přístup k verzi %s zajiÅ¡Å¥ující podporu a nejen bezpeÄnostní aktualizace. Placená verze %1s je již nainstalována. Aktivujte jí, abyste mohli těžit z %2s funkcí. %3s%1s okamžitÄ› zastaví vÅ¡echny budoucí opakující se platby a licence k plánu %s vyprší za %s.%1$s okamžitÄ› zastaví vÅ¡echny budoucí opakující se platby a licence k plánu %s vyprší za %s.DokonÄit aktivaci „%s“Rozšíření %s bylo úspěšnÄ› zakoupeno.%s instalací%s licencíPÅ™ed %s%s a jeho doplňky%s provizi, když zákazník zakoupí novou licenci.%s bezplatná zkuÅ¡ební verze byla úspěšnÄ› zruÅ¡ena. Jelikož toto rozšíření nenabízí bezplatnou verzi, bylo automaticky deaktivováno. Chcete-li jej v budoucnu používat, budete si muset zakoupit licenci.%s je pouze prémiové rozšíření. PÅ™ed aktivací pluginu si musíte nejprve zakoupit licenci.%s je nový vlastník úÄtu.%s minimální Äástka výplaty.%s nebo vyšší%s hodnocení%s hodnocení%s s%s hvÄ›zda%s hvÄ›zd%s krát%s krát%s pro přístup k verzi %s zajiÅ¡Å¥ující podporu a nejen bezpeÄnostní aktualizace.API←➤ÚÄetDetaily úÄtuAkceAktivovatAktivovat %sAktivovat %s plánAktivovat %s funkceAktivovat bezplatnou verziAktivovat licenciAktivovat toto rozšířeníAktivovanýRozšíření pro %sDoplnÄ›kDoplňkyRozšíření musí být nasazeno na WordPress.org nebo na Freemius.AdresaPartnerPo bezplatné %s platit jen v %sAktivovat licenciVÅ¡echny typyPovolit a pokraÄovatČástkaBÄ›hem nastavování uživatelského beta módu doÅ¡lo k neoÄekávané chybÄ›.DoÅ¡lo k neznámé chybÄ›.Aktualizováním na Beta verzi nahradíte nainstalovanou verzi %s nejnovÄ›jším vydáním Beta verze - používejte s opatrností a ne na produkÄních webech. Varovali jsme vás.Anonymní zpÄ›tná vazbaOpravdu chcete smazat veÅ¡kerá Freemius data?Opravdu chcete pokraÄovat?Automaticky se obnoví za %sPrůmÄ›rné hodnoceníÚžasnýStaňte se naším afiliátemFakturaceFakturace a platbyBlokováníBlog IDTÄ›loJméno firmyKoupit licenci nyníKoupit licenciNemůžete najít svůj licenÄní klíÄ?ZruÅ¡itZruÅ¡it %s > pokraÄovatZruÅ¡it pÅ™edplatnéZruÅ¡it zkuÅ¡ební verziZruÅ¡enaRuším %sRuším %s...Ruším pÅ™edplatnéZruÅ¡ení zkuÅ¡ební verze okamžitÄ› zablokuje přístup ke vÅ¡em prémiovým funkcím. Opravdu chcete pokraÄovat?ZmÄ›nit licenciZmÄ›nit vlastnictvíZmÄ›nit plánPokladnaMÄ›stoVyÄistit API cacheVyÄistit transitenty aktualizacíKliknÄ›te zde pro anonymní používání tohoto pluginuKliknÄ›te pro zobrazení plné velikosti snímku obrazovky %dProduktyKódKompatibilní až poKontaktKontaktovat podporuSupportPÅ™ispÄ›vateléNelze aktivovat %s.ZemÄ›DatumDeaktivovatDeaktivovat licenciDeaktivaceLadící logDetailyNemáte licenÄní klíÄ?PÅ™ispÄ›jte na tento pluginSnižuji vaÅ¡e pÅ™edplatnéStáhnoutStáhnout verzi %sStáhnout nejnovÄ›jší verzi %sStáhnout nejnovÄ›jší verziStaženoEmailEmailová adresaKonecZadejte emailovou adresu použitou pÅ™i objednávce, abychom vám na nÄ›j mohli znovu poslat licenÄní klíÄ.ChybaChyba pÅ™ijatá ze serveru:VyprÅ¡eloVyprší za %sDalší doménySouborFiltrAby bylo vyhovÄ›no WordPress.org pokynům, pÅ™ed zahájením zkuÅ¡ebního období vás žádáme, abyste se rozhodli pro uživatele a necitlivé informace o webu, aby %s umožňoval periodicky odesílat data do %s za úÄelem kontroly aktualizací verzí a ověření zkuÅ¡ební verze.ZdarmaZkuÅ¡ební verze zdarmaVerze zdarmaFreemius APIFreemius DebugFreemius SDK nemohl najít hlavní soubor pluginu. S aktuální chybou se obraÅ¥te se na sdk@freemius.com.Stav FreemiusCelé jménoFunkceVýbornÄ›, nainstalujte prosím cURL a povolte ji v souboru php.ini. Dále vyhledejte v souboru php.ini direktivu 'disable_functions ' a odeberte vÅ¡echny zakázané metody zaÄínající na "curl_". Chcete-li se ujistit, že byla úspěšnÄ› aktivována, použijte 'phpinfo() '. Jakmile je aktivován, deaktivujte %s a znovu jej aktivujte.Máte licenÄní klíÄ?Jak se vám líbí %s? Otestujte vÅ¡echny naÅ¡e %s nadstandardní funkce s %d-denní zkuÅ¡ební verze zdarma.Jak nahrát a aktivovat?Jakým způsobem budete mé produkty propagovat?je drahý a nemohu si ho už dovolitNedokázal jsem jej zprovoznitNevím, co je cURL nebo jak jej nainstalovat, pomozte mi!Nechci s vámi sdílet své informacenaÅ¡el jsem lepší %sjiž nepotÅ™ebuji %spotÅ™eboval jsem %s jen doÄasnÄ›IDMáte-li chvilku, dejte nám vÄ›dÄ›t, proÄ %sPokud chcete použít %s na tÄ›chto stránkách, zadejte platný licenÄní klÃ­Ä a kliknÄ›te na tlaÄítko aktivovat.Za %sNainstalovat verzi zdarmaInstalovatNainstalovat aktualizaciInstaluji plugin: %sNeplatné ID modulu.Neplatné ID uživatele nebo emailová adresa.FakturaJe aktivníLicenci se nepodaÅ™ilo aktivovat.Deaktivace licence pravdÄ›podobnÄ› selhala.ZkuuÅ¡ební režim už vám skonÄil, takže už není co ruÅ¡it :)Není to to, co jsem hledalOdebírat betaverzeKlíÄDejte nám prosím vÄ›dÄ›t, co nefungovalo, aÅ¥ to můžeme opravit pro další uživatele...Dejte nám prosím vÄ›dÄ›t z jakého důvodu, aÅ¥ to můžeme zlepÅ¡it.PosledníPoslední aktualizacePoslední licenceNainstalována nejnovÄ›jší verze zdarmaNainstalována nejnovÄ›jší verzePÅ™eÄtÄ›te si víceDélkaLicenceLicenÄní smlouvaLicenÄní klíÄProblémy s licencí?LicenÄní klíÄLicenÄní klÃ­Ä je prázdný.DoživotníLocalhostZáznamLoggerZprávaMetodaModulCesta k moduluTyp moduluVíce informací o %sJménoNovýNová verze k dispoziciNovÄ›jší verze zdarma (%s) nainstalovánaNovÄ›jší verze (%s) nainstalovánaNewsletterNásledujícíNeNe - jen deaktivovatŽádné IDKreditní karta není vyžadovánaBez vyprÅ¡eníOKZúÄastnit seOdhlásit seZúÄastnÄ›te se, aby byl "%s" jeÅ¡tÄ› lepší!jinéE-mail vlastníkaID vlastníkaJméno vlastníkaKompatibilní s PCIPlacený doplnÄ›k musí být nasazen na Freemius.E-mailová adresa úÄtu PayPalPlatbyVyplácení probíhá pÅ™es PayPal jednou za mÄ›síc a v USD.Druh ÄlenstvíPlán %s neexistuje, proto nemůžete používt zkuÅ¡ební verzi.Plán %s nepodporuje zkuÅ¡ební období.ID ÄlenstvíKontaktujte nás prosím zdeKontaktujte nás prosím s následující zprávou:StáhnÄ›te si prosím %s.Zadejte licenÄní klíÄ, který najdete v emailu odeslaném po provedení objednávky:Pro povolení módu ladÄ›ní chyb zadejte licenÄní klíÄ.DokonÄete upgrade provedením následujících krokůVyberte si, jestli chcete být informování o bezpeÄnostních aktualizacích, vylepÅ¡ení funkcionality, vzdÄ›lávacímu obsahu nebo obÄasných obchodních nabídkách:Zadejte prosím jméno a příjmení.PluginHlavní stránka pluginuID pluginuInstalace pluginuHistorie zmÄ›nPopisFAQVlastnosti a ceníkInstalaceVaÅ¡e hodnoceníPluginyPluginy a synchronizace Å¡ablonPrémiumPrémiová verzePrémiová verze je již aktivní.CeníkZásady ochrany osobních údajůPokraÄovatProduktyOkresVeÅ™ejný klíÄKoupit licenciZakoupit dalšíRychlá zpÄ›tná vazbaZnovu poslat aktivaÄní emailObnovit licenciObnovte svou licenci teÄŽádostiVyžaduje verzi WordPressVýsledekSDKCesta l SDKUložit %sPlánované cronySnímky obrazovkyHledat podle adresyTajný klíÄZabezpeÄená stránka HTTPS %s spuÅ¡tÄ›ná z externí doményOmlouváme se, ale mÄ›li jsme nÄ›jaký doÄasný problém se zruÅ¡ením vaší zkuÅ¡ební licence. Zkuste to znovu za nÄ›kolik minut.PravdÄ›podobnÄ› máte nejnovÄ›jší verzi.Vyberte zemiOdeslat licenÄní klíÄLicence pro jednu instalaciID stránkyWebyPÅ™eskoÄit & %sZkratkaOmlouváme se za způsobené nepříjemnosti, ale když se nám dáte Å¡anci, tak se vám ze vÅ¡ech sil pokusíme pomoci.Omlouváme se, ale aktualizaci emailu jsem nemohli dokonÄit. Uživatel s vámi zadaným emailem už je registrován.ZaÄátekZaÄít TrialZaÄít můj bezplatný %sKrajOdeslat & %sPÅ™edplatnéPodporaFórum podporySynchronizovat data ze serveruDIÄŒPodmínky službyDÄ›kujeme!DÄ›kujeme %s!DÄ›kujeme za potvrzení zmÄ›ny vlastnictví. Email byl právÄ› odeslán na adresu %s, ke koneÄnému schválení.%s rozbil můj web%s nefungoval%s nefungoval podle oÄekávání%s je skvÄ›lý, ale potÅ™ebuji funkci, kterou není podporovaná%s nefunguje%s náhle pÅ™estal pracovatProces instalace byl zahájen a může trvat nÄ›kolik minut. PoÄkejte prosím na dokonÄení - neobnovujte tuto stránku.BalíÄek remote pluginů neobsahuje složku s žádoucím "slug" a pÅ™ejmenování nefunguje.Aktualizace %s byla úspěšnÄ› dokonÄena.Å ablonaZmÄ›na Å¡ablonyÅ ablonyJe k dispozici nová verze %s.Datum a ÄasNadpisPro zapnutí módu ladÄ›ní chyb zadejte tajný klÃ­Ä vlastníka licence (uživatel s ID = %d), který najdete v sekci "Můj profil" vaší nástÄ›nky.CelkemMÄ›stoZkouÅ¡kaTypNelze se pÅ™ipojit k systémovému souboru. PotvrÄte prosím svá pověření.Neomezené množství instalacíNeomezené aktualizaceAž pro %s webůAktualizovatAktualizovat licenciAktualizace, oznámení, marketing, žádný spamUpgradeNahrát a aktivovat stáhnutou verziCože?Uživatelská nástÄ›nkaID uživateleUživateléHodnotaOvěřovací zpráva byla právÄ› odeslána na email %s. Pokud ji nenajdete do 5 min, zkontrolujte prosím složku pro spam.OvěřenoOvěřit e-mailByla vydána verze %s.Zobrazit podrobnostiZobrazit placené funkceVarováníNemohli jsme najít vaÅ¡i e-mailovou adresu v systému, jste si jisti, že je to správná adresa?UdÄ›lali jsme nÄ›kolik vylepÅ¡ení %s, %sZkontaktujeme vaší hostingovou spoleÄnost a zkusíme vyÅ™eÅ¡it tento problém. Na %s dostanete upozornÄ›ní, jakmile budeme vÄ›dÄ›t nÄ›co nového.Jsme rádi, že vám můžeme ukázat integraci Freemiusu i v rámci sítÄ› webů.Statistika o webová stránc, emaiul a sociálních médiích%s vás vítá! Pro zaÄátek zadejte svůj licenÄní klíÄ:Co jste oÄekávali?Jaká funkce?Jaké je vaÅ¡e "%s"?Jakou cenu byste byli ochotni platit?Co jste hledali?Jak se %s jmenuje?Název pluginu na WordPress.orgChcete pokraÄovat v aktualizaci?AnoAno - %sAno - udÄ›lejte, co potÅ™ebujeteO zkuÅ¡ební licenci nelze žádat dvakrát.Jste jen na krok od - %sNemáte platnou licenci pro přístup k prémiové verzi.Máte licenci „%s“.Zakoupili jste licenci %s.ÚspěšnÄ› jste aktualizovali %s.ÚÄet byl úspěšnÄ› aktivován s %s plánem.Váš e-mail byl úspěšnÄ› ověřen - jste skvÄ›lý!Platnost bezplatné zkuÅ¡ební verze vyprÅ¡ela. %1$s Upgradujte nyní%2$s abyste mohli pokraÄovat v používání %3$s bez pÅ™eruÅ¡ení.Platnost bezplatné zkuÅ¡ební verze vyprÅ¡ela. Stále můžete pokraÄovat v používání vÅ¡ech naÅ¡ich bezplatných funkcí.VaÅ¡e licence byla zruÅ¡ena. Pokud si myslíte, že je to chyba, obraÅ¥te se na naší podporu.VaÅ¡e licence vyprÅ¡ela. %1$sObnovte pÅ™edplatné%2$s, abyste mohli mohli %3$s používat bez omezení.VaÅ¡e licence vyprÅ¡ela. Stále vÅ¡ak můžete používat vÅ¡echny funkce verze %s, ale pro získání technické podpory a nejnovÄ›jších aktualizací budete muset obnovit svou licenci.VaÅ¡e licence vyprÅ¡ela. Stále vÅ¡ak můžete free verzi %s bez omezení.VaÅ¡e licence byla úspěšnÄ› aktivována.VaÅ¡e licence byla úspěšnÄ› deaktivována, jste zpÄ›t na plánu %s.VaÅ¡e jméno bylo úspěšnÄ› aktualizováno.VaÅ¡e licence byla úspěšnÄ› aktivována.Váše pÅ™edplatné bylo úspěšnÄ› zmÄ›nÄ›n na %s.Váš plán byl úspěšnÄ› aktualizován.Váš server blokuje přístup k Freemium API, což je zásadní pro synchronizaci %1$s. ObraÅ¥te se na svého poskytovatele , aby pÅ™idal do svého whitelistu %2$sVaÅ¡e pÅ™edplatné bylo úspěšnÄ› zruÅ¡eno. Platnost licence %s vyprší za %s.VaÅ¡e zkuÅ¡ebí verze byla úspěšnÄ› spuÅ¡tÄ›na.PSÄŒ / smÄ›rovací Äíslo%s nelze spustit bez %s.%s nelze spustit bez tohoto pluginu.povolitZbývá %sProbíhá aktivacerokAPISkrýtDebuggingGratulujemeZablokovánoPÅ™ipojenoStáhnÄ›te si nejnovÄ›jšíStáhnÄ›te si nejnovÄ›jší bezplatnou verziMÄ›síÄnÄ›ExpiraceSložkaProbíhá odesílání emailůpoRoÄnÄ›RoÄnÄ›JedenkrátDruh ÄlenstvíTajný klÃ­Ä chybíSDK verzeLicenceSynchronizovatSynchronizovat licenceAutorVypnutoZapnutozaloženo na %sSkrýtSkrýtdeaktivujetedelegovatneposílejte mi bezpeÄnostní aktualizace a vylepÅ¡ení, vzdÄ›lávací obsah a nabídky.%s plánÚÄtováno %sNejlepšíDobrý denJejdaDobrý den %s,JupílicenceWebymsnová Beta verzenová verzenení ověřenoCenaCeníkVerzesposílejte mi bezpeÄnostní aktualizace a vylepÅ¡ení, vzdÄ›lávací obsah a nabídky.pÅ™eskoÄitHmmspustit zkuÅ¡ební verzipÅ™edplatnépÅ™epínámnejnovÄ›jší %s verze zdezkuÅ¡ebníTrialSmazatPÅ™ejít na nižší verziUpravitSkrýtZúÄastnit seOdhlásit seZakoupitZobrazitPÅ™eskoÄitAktualizovatVylepÅ¡itPÅ™ed %sfreemius/languages/freemius-nl_NL.mo000064400000135327146725417150013534 0ustar00Þ•T½Œ €+A+SÃ+%, =, I,U,\,6o,´¦,_[-#»-ß- ù- . ..".*.3.;.@D.H….Î.Oá.1/5/T/t/„/Œ/ •/¡/²/Ç/Ý/&î/-0C0 X0b0q0†0™0 05¨0Þ0æ0 ö0 1' 141 M1 Z1d1ou1å1žì1‹2ž2"º2Ý22ú2!-3aO30±3â3ô3 44"464>4G4O4 T4b4 t4€44¤4’¸4 K5V5j5 ~5 ‹5 •5£5´5YÐ5*696 J6V6_6d6t6(61¶6%è6:7I7N7_7g7 w7 ‚77¥7 ­7·7 ¼7Ç7xÚ7”S8 è8 õ8ÿ89+9t39¨9Â9Ø9î9÷9 :*: F:—Q:[é:fE;¬; ²;À;YÄ;a<€<†<¦< ®< ¼<;Ê<= =þ=> > !> .>;>jJ>µ> Ä>Î>3×> ?~?Už?ô?@)@)D@-n@œ@S°@A'ADAMGA7•AgÍAp5B¦BÀByÆB@CYC yC…C˜C®C ÁCâC êC1ôC.&DOUD¥DA%EygEáEaFcFBgF,ªF×F ÜF éFöFG -G8G?GGG YG eGqG‡G4GÅG ÔGÞGâGéGñGøG HH &H 2H>HXH ]H jHwH{H!‘H³H ÐHÛHàHãH%éH+I;I SI aI/nIžIm¢I~JJ–JžJºJ ÀJÌJ ÕJ àJ)îJK5K4>KsK5xK(®K×KßK-öK$LU8LÈŽL1WM~‰MN[%OO O§O ·OÁO(ÐO*ùO"$P1GP+yP*¥P&ÐPN÷PFQNQdQ.lQ)›QÅQÕQõQýQ R RR(R8RJR SR^RoR~R„RWR õRSS#S>SESISRSZS jSvS ˆS5“SsÉSl=T&ªTÑTàT ñTÿTU1UEUMUiU oUyU&~UL¥UfòUYV _VkV|V ‚V ŽV›V £V±V ÇVÔV•åV–{W/XBX)bX ŒX —X\¢XÿXY'YCFYŠY Y…ÀYdFZ-«ZÙZ ßZìZóZ'[M:[Gˆ[ Ð[Ú[à[æ[ë[ñ[Eö[<\O\a\x\‡\Ž\*\È\*Ð\^û\Z]b]h]dn]Ó] Ü]é] ^^"^i*^W”^"ì^B_6R_‰_ ž_¬_-½_ë_ `&`F```d`$m`M’`à`/ò`"aoBa>²aña&bZ/bTŠbRßb.2c.ac9cZÊc3%d<Ydb–dPùdUJe_ ešfK›f(çfGg#Xg)|g$¦gUËg)!hKh]hzh;h6Ëh>iAiGibi‚i$˜i½i×ióij&-j*Tj7j·jÎjìj3k9kNkdk|kk*­k1Øk l&l#:l^lzlŒl œl¨lÈlßl ôlmN mYmxm–m±mÁmÒm1ãmnn1n An Mn Zn enrn ŠnC–nÚnQßn1o Ao NoXosoyo Œo˜o §o ±o »o Ço Ôo âo ìo öo p pÃpFàs't$Atft vt ƒtŽt6®tâåtqÈu):vdv ƒvvžv¯v¶v ¾vÉv ÑvGÛvM#wqwJ‹wÖwÚwãwìwüwx xx)x?xVx6hx/ŸxÏx äxðxyy 4y @y:Ny‰y y y §y"²yÕy ñy ÿy znzŽz£•z9{,Q{%~{.¤{7Ó{# |{/|?«|ë|}}2};} O} [}g}o} t}} –}&¤}Ë}Ô}´ê} Ÿ~­~Â~Ö~ ì~ ø~u6¬¾ Ò Þèí€,€5K€?€ Á€Ë€Ѐ߀ç€ú€ , 1; AL‚`¯ã “‚ Ÿ‚©‚Ç‚Þ‚æ‚hƒ…ƒƒ½ƒƃ$Ùƒ!þƒ „½+„aé„^K…ª… ±…½…jÃ…~.†­†$²†׆à†ñ†7‡8‡@‡!G‡iˆpˆ „ˆ ’ˆŸˆ{®ˆ*‰:‰I‰>Q‰‰ƒ¬‰f0Š—ŠµŠ'ÍŠ3õŠ?)‹i‹Y~‹Ø‹1ö‹(ŒZ+Œj†ŒhñŒ|Z× ÷zŽ|Ž"—Ž ºŽÈŽÝŽùŽ' 5 =;G>ƒ`Âœ#AÀ˜‘ ›‘]¼‘’‚"’l¥’““,“%=“#c“ ‡“‘“˜“¡“¶“Æ“Ö“ ï“Bú“ =” K”U”Y”`”h”q” Ž”›” ¢” ­”¸”Д Õ”â”ô”ú”*•#?• c•o•x•|•/„•7´•ì•––4$–Y–†^–€å–f—m—u—“—›— «— ·— Å—3Ñ—˜ ˜E+˜q˜Bv˜&¹˜à˜#è˜8 ™E™Y[™æµ™8œš—Õšm›_‹œ#ëœ (3G Wdx ‹—§N¯þ!ž)ž+1ž.]žŒž›ž¸ž ÀžΞ מ ážëžŸ ŸŸ/Ÿ>ŸTŸZŸmzŸèŸúŸ    6 @ D  L W f  y ‡ 8— ‘Р‹b¡3î¡"¢1¢I¢[¢t¢‰¢ž¢¦¢½¢ âÑ¢&Ö¢Sý¢xQ£Ê£Уã£ø£ þ£ ¤ ¤ %¤2¤ R¤]¤¶p¤«'¥HÓ¥*¦8G¦€¦ ‰¦„•¦"§=§ O§Zp§˧ܧ“ú§\Ž¨(먩 ©'© /©+P©P|©AÍ© ªª!ª(ª /ª<ªXAªšª¯ªª Ùª æªðª-«.«(6«_« d« r«}«}„« ¬¬ ¬:¬I¬ c¬dp¬^Õ¬64­Fk­8²­ë­® ®'®E®_®z®•®²®µ®(½®bæ®I¯!X¯(z¯—£¯5;°q°#‰°W­°_±ae±-DZ1õ±4'²\\²,¹²9æ²k ³`Œ³jí³`X´™¹´RSµ%¦µE̵ ¶'3¶![¶V}¶%Ô¶ú¶· ·· ,· M·Z·c· r·|·· …· · ™· §· ³·½·Ï· ï· û·¸ ¸¸ !¸ +¸5¸>¸ C¸ O¸[¸d¸ i¸w¸~¸‚¸†¸–¸ °¸ º¸ ĸ иUÚ¸0¹8¹I¹O¹S¹X¹`¹f¹o¹u¹ x¹†¹˜¹ž¹¦¹­¹L±¹ þ¹º º "º -º;º [º hº uº º‰ºº˜ºŸº§º¬º±º ººĺ ̺Ÿãk…2;‡—`|Üž4¢|®?*rë@¬tÐÔZ"ºGÛ ^î<7Aç”öñ:lƒ˜]Ó;õÇQ¢cËq¦ Ù…°¨iØS«4–\bKBÖ´“‰9L‚êmÈ’â'¾Òô( ×asü¤Iþ=ƒCÛéÕcán¿$!RN 21ð©’ò}8#ûƉw¨UŠßÅ:߶B¯]xC{J<ˆ­²Æq³iÑPåªëÔISHjWW• šX®Tïüö˜7¦ŸÄ3\rÚ‹ó[žœsÖºEíg÷ÐÚ¡†Œ ɽ8¤?»³6vfì›z}Ï+o,äÎ%l£dF„a“ÀM™€.;JpAè·ÝU¼çÌÂïÞQµ0‹úô$Ì£¹w‘,>MRÄjfvþ ýêãVP¶†ýK(°Ãù í¥Œ&`¸Å3¸æ«#×Îy”YÊZî0ÒykæbÁEÙ6L€òš±øDOÕÝäÂ~5&_Ê^©¿åËÏ~œe>@9¯ªnì ù{ÜFàÀ)=Dh§™Ç5-VÓ·Š1à+z)é²pÿÈNÑOHñ"û ˆTÉ[‡øÃX– Þx—Á.¥/½_•eµ‚ð%§Ž'›õ¼t*»!úó͹Y„â/´-duØŽog áG‘ ¡u豬÷ÿh­m %s to access version %s security & feature updates, and support.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is the new owner of the account.%s minimum payout amount.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.APIASCII arrow left icon←ASCII arrow right icon➤Account DetailsActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre you sure you want to delete all Freemius data?Are you sure you want to proceed?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBillingBlockingBlog IDBodyBusiness nameBuy a license nowBuy licenseCan't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanCheckoutCityClear API CacheClear Updates TransientsClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDelegate to Site AdminsDelete All AccountsDetailsDon't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload the latest %s versionDownload the latest versionDownloadedDue to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.During the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEndEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used for the upgrade below and we will resend you the license key.ErrorError received from the server:ExpiredExpires in %sExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.FreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFull nameFunctionGet commission for automated subscription renewals.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!How do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I can't pay for it anymoreI couldn't understand how to make it workI don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid module ID.Invalid site details collection.InvoiceIs ActiveIt looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's not what I was looking forJust letting you know that the add-ons information of %s is being pulled from an external server.KeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense KeyLicense keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerMessageMethodMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNetwork BlogNetwork UserNewNew Version AvailableNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicenseQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires WordPress VersionResultSDKSDK PathSave %sScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSimulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSocial media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart TrialStart my free %sStateSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.TimestampTitleTotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser IDUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We made a few tweaks to the %s, %sWe're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress.org Plugin PageYesYes - %sYou already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have successfully updated your %s.You might have missed it, but you don't have to share any data and can just %s the opt-in.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onactive add-onActiveaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismissdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,interjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew versionnot verifiednounPricenounPricingproduct versionVersionsecondssecsend me security & feature updates, educational content and offers.skipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialsubscriptionswitchingthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Leo Fajardo , 2022 Language-Team: Dutch (Netherlands) (http://www.transifex.com/freemius/wordpress-sdk/language/nl_NL/) Language: nl_NL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js %svoor toegang to versie %s beveiliging & features updates en support.Voltooi "%s" Activatie Nu%s Add-on werd succesvol aangekocht.%s Installaties%s Licenties%s geleden%sen bijbehorende uitbreidingen%s commissie als een klant een nieuwe licentie koopt. %s gratis proefperiode werd succesvol stop gezet. Daar de add-on alleen als premium versie beschikbaar is werd deze automatisch gedeactiveerd. Als u de add-on in de toekomst wilt gebruiken dient u een licentie aan te schaffen.%s is uitsluitend beschikbaar als een premium add-on. Je moet een licentie kopen voordat je de plug-in activeert.%s is de nieuwe eigenaar van het account.%s minimum uitbetalingsbedrag.%s of hoger%s beoordeling%s beoordelingen%s sec%s ster%s sterren%s tijd%s tijden%svoor toegang tot versie %s beveiliging en feature updates en support.%s tracking cookie na eerste bezoek om je verdienpotentieel te maximaliseren.%s betaalde mogelijkheden%sKlik hier%s om de sites te kiezen waar op je de licentie wilt activeren.API←➤AccountgegevensActiesActiveerActiveer %sActiveer %s PlanActiveer %s features.Activeer Gratis VersieActiveer LicentieActiveer licentie op alle in behandeling zijnde sites.Activeer licentie op alle sites in het netwerk.Activeer deze add-onGeactiveerdAdd-ons voor %sUitbreidingen van module %sVoeg nog een domein toeUitbreidingUitbreidingenAdd-on moet op WordPress.org of Freemius geplaatst worden.AdresAdresregel %dAffiliateAffiliatieNa uw gratis %s, betaal slechts %sAkkoord & Activeer LicentieAlle RequestsAlle TypesToestaan & Ga VerderJe kunt dat eventueel ook nu overslaan en de licentie later in je %s netwerk-niveau Account pagina activeren. BedragEen geautomatiseerde download en installatie van %s (betaalde versie) van %s zal starten binnen %s. Als je dit handmatig wil doen, klik dan nu op de annuleer knop.Anonieme terugkoppelingPas toe op alle in behandeling zijnde sites.Pas toe op alle sites in het netwerk.Meld je aan om een affiliate partner te wordenWeet u zeker dat u alle Freemius data wilt verwijderen?Weet je zeker dat je wilt doorgaan?Omdat wij 30 dagen reserveren voor eventuele terugstortingen, betalen we alleen commissies uit die ouder dan 30 dagen zijn.Automatische installatie werkt alleen voor opted-in gebruikers.Auto hernieuwd over %sAutomatische InstallatieGemiddelde BeoordelingGeweldigWordt een affiliateFactureringGeblokkeerdBlog IDBodyBedrijfsnaamKoop nu een licentieKoop licentieKan je je licentiesleutel niet vinden?AnnuleerAnnuleer %s & Ga DoorAnnuleer %s - Ik heb niet meer enige beveiligings- en uitbreidingsupdates of ondersteuning voor %s nodig, omdat ik niet van plan ben de %sop deze of enige andere site te gebruiken.%s annuleren?Annuleer InstallatieAbonnement OpzeggenProefperiode OpzeggenGeannuleerdAnnuleren %s%s wordt geannuleerd...Het abonnement annulerenHet stopzetten van de proefperiode zal de toegang tot de premium features onmiddellijk blokkeren. Weet je dat zeker?Verander LicentieEigendom OverdragenWijzig PlanAfrekenenStadAPI-Cache LeegmakenUpdates Transients OpschonenKlik hier om de plug-in anoniem te gebruikenKlik om reviews te bekijken met een beoordeling van%sKlik voor het op volle-grootte bekijken van schermafbeelding %dProductenCodeCompatible totContactContacteer SupportContacteer OnsMedewerkersKon %s niet activeren.LandCron TypeDatumDeactiveerDeactiveer LicentieHet deactiveren en deïnstalleren van de %s zal de licentie automatisch uitschakelen, die je dan kan gebruiken op een andere site.Deactiveren van je licentie zal alle premium features blokkeren, maar geeft je de mogelijkheid de licentie op een andere site te activeren. Weet je zeker dat je wilt doorgaan?DeactivatieDebug LogDelegeren aan Site BeheerdersVerwijder All AccountsDetailsAnnuleer %s niet - Ik wil nog steeds zowel beveiligings- en uitbreidingsupdates ontvangen als contact kunnen opnemen met Support.Heb je geen licentiesleutel?Doneer aan deze plug-inJe plan naar beneden bijstellenDownloadDownload %s VersieDownload de meeste recente %s versieDownload de meeste recente versieGedownloadAls gevolg van het overtreden van onze affiliate voorwaarden, hebben we besloten je affiliate account tijdelijk te blokkeren. Neem voor eventuele vragen alsjeblieft contact op met support.Tijdens het update proces detecteerden we %dsite(s) waarvoor de licentie nog niet geactiveerd is.Tijdens het update proces detecteerden we %dsite(s) in het netwerk die jouw aandacht vereisen.E-mailE-mailadresEindeVoer de domeinnaam in van je website of andere websites waar vanaf je van plan bent de %ste gaan promoten.Voer hieronder het e-mailadres in dat je gebruikt hebt voor de upgrade en we zullen je jouw licentiesleutel opnieuw toesturen.FoutFoutmelding ontvangen van de server:VerlopenVerloopt over %sExtra DomeinenExtra domeinen vanaf waar je het product gaat promoten.BestandFilterVoordat we de proefperiode kunnen starten, vragen we je, in overeenstemming met de Wordpress.org-richtlijnen, in te stemmen je gebruikers- en niet-sensitieve site informatie door de %s periodiek te laten verzenden naar %s om te controleren op nieuwe versies en je proefversie te valideren.GratisGratis ProefperiodeGratis versieFreemius APIFreemius DebugFreemius SDK kon het hoofdbestand van de plug-in niet vinden. Neem a.j.b. contact op met sdk@freemius.com m.b.t. deze fout.Freemius StatusVolledige naamFunctieKrijg een commissie voor automatische abonnementsverlengingen.Heb je een licentiesleutel?Hey, wist je dat %s een samenwerkingsprogramma heeft? Als je de %s goedvindt, kun je onze ambassadeur worden en wat geld verdienen!Hoe bevalt %s tot dusver? Test al onze %s premium features gedurende een%d-daagse gratis proefperiode.Hoe te uploaden en activeren?Hoe ga je ons promoten?Ik kan er niet langer meer voor betalenIk snapte niet hoe ik het aan het werk kon krijgen.Ik vind het niet prettig om mijn informatie met jullie te delenIk vond een beter %sIk heb mijn account geüpgraded maar als ik probeer te Synchroniseren blijft het plan %s.Ik heb de %s niet meer nodig Ik had de %s alleen nodig voor een korte periode.IDAl je er op klikt, zal deze beslissing gedelegeerd worden aan de beheerders van de sites. We zouden het zeer op prijs stellen, als je even hebt, om ons alsjeblieft te laten weten waarom je gaat %sAls je het eigendom van het %s account wilt overdragen aan %s, klik dan op de Eigendom Overdragen knop. Als je de %s op deze sites wil gebruiken, voer dan alsjeblieft de licentiesleutel hieronder in en klik op de activatie-knop.Belangrijke Upgrade Mededeling:Binnen %sMocht je NIET van plan zijn om deze %s te gebruiken op deze site (of op een andere site) - wil je dan het %s ook opzeggen?Installer Gratis Versie NuInstalleer Gratis Versie Update NuInstalleer NuInstalleer Update NuInstalleren van plug-in: %sOngeldige Module-IDOngeldige verzameling van Site Details.FactuurIs ActiefHet lijkt erop dat de licentie niet geactiveerd kon worden.Het lijkt erop dat het deactiveren van je licentie mislukt is.Het lijkt er op dat u niet langer meer in de proefperiode zit, dus er valt niets stop te zetten.Het lijkt erop dat u nog steeds op het %s plan zit. Als u uw plan geüpgraded of veranderd heeft, dan is het waarschijnlijk een fout aan onze kant - sorry.Het lijkt erop dat je site momenteel geen actieve licentie heeft.Het lijkt erop dat een van de authenticatie parameters niet klopt. Update je Publieke Sleutel, Geheime Sleutel & Gebruikers ID en probeer het nogmaals. Het is niet waarna ik opzoek wasVoor alle duidelijkheid, de add-ons informatie van %s wordt opgehaald van een externe server.SleutelWil je alsjeblieft zo vriendelijk zijn om te delen wat niet werkte, zodat we dat kunnen verbeteren voor toekomstige gebruikers ...Wilt je alsjeblieft zo vriendelijk zijn om de reden te vermelden, zodat wij verbeteringen kunnen doorvoeren.LaatsteLaatst GeüpdatetLaatste licentieNieuwste Gratis Versie GeïnstalleerdMeest Recente Versie GeïnstalleerdLees meerLengteLicentieLicentieovereenkomstLicentiesleutelLicentiesleutelLicentiesleutel is leeg.LevenslangVind je de %s goed? Word dan onze ambassadeur en verdien cash ;-)Laad DB-optieLocalhostLogLoggerBerichtMethodesZet Opties over naar NetwerkMobiele appsModuleModule PadModuletypeMeer informatie over %sNaamNetwerk BlogNetwerk GebruikerNieuwNieuwe Versie BeschikbaarNieuwere Gratis Versie (%s) GeïnstalleerdNieuwere Versie (%s) GeïnstalleerdNieuwsbriefVolgendeNeeGeen IDGeen verplichting voor %s - opzeggen kan altijdGeen verplichting voor %s dagen - elk moment opzeggen!Geen creditcard nodigGeen verloopdatumNiet-verlopendeGeen van de %s plannen ondersteunt een proefperiode.OkéAls je licentie verloopt kan je nog steeds gebruik maken van de Gratis versie, maar je zal GEEN toegang meer hebben tot de %sfeatures.Als je licentie afloopt, zul je %s niet meer kunnen gebruiken, tenzij je het opnieuw activeert met een geldige Premium-licentie.Opt InOpt OutOpt-in om "%s" te verbeteren!OverigeE-mail EigenaarID EigenaarNaam EigenaarPCI-comformBetaalde add-on moet op Freemius geplaatst worden.PayPal account e-mailadresBetalingenUitbetalingen zijn in USD en worden maandelijks uitgevoerd via PayPalPlanPlan %s bestaat niet, daarom kan proefperiode niet gestart worden.Plan %s ondersteunt geen proefperiode.Plan IDNeem hier a.u.b. contact met ons opNeem a.u.b. contact met ons op met het volgende bericht:A.u.b. %s downloaden.Voer aalsjeblieft de licentiesleutel in die je ontving in de e-mail direct na de aankoop:Voel je alsjeblieft vrij om elke relevante website of social media statistieken met ons te delen, bijvoorbeeld maandelijkse unieke bezoekers, aantal e-mail abonnees , volgers, etc. (we zullen deze informatie vertrouwelijk houden).Volg alsjeblieft deze stappen om de upgrade te voltooienLaat ons alsjeblieft weten als je op de hoogte gehouden wilt worden van beveiliging & feature updates, educatieve content en zo nu en dan aanbiedingen:Onthou alsjeblieft dat we geen oude prijzen voor verlengingen/nieuwe abonnementen na een annulering kunnen aanhouden. Als je in de toekomst besluit om een abonnement handmatig te vernieuwen, zal de nieuwe prijs (na een prijsverhoging die meestal jaarlijks plaatsvindt) worden berekend.Geef alsjeblieft zo gedetailleerd als mogelijk aan hoe je van plan bent om %s te gaan promoten.Geef alsjeblieft je volledige naam.Plug-inPlug-in HomepagePlug-in IDPlug-in InstallatieWijzigingen LogBeschrijvingVeelgestelde VragenFeatures & PrijzenInstallatieAndere NotitiesReviewsPlug-in is 'Serviceware' wat betekent dat het geen premium code versie bevat. Plug-insSynchronisatie Plug-ins & Thema'sPremiumPremium %s versie is succesvol geactiveerd.Premium add-on versie is reeds geïnstalleerd.Premium versiePremium versie reeds actief.PrijzenPrivacybeleidDoorgaanProces-IDProductenProgramma SamenvattingPromotie methodesProvinciePublieke SleutelLicentie KopenSnelle terugkoppelingQuotaActivatiemail opnieuw versturenVerwijs nieuwe klanten naar onze %s en krijg %s commissie op iedere door jou doorverwezen, geslaagde verkoop!Vernieuw licentieVernieuw je licentie nuAanvragenVereiste WordPress-versieResultaatSDKSDK PadBespaar %sGeplande CronsSchermafbeeldingenZoek op adresGeheime SleutelBeveiligde HTTPS %s pagina, loopt via een extern domeinHet lijkt erop, dat we een tijdelijk probleem hebben met het annuleren van je abonnement. Probeer het alsjeblieft over een paar minuten nog eens.Het lijkt er op dat we een tijdelijk probleem hebben met het opzeggen van uw proefperiode. Probeer het a.u.b. over enkele minuten nog eens.Het lijkt erop dat je de meest recente versie hebt.Selecteer LandVerzend LicentiesleutelActiveer DB-OptieSimuleer Netwerk UpgradeSimuleer Trial ActieEnkele Site LicentieSite IDSite opt-in geslaagd. SitesSla over & %sSlugSocial media (Facebook, Twitter, etc.)Sorry voor het ongemak en we zijn er om je te helpen als je daartoe de kans geeft..Sorry, we konden de e-mail update niet voltooien. Een andere gebruiker met hetzelfde e-mailadres is reeds geregistreerd.StartStart ProefperiodeStart mijn gratis %sStaatVerstuur & %sAbonnementOndersteuningSupportforumSynchroniseer Data Vanaf ServerBtw-nummerServicevoorwaardenBedankt voor je aanvraag voor deelname aan ons affiliate programma, helaas, op dit moment hebben we besloten je aanvraag af te wijzen. Probeer het alsjeblieft over 30 dagen nog eens.Bedankt voor je aanvraag voor deelname aan ons samenwerkingsprogramma. We zullen binnen 14 dagen je gegevens doornemen, waarna we je aanvullende informatie zullen sturen.Hartelijk bedankt voor het gebruik van %s en bijbehorende uitbreidingen!Hartelijk bedankt voor het gebruik van %s!Hartelijk bedankt voor het gebruiken van onze producten!Bedankt!Bedankt %s!Bedankt voor het bevestigen van de eigendomsoverdracht. Zojuist is er een e-mail verstuurd naar %s voor de definitieve goedkeuring. De %s maakte mijn site onbruikbaarDe %s werkte nietDe %s werkte niet zoals verwachtDe %s is uitstekend, maar ik heb een specifieke feature nodig die jullie niet ondersteunenDe %s werkt nietDe %s werkte opeens niet meerHet installatieproces is gestart en kan enkele minuten duren om te voltooien. Wacht alsjeblieft totdat dat gebeurt is - deze pagina niet verversen.Het remote plug-in pakket bevat geen folder met de verwachte slug en hernoemen werkte niet. De upgrade van %s is succesvol voltooid.ThemaThema WisselThema'sEr is een %s van %s beschikbaar.Er is een nieuwe versie van %s beschikbaar.Deze plug-in is niet als compatibel aangemerkt voor je huidige WordPress versie.Deze plug-in is nog niet getest met je huidige WordPress versie. TijdstempelTitelTotaalPlaatsProefperiodeTypeToegang tot het bestandssysteem is niet mogelijk. Bevestig alsjeblieft je inloggegevens.Onbeperkte LicentiesOnbeperkte UpdatesOnbeperkte commissies.Tot %s SitesBijwerkenUpdate LicentieUpdates, aankondigingen, marketing, geen spamUpgradeUpload en activeer de gedownloade versieW00tGebruikers IDGebruikersWaardeVerificatiemail zojuist verstuurd naar %s. Als je deze niet binnen 5 min. hebt ontvangen, kijk dan alsjeblieft in je spambox.GeverifieerdVerifieer E-mailVersie %s is vrijgegeven.Bekijk detailsBekijk betaalde kenmerkenWaarschuwingEr is geen actieve licentie gekoppeld aan dat e-mailadres, ben je zeker dat dat het juiste adres is?We konden je e-mailadres niet vinden in het systeem, ben je zeker dat dat het juiste adres is?We hebben een aantal aanpassingen gedaan op de %s, %s We zijn verheugd om Freemius network-level integratie te introduceren.Website, mail, and social media statistieken (optioneel)Wat had je verwacht?Welke feature?Wat is je %s?Welke bedrag zou je ervoor over hebben?Waar was je naar op zoek?Wat is de naam van het %s?Waar ga je de %s promoten?WordPress.org Plug-in PaginaJaJa - %sU heeft reeds een proefperiode gebruikt.U bent 1-klik verwijderd van het starten van uw %1$s-daagse gratis proefperiode van het %2$s plan.Alles is goed!Je draait de %s al in proefmodus.Je bent slechts een stap verwijderd - %sJe kunt nog steeds van alle %s-mogelijkheden genieten, maar je zult geen toegang hebben tot %s veiligheids- en uitbreidingsupdates, noch ondersteuning.Je hebt geen geldige licentie voor de premium versie.Je hebt een %s licentieJe hebt je %s succesvol geüpdatet.Misschien heb je het gemist, maar je hoeft geen gegevens te delen en kunt de opt-in %s.Je hebt reeds ingestemd met onze gebruiks-tracking, wat ons helpt om %s te blijven verbeteren.Je hebt reeds ingestemd met onze gebruiks-tracking, wat ons helpt om deze te blijven verbeteren.Uw %sAdd-on plan werd succesvol geüpgraded. Uw gratis %s proefperiode is succesvol opgezegd. Je account is succesvol geactiveerd met het %s plan.Je samenwerkingsaanvraag voor %s is geaccepteerd! Log in op je samenwerkingsomgeving op: %s.Je affiliate account is tijdelijk geschorst.Je e-mail werd succesvol geverifieerd - je bent GEWELDIG!Je gratis proefperiode is verlopen. %1$sUpgrade nu%2$som de %3$s zonder interrupties te blijven gebruiken. Je gratis proefperiode is verlopen. Je kan nog steeds al onze gratis features blijven gebruiken.Je licentie is geannuleerd. Als je denkt dat dat een fout is, neem dan alsjeblieft contact op met support.Je licentie is verlopen. %1$sUpgrade nu%2$s om de %3$s zonder interrupties te blijven gebruiken.Je licentie is verlopen. Je kan nog steeds alle %s features gebruiken, maar je zal je licentie moeten vernieuwen om weer updates en support te ontvangen.Je licentie is verlopen. Je kan echter de gratis %s voor altijd blijven gebruiken.Je licentie is succesvol geactiveerd.Je licentie is succesvol gedeactiveerd, je bent terug op het %s plan.Je naam is succesvol bijgewerkt.Je plan is succesvol veranderd naar %s.Je plan is succesvol geüpgraded.Je abonnement is succesvol geannuleerd. De licentie van je %s-plan al over %s aflopen.U proefperiode is met succes gestart.PostcodeToppieActiveer%s werkt niet zonder %s.%s werkt niet zonder de plug-in.Aankondigingtoestaan%s beschikbaarActiverenjaarAPIAfsluitenDebuggingGefeliciteerdGeblokkeerdVerbondenDownload NieuwsteDownload Nieuwste Gratis VersieMaandelijksVerloopdatumPadE-mail versturenmndJaarlijksJaarlijksEenmaligPlanGeen GeheimSDK VersiesLicentieSyncSync LicentieAuteurUitAangebaseerd op %sStart gratis proefperidoeAfsluitenAfsluitendeactiverendeligerenstuur mij %sGEEN%s beveiliging & feature updates, educatieve content of aanbiedingen.%s Plan%s gefactureerd BesteHoiOepsHoi %s,HoeralicentieSitesmsnieuwe versieniet geverifieerdPrijsPrijzenVersiesecstuur mij beveiliging & feature updates, educatieve content en aanbiedingen.overslaanHmmstart de proefperiodeabonnementoverschakelende meest recente %s versie hierproefperiodeProefperiodeVerwijderDowngradeBewerkVerbergOpt InOpt OutKoopToonSla OverBijwerkenUpgrade%s geledenfreemius/languages/freemius-de_DE.mo000064400000217517146725417150013474 0ustar00Þ•¡$‹,*X8Y8^8Ad8¢¦8nI92¸9Zë9hF:d¯:S;%h; Ž; š;¦;­;¥À;6f<´<_R=²=Ò=#é= >%'> M> Z> d>o>v>~>‡>>@˜>HÙ>"?O5?M…?jÓ?›>@Ú@Þ@ý@A%AŒ5AÂAÊA ÓAßAðABB&,B-SBB –B B¯BÄB×BÞB5æBC$C 4C >C'JCrC ‹C ˜C¢Co³C#Dž*DGÉDTEfE©…E/FBF"^FF(žF2ÇF!úF>Ga[G+½G0éGH,HCHRHZHnHsH{HŽH—HŸH¤H «H ·HÅH ×HEãHy)I£IÀIÇI’ÛI nJyJJ ¡J ®J ¸JÆJ×JYóJMK\K mK yK…KŽK“K£K ¼K(ÇK1ðK%"L:HLƒL ˆL–L§L¯L ¿L ÊL×LíL õL7ÿL7M 5]mt]gâ]pJ^»^Õ^yÛ^U_n_ Ž_š_­_ Ã_ä_%÷_ `>`F`c`z` ˜`&¢`•É`1_a.‘aOÀabAbÒbyòb2lcŸc¿caÕc 7dDd[dB_d,¢dÏd Ôd ádîd e %e0e7e?e Qe \ehe xe„eše4£eØe çeñeõeüefff'f7f Rf^f ef qf}f—f,œf Éf Öfãf¡g¤g¨g ¾g!Êgìg hhhh%1hWh%]h+ƒh¯h Çh Õh/âhimi~„ij jujÛˆj¡dklm*m 0muDuW]u µuÃuÚuãuøuv/v6v:vCvKvQv avmv v5ŠvsÀvl4w&¡wÈw×w èw öwyy4yHyPyly ry|y y=y&ËyLòyf?z¦z ¬z ¸zÄzÕzÛz êzõz üz {{ {+{ A{N{¯_{•|–¥|%<}/b}’})²} Ü} ç}\ò}˜O~è~ý~C/s‰©…ÁmG€xµ€d.-“Á ÇÔÛ'ú¬"‚MÏ‚Gƒ,eƒ’ƒ ¨ƒ²ƒ¦¸ƒS_„ ³„‘T…çæ…ΆÔ†Ù†߆Eä†*‡=‡O‡f‡u‡|‡*‹‡¶‡*¾‡é‡ø‡ˆ ˆˆdˆzˆ ƒˆˆ ©ˆ·ˆʈâˆúˆ‰'‰ B‰O‰b‰ij‰WÔ‰n,Š¤›Š"@‹ƒc‹Bç‹6*Œ=aŒŸŒ ´ŒÂŒ-ÓŒ&5/\Œ#¦*ÊõùŽ Ž/4ŽQdŽU¶ŽD $QMvÄ/Öo&>–Õ ì& ‘<4‘Dq‘Z¶‘€’T’’Rç’.:“.i“˜“-ª”;Ø”9•ZN•3©•<Ý•b–P}–UΖ_$—š„—K˜(k˜G”˜#ܘ%™)&™$P™Šu™Uš)Vš€š’š¯šÇš;Üš6›>O›Ž›”›¯›Ï›$å› œ$œ@œ\œ&zœ*¡œ7Ìœ93R†›±ÉÝ*ú1%žWžsž#‡ž«žÇžÙž éžõžŸ,ŸAŸUŸZŸ _ŸlŸNuŸÄŸãŸ  , = N S Y 1t ¦ ®  Ò  ã  ï  ü  ¡¡¡5¡ >¡ L¡9X¡C’¡Ö¡Û¡ ë¡ ø¡¢¢7¢=¢ P¢\¢ k¢ u¢ ¢ ‹¢ ˜¢ ¦¢ °¢ º¢ Æ¢ Ó¢±à¢’¦–¦]›¦¾ù¦„¸§=¨vD¨x»¨s4©'¨©%Щö© ªªª¬0ª4ݪÀ«nÓ«'B¬j¬$†¬«¬*Ȭó¬ ­­­#­ ,­6­=­\D­Q¡­ó­[®Mj®ž¸®ÉW¯!°%°.°7° =°®K°ú° ± ±±-±E±e±3y±2­±à± ø±²²'²B²I²FQ²˜² ² ±² »²4Ųú² ³ &³1³G³dz·Î³e†´hì´'Uµ±}µ/¶)A¶%k¶'‘¶+¹¶?å¶*%·2P·vƒ·-ú·G(¸"p¸“¸­¸ ɸÕ¸ä¸ é¸ô¸ ¹¹ ¹)¹ /¹:¹I¹ b¹Wp¹|ȹ/Eº uºº¹™º S»a»x»» £»¯» ¾»Ë»oä»T¼c¼ x¼…¼–¼œ¼¢¼$µ¼ Ú¼+ç¼J½7^½–½Ÿ½ ¤½²½Ľ̽འè½ô½¾¾?¾^¾ d¾q¾’…¾·¿ п Þ¿·è¿  ÀÁÀÖÀÞÀ6ôÀ"+ÁZNÁœ©Á FÂg‚˜¡µÂ$ÔÂ!ùÂÃÈ+ýôòÄhÇÄr0ţŪŹŠÖÅ÷ÅüÅaÆovÆ{æÆbÇ‚Ç‰Ç ¦Ç±Ç ÁÇ ÏÇDÝÇ"È(È%/È`UÉ ¶ÉÀÉ×É êÉ÷É}Ê„ÊG”ÊÜÊðÊBùÊ4<ËtqËæÌ…ÍIŒÍhÖÍ)?ÎiÎ$„ΩÎ3ÉÎJýÎ4HÏ!}ÏkŸÏ Ð8)ÐbÐVeÐY¼Ð_ÑQvÑuÈÑt>Ò…³Ò9ÓXÓ^Ó%ìÓ1ÔDÔWÔqÔ"ŒÔ¯Ô0ÄÔ"õÔÕ!ÕAÕ]Õ |Õ)†Õ´°ÕAeÖB§Ö\êÖ²G×Dú×%?ØeØ2õØ)(ÙRÙtnÙ ãÙ!ñÙ ÚhÚ<‡ÚÄÚËÚ àÚ)îÚÛ 7ÛEÛLÛ SÛ aÛkÛ|ÛŒÛÛ ¼ÛDÇÛ Ü Ü*Ü.Ü5Ü LÜVÜ ^ÜhÜ'yÜ ¡Ü­Ü ³Ü ¾ÜÈÜäÜ/éÜ Ý'Ý(9Ý´bÝÞÞ 3Þ*@ÞkÞ ‹Þ–ÞŸÞ¤Þ4¼ÞñÞ1úÞ6,ßcß‚ß“ß5¤ßÚß|ÝߊZàåàìà¦õà+œáÓÈâRœã#ïäåå )å5å HåETåšå ¶åOÀåæDæ)Zæ„æŒæ2§æÚæ\òæEOçó•ç;‰è˜ÅèS^é]²ê)ë:ëAë Që[ë oë yë†ëŠë žë«ë »ëSÇëì#ì9ì/Aì+qìì­ìÌìÓì éì ôì ÿì íí.íAíIí bí pí|í íšíq¹í+î;îZîcîxî,”îÁîÊîÎî ×î äîðî ÿî ï#ïB7ï‰zï‡ð2Œð¿ðÏðçðBøð;òWòrò „ò ‘ò ²ò¼òÏò ÓòJßò(*ómSó~Áó@ôFôXôkô†ôŒôô¯ô¸ô ÈôÓô âô ðôõ )õæJõ¸1ö¶êö4¡÷2Ö÷ ø-*ø Xø cøzmø¨èø%‘ù·ù*ÕùUúVú*pú›ú‹²ú>û–Ìûscü3×ü ýý ý 'ý+HýÛtýSPþP¤þ,õþ"ÿ ?ÿKÿÒQÿp$·•ÃM#) /;a?¡µÉâóú-=8E~ ‘°¹„¾ COc%”)º+ä/#Nr‚ž‰¦l0‘Ì/4ü1 LÏ 9 HV Ÿ µ Æ 6Ý  , H ;a  &¸ $ß    . CB M† PÔ E% =k i© &'=eFö= U*vD¡Læ_3€“f~{1ú<,Mi.·=æ9$e^2Ä:÷y2q¬diƒží[Œ)èG)Z&„-«'Ù«O­.ý, ?I`f%„ ª´ ½ÇÖÛ ß éõ  !(3 \fo t‚ ‡ ‘›¢§ ÀÎÕÚðöúý! 0 ;FZ` e qV{ÒÚîôøÿ "( /9< N[jpw€ˆ‘¬d®L `n † ‘œ¹ÕÛà é ó þ " +9@HؾÀyl~|Ÿ'§€ñ4Žm”f‘ýÃ*“f-/¨ŒÝÞi#¡$£÷Ÿ†MèÉ}ª#à:’  YÝ*ߊD5uàiý^‘]‚L³yptÍw;xFœk|¿K³3ž Ÿ!Pt'”o.Y¨g‡_ûø8½,!Ù@ÅvhBΙf,²Õ0``Åj… é%ù7?Û–6°êCú¦Œz9™k¹ù¡zœ¦J[,h†ܤæ42e­SWÐB¸ÎîXr6ëÀ2ÒçJj“ôíìLˆƒ|ñÙø â"c<€(Ï:Ö{@ „6Z±ál‡»p½o\/ü†žºÔ^+š-nA˜l5%wا"T0=\O7õÜEÍnP‹)<Jv¼Çs&Žqé?ƸóuNyA}˜Ž{FE‰·;#¥¢µOè8žþ‰ã =öü_{F¥÷D«±´ŠSLDM3ÿaqRG´v 5¬Q[ ÒrIú­îÞ„ÓSZg>å%©$Ì®]Uš~9T« u2cÄŒGKª×n;’~ãg¾Úá®Áo…$U€Oß0ƒXë)£a í+—–ÃmQ‹_s1Zxä›GÑp ÛË:”Ïÿ^ô·ò`QÕ¯Âì‘êmöNYº ©&ˆ9œWÈ!R& [ó…xjÊïæòÌqÁdä‡bÉ4‹Ôâ>3?‚BÐ]ˆç—\t'eA¢Ú¡bõšH¬Ç/dR»=“>w)að eHƒÄÆX}sKNŠ¹C+V*ï×.¶@傶c™(r °1 "ð•E‰Ë <I¤—TÈd˜ûÊ I²U1›H-¿V„V•8 W–ziP.kb(•Ö¯ þC’ÓMµѼ›h7HmmW00t %s to access version %s security & feature updates, and support. The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"The ", e.g.: "The plugin"The %s's%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is my client's email address%s is my email address%s is the new owner of the account.%s minimum payout amount.%s opt-in was successfully completed.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.Click here to learn more about updating PHP.A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.APIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsAccount is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.ActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.An unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred while trying to toggle the license's white-label mode.An unknown error has occurred.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre both %s and %s your email addresses?Are you sure you want to delete all Freemius data?Are you sure you want to proceed?Are you sure you would like to proceed with the disconnection?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Associate with the license owner's account.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBetaBillingBilling & InvoicesBlockingBlog IDBodyBundleBundle PlanBusiness nameBuy a license nowBuy licenseBy changing the user, you agree to transfer the account ownership to:By disconnecting the website, previously shared diagnostic data about %1$s will be deleted and no longer visible to %2$s.Can't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanChange UserCheckoutCityClear API CacheClear Updates TransientsClick hereClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCommunicationCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeCurrent %s & SDK versions, and if active or uninstalledDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDebug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.Delegate to Site AdminsDelete All AccountsDetailsDiagnostic InfoDiagnostic data will no longer be sent from %s to %s.Disabling white-label modeDisconnecting the website will permanently remove %s from your User Dashboard's account.Don't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload Paid VersionDownload the latest %s versionDownload the latest versionDownloadedDue to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.Duplicate WebsiteDuring the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEmail address updateEnabling white-label modeEndEnter email addressEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used during the purchase and we will resend you the license key.Enter the email address you've used for the upgrade below and we will resend you the license key.Enter the new email addressErrorError received from the server:ExpiredExpires in %sExtensionsExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.For delivery of security & feature updates, and license management, %s needs toFreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFreemius is our licensing and software updates engineFull nameFunctionGet commission for automated subscription renewals.Get updates for bleeding edge Beta versions of %s.Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!Homepage URL & title, WP & PHP versions, and site languageHow do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I Agree - Change UserI can't pay for it anymoreI couldn't understand how to make it workI don't know what is cURL or how to install it, help me!I don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.If you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you skip this, that's okay! %1$s will still work just fine.If you wish to cancel your %1$s plan's subscription instead, please navigate to the %2$s and cancel it there.If you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid clone resolution action.Invalid module ID.Invalid new user ID or email address.Invalid site details collection.InvoiceIs %2$s a duplicate of %4$s?Is %2$s a new website?Is %2$s the new home of %4$s?Is ActiveIs active, deactivated, or uninstalledIs this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.It looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It requires license activation.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's a temporary %s - I'm troubleshooting an issueIt's not what I was looking forJoin the Beta programJust letting you know that the add-ons information of %s is being pulled from an external server.Keep SharingKeep automatic updatesKeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense IDLicense KeyLicense issues?License keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerLong-Term DuplicateMessageMethodMigrateMigrate LicenseMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNames, slugs, versions, and if active or notNetwork BlogNetwork UserNever miss an important updateNever miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.NewNew Version AvailableNew WebsiteNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo - just deactivateNo - only move this site's data to %sNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to get email notifications for security & feature updates, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please enter the license key to enable the debug mode:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires PHP VersionRequires WordPress VersionReset Deactivation SnoozingResultSDKSDK PathSave %sSavedScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSharing diagnostic data with %s helps to provide functionality that's more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to.Simulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSnooze & %sSo you can reuse the license when the %s is no longer active.Social media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart DebugStart TrialStart my free %sStateStay ConnectedStop DebugSubmitSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience.Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you for updating to %1$s v%2$s!Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe following products'The installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$sThe products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$sThe remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn't work, contact the %s's author with the following:This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.This plugin requires a newer version of PHP.This will allow %s toTimestampTitleTo avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.To ensure compatibility and avoid conflicts with your installed plugins and themes.To enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.To provide additional functionality that's relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.TotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUser DashboardUser IDUser keyUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View %s StateView Basic %s InfoView Basic Profile InfoView Basic Website InfoView Diagnostic InfoView License EssentialsView Plugins & Themes ListView detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We couldn't load the add-ons list. It's probably an issue on our side, please try to come back in few minutes.We have introduced this opt-in so you never miss an important update and help us make the %s more compatible with your site and better at doing what you need it to.We made a few tweaks to the %s, %sWe'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.We're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)Welcome to %s! To get started, please enter your license key:What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress & PHP versions, site language & titleWordPress.org Plugin PageWould you like to merge %s into %s?Would you like to proceed with the update?YesYes - %sYes - both addresses are mineYes - do your thingYes - move all my data and assets from %s to %sYes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s.Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.Yes, %2$s is a new and different website that is separate from %4$s.You already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have purchased a %s license.You have successfully updated your %s.You marked this website, %s, as a temporary duplicate of %s.You marked this website, %s, as a temporary duplicate of these sitesYou might have missed it, but you don't have to share any data and can just %s the opt-in.You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s.Your %s license was successfully deactivated.Your WordPress user's: first & last name, and email addressYour account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$sYour subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onactivate a license hereactive add-onActiveaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismisscomplete the opt-indatadaysdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,hourhoursinstalled add-onInstalledinterjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew Beta versionnew versionnot verifiednounPricenounPricingoptionalproduct versionVersionproductsrevert it nowsecondssecseems like the key you entered doesn't match our records.send me security & feature updates, educational content and offers.skipstart the trialsubscriptionswitchingthe above-mentioned sitesthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Oliver Heinrich, 2022 Language-Team: German (Germany) (http://www.transifex.com/freemius/wordpress-sdk/language/de_DE/) Language: de_DE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js HmmW00t %s, um auf die Sicherheits- und Funktionsupdates der Version %s und den Support zuzugreifen.Der %sDownload-Link%s, der Lizenzschlüssel und die Installationsanleitung wurden an %s gesendet. Wenn du die E-Mail nach 5 Minuten nicht finden kannst, überprüfe bitte dein Spam-Postfach. Die kostenpflichtige Version von %1$s ist bereits installiert. Bitte aktiviere sie, um von den %2$s Funktionen zu profitieren. %3$sDie %s%1$s wurde in den abgesicherten Modus versetzt, weil wir festgestellt haben, dass %2$s eine exakte Kopie von %3$s ist.%1$s wird sofort alle zukünftigen wiederkehrenden Zahlungen stoppen und deine %2$s Planz-Lizenz wird in %3$s auslaufen.%1$s wird sofort alle zukünftigen wiederkehrenden Zahlungen stoppen und deine %s Plan-Lizenz wird in %s auslaufen.Schließe jetzt die "%s"-Aktivierung ab%s Add-on wurde erfolgreich erworben.%s Installationen%s Lizenzenvor %s%s und seine Add-ons%s automatische Sicherheits- und Funktionsupdates und kostenpflichtige Funktionen funktionieren bis %s (oder bis zum Ablauf deiner Lizenz, je nachdem, was zuerst eintritt).%s Provision, wenn ein Kunde eine neue Lizenz kauft.%s kostenlose Testversion wurde erfolgreich abgebrochen. Da das Add-on nur Premium ist, wurde es automatisch deaktiviert. Wenn du es in Zukunft nutzen möchtest, musst du eine Lizenz erwerben.%s ist ein reines Premium Add-on. Du musst zuerst eine Lizenz erwerben, bevor du das Plugin aktivieren kannst.%s ist die E-Mail-Adresse meines Kunden%s ist meine E-Mail-Adresse%s ist der neue Besitzer des Kontos.%s Mindestauszahlungsbetrag.%s Opt-In wurde erfolgreich abgeschlossen.%s oder höher%s Bewertung%s Bewertungen%s s%s Stern%s Sterne%s mal%s mal%s, um auf die Sicherheits- und Funktionsupdates der Version %s und den Support zuzugreifen.%s Tracking-Cookie nach dem ersten Besuch, um das Ertragspotenzial zu maximieren.Bezahlte Funktionen von %s%sKlicke hier%s um die Webseite auszuwählen, auf denen du die Lizenz aktivieren möchtest.Click here to learn more about updating PHP.Eine Bestätigungs-E-Mail wurde gerade an %s gesendet. Der Besitzer der E-Mail-Adresse muss die Aktualisierung innerhalb der nächsten 4 Stunden bestätigen.Eine Bestätigungs-E-Mail wurde gerade an %s gesendet. Du musst die Aktualisierung innerhalb der nächsten 4 Stunden bestätigen. Wenn du die E-Mail nicht findest, überprüfe bitte deinen Spam-Ordner.API←➤KontoKonto DetailsDie Aktivierung des Kontos steht noch aus. Bitte überprüfe deine E-Mails und klicke auf den Link, um dein Konto zu aktivieren, und sende dann das Affiliate-Formular erneut.AktionenAktivierenAktiviere %sAktiviere %s PlanAktiviere %s FunktionenKostenlose Version freischaltenLizenz freischaltenAktiviere die Lizenz auf allen ausstehenden Seiten.Aktiviere die Lizenz auf allen Seiten im Netzwerk.Aktiviere dieses Add-onAktiviertAdd-Ons für %sAdd-Ons von Modul %sWeitere Domain hinzufügenAdd-onAdd-onsDas Add-on muss auf WordPress.org oder Freemius bereitgestellt werden.AdresseAdresse Zeile %dAffiliateAffiliateNach deinem kostenlosen %s zahlst du so wenig wie %sZustimmen & Lizenz aktivierenAlle AnfragenAlle ArtenErlauben & FortfahrenAlternativ kannst du auch diesen Schritt überspringen und die Lizenz später auf der Netzwerk-Kontoseite deines %s aktivieren.BetragEin automatischer Download und die Installation von %s (kostenpflichtige Version) von %s wird in %s starten. Wenn du es manuell machen möchtest - klicke jetzt auf den Abbruch-Button.Beim Versuch, den Beta-Modus für den Benutzers einzustellen, ist ein unbekannter Fehler aufgetreten.Beim Versuch, auf den White-Label-Modus der Lizenz umzuschalten, ist ein unbekannter Fehler aufgetreten.Ein unbekannter Fehler ist aufgetreten.Ein Update auf eine Beta-Version ersetzt deine installierte Version von %s durch die neueste Beta-Version - verwende sie mit Vorsicht und nur auf Testseiten. Du wurdest gewarnt.Anonymes FeedbackAuf alle ausstehenden Webseiten anwenden.Auf alle Seiten im Netzwerk anwenden.Bewirb dich, um ein Affiliate zu werdenSind %s und %s beide deine E-Mail-Adressen?Bist du sicher, dass du alle Freemius-Daten löschen möchtest?Bist du sicher, dass du fortfahren willst?Möchtest du wirklich mit der Trennung fortfahren?Da wir 30 Tage für mögliche Rückzahlungen reservieren, zahlen wir nur Provisionen aus, die älter als 30 Tage sind.Mit dem Konto des Lizenzinhabers verknüpfen.Die automatische Installation funktioniert nur für eingeloggte Nutzer.Verlängert sich automatisch in %sAutomatische InstallationDurchschnittliche BewertungFantastischPartner werdenBetaAbrechnungAbrechnung & RechnungenBlockierenBlog IDHauptteilPaketPaket-PlanGeschäftsnameJetzt eine Lizenz kaufenLizenz kaufenIndem du den Benutzer wechselst, stimmst du zu, den Besitz des Accounts zu übertragen:Durch das Trennen der Website werden zuvor geteilte Diagnosedaten über %1$sgelöscht und sind für %2$snicht mehr sichtbar.Du kannst deinen Lizenzschlüssel nicht finden?Abbrechen%s abbrechen & fortfahrenAbbrechen %s - Ich benötige keine Sicherheits- und Funktionsupdates mehr und auch keinen Support für %s, da ich nicht vorhabe, das %s auf dieser oder einer anderen Seite zu verwenden.%s abbrechen?Installation abbrechenAbonnement kündigenTestversion abbrechenAbgebrochenAbbruch von %sStoppe %s...Das Abonnement kündigenWenn du die Testversion abbrichst, wird der Zugang zu allen Premium-Funktionen sofort gesperrt. Bist du sicher?Lizenz ändernEigentümer wechselnPlan ändernBenutzer ändernKasseStadtAPI Cache löschenLöschen von Aktualisierungen RestenHier klickenKlicke hier, um das Plugin anonym zu nutzenKlicke, um Bewertungen zu sehen, die eine Bewertung von %s abgegeben habenKlicke, um den Screenshot in voller Größe zu sehen %dProdukteCodeKommunikationKompatibel bis zuKontaktKontaktiere SupportKontaktMitwirkendeKonnte %s nicht aktivieren.LandCron TypAktuelle %sund SDK-Versionen und falls aktiv oder deinstalliertDatumDeaktivierenLizenz deaktivierenWenn du das %s deaktivierst oder deinstallierst, wird die Lizenz hier automatisch deaktiviert und du kannst sie auf einer anderen Seite verwenden.Wenn du deine Lizenz deaktivierst, werden alle Premium-Funktionen gesperrt, aber du kannst die Lizenz auf einer anderen Seite aktivieren. Bist du sicher, dass du fortfahren möchtest?DeaktivierungDebug LogDer Debug-Modus wurde erfolgreich aktiviert und wird in 60 Minuten automatisch wieder deaktiviert. Du kannst ihn auch früher deaktivieren, indem du auf den Link "Stop Debug" klickst.An die Website Admins delegierenAlle Konten löschenDetailsDiagnoseinformationenDiagnosedaten werden nicht mehr von %s bis %sgesendet.Deaktivieren des White-Label-ModusDas Trennen der Website wird %sdauerhaft aus dem Konto Ihres Benutzer-Dashboards entfernt.%s bitte nicht stornieren - ich bin immer noch daran interessiert, Sicherheits- und Funktionsupdates zu erhalten, sowie den Support kontaktieren zu können.Du hast keinen Lizenzschlüssel?Für dieses Plugin spendenDowngrade deinen PlanDownloadDownload %s VersionBezahlte Version herunterladenLade die neueste %s Version herunterLade die neueste Version herunterHeruntergeladenAufgrund der neuen %sEU Datenschutzgrundverordnung (DSGVO)%s Compliance-Anforderungen ist es erforderlich, dass du deine ausdrückliche Zustimmung gibst und damit bestätigst, dass du an Bord bist :-)Aufgrund eines Verstoßes gegen unsere Partnerschaftsbedingungen haben wir beschlossen, dein Affiliate-Konto vorübergehend zu sperren. Wenn du Fragen hast, wende dich bitte an den Support.Duplizierte WebseiteWährend des Update-Prozesses haben wir %d Site(s) entdeckt, die noch auf eine Lizenzaktivierung warten.Während des Update-Prozesses haben wir %s Site(s) im Netzwerk entdeckt, die noch deine Aufmerksamkeit benötigen.E-MailE-Mail-AdresseE-Mail-Adresse aktualisierenAktivieren des White-Label-ModusEndeE-Mail-Adresse eingebenGib die Domain deiner Website oder anderer Webseiten an, von denen aus du planst, %s zu bewerben.Gib die E-Mail-Adresse ein, die Du beim Kauf verwendet hast, und wir senden Dir den Lizenzschlüssel erneut zu.Gib unten die E-Mail-Adresse ein, die du für das Upgrade verwendet hast und wir senden dir den Lizenzschlüssel erneut zu.Gib die neue E-Mail-Adresse einFehlerFehler vom Server empfangen:AbgelaufenLäuft in %s abErweiterungenExtra DomainsZusätzliche Domains, von denen aus du das Produkt vermarkten wirst.DateiFilterUm die Richtlinien von WordPress.org einzuhalten, bitten wir dich vor dem Start der Testversion um ein Opt-In mit deinen Benutzer- und nicht sensiblen Seite-Informationen, damit %s regelmäßig Daten an %s senden kann, um nach Versions-Updates zu suchen und um deine Testversion zu validieren.Für die Bereitstellung von Sicherheits- und Funktionsupdates sowie die Lizenzverwaltung muss %sKostenlosKostenlose TestversionKostenlose VersionFreemius APIFreemius DebugDas Freemius SDK konnte die Hauptdatei des Plugins nicht finden. Bitte kontaktiere sdk@freemius.com mit dem aktuellen Fehler.Freemius StatusFreemius ist unser Dienstleister für Lizenzierung und Software-UpdatesVollständiger NamePositionErhalte Provisionen für automatisierte Abonnementverlängerungen.Erhalte Updates für aktuelle Beta-Versionen von %s.Toll, bitte installiere cURL und aktiviere es in deiner php.ini Datei. Suche außerdem nach der 'disable_functions' Direktive in deiner php.ini Datei und entferne alle deaktivierten Methoden, die mit 'curl_' beginnen. Um sicherzustellen, dass sie erfolgreich aktiviert wurde, benutze 'phpinfo()'. Danach aktiviere, deaktiviere das %s und aktiviere es anschließend wieder.Hast du einen Lizenzschlüssel?Hallo, wusstest du, dass %s ein Partnerprogramm hat? Wenn du die %s magst, kannst du unser Affiliate werden und etwas Geld verdienen!URL und Titel der Homepage, WP- und PHP-Versionen und Sprache der WebsiteWie gefällt dir %s bis jetzt? Teste alle %s-Premium-Funktionen mit der kostenlosen %d-Tage-Testversion.Wie kann ich es hochladen und aktivieren?Wie wirst du uns bewerben?Ich stimme zu - ändere den BenutzerIch kann es nicht mehr bezahlenIch habe nicht gewusst wie ich es zum Laufen bringeIch weiß nicht, was cURL ist oder wie man es installiert. Bitte hilf mir!Ich möchte meine Informationen nicht mit dir teilenIch habe ein besseres %s gefundenIch habe mein Konto hochgestuft, aber wenn ich versuche, die Lizenz zu synchronisieren, bleibt der Plan %s.Ich brauche das %s nicht mehrIch habe das %s nur für einen kurzen Zeitraum benötigtIDWenn dies ein langfristiges Webseiten-Duplikat ist, dann brauchst du nach %s bitte %s.Wenn du es anklickst, wird diese Entscheidung an die Administratoren der Seite delegiert.Wenn du einen Moment Zeit hast, lass uns bitte wissen, warum du das Plugin deaktivieren willst:Wenn Du das überspringst, ist das in Ordnung! %1$swird immer noch funktionieren.Wenn Du stattdessen das Abonnement deines %1$sPlans kündigen möchtest, navigiere bitte zu %2$sund kündige es dort.Wenn du die Eigentümerschaft des Kontos von %s an %s abgeben möchtest, klicke auf den Button Eigentümer wechseln.Wenn du das %s auf diesen Seiten nutzen möchtest, gib bitte deinen Lizenzschlüssel unten ein und klicke auf den Aktivierungsbutton.Wichtiger Hinweis zum Upgrade:In %sFür den Fall, dass du NICHT vorhast, diesen %s auf dieser Seite (oder einer anderen Seite) zu verwenden - möchtest du den %s auch löschen?Kostenlose Version jetzt installierenUpdate der kostenlosen Version jetzt installierenJetzt installierenUpdate jetzt installierenInstalliere das Plugin: %sUngültige Klon-Auflösungsaktion.Ungültige Modul-ID.Ungültige neue Benutzer-ID oder E-Mail Adresse.Ungültige Website-Detailsammlung.RechnungIst %2$s ein Duplikat von %4$s?Ist %2$s eine neue Website?Wurde %4$s auf %2$s umgezogen?Ist AktivIst aktiv, deaktiviert oder deinstalliertIst dies die Seite deines Kunden? %s wenn du sensible Informationen wie deine E-Mail, Lizenzschlüssel, Preise, Rechnungsadresse & Rechnungen vor dem WP Admin verstecken möchtest.Es sieht so aus, als ob die Lizenz nicht aktiviert werden konnte.Es sieht so aus, als wäre die Lizenzdeaktivierung fehlgeschlagen.Es sieht so aus, als wärst du nicht mehr im Testmodus, also gibt es nichts zu stornieren :)Es sieht so aus, als wärst du immer noch im %s-Plan. Wenn du ein Upgrade oder einen Planwechsel durchgeführt hast, ist das wahrscheinlich ein Problem auf unserer Seite - sorry.Es sieht so aus, als ob deine Seite derzeit keine aktive Lizenz hat.Das erfordert eine Lizenzaktivierung.Es scheint, dass einer der Authentifizierungsparameter falsch ist. Aktualisiere deinen Public Key, Secret Key & User ID und versuche es erneut.Es ist eine temporäre %s - ich behebe ein ProblemEs ist nicht das, wonach ich gesucht habeAm Beta Programm teilnehmenIch wollte dich nur darauf hinweisen, dass die Add-on-Informationen von %s von einem externen Server bezogen werden.Weiter teilenBehalten automatische Updates beiSchlüsselBitte teile uns mit, was nicht funktioniert hat, damit wir es für zukünftige Nutzer beheben können...Bitte nenne uns den Grund, damit wir uns verbessern können.LetzteZuletzt aktualisiertLetzte LizenzAktuellste kostenlose Version installiertAktuellste Version installiertMehr erfahrenLängeLizenzLizenzvertragLizenz IDLizenzschlüsselLizenzprobleme?LizenzschlüsselDer Lizenzschlüssel ist leer.LebenslangMagst du %s? Werde unser Botschafter/Affiliate und verdiene Geld ;-)Lade DB EinstellungLocalhostLogLoggerLangfristiges DuplikatNachrichtMethodeMigrierenLizenz migrierenMigriere die Einstellungen ins NetzwerkMobile AppsModulModul PfadModul TypMehr Informationen über %sNameNamen, Slugs, Versionen und ob aktiv oder nichtNetzwerk BlogNetzwerk BenutzerVerpasse nie wieder ein wichtiges UpdateVerpasse keine wichtigen Updates, erhalte Sicherheitswarnungen, bevor sie öffentlich bekannt werden, und erhalte Benachrichtigungen über Sonderangebote und tolle neue Funktionen.NeuNeue Version verfügbarNeue WebsiteNeuere kostenlose Version (%s) InstalliertNeuere Version (%s) InstalliertNewsletterNächsteNeinNein - nur deaktivierenNein - verschiebe nur die Daten dieser Seite nach %sKeine IDKeine Verpflichtung für %s - jederzeit kündigenKeine Verpflichtung für %s Tage - jederzeit kündbar!Keine Kreditkarte erforderlichKein AblaufdatumNicht auslaufendKeiner der Pläne von %s unterstützt eine Probezeit.OKSobald deine Lizenz abläuft, kannst du die Free Version immer noch nutzen, aber du hast KEINEN Zugriff auf die %s Features.Sobald deine Lizenz abläuft, kannst du das %s nicht mehr nutzen. Es sei denn, du aktivierst ihn erneut mit einer gültigen Premiumlizenz.Opt-InAbmeldenMelde dich an, um E-Mail-Benachrichtigungen für Sicherheits- und Funktionsupdates zu erhalten und einige grundlegende Informationen zur WordPress-Umgebung zu teilen.Melde dich an, um E-Mail-Benachrichtigungen für Sicherheits- und Funktionsupdates zu erhalten und einige grundlegende Informationen zur WordPress-Umgebung zu teilen. Dies wird uns helfen, die Kompatibilität von %smit Ihrer Website zu verbessern und uns auf das zu konzentrieren, was du benötigst.Melden dich an, um E-Mail-Benachrichtigungen für Sicherheits- und Funktionsupdates, Bildungsinhalte und gelegentliche Angebote zu erhalten und einige grundlegende Informationen zur WordPress-Umgebung zu teilen.Melde dich an, um E-Mail-Benachrichtigungen für Sicherheits- und Funktionsupdates, Bildungsinhalte und gelegentliche Angebote zu erhalten und einige grundlegende Informationen zur WordPress-Umgebung zu teilen. Dies wird uns helfen, die Kompatibilität mit deiner Website zu verbessern und uns auf das zu konzentrieren, was du benötigst.Mach mit, um "%s" besser zu machen!AndereBesitzer EmailBesitzer IDName des BesitzersPCI-konformDas kostenpflichtige Add-on muss auf Freemius veröffentlicht werden.PayPal Konto E-Mail AdresseZahlungenDie Auszahlungen erfolgen in USD und werden monatlich über PayPal abgewickelt.PlanPlan %s existiert nicht, es kann keine Testversion gestartet werden.Der Plan %s unterstützt keine Probezeit.Plan IDBitte kontaktiere uns hierBitte kontaktiere uns mit der folgenden Nachricht:Bitte lade %s herunter.Bitte gib den Lizenzschlüssel ein, den du in der E-Mail direkt nach dem Kauf erhalten hast:Bitte gib den Lizenzschlüssel ein, um den Debug-Modus zu aktivieren:Du kannst uns gerne relevante Statistiken über deine Website oder soziale Medien zur Verfügung stellen, z.B. monatliche Besuche der Website, Anzahl der E-Mail-Abonnenten, Follower, etc. (wir werden diese Informationen vertraulich behandeln).Bitte folge diesen Schritten, um das Upgrade abzuschließenBitte lass uns wissen, wenn du möchtest, dass wir dich für Sicherheits- und Funktionsupdates, Bildungsinhalte und gelegentliche Angebote kontaktieren:Bitte beachte, dass wir nicht in der Lage sind, veraltete Preise für Verlängerungen/neue Abonnements nach einer Kündigung beizubehalten. Wenn du dich dafür entscheidest, das Abonnement in Zukunft nach einer Preiserhöhung, die in der Regel einmal im Jahr stattfindet, manuell zu verlängern, wird dir der aktualisierte Preis berechnet.Bitte gib Details an, wie du beabsichtigst, %s zu fördern (bitte sei so genau wie möglich).Bitte gib deinen vollständigen Namen an.PluginPlugin HomepagePlugin IDPlugin installierenChangelogBeschreibungFAQFunktionen & PreiseInstallationWeitere NotizenBewertungenDas Plugin ist eine "Serviceware", was bedeutet, dass es keine Premium Version hat.PluginsPlugins & Themes SyncPremiumPremium %s Version wurde erfolgreich aktiviert.Premium Add-on Version bereits installiert.Premium VersionPremium Version bereits aktiv.PreiseDatenschutzrichtlinieFortfahrenProzess-IDVerarbeitungProdukteProgramm ZusammenfassungPromotion MethodenProvinzÖffentlicher SchlüsselLizenz kaufenMehr kaufenSchnelles FeedbackKontingentAktivierungsmail erneut sendenEmpfehle neue Kunden an unsere %s und verdiene %s Provision für jeden erfolgreichen Verkauf, den du vermittelst!Lizenz erneuernVerlängere deine Lizenz jetztAnfragenRequires PHP VersionBenötigt WordPress VersionZurücksetzen des Deaktivierungs-SchlummernsErgebnisSDKSDK Pfad%s speichernGespeichertGeplante CronsScreenshotsSuche über die AdresseGeheimer SchlüsselSichere HTTPS %s Seite, die von einer externen Domain geladen wirdEs scheint, als ob wir ein temporäres Problem mit der Kündigung deines Abonnements haben. Bitte versuche es in ein paar Minuten erneut.Es scheint, als hätten wir ein temporäres Problem mit der Abmeldung deiner Testversion. Bitte versuche es in ein paar Minuten erneut.Sieht so aus, als hättest du die neueste Version.Land auswählenLizenzschlüssel sendenDB Option setzenDas Teilen von Diagnosedaten mit hilft dabei, Funktionen bereitzustellen, die für deine Website relevanter sind, Inkompatibilitäten mit WordPress- oder PHP-Versionen zu vermeiden, die deine Website beschädigen können, und zu erkennen, auf welche Sprachen und Regionen das Plugin übersetzt und angepasst werden sollte.Netzwerk Upgrade simulierenTrial Promotion simulierenEinzelplatzlizenzWebseiten-IDWebseite erfolgreich eingeloggt.WebseitenÃœberspringen & %sURLSnooze & %sSo kannst du die Lizenz wiederverwenden, wenn die %s nicht mehr aktiv ist.Soziale Medien (Facebook, Twitter, etc.)Wir entschuldigen uns für die Unannehmlichkeiten und sind hier, um zu helfen, wenn du uns eine Chance gibst.Sorry, wir konnten das E-Mail-Update nicht abschließen. Ein anderer Benutzer mit der gleichen E-Mail ist bereits registriert.StartDebugging startenStarte TestversionStarte mein kostenloses %sStaatBleib in KontaktDebugging stoppenAbsendenAbschicken & %sAbonnementUnterstützungSupport ForumDaten vom Server synchronisierenSteuer-/Umsatzsteuer-IDAllgemeine GeschäftsbedingungenDanke, dass du uns die Chance gibst, das Problem zu beheben! Eine Nachricht wurde soeben an unser technisches Personal gesendet. Wir werden uns bei dir melden, sobald wir ein Update für %s haben. Wir danken dir für deine Geduld.Vielen Dank, dass du dich für unser Partnerprogramm beworben hast. Leider haben wir uns an dieser Stelle entschieden, deine Bewerbung abzulehnen. Bitte versuche es in 30 Tagen erneut.Vielen Dank, dass du dich für unser Partnerprogramm beworben hast. Wir werden deine Angaben in den nächsten 14 Tagen überprüfen und uns mit weiteren Informationen bei dir melden.Vielen Dank für die Aktualisierung auf %1$s v %2$s!Vielen Dank, dass du %s und seine Add-ons benutzt!Vielen Dank, dass du %s benutzt!Vielen Dank, dass du unsere Produkte benutzt!Danke dir!Danke %s!Danke für die Bestätigung des Eigentümerwechsels. Eine E-Mail wurde soeben an %s zur endgültigen Genehmigung gesendet.%1$swird regelmäßig wichtige Lizenzdaten an %2$ssenden, um nach Sicherheits- und Funktionsaktualisierungen zu suchen und die Gültigkeit Ihrer Lizenz zu überprüfen.Das %s hat meine Seite kaputt gemachtDas %s hat nicht funktioniertDas %s hat nicht wie erwartet funktioniertDas %s ist toll, aber ich brauche ein bestimmtes Feature, das nicht unterstützt wirdDas %s funktioniert nichtDas %s funktionierte plötzlich nicht mehrDie folgenden ProdukteDer Installationsprozess hat begonnen und kann ein paar Minuten dauern. Bitte warte, bis er abgeschlossen ist - lade diese Seite nicht neu.Die folgenden Produkte wurden in den abgesicherten Modus versetzt, weil wir festgestellt haben, dass %2$s eine exakte Kopie von %3$s:%1$s istDie folgenden Produkte wurden in den abgesicherten Modus versetzt, weil wir festgestellt haben, dass %2$s eine exakte Kopie dieser Seiten ist:%3$s%1$sDas Remote-Plugin-Paket enthält keinen Ordner mit dem gewünschten Slug und das Umbenennen hat nicht funktioniert.Das Upgrade von %s wurde erfolgreich abgeschlossen.ThemeTheme wechselnThemesEs ist ein %s von %s verfügbar.Es ist eine neue Version von %s verfügbar.Beim Verarbeiten Ihrer Anfrage ist ein unerwarteter API-Fehler aufgetreten. Bitte versuche es in ein paar Minuten erneut und wenn es immer noch nicht funktioniert, kontaktiere den Autor von %s mit den folgenden Angaben:Dieses Plugin wurde als nicht kompatibel mit deiner Version von WordPress markiert.Dieses Plugin wurde nicht mit deiner derzeitigen Version von WordPress getestet.This plugin requires a newer version of PHP.Dies wird es %s ermöglichenZeitstempelTitelUm zu vermeiden, dass deine Website aufgrund von WordPress- oder PHP-Versionsinkompatibilitäten beschädigt wird, und um zu erkennen, welche Sprachen und Regionen von %sübersetzt und angepasst werden sollten.Um die Kompatibilität zu gewährleisten und Konflikte mit deinen installierten Plugins und Themes zu vermeiden.Um in den Debug-Modus zu gelangen, gib bitte den geheimen Schlüssel des Lizenzinhabers (UserID = %d) ein, den du in deinem "Mein Profil"-Bereich deines "Benutzer Dashboards" findest:Damit du verwalten und kontrollieren kannst, wo die Lizenz aktiviert wird, und um sicherzustellen, dass %s Sicherheits- und Funktionsupdates nur an von dir autorisierte Websites geliefert werden.Um zusätzliche Funktionen bereitzustellen, die für deine Website relevant sind, Inkompatibilitäten von WordPress- oder PHP-Versionen, die deine Website beschädigen können, und um zu erkennen, welche Sprachen und Regionen für %sübersetzt und angepasst werden sollten.TotalStadtTestversionTypEs kann keine Verbindung zum Dateisystem hergestellt werden. Bitte bestätige deine Anmeldedaten.Unbegrenzt LizenzenUnbegrenzte UpdatesUnbegrenzte Provisionen.Bis zu %s SeitenUpdateLizenz aktualisierenUpdates, Ankündigungen, Marketing, kein SpamUpgradeLade die heruntergeladene Version hoch und aktiviere sieBenutzer DashboardBenutzer-IDBenutzerschlüsselBenutzerWertVerifizierungsmail wurde gerade an %s gesendet. Wenn du sie nach 5 Minuten nicht finden kannst, überprüfe bitte deine Spam-Ordner.VerifiziertE-Mail verifizierenVersion %s wurde freigegeben.%s Status anzeigenGrundlegende %sInformationen anzeigenGrundlegende Profilinformationen anzeigenGrundlegende Website-Informationen anzeigenDiagnoseinformationen anzeigenGrundlegende Lizenzen anzeigenListe der Plugins & Themes anzeigenDetails ansehenBezahlte Funktionen ansehenWarnungWir können keine aktiven Lizenzen sehen, die mit dieser E-Mail-Adresse verbunden sind. Bist du sicher, dass es die richtige Adresse ist?Wir konnten deine E-Mail-Adresse nicht im System finden. Bist du sicher, dass dies die richtige Adresse ist?Wir konnten die Liste der Add-ons nicht laden. Es ist wahrscheinlich ein Problem auf unserer Seite, bitte versuche es in ein paar Minuten wieder.Wir haben dieses Opt-in eingeführt, damit du kein wichtiges Update verpasst und uns hilfst, die Kompatibilität von %smit deiner Website zu verbessern und uns auf das zu konzentrieren, was du benötigst.Wir haben ein paar Anpassungen an den %s, %s gemachtWir stellen sicher, dass wir dein Hosting-Unternehmen kontaktieren und das Problem beheben. Du bekommst eine Folge-E-Mail an %s, sobald wir ein Update haben.Wir freuen uns, dir die Freemius Netzwerk-Integration vorstellen zu können.Website-, E-Mail- und Social Media-Statistiken (optional)Willkommen bei %s! Um loszulegen, gib bitte deinen Lizenzschlüssel ein:Was hast du erwartet?Welche Funktion?Wie lautet dein(e) %s?Welchen Preis würdest du als gerechtfertigt erachten?Wonach hast du gesucht?Wie lautet der Name des %s?Wo wirst du %s bewerben?WordPress- und PHP-Versionen, Sprache und Titel der WebsiteWordPress.org Plugin SeiteMöchtest du %s in %s zusammenführen?Willst du mit dem Update fortfahren?JaJa - %sJa - beide Adressen sind meineJa - mach dein DingJa - verschiebe alle meine Daten und Vermögenswerte von %s nach %sJa, %%2$s ersetzt %%4$s. Ich möchte meine %s von %%4$s nach %%2$s migrieren.Ja, %2$s ist ein Duplikat von %4$s für Test-, Staging- oder Entwicklungszwecke.Ja, %2$s ist eine neue und andere Website, die von %4$s getrennt ist.Du hast schon einmal einen Testzeitraum in Anspruch genommen.Du bist einen Klick davon entfernt, deinen kostenlosen %1$s-Tage Testzeitraum des %2$s-Planes zu starten.Ihr seid alle gut!Du testest %s bereits.Du bist nur einen Schritt entfernt - %sDu kannst immer noch alle %s-Funktionen nutzen, aber du wirst keinen Zugang zu %s-Sicherheits- und Funktionsupdates und keinen Support bekommen.Du hast keine gültige Lizenz, um auf die Premium-Version zuzugreifen.Du hast eine %s Lizenz.Du hast eine %s-Lizenz erworben.Du hast deine %s erfolgreich aktualisiert.Du hast diese Website, %s, als temporäres Duplikat von %s markiert.Du hast diese Website, %s, als temporäres Duplikat dieser Websites markiertDu hast es vielleicht übersehen: du musst keine Daten teilen und kannst einfach das Opt-in %s.You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s.Du hast dich bereits für unser Nutzungs-Tracking entschieden, was uns hilft, %s weiter zu verbessern.Du hast Dich bereits für unser Nutzungs-Tracking entschieden, was uns hilft, die Benutzerfreundlichkeit weiter zu verbessern.Dein %s Add-on Plan wurde erfolgreich upgegradet.Deine %s kostenlose Testversion wurde erfolgreich storniert.Deine %s-Lizenz wurde als White-Label gekennzeichnet, um sensible Informationen vor dem WP Admin zu verbergen (z.B. deine E-Mail, Lizenzschlüssel, Preise, Rechnungsadresse und Rechnungen). Solltest du das wieder rückgängig machen wollen, kannst du das ganz einfach über dein %s tun. Wenn dies ein Fehler war, kannst du es auch %sDeine %s-Lizenz wurde erfolgreich deaktiviert.Dein WordPress-Benutzer: Vor- und Nachname und E-Mail-AdresseDein Konto wurde erfolgreich mit der %s-Lizenz aktiviert.Dein Affiliate-Antrag für %s wurde angenommen! Logge dich in deinen Affiliate-Bereich ein unter: %s.Dein Mitgliedskonto wurde vorübergehend gesperrt.Deine E-Mail wurde erfolgreich verifiziert - Glückwunsch!Deine kostenlose Testversion ist abgelaufen. %1$sUpgrade jetzt%2$s, um das %3$s weiterhin ohne Unterbrechungen zu nutzen.Dein kostenloser Testzeitraum ist abgelaufen. Du kannst aber weiterhin alle unsere kostenlosen Funktionen nutzen.Deine Lizenz wurde gelöscht. Wenn du denkst, dass es ein Fehler ist, kontaktiere bitte den Support.Deine Lizenz ist abgelaufen. %1$sUpgrade jetzt%2$s, um das %3$s weiterhin ohne Unterbrechungen zu nutzen.Deine Lizenz ist abgelaufen. Du kannst weiterhin alle %s Funktionen nutzen, aber du musst deine Lizenz erneuern, um weiterhin Updates und Support zu erhalten.Deine Lizenz ist abgelaufen. Du kannst das kostenlose %s trotzdem für immer weiter nutzen.Deine Lizenz wurde erfolgreich aktiviert.Deine Lizenz wurde erfolgreich deaktiviert, du bist zurück im %s Plan.Dein Name wurde erfolgreich aktualisiert.Dein Plan wurde erfolgreich aktiviert.Dein Plan wurde erfolgreich auf %s geändert.Dein Plan wurde erfolgreich upgegradet.Dein Server blockiert den Zugriff auf Freemius' API, die für die %1$s-Synchronisation entscheidend ist. Bitte kontaktiere deinen Host, um %2$s auf die Whitelist zu setzenDein Abonnement wurde erfolgreich gekündigt. Dein %s Plan wird in %s ablaufen.Dein Testzeitraum wurde erfolgreich gestartet.PLZ / PostleitzahlDirekt anLizenz hier aktivierenAktiv%s kann nicht ohne %s laufen.%s kann ohne das Plugin nicht laufen.Kopf hocherlauben%s übrigAktivieren vonJahrAPIVerwerfenFehlersucheHerzlichen GlückwunschBlockiertVerbundenNeuester DownloadNeueste kostenlose Version herunterladenMonatlichVerfallsPfadE-Mail sendenmtl.JährlichJährlichEinmalPlanKein geheimer SchlüsselSDK VersionenLizenzSyncSynchronisiere LizenzAutorAusAnbasierend auf %sStarte die kostenlose TestversionSchließenSchließencomplete the opt-inDatenTagedeaktivieredelegiereschicke mir %sKEINE%s Sicherheits- und Funktionsupdates, Bildungsinhalte und Angebote.%s PlanAbgerechnet wird %sBesteHeyHopplaHey %s,StundeStundenInstalliertHurraLizenzWebseitenmsneue Beta Versionneue Versionnicht geprüftPreisPreiseoptionalVersionProduktejetzt rückgängig machen.ses scheint, dass der von dir eingegebene Schlüssel nicht mit unseren Aufzeichnungen übereinstimmt.schicke mir Sicherheits- und Funktionsupdates, Bildungsinhalte und Angebote.überspringendie Testversion startenAbonnementveränderedie oben erwähnten Websitesdie neueste %s Version hiertesteTestLöschenDowngradeBearbeitenVersteckenAnmeldenAbmeldenKaufenAnzeigenÃœberspringenUpdateUpgradevor %sfreemius/languages/freemius-zh_CN.mo000064400000154243146725417150013531 0ustar00Þ•gT5Œ&`3Aa3¢£3nF42µ4Zè4hC5d¬5S6%e6 ‹6 —6£6ª6¥½66c7´š7_O8¯8Ï8#æ8 9 $9 19 ;9F9M9U9^9f9@o9H°9ù9O :j\:›Ç:c;g;†;¦;®;¾;Æ; Ï;Û;ì;<<&(<-O<}< ’<œ<«<À<Ó<Ú<5â<= = 0= :='F=n= ‡= ”=ž=o¯=>ž&>GÅ>T ?b?©?+@>@"Z@}@(š@2Ã@!ö@aA+zA0¦A×AéABBB+B0B8BKBTB\B aB mB{B BE™BßBüBC’C ªCµCÉC ÝC êC ôCDDY/D‰D˜D ©D µDÁDÊDÏDßD øD(E1,E%^E:„E¿EÄEÕEÝE íE øEFF #F-F 2F=FxPF”ÉF ^G kG”uG H"H6H>HtYHÎHèHþHII1IGIfI ‚I¹I—GJßJ[ñJfMK´K ºKÈKÝK÷KûKYLaiLËLçLíL M M #M;1MmMrMþyMxN }N ˆN •N¢Nj±NO5+O aOkO3tO2¨OÛO~ïOUnPÄPàPùPQ)*Q-TQ‚QS–QêQ'R*Rg-RM•R7ãRgSpƒSôSTyTŽT§T ÇTÓTæT üTU%0U VUwUUœU³U ÑU•ÛU1qV.£VOÒV"WA¢WäWyX2~X±XÑXaçXIYBMY,Y½Y ÂY ÏYÜYúY ZZ%Z-Z ?Z JZVZ fZrZˆZ4‘ZÆZ ÕZßZãZêZþZ[ [[%[ @[L[ S[ _[k[…[ Š[ —[¤[¨[ ¾[!Ê[ì[ \\\%\B\%H\+n\š\ ²\ À\/Í\ý\m]~o]î]õ]ý]^ ^+^ 4^ ?^)M^w^”^4^Ò^5×^( _6_>_-U_ƒ_U—_6í_È$`1í`~aža[»bc6c=c McWc(fc*c"ºc1Ýc+d*;d&fdNdÜdädúd.e)1e[eke‹e“e¢e ªe µeÀeÉeÙeëe ôeÿe ff-f3fWLf ¤f²fÉfÒfíf gggg%g+g ;gGg Yg5dgsšglh&{h¢h±h ÂhÐhéhiii:i @iJi Oi=[i&™iLÀif jtj zj †j’j£j ©j´j »j ÇjÔj Üjêj k k•k–´k/Kl{l)›l Ål Ðl\Ûl8mMm`mCmÃmÙmùm…nm—nxod~o-ãop p$p+p'JpMrpGÀp qq q¹q¿qÄqÊqEÏqr(r:rQr`rgr*vr¡r*©r^Ôr3sBsJsSsYsd_sÄs ÍsÚs ósttitW…tnÝt"LuBou6²u=éu'v Úyz 0z&Qz<xzDµzZúzTU{Rª{.ý{.,|[|-m}9›}ZÕ}30~<d~b¡~PUU_«š €K¦€(ò€G#c%‡)­$×Uü)R‚|‚Ž‚«‚Â;Ø‚6ƒ>KƒŠƒƒ«ƒ˃$Ⴤ „<„X„&v„*„7È„……5…3N…‚…—…­…Å…Ù…*ö…1!†S†o†#ƒ†§†ÆÕ† å†ñ†‡(‡=‡B‡ G‡T‡N]‡¬‡ˇé‡ˆˆ%ˆ6ˆ;ˆAˆ1\ˆŽˆ–ˆªˆºˆ ˈ ׈ äˆ ïˆüˆ‰‰ &‰ 4‰9@‰Cz‰¾‰QÉŠ %Š 2Š<ŠVŠqŠwŠ ŠŠ–Š ¥Š ¯Š ¹Š ÅŠ ÒŠ àŠ êŠ ôŠ ‹ ‹³‹:ÎŽ  QªüScW_»‘6‘T‘ ]‘i‘r‘“‡‘,’˜H’\á’$>“c“‚““ µ“Á“Ç“ГÖ“Ü“â“ë“:ó“G.”v”7ˆ”vÀ”¯7•ç•ë•ô•ý•–––%–.–=–L–_–-o–0–Ζá–è–÷– — — ,—39—m— t—€— ‡—”—±— Ê— ×—ä—Yô—N˜„U˜<Ú˜<™T™Šj™ õ™$š$'šLš.eš,”šÁšOך''›-O›}› ’› Ÿ›¬›³› Æ› Ó›à›ð›÷›œ œ œ!œ7œ<Gœ!„œ¦œ­œ‘¿œ Q ] j w„‹š ¬E¹ÿž ž ,ž9ž@žGžYž lžyž)˜ž,žïžöž ýž Ÿ Ÿ !Ÿ .Ÿ8ŸJŸ QŸ\ŸcŸjŸ\zŸlןD  K €X Ù ò ¡ ¡`¡€¡™¡¯¡¡É¡Ø¡ë¡¢¢‰¢Š§¢ 2£M?£V£ ä£ñ£¤¤0¤7¤;M¤f‰¤ð¤¥¥2¥ 9¥ E¥'O¥w¥~¥È…¥ N¦ X¦ e¦ r¦¦[¦ë¦/û¦+§2§9§)X§‚§p›§i ¨v¨¨«¨ĨÚ¨!ó¨©\-©Š©#œ©À©Xé9ª2VªU‰ªkߪK«a«aj«Ì«å« ¬¬$¬<¬[¬,m¬!š¬¼¬ìᬠÿ¬ ­©3­Ý­ü­N®uj®0யk-¯6™¯Яæ¯Gù¯A°QH°*š°Å°Ì°ß°õ°± *±7± >± H± U±a±q±±‘±ª±6±±è±þ±² ² ²#²*²1²8²H²a²t² {² ˆ²•²­² ´² Á²βÕ² å²&ï² ³ 7³ A³K³*O³z³³!³¿³ Ò³ ß³)é³´Y´eq´ ×´ ä´#ñ´µµ 2µ?µ Oµ,Yµ†µ¦µ8­µæµ/íµ¶;¶D¶']¶…¶?”¶0Ô¶½·!÷uå·¯[¸P ¹\¹u¹ |¹‰¹ ’¹ Ÿ¹¬¹³¹ƹÖ¹ݹð¹N÷¹FºMº cº pº!‘º ³º½ºÖº ݺêº ñºûº» » »#»'».» >» K»X»_»L~»Ë»Û»ñ»ø»¼!¼(¼ >¼I¼ R¼\¼ l¼y¼‰¼(¼]¹¼]½$u½ š½§½½½Ó½æ½ù½ ¾¾5¾ <¾F¾ K¾AW¾$™¾`¾¾i¿‰¿ ¿ ¿ª¿¿¿ Æ¿Ó¿ Ú¿æ¿í¿ ô¿!À#À 6ÀzCÀŒ¾À,KÁxÁ'“Á »Á ÈÁ_ÔÁ4ÂLÂ[Â2s¦µ ÊÂa×Â^9Ãh˜ÃKÄMÄkÄ rÄĆĠÄ9»Ä9õÄ /Å9Åž@ÅßÅæÅíÅôÅ6ûÅ2Æ BÆOÆbÆtÆ{Æ*‹Æ¶Æ½ÆÜÆáÆ ñÆ ûÆÇÇWÇ kÇxNjǠdzÇÆÇlÍÇQ:ÈZŒÈ%çÈ/ É6=É;tÉ°ÉÃÉÓÉèÉÊÊ2ÊPÊ kʌʢʦÊ!­Ê4ÏÊSËDXË5ËÓËGïË7Ì&JÌqÌg‰Ì0ñÌ"Í7ÍTÍ2lÍ7ŸÍM×ÍV%ÎW|Î#ÔÎ&øÎ Ï#*Ð)NÐOxÐ$ÈÐ4íÐT"ÑWwÑZÏÑQ*Ò†|ÒJÓ!NÓ8pÓ©ÓÈÓ#çÓ ÔI*ÔtÔ “Ô Ô§Ô ÀÔÊÔ çÔÕÕÕ Õ,Õ0Õ4Õ;ÕBÕ IÕ VÕ`ÕsՌՓ՚ամջÕÂÕÉÕÐÕ ×Õ äÕ ïÕùÕÖÖÖÖ%Ö.ÖAÖHÖOÖVÖ ZÖdÖFkÖ²Ö»Ö ÄÖÎÖÒÖÙÖâÖéÖðÖ÷Ö þÖ×× × #× -×7×>× E×O×V× ]×j×3n×?¢×â×é× í×ú× Ø ØØ3Ø:ØAØHØOØVØ ]Ø jØwØ~؅،ؚؓØÆäŒkÝd¾.z­<="åÍé àNH<æ+Yo°HÖ#ʆCÖ”  j'ÜS8MÚ±?PÄN¯6ÅXõ£< xÇŠðF¢8:šó,I¿}¿’÷—Z*G”÷ü0C";(YZ6½ E»¡ßs®a-€nfûPUr/²¥›uv4EÁnh¦Yv «&]e³ˆhJµ§–¼L'¯ÕÀ¢Típ5Iw9¸BA²ÓFœ`S\|WmVúÔP:„õ¼þ2O_S€öyÃäÑ'c¦¹[ ~Qû2ª¸ Ì_qjæÑêë…Û9(ã.ÿùª7À%GRÞÿ¶Þ¶·°3Õ!iw‘Rô Qg‡¤ ê 0ÒËoƒÈ!“2m ±¥š|OEðžï\V ¹3Ý4í¬ÛdÅ] ÎòQ"g ?ŽÄzœØ•WëG©ö.ɉTºàçgD$ºU$DFìUM9{Û‚cÙÔãÂ…Ê™^á™Á@#’y=Ì©[&`;ñlC“> ?@·Ž{®8=´sTX7î`ˆ–¤t>a†~ÇRx ÎÙN× bøîb0,åÈ\ fž/×l˜f#b—ç1лMVøòB^Ð)Zý³%¨‰§Ø­qeÜ[ôú}eŸ‹:-„ŠèÏ5¬$>½Œ•ŸJ*BËý/k¡;Ét&LXá‚ ‹«ƒµß]ÒÂp)âéL,Ú@*IÍèr!âùi1uKdÆ´%ì)6^A(W4AþüKO¾‘˜+1ÏDó‡Ha¨7ï5ñK_J+Óc£3- %s to access version %s security & feature updates, and support. The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"The ", e.g.: "The plugin"The %s's%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is my client's email address%s is my email address%s is the new owner of the account.%s minimum payout amount.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.APIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.An unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred while trying to toggle the license's white-label mode.An unknown error has occurred.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre both %s and %s your email addresses?Are you sure you want to delete all Freemius data?Are you sure you want to proceed?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Associate with the license owner's account.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBetaBillingBilling & InvoicesBlockingBlog IDBodyBundle PlanBusiness nameBuy a license nowBuy licenseBy changing the user, you agree to transfer the account ownership to:Can't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanChange UserCheckoutCityClear API CacheClear Updates TransientsClick hereClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDebug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.Delegate to Site AdminsDelete All AccountsDetailsDisabling white-label modeDon't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload Paid VersionDownload the latest %s versionDownload the latest versionDownloadedDue to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.Duplicate WebsiteDuring the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEmail address updateEnabling white-label modeEndEnter email addressEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used for the upgrade below and we will resend you the license key.Enter the new email addressErrorError received from the server:ExpiredExpires in %sExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.FreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFreemius is our licensing and software updates engineFull nameFunctionGet commission for automated subscription renewals.Get updates for bleeding edge Beta versions of %s.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!How do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I Agree - Change UserI can't pay for it anymoreI couldn't understand how to make it workI don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.If you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid clone resolution action.Invalid module ID.Invalid new user ID or email address.Invalid site details collection.InvoiceIs %2$s a duplicate of %4$s?Is %2$s a new website?Is %2$s the new home of %4$s?Is ActiveIs this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.It looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It requires license activation.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's a temporary %s - I'm troubleshooting an issueIt's not what I was looking forJoin the Beta programJust letting you know that the add-ons information of %s is being pulled from an external server.KeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense IDLicense KeyLicense issues?License keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerLong-Term DuplicateMessageMethodMigrateMigrate LicenseMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNetwork BlogNetwork UserNewNew Version AvailableNew WebsiteNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo - only move this site's data to %sNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please enter the license key to enable the debug mode:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires WordPress VersionReset Deactivation SnoozingResultSDKSDK PathSave %sSavedScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSimulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSnooze & %sSo you can reuse the license when the %s is no longer active.Social media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart DebugStart TrialStart my free %sStateStop DebugSubmitSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe following products'The installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$sThe products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$sThe remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.TimestampTitleTo enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:TotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser DashboardUser IDUser keyUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We couldn't load the add-ons list. It's probably an issue on our side, please try to come back in few minutes.We made a few tweaks to the %s, %sWe're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)Welcome to %s! To get started, please enter your license key:What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress.org Plugin PageWould you like to merge %s into %s?Would you like to proceed with the update?YesYes - %sYes - both addresses are mineYes - move all my data and assets from %s to %sYes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s.Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.Yes, %2$s is a new and different website that is separate from %4$s.You already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have purchased a %s license.You have successfully updated your %s.You marked this website, %s, as a temporary duplicate of %s.You marked this website, %s, as a temporary duplicate of these sitesYou might have missed it, but you don't have to share any data and can just %s the opt-in.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s.Your %s license was successfully deactivated.Your account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onactivate a license hereactive add-onActiveaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismissdatadaysdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,hourhoursinstalled add-onInstalledinterjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew Beta versionnew versionnot verifiednounPricenounPricingoptionalproduct versionVersionproductsrevert it nowsecondssecseems like the key you entered doesn't match our records.send me security & feature updates, educational content and offers.skipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialsubscriptionswitchingthe above-mentioned sitesthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Yulinn <977869645@qq.com>, 2022 Language-Team: Chinese (China) (http://www.transifex.com/freemius/wordpress-sdk/language/zh_CN/) Language: zh_CN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js %s以访问版本%s的安全和功能更新以åŠæ”¯æŒã€‚%s çš„ %s 下载链接 %sã€è®¸å¯è¯å¯†é’¥å’Œå®‰è£…说明已å‘é€åˆ° %s。如果您在 5 分钟åŽæ‰¾ä¸åˆ°è¯¥ç”µå­é‚®ä»¶ï¼Œè¯·æ£€æŸ¥æ‚¨çš„垃圾邮件箱。已安装%1$s的付费版本。请激活它以开始使用%2$s功能。%3$så…¬å¸%s çš„%1$s 已进入安全模å¼ï¼Œå› ä¸ºæˆ‘们注æ„到 %2$s 是 %3$s 的精确副本。%1$s将立å³åœæ­¢æ‰€æœ‰æœªæ¥çš„定期付款,并且您的%2$s计划许å¯è¯å°†åœ¨%3$s过期。%1$s将立å³åœæ­¢æ‰€æœ‰æœªæ¥çš„定期付款,并且您的%s计划许å¯è¯å°†åœ¨%s过期。立å³å®Œæˆâ€%s“激活已æˆåŠŸè´­ä¹°%s加载项。%s安装%s许å¯è¯%s以å‰%såŠå…¶é™„加组件%s 自动安全和功能更新以åŠä»˜è´¹åŠŸèƒ½å°†ç»§ç»­è¿è¡Œè€Œä¸ä¼šä¸­æ–­ï¼Œç›´åˆ° %s(或当您的许å¯è¯åˆ°æœŸæ—¶ï¼Œæ— è®ºå…ˆåˆ°è€…)。%s客户购买新许å¯è¯æ—¶æ”¶å–佣金。%så…费试用已æˆåŠŸå–消。因为附加组件是高级的,所以它被自动åœç”¨ã€‚如果你想在将æ¥ä½¿ç”¨å®ƒï¼Œä½ å¿…须购买许å¯è¯ã€‚%s是一款仅é™é«˜çº§çš„附加组件。在激活æ’件之å‰ï¼Œå¿…须先购买许å¯è¯ã€‚%s 是我客户的电å­é‚®ä»¶åœ°å€%s 是我的电å­é‚®ä»¶åœ°å€%s是å¸æˆ·çš„新主人。%s最低付款金é¢ã€‚%s或更高%s级%s评级%s秒%s星%s星%s时间%年代%s以访问版本%s的安全和功能更新以åŠæ”¯æŒã€‚%s首次访问åŽè·Ÿè¸ªCookie,以最大é™åº¦åœ°æ高收益潜力。%s的付费功能%så•å‡»æ­¤å¤„%så¯é€‰æ‹©è¦æ¿€æ´»è®¸å¯è¯çš„ç«™ç‚¹ã€‚åˆšåˆšå‘ %s å‘é€äº†ä¸€å°ç¡®è®¤ç”µå­é‚®ä»¶ã€‚电å­é‚®ä»¶æ‰€æœ‰è€…必须在接下æ¥çš„ 4 å°æ—¶å†…ç¡®è®¤æ›´æ–°ã€‚åˆšåˆšå‘ %s å‘é€äº†ä¸€å°ç¡®è®¤ç”µå­é‚®ä»¶ã€‚您必须在接下æ¥çš„ 4 å°æ—¶å†…确认更新。如果您找ä¸åˆ°è¯¥ç”µå­é‚®ä»¶ï¼Œè¯·æ£€æŸ¥æ‚¨çš„垃圾邮件文件夹。API←➤å¸æˆ·å¸æˆ·è¯¦ç»†ä¿¡æ¯è¡ŒåŠ¨æ¿€æ´»æ¿€æ´»%s激活%s计划激活%s功能激活å…费版本激活许å¯è¯åœ¨æ‰€æœ‰æŒ‚起的站点上激活许å¯è¯ã€‚在网络中的所有站点上激活许å¯è¯ã€‚激活此加载项激活%s的加载项模å—%s的加载项添加å¦ä¸€ä¸ªåŸŸé™„加组件附加组件加载项必须部署到WordPress.org或Freemius。网å€åœ°å€è¡Œ%d会员推广è”盟å…è´¹%såŽï¼Œåªéœ€æ”¯ä»˜%såŒæ„并激活许å¯è¯æ‰€æœ‰è¯·æ±‚所有类型å…许并继续或者,您å¯ä»¥æš‚时跳过它,ç¨åŽåœ¨%s的网络级å¸æˆ·é¡µä¸­æ¿€æ´»è®¸å¯è¯ã€‚æ•°é‡ä»Ž%s自动下载并安装的%s(付费版本)将在%s中å¯åŠ¨ã€‚如果è¦æ‰‹åŠ¨æ‰§è¡Œæ­¤æ“作,请å•å‡»â€œå–消â€æŒ‰é’®ã€‚å°è¯•è®¾ç½®ç”¨æˆ·çš„测试模å¼æ—¶å‘生了未知错误。å°è¯•åˆ‡æ¢è®¸å¯è¯çš„白标模å¼æ—¶å‘生未知错误。å‘生未知错误。测试版的更新将用最新的测试版替æ¢æ‚¨å®‰è£…çš„%s版本-请å°å¿ƒä½¿ç”¨ï¼Œä¸è¦åœ¨ç”Ÿäº§ç«™ç‚¹ä¸Šä½¿ç”¨ã€‚你被警告了。匿åå馈在所有挂起的站点上应用。应用于网络中的所有站点。申请æˆä¸ºæŽ¨å¹¿è”盟%s å’Œ %s 都是您的电å­é‚®ä»¶åœ°å€å—?是å¦ç¡®å®žè¦åˆ é™¤æ‰€æœ‰Freemiusæ•°æ®ï¼Ÿç¡®å®šè¦ç»§ç»­å—?由于我们ä¿ç•™30天的潜在退款,我们åªæ”¯ä»˜è¶…过30天的佣金。与许å¯è¯æ‰€æœ‰è€…çš„å¸æˆ·å…³è”。自动安装仅适用于已选择的用户。在%s中自动续订自动安装平å‡è¯„级真棒加入推广è”盟测试版本开具账å•è´¦å•å’Œå‘票阻止åšå®¢ID身体æ†ç»‘计划ä¼ä¸šå称立å³è´­ä¹°è®¸å¯è¯è´­ä¹°è®¸å¯è¯é€šè¿‡æ›´æ”¹ç”¨æˆ·ï¼Œæ‚¨åŒæ„å°†å¸æˆ·æ‰€æœ‰æƒè½¬è®©ç»™ï¼šæ‰¾ä¸åˆ°æ‚¨çš„许å¯è¯å¯†é’¥ï¼Ÿå–消å–消%s并继续å–消%s-我ä¸å†éœ€è¦ä»»ä½•å®‰å…¨å’ŒåŠŸèƒ½æ›´æ–°ï¼Œä¹Ÿä¸éœ€è¦%s的支æŒæœåŠ¡ï¼Œå› ä¸ºæˆ‘ä¸æ‰“算在此或任何其他站点上使用%s。å–消%s?å–消安装å–消订阅å–消试用å–消正在å–消%s正在å–消%s...å–消订阅å–消试用将立å³é˜»æ­¢ä½¿ç”¨æ‰€æœ‰é«˜çº§åŠŸèƒ½ã€‚你确定å—?更改许å¯è¯å˜æ›´æ‰€æœ‰æƒå˜æ›´è®¡åˆ’更改用户结å¸åŸŽå¸‚清除 API 缓存清除更新瞬æ€ç‚¹å‡»è¿™é‡Œå•å‡»æ­¤å¤„匿å使用æ’件å•å‡»æ­¤å¤„å¯æŸ¥çœ‹è¯„分为%s的评论å•å‡»æ­¤å¤„å¯æŸ¥çœ‹å…¨å°ºå¯¸å±å¹•æˆªå›¾%d产å“代ç å…¼å®¹è‡³è”系方å¼è”系支æŒè”系我们贡献者无法激活%s。国家Cron类型日期åœç”¨åœç”¨è®¸å¯è¯åœç”¨æˆ–å¸è½½%s将自动ç¦ç”¨è®¸å¯è¯ï¼Œæ‚¨å¯ä»¥åœ¨å…¶ä»–站点上使用该许å¯è¯ã€‚åœç”¨è®¸å¯è¯å°†é˜»æ­¢æ‰€æœ‰é«˜çº§åŠŸèƒ½ï¼Œä½†å°†åœ¨å…¶ä»–站点上激活许å¯è¯ã€‚确定è¦ç»§ç»­å—?åœç”¨è°ƒè¯•æ—¥å¿—调试模å¼å·²æˆåŠŸå¯ç”¨ï¼Œå°†åœ¨60分钟以内自动ç¦ç”¨ã€‚您也å¯ä»¥é€šè¿‡å•å‡»â€œåœæ­¢è°ƒè¯•â€é“¾æŽ¥æå‰ç¦ç”¨ã€‚委派给站点管ç†å‘˜åˆ é™¤æ‰€æœ‰å¸æˆ·ç»†èŠ‚ç¦ç”¨ç™½æ ‡æ¨¡å¼ä¸è¦å–消%s-我ä»ç„¶å¯¹èŽ·å–安全和功能更新感兴趣,也å¯ä»¥è”系支æŒäººå‘˜ã€‚没有许å¯è¯å¯†é’¥ï¼Ÿæ赠给这个æ’件é™ä½Žæ‚¨çš„计划下载下载%s版本下载付费版本下载最新的%s版本下载最新版本下载由于新的%sEU通用数æ®ä¿æŠ¤æ¡ä¾‹ï¼ˆGDPR)%sçš„åˆè§„性è¦æ±‚,è¦æ±‚您å†æ¬¡æ˜Žç¡®è¡¨ç¤ºåŒæ„,确认您已ç»åŠ å…¥ï¼š-)由于è¿å我们的推广è”盟æ¡æ¬¾ï¼Œæˆ‘们决定暂时å°é”您的附属å¸æˆ·ã€‚如果您有任何问题,请è”系支æŒäººå‘˜ã€‚å¤åˆ¶ç½‘站在更新过程中,我们检测到%d个网站ä»åœ¨ç­‰å¾…许å¯è¯æ¿€æ´»ã€‚在更新过程中,我们在网络中检测到%s个网站ä»ç„¶éœ€è¦æ‚¨çš„注æ„。电å­é‚®ä»¶ç”µå­é‚®ä»¶åœ°å€ç”µå­é‚®ä»¶åœ°å€æ›´æ–°å¯ç”¨ç™½æ ‡æ¨¡å¼ç»ˆç‚¹è¯·è¾“入邮箱地å€è¯·è¾“入您计划å‡çº§%s的网站或其他网站的域。请在下é¢è¾“入您用于å‡çº§çš„电å­é‚®ä»¶åœ°å€ï¼Œæˆ‘们将é‡æ–°å‘您å‘é€è®¸å¯è¯å¯†é’¥ã€‚输入新的电å­é‚®ä»¶åœ°å€é”™è¯¯ä»ŽæœåŠ¡å™¨æ”¶åˆ°é”™è¯¯ï¼šæœŸæ»¡%såŽè¿‡æœŸé¢å¤–域您将è¥é”€äº§å“çš„é¢å¤–的网域。文件过滤为了éµå®ˆWordPress.org指å—,在开始试用之å‰ï¼Œæˆ‘们è¦æ±‚您选择使用您的用户和éžæ•æ„Ÿç«™ç‚¹ä¿¡æ¯ï¼Œå…许%s定期å‘%så‘é€æ•°æ®ä»¥æ£€æŸ¥ç‰ˆæœ¬æ›´æ–°å¹¶éªŒè¯æ‚¨çš„试用。å…费的å…费试用å…费版本Freemius APIFreemius 调试Freemius SDK找ä¸åˆ°æ’件的主文件。请关于当å‰é”™è¯¯ä¸Žsdk@freemius.comè”系。Freemius 状æ€Freemius是我们的许å¯å’Œè½¯ä»¶æ›´æ–°å¼•æ“Žå…¨å函数获得自动续订的佣金。获å–%sçš„å‰æ²¿æµ‹è¯•ç‰ˆæœ¬çš„更新。有许å¯è¯å¯†é’¥å—?嘿,你知é“%s有会员计划å—?如果您喜欢%s,您å¯ä»¥æˆä¸ºæˆ‘们的大使并赚å–一些现金ï¼åˆ°ç›®å‰ä¸ºæ­¢ï¼Œæ‚¨è§‰å¾—%s怎么样?使用%d天å…费试用æ¥æµ‹è¯•æˆ‘们所有的%s高级功能。如何上传和激活?您将如何推广我们?我åŒæ„ - 更改用户我å†ä¹Ÿä»˜ä¸èµ·äº†æˆ‘ä¸æ˜Žç™½è¯¥æ€Žä¹ˆåšæˆ‘ä¸æƒ³å’Œä½ åˆ†äº«æˆ‘çš„ä¿¡æ¯æˆ‘找到了更好的%s我已ç»å‡çº§äº†æˆ‘çš„å¸æˆ·ï¼Œä½†æ˜¯å½“我å°è¯•åŒæ­¥è®¸å¯è¯æ—¶ï¼Œè®¡åˆ’ä»ç„¶æ˜¯%s。我ä¸å†éœ€è¦%s我åªéœ€è¦åœ¨çŸ­æ—¶é—´å†…使用%sID如果这是长期副本,è¦åœ¨ %s 之åŽä¿ç•™è‡ªåŠ¨æ›´æ–°å’Œä»˜è´¹åŠŸèƒ½ï¼Œè¯· %s。如果å•å‡»å®ƒï¼Œæ­¤å†³å®šå°†å§”派给站点管ç†å‘˜ã€‚如果您有空,请告诉我们您为什么是%s如果è¦å°†%så¸æˆ·çš„所有æƒæ”¾å¼ƒç»™%s,请å•å‡»â€œæ›´æ”¹æ‰€æœ‰æƒâ€æŒ‰é’®ã€‚如果è¦åœ¨è¿™äº›ç«™ç‚¹ä¸Šä½¿ç”¨%s,请在下é¢è¾“入许å¯è¯å¯†é’¥ï¼Œç„¶åŽå•å‡»â€œæ¿€æ´»â€æŒ‰é’®ã€‚é‡è¦å‡çº§é€šçŸ¥ï¼šåœ¨%s中如果您ä¸æ‰“算在此站点(或任何其他站点)上使用此%s,是å¦ä¹Ÿè¦å–消%s?立å³å®‰è£…å…费版本立å³å®‰è£…å…费版本更新立å³å®‰è£…ç«‹å³å®‰è£…更新正在安装æ’件:%s无效的克隆解æžæ“作。模å—ID无效。无效的新用户ID或电å­é‚®ä»¶åœ°å€ã€‚无效网站详细信æ¯é›†åˆã€‚å‘票%2$s 是 %4$s 的副本å—?%2$s 是一个新网站å—?%2$s 是 %4$s 的新主页å—?处于活动状æ€è¿™æ˜¯æ‚¨å®¢æˆ·çš„网站å—?如果您希望从WP管ç†å‘˜é‚£é‡Œéšè—æ•æ„Ÿä¿¡æ¯ï¼Œä¾‹å¦‚电å­é‚®ä»¶ï¼Œè®¸å¯è¯å¯†é’¥ï¼Œä»·æ ¼ï¼Œè´¦å•åœ°å€å’Œå‘票,则为%s。似乎无法激活许å¯è¯ã€‚许å¯è¯åœç”¨ä¼¼ä¹Žå¤±è´¥ã€‚看起æ¥æ‚¨ä¸å†å¤„于试用模å¼ï¼Œæ‰€ä»¥æ²¡æœ‰ä»€ä¹ˆéœ€è¦å–消的:)看æ¥ä½ è¿˜åœ¨%s计划中。如果你确实å‡çº§æˆ–更改了计划,这å¯èƒ½æ˜¯æˆ‘们这边的问题-对ä¸èµ·ã€‚您的站点当å‰ä¼¼ä¹Žæ²¡æœ‰æ´»åŠ¨è®¸å¯è¯ã€‚它需è¦è®¸å¯è¯æ¿€æ´»ã€‚似乎身份验è¯å‚数中的一个ä¸æ­£ç¡®ã€‚请更新您的公钥ã€å¯†é’¥å’Œç”¨æˆ·ID,然åŽé‡è¯•ã€‚这是一个临时的 %s - 我正在解决一个问题这ä¸æ˜¯æˆ‘è¦æ‰¾çš„加入测试计划åªæ˜¯è®©æ‚¨çŸ¥é“%s的加载项信æ¯æ˜¯ä»Žå¤–部æœåŠ¡å™¨æå–的。钥匙请分享什么地方出了错,以便我们å¯ä»¥ä¸ºæœªæ¥çš„用户修å¤å®ƒ...请告诉我们原因以便我们改进。最åŽä¸Šæ¬¡æ›´æ–°æ—¶é—´æœ€åŽä¸€ä¸ªè®¸å¯è¯å·²å®‰è£…最新的å…费版本已安装最新版本了解更多长度许å¯è¯è®¸å¯å议许å¯è¯ID许å¯è¯å¯†é’¥è®¸å¯é—®é¢˜ï¼Ÿè®¸å¯è¯å¯†é’¥è®¸å¯è¯å¯†é’¥ä¸ºç©ºã€‚终身喜欢%så—?æˆä¸ºæˆ‘们的大使并赚å–现金 ;-)加载数æ®åº“选项本机日志记录器长期副本消æ¯æ–¹æ³•è¿ç§»è¿ç§»è®¸å¯è¯å°†é€‰é¡¹è¿ç§»åˆ°ç½‘络移动应用程åºæ¨¡å—模å—路径模å—类型有关%s的详细信æ¯å§“å网络åšå®¢ç½‘络用户新的新版本å¯ç”¨æ–°ç½‘站已安装较新的å…费版本(%s)安装了较新的版本(%s)新闻稿下一个ä¸å¦ - 仅将此站点的数æ®ç§»åŠ¨åˆ° %sæ—  ID%s没有承诺-éšæ—¶å–消%s天没有承诺-éšæ—¶å–消ï¼ä¸éœ€è¦ä¿¡ç”¨å¡æ°¸ä¸è¿‡æœŸéžåˆ°æœŸ%s的任何计划都ä¸æ”¯æŒè¯•ç”¨æœŸã€‚好许å¯è¯è¿‡æœŸåŽï¼Œæ‚¨ä»ç„¶å¯ä»¥ä½¿ç”¨å…费版本,但您将无法使用%s功能。许å¯è¯è¿‡æœŸåŽï¼Œæ‚¨å°†æ— æ³•å†ä½¿ç”¨%s,除éžæ‚¨ä½¿ç”¨æœ‰æ•ˆçš„高级许å¯è¯å†æ¬¡æ¿€æ´»ã€‚选择加入选择退出选择加入以使“%sâ€æ›´å¥½ï¼å…¶ä»–所有者电å­é‚®ä»¶æ‰€æœ‰è€… ID所有者å称PCI兼容付费附加组件必须部署到Freemius。PayPal å¸æˆ·ç”µå­é‚®ä»¶åœ°å€ä»˜æ¬¾ä»˜æ¬¾ä»¥ç¾Žå…ƒä¸ºå•ä½ï¼Œæ¯æœˆé€šè¿‡ PayPal 处ç†ã€‚计划计划%sä¸å­˜åœ¨ï¼Œå› æ­¤æ— æ³•å¯åŠ¨è¯•ç”¨ã€‚计划%sä¸æ”¯æŒè¯•ç”¨æœŸã€‚计划ID请在这里è”系我们请通过以下信æ¯ä¸Žæˆ‘们è”系:请下载%s。请输入购买åŽåœ¨ç”µå­é‚®ä»¶ä¸­æ”¶åˆ°çš„许å¯è¯å¯†é’¥ï¼šè¯·è¾“入许å¯è¯å¯†é’¥ä»¥å¯ç”¨è°ƒè¯•æ¨¡å¼ï¼šè¯·éšæ—¶æ供任何相关的网站或社交媒体统计数æ®ï¼Œä¾‹å¦‚æ¯æœˆç‹¬ç‰¹çš„网站访问é‡ã€ç”µå­é‚®ä»¶è®¢æˆ·æ•°é‡ã€å…³æ³¨è€…æ•°é‡ç­‰ï¼ˆæˆ‘们将对这些信æ¯ä¿å¯†ï¼‰ã€‚请按照以下步骤完æˆå‡çº§å¦‚果您希望我们与您è”系以获å–安全和功能更新ã€æ•™è‚²å†…容和å¶å°”的优惠,请告知我们:请注æ„,å–消åŽï¼Œæˆ‘们将无法获å–æ›´æ–°/新订阅的过期定价。如果您选择在未æ¥æ‰‹åŠ¨ç»­è®¢ï¼Œåœ¨ä»·æ ¼ä¸Šæ¶¨åŽï¼Œå°†å‘您收å–æ›´æ–°åŽçš„价格。请æ供有关您打算如何推广%s的详细信æ¯ï¼ˆè¯·å°½å¯èƒ½å…·ä½“)。请æ供您的全å。æ’件æ’件主页æ’件IDæ’件安装å˜æ›´æ—¥å¿—说明常è§é—®é¢˜è§£ç­”功能和定价安装其他注æ„事项评论æ’件是一个“æœåŠ¡è½¯ä»¶â€ï¼Œè¿™æ„味ç€å®ƒæ²¡æœ‰é«˜çº§ä»£ç ç‰ˆæœ¬ã€‚æ’件æ’件和主题åŒæ­¥é«˜çº§ç‰ˆæœ¬é«˜çº§%s版本已æˆåŠŸæ¿€æ´»ã€‚已安装高级加载项版本。高级版高级版本已激活。定价éšç§æ”¿ç­–继续进程 ID处ç†äº§å“计划摘è¦æŽ¨å¹¿æ–¹å¼çœå…¬é’¥è´­ä¹°è®¸å¯è¯è´­ä¹°æ›´å¤šå¿«é€Ÿå馈é…é¢é‡æ–°å‘é€æ¿€æ´»ç”µå­é‚®ä»¶å‘新客户介ç»æˆ‘们的%s,并在æ¯æ¬¡é”€å”®æˆåŠŸæ—¶èŽ·å¾—%s佣金ï¼æ›´æ–°è®¸å¯è¯ç«‹å³ç»­è®¢è®¸å¯è¯è¯·æ±‚需è¦WordPress版本å¤ä½å¤±æ´»ä¼‘眠结果软件开å‘工具包SDK 路径ä¿å­˜%så·²ä¿å­˜è®¡åˆ’çš„ Cronså±å¹•æˆªå›¾æŒ‰ç½‘å€æœç´¢å¯†é’¥ä»Žå¤–部域è¿è¡Œçš„安全HTTPS%s页é¢ä¼¼ä¹Žå…³äºŽæ‚¨çš„订阅å–消å‘生了一些暂时的问题。请过几分钟å†è¯•ä¸€æ¬¡ã€‚看æ¥å…³äºŽæ‚¨çš„试用å–消å‘生了一些暂时的问题。请过几分钟å†è¯•ä¸€æ¬¡ã€‚好åƒä½ å¾—到了最新的版本。选择国家å‘é€è®¸å¯è¯å¯†é’¥è®¾ç½®æ•°æ®åº“选项模拟试用推广模拟试用推广å•ç«™ç‚¹è®¸å¯è¯ç«™ç‚¹ ID站点已æˆåŠŸé€‰æ‹©åŠ å…¥ã€‚站点跳过&%sSlugæš‚åœ & %s因此,当%sä¸å†æ´»åŠ¨æ—¶ï¼Œæ‚¨å¯ä»¥é‡æ–°ä½¿ç”¨è®¸å¯è¯ã€‚社交媒体(脸书ã€æŽ¨ç‰¹ç­‰ï¼‰å¾ˆæŠ±æ­‰ç»™æ‚¨å¸¦æ¥ä¸ä¾¿ï¼Œå¦‚果您能给我们一个机会,我们将竭诚为您æœåŠ¡ã€‚对ä¸èµ·ï¼Œæˆ‘们无法完æˆç”µå­é‚®ä»¶æ›´æ–°ã€‚具有相åŒç”µå­é‚®ä»¶çš„å¦ä¸€ä¸ªç”¨æˆ·å·²æ³¨å†Œã€‚起点开始调试开始试用开始我的å…è´¹%s国家åœæ­¢è°ƒè¯•æ交æ交 & %s订阅支æŒæ”¯æŒè®ºå›ä»ŽæœåŠ¡å™¨å¾—到的åŒæ­¥æ•°æ®ç¨ŽåŠ¡/增值税IDæœåŠ¡æ¡æ¬¾æ„Ÿè°¢æ‚¨ç”³è¯·æˆ‘们的推广è”盟计划,ä¸å¹¸çš„是,我们现在决定拒ç»æ‚¨çš„申请。请在30天åŽå†è¯•ã€‚感谢您申请我们的推广è”盟计划,我们将在未æ¥14天内审查您的详细信æ¯ï¼Œå¹¶å°†ä¸Žæ‚¨è”ç³»æ供更多的信æ¯ã€‚éžå¸¸æ„Ÿè°¢æ‚¨ä½¿ç”¨%såŠå…¶é™„加组件ï¼éžå¸¸æ„Ÿè°¢æ‚¨ä½¿ç”¨%sï¼éžå¸¸æ„Ÿè°¢æ‚¨ä½¿ç”¨æˆ‘们的产å“ï¼è°¢è°¢æ‚¨ï¼è°¢è°¢%sï¼æ„Ÿè°¢æ‚¨ç¡®è®¤æ‰€æœ‰æƒå˜æ›´ã€‚刚刚å‘%så‘é€äº†ä¸€å°ç”µå­é‚®ä»¶ä»¥èŽ·å¾—最终批准。%sç ´å了我的网站%sä¸èµ·ä½œç”¨%s没有按预期工作%s很好,但我需è¦æ‚¨ä¸æ”¯æŒçš„特定功能%sä¸èµ·ä½œç”¨%sçªç„¶åœæ­¢å·¥ä½œä»¥ä¸‹äº§å“安装过程已开始,å¯èƒ½éœ€è¦å‡ åˆ†é’Ÿæ‰èƒ½å®Œæˆã€‚请等待完æˆ-ä¸è¦åˆ·æ–°æ­¤é¡µã€‚以下产å“已进入安全模å¼ï¼Œå› ä¸ºæˆ‘们注æ„到 %3$s 是 %1$s 的精确副本:%2$s以下产å“已进入安全模å¼ï¼Œå› ä¸ºæˆ‘们注æ„到 %3$s 是这些网站的精确副本:%1$s%2$s远程æ’件包ä¸åŒ…å«å…·æœ‰æ‰€éœ€æ®µå¡žçš„文件夹,é‡å‘½å失败。%sçš„å‡çº§å·²æˆåŠŸå®Œæˆã€‚主题主题切æ¢ä¸»é¢˜æœ‰ä¸€ä¸ª%sçš„%så¯ç”¨ã€‚有新版本的%så¯ç”¨ã€‚æ­¤æ’件尚未标记为与您的WordPress版本兼容。此æ’件尚未用当å‰ç‰ˆæœ¬çš„WordPress进行测试。时间戳标题è¦è¿›å…¥è°ƒè¯•æ¨¡å¼ï¼Œè¯·è¾“入许å¯è¯æ‰€æœ‰è€…的密钥(用户ID=%d),您å¯ä»¥åœ¨ç”¨æˆ·ä»ªè¡¨æ¿çš„“我的é…置文件â€éƒ¨åˆ†æ‰¾åˆ°è¯¥å¯†é’¥ï¼šæ€»è®¡åŸŽé•‡å®¡åˆ¤ç±»åž‹æ— æ³•è¿žæŽ¥åˆ°æ–‡ä»¶ç³»ç»Ÿã€‚请确认您的凭æ®ã€‚æ— é™è®¸å¯è¯æ— é™æ›´æ–°ä½£é‡‘无上é™ã€‚最多%s个站点更新更新许å¯è¯æ›´æ–°ã€å…¬å‘Šã€è¥é”€ï¼Œæ— åžƒåœ¾é‚®ä»¶å‡çº§ä¸Šä¼ å¹¶æ¿€æ´»ä¸‹è½½çš„版本W00t用户仪表盘用户 ID用户密钥用户值验è¯é‚®ä»¶åˆšåˆšå‘é€åˆ°%s。如果5分钟åŽæ‰¾ä¸åˆ°ï¼Œè¯·æ£€æŸ¥åžƒåœ¾é‚®ä»¶æ¡†ã€‚已验è¯çš„验è¯ç”µå­é‚®ä»¶ç‰ˆæœ¬%så·²å‘布。查看详细信æ¯æŸ¥çœ‹ä»˜è´¹åŠŸèƒ½è­¦å‘Šæˆ‘们看ä¸åˆ°ä¸Žè¯¥ç”µå­é‚®ä»¶åœ°å€å…³è”的任何活动许å¯è¯ï¼Œæ‚¨ç¡®å®šå®ƒæ˜¯æ­£ç¡®çš„地å€å—?我们在系统中找ä¸åˆ°æ‚¨çš„电å­é‚®ä»¶åœ°å€ï¼Œæ‚¨ç¡®å®šåœ°å€æ­£ç¡®å—?无法加载加载项列表。这å¯èƒ½æ˜¯æˆ‘们这边的问题,请几分钟åŽå†æ¥ã€‚我们对%s,%s进行了一些调整我们很高兴介ç»Freemius网络级集æˆã€‚网站ã€ç”µå­é‚®ä»¶å’Œç¤¾äº¤åª’体统计(å¯é€‰ï¼‰æ¬¢è¿Žä½¿ç”¨%sï¼é¦–先,请输入您的许å¯è¯å¯†é’¥ï¼šä½ æœŸæœ›ä»€ä¹ˆï¼Ÿä»€ä¹ˆåŠŸèƒ½ï¼Ÿä½ çš„%s是什么?你愿æ„付出什么价钱?你在找什么?%sçš„å字是什么?您打算在哪里推广%s?WordPress.org æ’件页é¢è¦å°† %s åˆå¹¶åˆ° %s 中å—?是å¦ç»§ç»­æ›´æ–°ï¼Ÿæ˜¯æ˜¯-%s是的 - 两个地å€éƒ½æ˜¯æˆ‘的是 - 将我的所有数æ®å’Œèµ„产从 %s 移至 %s是的,%%2$s æ­£åœ¨æ›¿æ¢ %%4$s。我想将我的 %s 从 %%4$s è¿ç§»åˆ° %%2$s。是的,%2$s 是 %4$s 的副本,用于测试ã€æš‚存或开å‘。是的,%2$s 是一个与 %4$s ä¸åŒçš„新网站。您以å‰å·²ç»è¯•ç”¨è¿‡ã€‚您åªéœ€å•å‡»ä¸€æ¬¡å°±å¯ä»¥å¼€å§‹%1$s天的%2$s计划å…费试用。你们都很好ï¼æ‚¨å·²ç»åœ¨è¯•ç”¨æ¨¡å¼ä¸‹è¿è¡Œ%s。你离%såªå·®ä¸€æ­¥ã€‚您ä»ç„¶å¯ä»¥äº«å—所有%s功能,但您将无法获得%s安全和功能更新以åŠæ”¯æŒæœåŠ¡ã€‚您没有访问高级版本的有效许å¯è¯ã€‚您有%s许å¯è¯ã€‚您购买了 %s 许å¯è¯ã€‚您已æˆåŠŸæ›´æ–°%s。您将此网站 %s 标记为 %s 的临时副本。您将此网站 %s 标记为这些网站的临时副本您å¯èƒ½é”™è¿‡äº†ï¼Œä½†æ‚¨ä¸å¿…共享任何数æ®ï¼Œåªéœ€é€‰æ‹©%så³å¯ã€‚您已ç»é€‰æ‹©åŠ å…¥æˆ‘们的使用情况跟踪,这有助于我们ä¸æ–­æ”¹è¿›%s。您已ç»é€‰æ‹©äº†æˆ‘们的使用情况跟踪,这有助于我们ä¸æ–­æ”¹è¿›å®ƒä»¬ã€‚%s加载项计划已æˆåŠŸå‡çº§ã€‚您的%så…费试用已æˆåŠŸå–消。您的%s许å¯è¯è¢«æ ‡è®°ä¸ºç™½æ ‡ï¼Œä»¥å¯¹WP管ç†å‘˜éšè—æ•æ„Ÿä¿¡æ¯ï¼ˆä¾‹å¦‚,您的电å­é‚®ä»¶ï¼Œè®¸å¯è¯å¯†é’¥ï¼Œä»·æ ¼ï¼Œè´¦å•åœ°å€å’Œå‘票)。如果您希望将其还原,则å¯ä»¥é€šè¿‡%sè½»æ¾å®Œæˆã€‚如果这是一个错误,您也å¯ä»¥%s。您的%s许å¯è¯å·²æˆåŠŸåœç”¨ã€‚您的å¸æˆ·å·²ç”¨%s计划æˆåŠŸæ¿€æ´»ã€‚您的%s会员申请已被接å—ï¼ç™»å½•åˆ°æ‚¨çš„分支区域,地å€ä¸º%s。您的会员å¸æˆ·å·²æš‚时挂起。你的电å­é‚®ä»¶å·²è¢«æˆåŠŸéªŒè¯-你太棒了ï¼æ‚¨çš„å…费试用已过期。%1$sç«‹å³å‡çº§%2$s以继续使用%3$s而ä¸ä¸­æ–­ã€‚您的å…费试用已过期。您ä»ç„¶å¯ä»¥ç»§ç»­ä½¿ç”¨æˆ‘们所有的å…费功能。你的许å¯è¯è¢«å–消了。如果您认为这是一个错误,请è”系支æŒäººå‘˜ã€‚您的许å¯è¯è¿‡æœŸäº†ã€‚%1$sç«‹å³å‡çº§%2$s以继续使用%3$s而ä¸ä¸­æ–­ã€‚您的许å¯è¯è¿‡æœŸäº†ã€‚您ä»ç„¶å¯ä»¥ç»§ç»­ä½¿ç”¨æ‰€æœ‰%s功能,但您需è¦ç»­è®¢è®¸å¯è¯æ‰èƒ½ç»§ç»­èŽ·å–更新和支æŒã€‚您的许å¯è¯è¿‡æœŸäº†ã€‚您ä»ç„¶å¯ä»¥ç»§ç»­æ°¸è¿œä½¿ç”¨å…费的%s。您的许å¯è¯å·²æˆåŠŸæ¿€æ´»ã€‚您的许å¯è¯å·²æˆåŠŸåœç”¨ï¼Œæ‚¨å›žåˆ°äº†%s计划。您的姓åå·²æˆåŠŸæ›´æ–°ã€‚您的计划已æˆåŠŸæ¿€æ´»ã€‚您的计划已æˆåŠŸæ›´æ”¹ä¸º%s。您的计划已æˆåŠŸå‡çº§ã€‚您的订阅已æˆåŠŸå–消。您的%s计划许å¯è¯å°†åœ¨%såŽè¿‡æœŸã€‚您的试用已æˆåŠŸå¼€å§‹ã€‚邮政编ç å°±åœ¨åœ¨æ­¤å¤„激活许å¯è¯æ´»è·ƒçš„没有%s,%s无法è¿è¡Œã€‚没有æ’件,%s无法è¿è¡Œã€‚抬头å…许剩下%s正在激活年API关闭调试æ­å–œæ­¤è·¯ä¸é€šå·²è¿žæŽ¥ä¸‹è½½æœ€æ–°ç‰ˆæœ¬ä¸‹è½½æœ€æ–°å…费版本æ¯æœˆåˆ°æœŸè·¯å¾„å‘é€ç”µå­é‚®ä»¶çž¬é—´æ¯å¹´æ¯å¹´ä¸€æ¬¡è®¡åˆ’没有秘密SDK 版本许å¯è¯åŒæ­¥åŒæ­¥è®¸å¯è¯ä½œè€…关闭打开基于%s开始å…费试用关闭关闭数æ®å¤©åœç”¨ä¸­ä»£è¡¨ä¸%sè¦%så‘我å‘é€å®‰å…¨å’ŒåŠŸèƒ½æ›´æ–°ã€æ•™è‚²å†…容和æœåŠ¡ã€‚%s计划å¸å•%s最好的嘿哎呀嘿%s,å°æ—¶å°æ—¶å®‰è£…哟哈许å¯è¯ç«™ç‚¹æ¯«ç§’新测试版新版本未验è¯ä»·æ ¼å®šä»·å¯é€‰çš„版本产å“现在还原秒好åƒä½ è¾“入的钥匙和我们的记录ä¸ç¬¦ã€‚请给我å‘é€å®‰å…¨å’ŒåŠŸèƒ½æ›´æ–°ï¼Œæ•™è‚²å†…容和优惠。跳过嗯开始试用订阅切æ¢ä¸­ä¸Šè¿°ç½‘站这儿有最新的%s版本试用试用删除é™çº§ç¼–辑éšè—选择加入选择退出购买显示跳过更新å‡çº§%s以å‰freemius/languages/freemius-es_ES.mo000064400000214540146725417150013523 0ustar00Þ•¡$‹,*X8Y8^8Ad8¢¦8nI92¸9Zë9hF:d¯:S;%h; Ž; š;¦;­;¥À;6f<´<_R=²=Ò=#é= >%'> M> Z> d>o>v>~>‡>>@˜>HÙ>"?O5?M…?jÓ?›>@Ú@Þ@ý@A%AŒ5AÂAÊA ÓAßAðABB&,B-SBB –B B¯BÄB×BÞB5æBC$C 4C >C'JCrC ‹C ˜C¢Co³C#Dž*DGÉDTEfE©…E/FBF"^FF(žF2ÇF!úF>Ga[G+½G0éGH,HCHRHZHnHsH{HŽH—HŸH¤H «H ·HÅH ×HEãHy)I£IÀIÇI’ÛI nJyJJ ¡J ®J ¸JÆJ×JYóJMK\K mK yK…KŽK“K£K ¼K(ÇK1ðK%"L:HLƒL ˆL–L§L¯L ¿L ÊL×LíL õL7ÿL7M 5]mt]gâ]pJ^»^Õ^yÛ^U_n_ Ž_š_­_ Ã_ä_%÷_ `>`F`c`z` ˜`&¢`•É`1_a.‘aOÀabAbÒbyòb2lcŸc¿caÕc 7dDd[dB_d,¢dÏd Ôd ádîd e %e0e7e?e Qe \ehe xe„eše4£eØe çeñeõeüefff'f7f Rf^f ef qf}f—f,œf Éf Öfãf¡g¤g¨g ¾g!Êgìg hhhh%1hWh%]h+ƒh¯h Çh Õh/âhimi~„ij jujÛˆj¡dklm*m 0muDuW]u µuÃuÚuãuøuv/v6v:vCvKvQv avmv v5ŠvsÀvl4w&¡wÈw×w èw öwyy4yHyPyly ry|y y=y&ËyLòyf?z¦z ¬z ¸zÄzÕzÛz êzõz üz {{ {+{ A{N{¯_{•|–¥|%<}/b}’})²} Ü} ç}\ò}˜O~è~ý~C/s‰©…ÁmG€xµ€d.-“Á ÇÔÛ'ú¬"‚MÏ‚Gƒ,eƒ’ƒ ¨ƒ²ƒ¦¸ƒS_„ ³„‘T…çæ…ΆÔ†Ù†߆Eä†*‡=‡O‡f‡u‡|‡*‹‡¶‡*¾‡é‡ø‡ˆ ˆˆdˆzˆ ƒˆˆ ©ˆ·ˆʈâˆúˆ‰'‰ B‰O‰b‰ij‰WÔ‰n,Š¤›Š"@‹ƒc‹Bç‹6*Œ=aŒŸŒ ´ŒÂŒ-ÓŒ&5/\Œ#¦*ÊõùŽ Ž/4ŽQdŽU¶ŽD $QMvÄ/Öo&>–Õ ì& ‘<4‘Dq‘Z¶‘€’T’’Rç’.:“.i“˜“-ª”;Ø”9•ZN•3©•<Ý•b–P}–UΖ_$—š„—K˜(k˜G”˜#ܘ%™)&™$P™Šu™Uš)Vš€š’š¯šÇš;Üš6›>O›Ž›”›¯›Ï›$å› œ$œ@œ\œ&zœ*¡œ7Ìœ93R†›±ÉÝ*ú1%žWžsž#‡ž«žÇžÙž éžõžŸ,ŸAŸUŸZŸ _ŸlŸNuŸÄŸãŸ  , = N S Y 1t ¦ ®  Ò  ã  ï  ü  ¡¡¡5¡ >¡ L¡9X¡C’¡Ö¡Û¡ ë¡ ø¡¢¢7¢=¢ P¢\¢ k¢ u¢ ¢ ‹¢ ˜¢ ¦¢ °¢ º¢ Æ¢ Ó¢æà¢Ǧ˦WЦÞ(§‡¨¨Z˜¨pó¨id©&Ω1õ©'ª 8ªEªMª¥cª9 «ÀC«k¬p¬¬#§¬ˬ%è¬ ­­*­<­ C­ O­\­c­Vl­Zí®W:®M’®jà®›K¯ç¯ë¯ô¯ý¯°Œ°§°°° ¸°ðÓ°ï° ±0±/K±{±”±±²±α ã± ï±Aü± >²I²d² m²3y²­²˲à²ð²r³x³¤³U&´`|´%Ý´·µ»µ'ѵ&ùµ ¶(>¶>g¶%¦¶>̶h ·4t·G©·ñ· ¸"¸ 6¸A¸R¸ W¸d¸ |¸ ‡¸“¸š¸¡¸°¸Ÿ߸Kð¸y<¹+¶¹â¹ë¹—ºšº©º¿ºÕº ñº ûº »»z5»°»Á» Õ»â»ò»ø»ÿ»$¼<¼9K¼;…¼;Á¼ ý¼½ ½½.½7½ I½ V½d½|½ ‚½7½ǽ ͽؽh콯U¾¿ ¿·!¿#Ù¿ý¿ÀÀ5/À"eÀXˆÀáÀ"oÁ’Á¦Á¶Á¿ÁÕÁ óÁ 2ÂÝ=¹ÃÕÃyçÃuaÄ×Ä!ëÄ Å"ÅBÅ FÅXgÅ_ÀŠƠƼÆÂÆßÆ èÆ õÆÇ6ÇFÇNÇ;UÇO‘ÈáÈèÈÉ É#Éz2É­ÉD½ÉÊÊFÊBbÊ:¥ÊàË~Ì:ÌuºÌ0ÍMÍ"hÍ$‹Í#°Í3ÔÍ-Î6Î_PΰÎ,ÅÎòÎgõÎR]Ï9°Ï>êÏm)Ðl—ÐÑ#„Ѩу®Ñ#2Ò)VÒ€ÒÒ­Ò ÃÒäÒCþÒ,BÓoÓwÓ”Ó«Ó ÉÓ&ÖÓÆýÓ*ÄÔ4ïÔO$ÕŒtÕ=Ö?Ö”_Ö2ôÖ'×D×o\× Ì×Ù×ð×`ö×5WØؕجØ#½ØáØ üØÙÙÙ-Ù<ÙNÙgÙ"yÙ œÙB§ÙêÙ ÿÙ Ú ÚÚ(Ú0Ú8Ú@ÚPÚ iÚwÚÚÚ Ú»Ú,ÂÚ ïÚûÚ Û¡)ÛËÛÑÛ ëÛ.÷Û%&ÜLÜ UÜ_ÜbÜ%xÜžÜ6¥Ü>ÜÜ"Ý >Ý LÝ;ZÝ–Ý|šÝƒÞ ›Þ §ÞuµÞÛ+ß¡à©à$±áÖá#Ûáÿáâ)â7<â+tâ âD¦âëâMðâ+>ã jãvã0’ãÃãhÚãNCäà’ä=s儱å46æikç$Õçúçè è&è6è JèWè[è vè ƒè è\œèùèéé3%é.Yéˆé™éµé¼éÔéÝé ìé ÷éêê -ê7êFê Wêdêyê+êt«ê ë4ë NëYë!nëë ¬ë¶ë ºë ÇëÒëÛëíëì ì1&ìXìxÚì&SízíŒí¥í »íÇîåîï ï!+ïMï Tï`ï eïMqï&¿ïPæï•7ðÍðÔðèð#ñ+ñ2ñAñXñ _ñ kñxñ€ñ#ñ´ñÃñÛÙñŸµò¤Uó%úó4 ô!Uô1wô ©ô ´ônÂô˜1õÊõÞõòõAöTö$fö‹ö™£öm=÷x«÷k$ø0øÁø ÆøÓøÙø(öø¬ùLÌùCú,]úŠú  úªú¦²úSYû­û‘püçýêý ðýúýþVþrþ‡þ¢þ¹þ ÉþÔþ.åþ ÿ'ÿGÿ gÿuÿ†ÿÿ}•ÿ < Zh{“«ÀØ ó›#‘¿ŒQ¤Þ0ƒÀ´MuIÃ@ N^v0ˆ¹Ôð/#?#c)‡±´¼Ú/êQUlDÂ*R2…'™ÁqÝBO ’ ª $È <í D* go €× UX R® 4 26 Ui 1¿ ;ñ 6-nd7ÓA mMd»i cŠ©îO˜'èA(R{&š!Á¯ãY“0í -8PW&w ž¨ ± »ÅÊ Î Ø â î ø&> FPUru {†Ž“ ¥³ ¼ÈÝã ë õ' * 4>RW \igqÙ áî÷û  "+25I Xfmt}† K¤^ðOV u ‚Œ¦ÃÖòù   +3; B MXؾÀyl~|Ÿ'§€ñ4Žm”f‘ýÃ*“f-/¨ŒÝÞi#¡$£÷Ÿ†MèÉ}ª#à:’  YÝ*ߊD5uàiý^‘]‚L³yptÍw;xFœk|¿K³3ž Ÿ!Pt'”o.Y¨g‡_ûø8½,!Ù@ÅvhBΙf,²Õ0``Åj… é%ù7?Û–6°êCú¦Œz9™k¹ù¡zœ¦J[,h†ܤæ42e­SWÐB¸ÎîXr6ëÀ2ÒçJj“ôíìLˆƒ|ñÙø â"c<€(Ï:Ö{@ „6Z±ál‡»p½o\/ü†žºÔ^+š-nA˜l5%wا"T0=\O7õÜEÍnP‹)<Jv¼Çs&Žqé?ƸóuNyA}˜Ž{FE‰·;#¥¢µOè8žþ‰ã =öü_{F¥÷D«±´ŠSLDM3ÿaqRG´v 5¬Q[ ÒrIú­îÞ„ÓSZg>å%©$Ì®]Uš~9T« u2cÄŒGKª×n;’~ãg¾Úá®Áo…$U€Oß0ƒXë)£a í+—–ÃmQ‹_s1Zxä›GÑp ÛË:”Ïÿ^ô·ò`QÕ¯Âì‘êmöNYº ©&ˆ9œWÈ!R& [ó…xjÊïæòÌqÁdä‡bÉ4‹Ôâ>3?‚BÐ]ˆç—\t'eA¢Ú¡bõšH¬Ç/dR»=“>w)að eHƒÄÆX}sKNŠ¹C+V*ï×.¶@傶c™(r °1 "ð•E‰Ë <I¤—TÈd˜ûÊ I²U1›H-¿V„V•8 W–ziP.kb(•Ö¯ þC’ÓMµѼ›h7HmmW00t %s to access version %s security & feature updates, and support. The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"The ", e.g.: "The plugin"The %s's%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is my client's email address%s is my email address%s is the new owner of the account.%s minimum payout amount.%s opt-in was successfully completed.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.Click here to learn more about updating PHP.A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.APIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsAccount is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.ActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.An unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred while trying to toggle the license's white-label mode.An unknown error has occurred.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre both %s and %s your email addresses?Are you sure you want to delete all Freemius data?Are you sure you want to proceed?Are you sure you would like to proceed with the disconnection?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Associate with the license owner's account.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBetaBillingBilling & InvoicesBlockingBlog IDBodyBundleBundle PlanBusiness nameBuy a license nowBuy licenseBy changing the user, you agree to transfer the account ownership to:By disconnecting the website, previously shared diagnostic data about %1$s will be deleted and no longer visible to %2$s.Can't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanChange UserCheckoutCityClear API CacheClear Updates TransientsClick hereClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCommunicationCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeCurrent %s & SDK versions, and if active or uninstalledDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDebug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.Delegate to Site AdminsDelete All AccountsDetailsDiagnostic InfoDiagnostic data will no longer be sent from %s to %s.Disabling white-label modeDisconnecting the website will permanently remove %s from your User Dashboard's account.Don't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload Paid VersionDownload the latest %s versionDownload the latest versionDownloadedDue to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.Duplicate WebsiteDuring the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEmail address updateEnabling white-label modeEndEnter email addressEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used during the purchase and we will resend you the license key.Enter the email address you've used for the upgrade below and we will resend you the license key.Enter the new email addressErrorError received from the server:ExpiredExpires in %sExtensionsExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.For delivery of security & feature updates, and license management, %s needs toFreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFreemius is our licensing and software updates engineFull nameFunctionGet commission for automated subscription renewals.Get updates for bleeding edge Beta versions of %s.Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!Homepage URL & title, WP & PHP versions, and site languageHow do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I Agree - Change UserI can't pay for it anymoreI couldn't understand how to make it workI don't know what is cURL or how to install it, help me!I don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.If you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you skip this, that's okay! %1$s will still work just fine.If you wish to cancel your %1$s plan's subscription instead, please navigate to the %2$s and cancel it there.If you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid clone resolution action.Invalid module ID.Invalid new user ID or email address.Invalid site details collection.InvoiceIs %2$s a duplicate of %4$s?Is %2$s a new website?Is %2$s the new home of %4$s?Is ActiveIs active, deactivated, or uninstalledIs this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.It looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It requires license activation.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's a temporary %s - I'm troubleshooting an issueIt's not what I was looking forJoin the Beta programJust letting you know that the add-ons information of %s is being pulled from an external server.Keep SharingKeep automatic updatesKeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense IDLicense KeyLicense issues?License keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerLong-Term DuplicateMessageMethodMigrateMigrate LicenseMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNames, slugs, versions, and if active or notNetwork BlogNetwork UserNever miss an important updateNever miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.NewNew Version AvailableNew WebsiteNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo - just deactivateNo - only move this site's data to %sNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to get email notifications for security & feature updates, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please enter the license key to enable the debug mode:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires PHP VersionRequires WordPress VersionReset Deactivation SnoozingResultSDKSDK PathSave %sSavedScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSharing diagnostic data with %s helps to provide functionality that's more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to.Simulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSnooze & %sSo you can reuse the license when the %s is no longer active.Social media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart DebugStart TrialStart my free %sStateStay ConnectedStop DebugSubmitSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience.Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you for updating to %1$s v%2$s!Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe following products'The installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$sThe products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$sThe remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn't work, contact the %s's author with the following:This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.This plugin requires a newer version of PHP.This will allow %s toTimestampTitleTo avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.To ensure compatibility and avoid conflicts with your installed plugins and themes.To enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.To provide additional functionality that's relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.TotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUser DashboardUser IDUser keyUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View %s StateView Basic %s InfoView Basic Profile InfoView Basic Website InfoView Diagnostic InfoView License EssentialsView Plugins & Themes ListView detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We couldn't load the add-ons list. It's probably an issue on our side, please try to come back in few minutes.We have introduced this opt-in so you never miss an important update and help us make the %s more compatible with your site and better at doing what you need it to.We made a few tweaks to the %s, %sWe'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.We're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)Welcome to %s! To get started, please enter your license key:What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress & PHP versions, site language & titleWordPress.org Plugin PageWould you like to merge %s into %s?Would you like to proceed with the update?YesYes - %sYes - both addresses are mineYes - do your thingYes - move all my data and assets from %s to %sYes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s.Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.Yes, %2$s is a new and different website that is separate from %4$s.You already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have purchased a %s license.You have successfully updated your %s.You marked this website, %s, as a temporary duplicate of %s.You marked this website, %s, as a temporary duplicate of these sitesYou might have missed it, but you don't have to share any data and can just %s the opt-in.You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s.Your %s license was successfully deactivated.Your WordPress user's: first & last name, and email addressYour account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$sYour subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onactivate a license hereactive add-onActiveaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismisscomplete the opt-indatadaysdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,hourhoursinstalled add-onInstalledinterjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew Beta versionnew versionnot verifiednounPricenounPricingoptionalproduct versionVersionproductsrevert it nowsecondssecseems like the key you entered doesn't match our records.send me security & feature updates, educational content and offers.skipstart the trialsubscriptionswitchingthe above-mentioned sitesthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Leo Fajardo , 2022 Language-Team: Spanish (Spain) (http://www.transifex.com/freemius/wordpress-sdk/language/es_ES/) Language: es_ES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2; X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js HmmW00t %s para acceder a la versión %s de actualizaciones de funciones, seguridad y soporte. El %s de %s enlace de descarga de %s, la clave de licencia y las instrucciones de instalación se han enviado a %s. Si no encuentras el correo electrónico después de 5 minutos, comprueba tu bandeja de correo no deseado. La versión de pago de %1$s ya está instalada. Por favor, actívala para empezar a beneficiarte de las características de %2$s. %3$sThe %s's%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.%1$s detendrá inmediatamente todos los pagos recurrentes futuros y tu licencia del plan %2$s caducará en %3$s.%1$s detendrá inmediatamente todos los pagos recurrentes futuros y tu licencia del plan caducará en %s.Completar la activación de "%s" ahoraEl complemento %s ha sido comprado correctamente.%s Instalaciones%s Licenciashace %s%s y sus complementos%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).%s comisión cuando un cliente compra una nueva licencia.la prueba gratuita de %s fue cancelada con éxito. Puesto que el complemento es sólo premium se desactivó automáticamente. Si quieres utilizarlo en el futuro, deberás comprar una licencia.%s es un complemento único de premium. Tienes que comprar una licencia primero antes de activar el plugin.%s is my client's email address%s is my email address%s es el nuevo dueño de la cuenta.%s cantidad mínima a pagar.%s opt-in was successfully completed.%s o mayor%s calificación%s calificaciones%s seg%s estrella%s estrellas%s vez%s veces%s para acceder a la versión %s de actualizaciones de funciones, seguridad y soporte.%s tracking cookie después de la primera visita para maximizar las ganancias potenciales.%s características de pago%sClick aquí %s para elegir los sitios sobre los que te gustaría activar la licencia.Click here to learn more about updating PHP.A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.API←➤CuentaDetalles de la cuentaAccount is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.AccionesActivarActivar %sActivar plan %sActivar características %sActivar versión gratuitaActivar licenciaAplicar licencia en todos los sitios pendientes.Activar licencia en todos los sitios de la red.Activar este complementoActivadoComplementos para %sComplementos del módulo %sAñadir otro dominioComplementoComplementosEl complemento debe implementarse en WordPress.org o en Freemius.DirecciónLínea de la dirección %dAfiliadoAfiliaciónDespués de su período gratuito %s, pague sólo %sDe acuerdo y activar licenciaTodas las peticionesTodos los TiposPermitir y continuarAlternativamente, puedes saltarlo ahora y activar la licencia después, en tu %s página de cuenta a nivel de red.CantidadUna descarga automatizada y la instalación de %s (versión de pago) de %s comenzará en %s. Si quieres hacerlo manualmente - haz clic en el botón de cancelación.Se ha producido un error desconocido al intentar establecer el modo beta del usuario.Se ha producido un error desconocido al intentar activar el modo de marca blanca de la licencia.Se ha producido un error desconocido.Una actualización a una versión Beta reemplazará tu versión instalada de %s con la última versión Beta - úsalo con precaución, y no en sitios de producción. Te hemos avisado.Comentarios anónimosAplicar en todos los sitios pendientes.Aplicar en todos los sitios de la red.Aceptar para hacerse afiliadoAre both %s and %s your email addresses?¿Está seguro que desea eliminar todos los datos de Freemius?¿Estás seguro que quieres proceder?Are you sure you would like to proceed with the disconnection?Como aplazamos 30 días para posible devoluciones, sólo pagamos comisiones que son de más de 30 días.Asocia con la cuenta del propietario de la licencia.La instalación automática sólo funciona para usuarios que aceptaron.Auto renovaciones en %sInstalación automáticaCalificación mediaIncreíbleHacerse afiliadoBetaFacturaciónFacturación y facturasBloqueandoID del blogCuerpoBundlePlan combinadoNombre de la empresaCompra una licencia ahoraComprar licenciaAl cambiar al usuario, usted acepta transferir la propiedad de la cuenta a:By disconnecting the website, previously shared diagnostic data about %1$s will be deleted and no longer visible to %2$s.¿No puedes encontrar tu clave de licencia?CancelarCancelar %s y procederCancelar %s - No necesito más actualizaciones de características y seguridad, ni soporte para %s porque no pretendo utilizar%s en este, u otro sitio.¿Cancelar %s?Cancelar instalaciónCancelar suscripciónCancelar período de pruebaCanceladoCancelando %sCancelando %s...Cancelando la suscripciónLa cancelación del período de prueba bloqueará inmediatamente el acceso a todas las funciones premium. ¿Estás seguro?Cambiar licenciaCambiar propietarioCambiar PlanCambiar usuarioPagarCiudadBorrar caché de la APIBorrar transients de actualizacionesHaz clic aquíHaz click aquí para utilizar el plugin de forma anónimaHaz clic para ver los comentarios con una valoración de %sClick para ver la captura de pantalla a tamaño completo %dProductosCódigoCommunicationCompatible hastaContactoContactar soporteContáctanosColaboradoresNo se puede activar %s.PaísTipo de cronCurrent %s & SDK versions, and if active or uninstalledFechaDesactivarDesactivar licenciaDesactivar o desinstalar %s deshabilitará automáticamente la licencia, que podrás usar en otro sitio.Al desactivar tu licencia todas las características premium se bloquearán, pero posibilitará poder activar tu licencia en otro sitio. ¿Estás seguro que quieres continuar?DesactivaciónLog de DebugEl modo de depuración se ha activado con éxito y se desactivará automáticamente en 60 minutos. También puedes desactivarlo antes haciendo clic en el enlace "Detener depuración".Delegar a administradores del sitioBorrar todas las cuentasDetallesDiagnostic InfoDiagnostic data will no longer be sent from %s to %s.Desactivar el modo de marca blancaDisconnecting the website will permanently remove %s from your User Dashboard's account.No cancelar %s - Todavía estoy interesado en obtener actualizaciones de características y seguridad, así como poder contactar con soporte.¿No tienes una clave de licencia?Donar a este pluginBajando tu planDescargaDescargar versión %sDescargar la versión de pagoDescargar la última versión %sDescargar la última versiónDescargadoDebido al nuevo %sEU Reglamento General de Protección de Datos (RGPD)%s los requisitos de obligado cumplimiento requieren que proporciones tu consentimiento explícito, una vez más, confirmando que estás de acuerdo :-)Debido a la violación de nuestros términos de afiliados, hemos decidido bloquear temporalmente tu cuenta de afiliación. Si tienes alguna pregunta, por favor contacta nuestro soporte.Duplicate WebsiteDurante el proceso de actualización hemos detectado%d sitio(s) que aún están pendientes de la activación de licencia.Durante el proceso de actualización detectamos %s sitio(s) en la red que todavía están pendientes de tu atención.Correo electrónicoDirección de correo electrónicoEmail address updateActivar el modo de marca blancaFinIntroduce el correo electrónicoIntroduce el dominio de tu sitio web o de otros sitios web donde planeas promocionar %s.Enter the email address you've used during the purchase and we will resend you the license key.Escribe abajo la dirección de correo electrónico que has usado para la actualización y te reenviaremos la clave de licencia.Enter the new email addressErrorError recibido del servidor:CaducadoCaduca en %sExtensionsDominios extraDominios extra desde donde promocionarás el producto.ArchivoFiltroPara el cumplimiento de las directrices de WordPress.org, antes de empezar el período de prueba te pedimos que aceptes con tu usuario e información no sensible del sitio web, permitiendo a %s enviar datos periódicamente a %s para comprobar si hay actualizaciones de versión y para validar la versión de prueba.For delivery of security & feature updates, and license management, %s needs toGratisPeríodo de prueba gratuitoVersión gratuitaAPI FreemiusDebug FreemiusFreemius SDK no pudo encontrar el archivo principal del plugin. Por favor contacta a sdk@freemius.com con el error actual.Estado FreemiusFreemius es nuestro motor de licencias y actualizaciones de softwareNombre completoFunciónObtén comisiones por renovaciones automatizadas de las suscripciones.Obten actualizaciones para las versiones Beta de vanguardia de %s.Genial, por favor instala cURL y habilítalo en el archivo php.ini. Además, busca la directiva 'disable_functions' en el archivo php.ini y quita cualquier método que comienza con 'curl_'. Para asegurarte de que se activó con éxito, utiliza 'phpinfo()'. Una vez activado, desactiva el %s y reactívalo de nuevo.¿Tienes una clave de licencia?Hey, ¿sabías que %s tiene un programa de afiliados? ¡Si te gusta %s puedes convertirte en nuestro embajador y ganar dinero!Homepage URL & title, WP & PHP versions, and site language¿Qué te pareció %s hasta ahora? Prueba todas nuestras funciones premium de %s con una prueba gratuita de %d-días.¿Cómo subirlo y activarlo?¿Como nos promocionarás?Estoy de acuerdo - Cambiar usuarioNo puedo pagarlo durante más tiempoNo entiendo cómo hacerlo funcionarNo sé qué es cURL o cómo instalarlo, ¡ayúdame!No me gusta compartir mi información contigoHe encontrado un %s mejorHe actualizado mi cuenta, pero cuando intento sincronizar la licencia, el plan sigue siendo %s.Ya no necesito el %sSólo necesitaba la %s por un corto períodoIDIf this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.Si haces click, esta decisión será delegada a los administradores de los sitios.Si tienes un momento, por favor, dinos por qué estás %sIf you skip this, that's okay! %1$s will still work just fine.If you wish to cancel your %1$s plan's subscription instead, please navigate to the %2$s and cancel it there.Si deseas renunciar a la titularidad de la cuenta de %s a %s haz clic en el botón de cambio de titularidad.Si quieres utilizar %s en estos sitios, introduce por favor tu clave de licencia abajo y haz click en el botón de activación.Aviso importante de actualización:En %sEn caso de que NO estés planeando utilizar este %s en este sitio (o en cualquier otro sitio), ¿te gustaría cancelar también %s?Instalar la versión gratuita ahoraInstalar la actualización gratuita ahoraInstalar ahoraInstalar actualización ahoraInstalando plugin: %sInvalid clone resolution action.Id de módulo no válido.Nuevo ID de usuario o dirección de correo electrónico no válido.Colección de detalles del sitio no válida.FacturaIs %2$s a duplicate of %4$s?Is %2$s a new website?Is %2$s the new home of %4$s?Está activoIs active, deactivated, or uninstalled¿Es este el sitio de clientes? %s si deseas ocultar información sensible como tu correo electrónico, clave de licencia, precios, dirección de facturación y facturas de la administración de WP.Parece que la licencia no se pudo activar.Parece que la desactivación de licencia ha fallado.Parece que ya no estás en modo de prueba, así que no hay nada que cancelar :)Parece que todavía estás en el plan %s. Si actualizaste o cambiaste tu plan, probablemente sea un problema de nuestra parte - lo sentimos.Parece que tu sitio actualmente no tiene una licencia activa.It requires license activation.Parece que uno de los parámetros de autenticación es incorrecto. Actualiza tu clave pública, clave secreta e ID de usuario e inténtelo de nuevo.It's a temporary %s - I'm troubleshooting an issueNo es lo que estaba buscandoÚnete al programa BetaSólo déjanos informarte que la información de complementos de %s se está extrayendo de un servidor externo.Keep SharingKeep automatic updatesClavePor favor, comparte lo que no funcionó para que podamos arreglarlo para los futuros usuarios...Por favor, dínos la razón para que podamos mejorar.ÚltimoÚltima actualizaciónÚltima licenciaÚltima versión gratuita instaladaÚltima versión instaladaSaber másLongitudLicenciaAcuerdo de licenciaID de licenciaClave de licencia¿Problemas de licencia?Clave de licenciaLa clave de licencia está vacía.Permanente¿Te gusta %s? Conviértete en nuestro embajador y gana dinero ;-)Cargar opción de BDLocalhostLogLoggerLong-Term DuplicateMensajeMétodoMigrateMigrate LicenseMigrar opciones a la redApps móvilesMóduloRuta del móduloTipo de móduloMás información sobre %sNombreNames, slugs, versions, and if active or notBlog de redUsuario de redNever miss an important updateNever miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.NuevoNueva versión disponibleNew WebsiteVersión gratuita más reciente (%s) instaladaVersión más reciente (%s) instaladaBoletínSiguienteNoNo - sólo desactivarNo - only move this site's data to %sSin IDSin compromiso para %s - cancelar en cualquier momentoSin compromiso por %s días - ¡cancelar en cualquier momento!No se necesita tarjeta de créditoSin caducidadSin caducidadNinguno de los planes de %s soportan un período de prueba.O.KUna vez que caduque tu licencia todavía puedes utilizar la versión gratuita pero NO tendrás acceso a las funciones de %s.Una vez que tu licencia caduque no podrás seguir utilizando %s, a no ser que lo actives de nuevo con una licencia premium válida.InscribirseDarse de bajaOpt in to get email notifications for security & feature updates, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.¡Inscríbite para hacer "%s" Mejor!OtraCorreo electrónico del propietarioID del propietarioNombre del propietarioCompatible con PCIEl complemento de pago se debe implementar en Freemius.Dirección de correo electrónico de PayPalPagosLos pagos son en USD y se procesan mensualmente por medio de PayPal.PlanEl plan %s no existe, por lo tanto, no puedes comenzar un período de prueba.El plan %s no admite un período de prueba.ID del planContacta aquí con nosotrosPor favor contáctanos con el siguiente mensaje:Por favor descarga %s.Por favor, introduce la clave de licencia que recibiste en el correo electrónico al realizar la compra:Por favor, introduce la clave de licencia para activar el modo de depuración:Siéntete libre de proporcionarnos estadísticas de tu sitio web o social media, p.ej. visitas únicas mensuales, número de suscriptores de correo electrónico, seguidores, etc. (mantendremos esta información confidencial)Por favor, sigue estos pasos para completar la actualizaciónIndica si deseas que te contactemos para actualizaciones de seguridad y nuevas funciones, contenido educativo y ofertas ocasionales:Ten en cuenta que no podremos abaratar los precios desactualizados para renovaciones/nuevas suscripciones después de una cancelación. Si eliges renovar la suscripción manualmente en el futuro, después de un aumento de precio, que generalmente ocurre una vez al año, se te cobrará el precio actualizado.Por favor, danos detalles de como pretendes promocionar %s (por favor, se lo más específico que puedas)Por favor, dinos tu nombre completo.PluginPágina web del pluginID del pluginInstalar pluginRegistro de cambiosDescripciónFAQCaracterísticas y preciosInstalaciónOtras notasValoracionesEl plugin es un "Serviceware" lo que significa que no tiene una versión de código premium.PluginsSincronizar plugins y temasPremiumLa versión Premium %s ha sido activada con éxito.Versión del complemento premium ya instalada.Versión premiumVersión premium ya activa.PrecioPolítica de privacidadProcederID del procesoProcesandoProductosSumario del programaMétodos de promociónProvinciaClave públicaComprar licenciaComprar másComentarios rápidosCuotaReenviar correo electrónico de activación¡Envíanos nuevos usuarios a nuestro %s y gana %s de comisión en cada venta satisfactoria que nos hayas referido!Renovar la licenciaRenueva tu licencia ahoraPeticionesRequires PHP VersionNecesita la versión de WordPressReset Deactivation SnoozingResultadoSDKRuta del SDKGuardar %sGuardadoCrons programadosCapturas de pantallaBuscar por direcciónClave secretaPágina segura HTTPS %s, desde un dominio externoParece que estamos teniendo algún problema temporal con tu cancelación de la suscripción. Vuelve a intentarlo en unos minutos.Parece que estamos teniendo algún problema temporal con tu cancelación de prueba. Vuelve a intentarlo en unos minutos.Parece que tienes la última versión.Seleccionar paísEnviar clave de licenciaGuardar opción en BDSharing diagnostic data with %s helps to provide functionality that's more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to.Simular actualización de redSimular período de pruebaLicencia para un único sitioID del sitioSitio dado de alta correctamente.SitiosSaltar y %sRutaSnooze & %sDe este modo, podrás reutilizar la licencia cuando el %s ya no esté activo.Social media (Facebook, Twitter, etc.)Disculpa las molestias y estamos aquí para ayudarte si nos das una oportunidad.Lo sentimos, no podemos completar la actualización de correo electrónico. Ya hay registrado otro usuario con esa dirección de correo electrónico.InicioIniciar DepuraciónComenzar el período de pruebaComenzar mi período gratuito de %sEstadoStay ConnectedDetener la depuraciónEnviarEnviar y %sSuscripciónSoporteForo de soporteSincronizar datos desde el servidorTax / Núm IVATérminos de servicio¡Gracias por darnos la oportunidad de arreglarlo! Acabamos de enviar un mensaje a nuestro personal técnico. Nos pondremos en contacto contigo tan pronto como tengamos una actualización de %s. Apreciamos tu paciencia.Gracias por aplicar a nuestro programa de asociados, infortunadamente, de momento hemos decidido rechazar tu petición. Por favor, prueba de nuevo en 30 días.Gracias por aplicar a nuestro programa de afiliados, revisaremos tu petición durante los próximos 14 días y te volveremos a contactar con información adicional.Thank you for updating to %1$s v%2$s!¡Muchas gracias por utilizar %s y sus complementos!¡Muchas gracias por utilizar %s!¡Muchas gracias por utilizar nuestros productos!¡Gracias!¡Gracias %s!Gracias por confirmar el cambio de propiedad. Se envió un correo electrónico a %s para su aprobación final.The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license.%s ha roto mi sitioEl %s no funcionabaEl %s no funciona como esperaba%s es genial, pero necesito una característica que no soportáisEl %s no funciona%s de repente ha dejado de funcionarThe following products'El proceso de instalación ha comenzado y puede tardar unos minutos en completarse. Por favor, espera hasta que se finalice - no actualices esta página.The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$sThe products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$sEl paquete de plugin remoto no contiene una carpeta con el Slug deseado y el cambio de nombre no funcionó.La actualización de %s se completó con éxito.TemaCambiar temaTemasHay una %s de %s disponible.Hay una nueva versión de %s disponible.There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn't work, contact the %s's author with the following:Este puglin no ha sido marcado como compatible con tu versión de WordPress.Este plugin no ha sido probado con tu versión actual de WordPress.This plugin requires a newer version of PHP.This will allow %s toTimestampTítuloTo avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.To ensure compatibility and avoid conflicts with your installed plugins and themes.Para entrar en el modo de depuración, introduce la clave secreta del propietario de la licencia (UserID = %d), que puedes encontrar en la sección "Mi perfil" de tu panel de control de usuario:To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.To provide additional functionality that's relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.TotalMunicipioPeríodo de prueba gratuitoTipoNo es posible conectarse al sistema de archivos. Por favor, confirma tus credenciales.Licencias ilimitadasActualizaciones IlimitadasComisiones Ilimitadas.Hasta %s sitiosActualizarActivar licenciaActualizaciones, anuncios, marketing, sin spamActualizarCargar y activar la versión descargadaPanel de escritorio del usuarioID de usuarioClave de usuarioUsuariosValorEl correo de verificación se acaba de enviar a %s. Si no puedes encontrarlo después de 5 min, comprueba tu carpeta de spam.VerificadoVerificar correo electrónicoLa versión %s se ha lanzado.View %s StateView Basic %s InfoView Basic Profile InfoView Basic Website InfoView Diagnostic InfoView License EssentialsView Plugins & Themes ListVer detallesVer las funciones de pagoAtencionNo vemos ninguna licencia activa asociada a esa dirección de correo electrónico, ¿estás seguro de que es la dirección de correo electrónico correcta?No podemos encontrar tu dirección de correo electrónico en el sistema, ¿estás seguro de que es la dirección de correo electrónico correcta?No pudimos cargar la lista de complementos. Probablemente sea un problema por nuestra parte, por favor, inténtalo de nuevo en unos minutos.We have introduced this opt-in so you never miss an important update and help us make the %s more compatible with your site and better at doing what you need it to.Hemos realizado algunas optimizaciones al %s, %sNos aseguraremos de ponernos en contacto con tu empresa de alojamiento web y resolver el problema. Recibirás un correo electrónico de seguimiento a %s tan pronto tengamos una actualización.Estamos emocionados de introducir la integración de Freemius a nivel de red.Sitio web, correo electrónico y estadísticas de social media (opcional)¡Bienvenido a %s! Para empezar, introduce tu clave de licencia:¿Qué esperas?¿Qué característica?¿Cual es tú %s?¿Con qué precio te sentirías cómodo pagando?¿Que has estado buscando?¿Cuál es el nombre de %s?¿Dónde vas a promocionar %s?WordPress & PHP versions, site language & titlePágina del plugin en WordPress.orgWould you like to merge %s into %s?¿Deseas continuar con la actualización?SiSi - %sYes - both addresses are mineVamos, adelanteYes - move all my data and assets from %s to %sYes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s.Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.Yes, %2$s is a new and different website that is separate from %4$s.Ya utilizaste un período de prueba antes.Estás a sólo 1-click de comenzar tu %1$s días de prueba gratuita del plan %2$s.¡Está todo listo!Estás ejecutando %s en modo de prueba.Estás a sólo un paso - %sTodavía puedes disfrutar de todas las funciones de %s pero no tendrás acceso a soporte y actualizaciones de %s.No tienes una licencia válida para acceder a la versión premium.Tienes una licencia %s.Has comprado una licencia %s.Has actualizado correctamente tu %s.You marked this website, %s, as a temporary duplicate of %s.You marked this website, %s, as a temporary duplicate of these sitesEs posible que te lo hayas perdido, pero no tienes que compartir ningún dato y puedes solo aceptar %s.You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s.Ya has optado por nuestro seguimiento de uso, lo que nos ayuda a seguir mejorando %s.Ya has optado por nuestro seguimiento de uso, lo que nos ayuda a seguir mejorando.Tu complemento %s del plan se actualizó con éxito.Tu prueba gratuita de %s fue cancelada con éxito.Tu licencia %s ha sido marcada como etiqueta blanca para ocultar información sensible del administrador de WP (por ejemplo, tu correo electrónico, clave de licencia, precios, dirección de facturación y facturas). Si alguna vez deseas revertirlo, puedes hacerlo fácilmente a través de tu %s. Si se trata de un error, también puedes %s.Tu licencia %s ha sido desactivada correctamente.Your WordPress user's: first & last name, and email addressTu cuenta se ha activado correctamente con el plan %s.¡Tu aplicación al programa de afiliación para %s ha sido aceptada! Entra en tu área de afiliado desde: %s.Tu cuenta de afiliado ha sido suspendida temporalmente.Tu email ha sido verificado correctamente - ¡Eres IMPRESIONANTE!Tu período de prueba ha caducado. %1$sActualiza ahora %2$s para continuar usando el %3$s sin interrupciones.Tu período de prueba ha caducado. Todavía puedes seguir usando todas nuestras funciones gratuitas.Tu licencia ha sido cancelada. Si crees que es un error, ponte en contacto con el servicio de asistencia.Tu licencia ha caducado. %1$sActualiza ahora %2$s para continuar usando el %3$s sin interrupciones.Tu licencia ha caducado. Todavía puedes seguir usando todas las funciones de %s, pero tendrás que renovar tu licencia para seguir recibiendo actualizaciones y soporte.Tu licencia ha caducado. Puedes seguir usando el plan gratuito %s para siempre.Tu licencia fue activada correctamente.Tu licencia fue desactivada correctamente, has vuelto al plan %s.Tu nombre fue actualizado correctamente.Tu plan se activó con éxito.Tu plan se cambió correctamente a %s.Tu plan se actualizó con éxito.Tu servidor está bloqueando el acceso al API de Freemius, que es crucial para sincronizar %1$s. Por favor, contacta a tu proveedor de hosting para permitir el acceso de %2$sTu suscripción ha sido cancelada correctamente. Tu %s licencia del plan caducará en %s.Tu versión de prueba se ha iniciado con éxito.Código postalBien hechoactivate a license hereActivo%s no se puede ejecutar sin %s.%s no se puede ejecutar sin el plugin.Atenciónpermitirquedan %sActivandoañoAPIDescartarDepurandoFelicidadesBloqueadoConectadoDescargar la últimaDescargar la última versión gratuitaMensualCaducidadRutaEnviando correo electrónicomeAnualAnualmenteUna vezPlanSin clave secretaVersiones SDKLicenciaSincronizarSincronizar licenciaAutorApagadoEncendidobasado en %sComenzar el período de prueba gratuitoDescartarDescartarcomplete the opt-indatadaysdesactivandodelegar%sNO%s me envíes actualizaciones de seguridad y nuevas funcionalidades, contenido educativo y ofertas.Plan %sFacturado %sEl mejorHeyOopsHey %s,hourhoursInstaladoVayalicenciaSitiosmsnueva versión Betanueva versiónno verificadoPrecioPrecioopcionalVersiónproductsrevertirlo ahorasegparece que la clave que has introducido no coincide con nuestros registros.envíame actualizaciones de seguridad y nuevas funcionalidades, contenido educativo y ofertas.saltarcomenzar el período de pruebasuscripcióncambiandothe above-mentioned sitesla última versión %s aquíperíodo de pruebaPeríodo de Prueba GratuitoBorrarDegradarEditarOcultarInscribirseDarse de bajaComprarMostrarSaltarActualizarActualizarhace %sfreemius/languages/freemius-ta.mo000064400000226640146725417150013135 0ustar00Þ•ìϼ!ø,Aù,n;-hª-d.Sx.%Ì. ò. þ. //6$/´[/_0#p0”0 ®0 »0 Å0Ð0×0ß0è0ð0@ù0H:1ƒ1O–1æ1ê1 2)212A2I2 R2^2o2„2š2&«2-Ò23 33.3C3V3]35e3›3£3 ³3 ½3'É3ñ3 4 4!4o24¢4ž©4GH55©¯5Y6l6"ˆ6«62È6!û6a707°7Â7Ù7è7ð78 88$8-858 :8 F8T8 f8r88–8’ª8 =9H9\9 p9 }9 ‡9•9¦9YÂ9:+: <:H:Q:V:f:(:1¨:%Ú::;;;@;Q;Y; i; t;;—; Ÿ;©; ®;¹;xÌ;”E< Ú< ç<ñ< ==t%=š=´=Ê=à=é=ý=> 8>¹C>—ý>[•?fñ?X@ ^@l@Yp@aÊ@,A2ARA ZA hA;vA²A·Aþ¾A½B ÂB ÍB ÚBçBjöBaC pCzC3ƒC2·CêC~þCU}DÓDïDE)#E-ME{ESEãE'ûE#FM&F7tFg¬FpG…GŸGy¥GH8H XHdHwHH  HÁH ÉH1ÓH.IO4I„IAJyFJÀJàJaöJXKB\K,ŸKÌK ÑK ÞKëK L "L-L4Lëf*g&AgZhgTÃgRh.kh.šh9ÉhZi3^i<’ibÏiP2jUƒj_Ùjš9kKÔk( lGIl#‘l%µl)Ûl$mU*m)€mªm¼mÙm;îm6*n>an n¦nÁnán$÷no6oRono&Œo*³o7Þop-pKp3dp˜p­pÃpÛpïp* q17qiq…q#™q½qÙqëq ûqr'r>r Sr`rNir¸r×rõrs s1sBs1]ss—s«s»s Ìs Øs ås ðsýs tC!tetQjt¼t Ìt Ùtãtþtu u#u 2u Ÿ=fŸ)¤ŸXΠ''¢ O¢VY¢P°¢££"/¤iR¤k¼¤(¥@G¥_ˆ¥Mè¥36¦j¦e}§ùã¨ùÝ©ת1öª(«ò;«.¬ E­†R­$Ù­3þ­(2®[®Û®à®Yç®A²@`²4¡² Ö²-ã²K³]´!s´•´¨ž´yGµÁµ>áµ$ ·|E¸†Â¸YI¹‰£¹„-ºg²ºÃ»>Þ»c¼ ¼´‹¼‚@½çýù«¾_¥¿ÀÀP#Á{tÁðÁ@ ÂJM ˜Â<¹Âö Ø޵þTÄuÅ¡‰ÆV+ÇN‚ÈZÑÈÀ,ÉíÉÈñÉœºÊWË4gË"œËx¿ËY8̲̒ÌÂÌ(ÕÌ þÌ Í5ÍLÍ¢eÍÎ Î!Î%Î,Î?ÎUÎ.pΟΠ¦Î²Î;ÌÎÏ Ï%Ï=ÏGSÏq›ÏR Ð*`ЋСбЛËбgÑ;Ò'UÒ*}Òy¨Ò"ÓP&ÓçwÔ_Õ%Õd¥Õ Ö=Ö![Ö.}Ö ¬Ö¤ºÖQ_×1±×|ã×`ØrvØféØPÙ;cÙ‹ŸÙ.+ÚZÚ|ÚÚ¯WÜoÝRwÞþÊàOÉáâF2âyâ4•â ÊâÔâíâ$ñâã+2ã$^㎃ã!ä,4äaä˜iäå1“åqÅå7æ=Wæ•æ ¨æ³æ$Éæ=îæX,ç(…ç ®ç4¹ç(îç1èIè{eèáèFûéFBê'‰êA±êóêë ë$ë'8ë"`ë,ƒë °ëž»ëÙZìó4í¢(î@Ëî$ ï 1ï?ïXï#qï•ïH²ïûïð/ð>4ðsðötñkò7„òM¼ò ó ó>ó Nó[óxó Žó.›ó™Êó\dõ~ÁöG@÷…ˆ÷øø73ørkù1ÞùWú•húAþú@@ûãû˜eüIþü Hý"Uýxý.Žýg½ýË%þ¯ñþ"¡ÿÄÿÚÿ ðÿ!ýÿ—2"ÊFí?4"t!—1¹Šë!v˜1QjYp6ÊUGW=ŸlÝJÊi¸4„írÎ ZÏ * #E ki `Õ &6 s] 9Ñ Ž  š ¤ ˆ³ Ú< 1°ICú>~OJÎMgôi&^w…ýŒà•û{‘ Çà×Ô¸‰Í`åÏFHp_vЈG ÆÐ S—!.ë!"'#"7K"Mƒ"Ñ"Ú"!í"3#C#V#Z#.z#'©#*Ñ#*ü#D'$cl$Ð$ì$ %O %\%l%'|%¤%º% Ð%"Ú%ý%& &'"&J&N&0Q&u‚&ø&'B8'{'„'ž(4·(ì())%)'?)g)o)‚)˜)8›)%Ô)Eú) @*M*m*ƒ*ã‡*k+„+@ˆ+É+ Ù+;ã+!,!A, c,m,‰,¢,¾,%Þ,----!F-!h-Š-»-^l}¡ÚGÇ@!Üu 7IÛ¤WžUT”¸[¶÷’¨ç÷  z( ‡i1ö˜#ÿü* eËh„.dVóªùr°úKÄ:õ}M´ÑoAÃñ="Á®C8g/w•Žðt£hS±>ìÖäK L;$UÓ JÜ'´ëV¹ó¤ºÌ®L‘…³¢þšZX0á \pW見"êH™nå…À{8àF¿kÐãÐÍäÒ(~`ª¸•kb,)u2—¡Ú½Ngì0yˆù“©Èq˜‘jé{ê \Þ_ÁsPïÙã «­ÝYX͇ƒd+¬íÄè‹­©†PÂaÕ—üß4y‰~ & Øî|4vÛ €oEñºR_A×/ŒÙ”N!µF^Õæ[ýq2·û-’D¯É£J1Œ=ÿr áò§²¼î@€ÝBµzâ籆cDÏØÌ–ò„?SO›G)íÔ%+t°Q3 ¬cÈ5âœôË5]9]¶l7mO ¢ßÆév#xŸf¾ÂYŽI™Eƒ6¥`exZsÊÓM¹õˆ«½¾»;p'abý3jÒmΦnèæ Çå‚Ÿë ž²À,¥ûÞ<ç΂¼öþ:QÏÆ×ø|Ñ·¿>*‰T–9¦Bw³à?ÅH<$ŠfiÊR&ÖÉ.¯ð%ô ›C‹“øÅœšúÔ6 %s to access version %s security & feature updates, and support. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is the new owner of the account.%s minimum payout amount.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.APIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.An unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre you sure you want to delete all Freemius data?Are you sure you want to proceed?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBetaBillingBilling & InvoicesBlockingBlog IDBodyBundle PlanBusiness nameBuy a license nowBuy licenseCan't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanCheckoutCityClear API CacheClear Updates TransientsClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDelegate to Site AdminsDelete All AccountsDetailsDon't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload the latest %s versionDownload the latest versionDownloadedDue to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.During the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEndEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used for the upgrade below and we will resend you the license key.ErrorError received from the server:ExpiredExpires in %sExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.FreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFull nameFunctionGet commission for automated subscription renewals.Get updates for bleeding edge Beta versions of %s.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!How do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I can't pay for it anymoreI couldn't understand how to make it workI don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid module ID.Invalid site details collection.InvoiceIs ActiveIt looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's not what I was looking forJoin the Beta programJust letting you know that the add-ons information of %s is being pulled from an external server.KeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense KeyLicense keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerMessageMethodMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNetwork BlogNetwork UserNewNew Version AvailableNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires WordPress VersionResultSDKSDK PathSave %sScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSimulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSocial media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart TrialStart my free %sStateSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.TimestampTitleTotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser IDUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We made a few tweaks to the %s, %sWe're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress.org Plugin PageWould you like to proceed with the update?YesYes - %sYou already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have successfully updated your %s.You might have missed it, but you don't have to share any data and can just %s the opt-in.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onactive add-onActiveaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismissdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,installed add-onInstalledinterjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew Beta versionnew versionnot verifiednounPricenounPricingproduct versionVersionsecondssecsend me security & feature updates, educational content and offers.skipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialsubscriptionswitchingthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Sankar Srinivasan , 2019 Language-Team: Tamil (http://www.transifex.com/freemius/wordpress-sdk/language/ta/) Language: ta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js %s பதிபà¯à®ªà®¿à®©à¯ பாதà¯à®•à®¾à®ªà¯à®ªà¯ & வசதி மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ மறà¯à®±à¯à®®à¯ உதவிகà¯à®•à¯%s.%1$sன௠விலையà¯à®³à¯à®³ பதிபà¯à®ªà¯ à®à®±à¯à®•à®©à®µà¯‡ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. %2$s வசதிகளை பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ அதை செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯. %3$sவரà¯à®•à®¿à®©à¯à®± அனைதà¯à®¤à¯ பணம௠செலà¯à®¤à¯à®¤à¯à®¤à®²à¯à®•à®³à¯ˆà®¯à¯à®®à¯ %1$s உடன௠நிறà¯à®¤à¯à®¤à¯à®•à®¿à®±à®¤à¯, மறà¯à®±à¯à®®à¯ உஙà¯à®•à®³à¯ %2$s திடà¯à®Ÿ உரிமம௠%3$sல௠காலாவதியாகிறதà¯.%1$s உடனடியாக அனைதà¯à®¤à¯ எதிரà¯à®µà®°à¯à®®à¯ பணம௠செலà¯à®¤à¯à®¤à®²à¯à®•à®³à¯ˆ நிறà¯à®¤à¯à®¤à¯à®®à¯ மறà¯à®±à¯à®®à¯ உஙà¯à®•à®³à¯ %s திடà¯à®Ÿ உரிமம௠%sல௠காலாவதியாகà¯à®®à¯."%s" செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ˆ à®®à¯à®Ÿà®¿à®¯à¯à®™à¯à®•à®³à¯%s ஆடà¯-ஆனை வாஙà¯à®•à®¿à®µà®¿à®Ÿà¯à®Ÿà¯€à®°à¯à®•à®³à¯.%s நிறà¯à®µà¯à®¤à®²à¯à®•à®³à¯%s உரிமஙà¯à®•à®³à¯%s à®®à¯à®©à¯à®ªà¯%sம௠அதன௠ஆடà¯-ஆனà¯à®•à®³à¯à®®à¯à®’ர௠வாடிகà¯à®•à¯ˆà®¯à®¾à®³à®°à¯ பà¯à®¤à¯ உரிமம௠வாஙà¯à®•à¯à®®à¯à®ªà¯‹à®¤à¯ %s லாபப௠பஙà¯à®•à¯€à®Ÿà¯.ஆட௠ஆன௠விலையà¯à®³à¯à®³à®¤à¯ எனà¯à®ªà®¤à®¾à®²à¯ %sன௠விலையிலà¯à®²à®¾ à®®à¯à®©à¯à®©à¯‹à®Ÿà¯à®Ÿà®®à¯ ரதà¯à®¤à®¾à®©à®¤à¯. நீஙà¯à®•à®³à¯ உரிமம௠வாஙà¯à®•à®¿à®ªà¯ பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ˆà®¤à¯ தொடரலாமà¯.%s ஒர௠விலையà¯à®³à¯à®³ ஆடà¯à®†à®©à¯. பà¯à®³à®•à¯à®‡à®©à¯ செயலà¯à®ªà®Ÿ நீஙà¯à®•à®³à¯ உரிமம௠வாஙà¯à®•à®µà¯‡à®£à¯à®Ÿà¯à®®à¯à®•à®£à®•à¯à®•à®¿à®©à¯ பà¯à®¤à®¿à®¯ உரிமையாளர௠%s.%s கà¯à®±à¯ˆà®¨à¯à®¤à®ªà®Ÿà¯à®š பணம௠பெறà¯à®¤à®²à¯.%s அலà¯à®²à®¤à¯ அதிகமாக%s மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯†à®£à¯%s மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯†à®£à¯à®•à®³à¯%s sec%s நடà¯à®šà®¤à¯à®¤à®¿à®°à®®à¯%s நடà¯à®šà®¤à¯à®¤à®¿à®°à®™à¯à®•à®³à¯%s à®®à¯à®±à¯ˆ%s à®®à¯à®±à¯ˆà®•à®³à¯%s பாதà¯à®•à®¾à®ªà¯à®ªà¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ மறà¯à®±à¯à®®à¯ உதவிகà¯à®•à¯ %sவரà¯à®®à®¾à®©à®®à¯ அதிகரிகà¯à®•, à®®à¯à®¤à®²à¯ தள வரà¯à®•à¯ˆà®¯à®¿à®²à¯ %s tracking cookie.%sன௠விலையà¯à®³à¯à®³ வசதிகளà¯à®‰à®™à¯à®•à®³à¯à®•à¯à®•à¯ வேணà¯à®Ÿà®¿à®¯ தளஙà¯à®•à®³à®¿à®²à¯ உரிமதà¯à®¤à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤ %s கிளிக௠செயà¯à®• %sAPI←➤கணகà¯à®•à¯à®•à®£à®•à¯à®•à¯ விபரஙà¯à®•à®³à¯à®šà¯†à®¯à®²à¯à®•à®³à¯à®šà¯†à®¯à®²à¯à®ªà®Ÿà¯à®¤à¯à®¤à¯%s செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯%s திடà¯à®Ÿà®®à¯ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤%s வசதிகளை செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà®¿à®²à¯ˆà®¯à®¿à®²à¯à®²à®¾ பதிபà¯à®ªà¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®‰à®°à®¿à®®à®®à¯ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®®à¯€à®¤à®®à¯à®³à¯à®³ எலà¯à®²à®¾ தளஙà¯à®•à®³à®¿à®²à¯à®®à¯ உரிமதà¯à®¤à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•à®µà®²à¯ˆà®ªà¯à®ªà®¿à®©à¯à®©à®²à®¿à®²à¯ உளà¯à®³ எலà¯à®²à®¾ தளஙà¯à®•à®³à®¿à®²à¯à®®à¯ உரிமதà¯à®¤à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•à®†à®Ÿà¯-ஆன௠செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®šà¯†à®¯à®²à¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯%sகà¯à®•à®¾à®© ஆடà¯à®†à®©à¯à®•à®³à¯Module %sன௠ஆடà¯à®†à®©à¯à®•à®³à¯à®…டà¯à®¤à¯à®¤ தளதà¯à®¤à¯ˆà®šà¯ சேரà¯à®•à¯à®•à®†à®Ÿà¯ ஆனà¯à®†à®Ÿà¯-ஆனà¯à®¸à¯à®†à®Ÿà¯à®†à®©à¯ WordPress.org அலà¯à®²à®¤à¯ Freemius à®à®¤à®¾à®µà®¤à¯ ஒனà¯à®±à®¿à®²à¯ வரிசைபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯ படà¯à®Ÿà®¿à®°à¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯.à®®à¯à®•à®µà®°à®¿à®®à¯à®•à®µà®°à®¿ வரி %dAffiliateபà¯à®°à®¿à®¨à¯à®¤à¯à®£à®°à¯à®µà¯à®µà®¿à®²à¯ˆà®¯à®¿à®²à¯à®²à®¾ %sகà¯à®•à¯à®ªà¯ பிறகà¯, கà¯à®±à¯ˆà®¨à¯à®¤à®³à®µà¯ %s செலà¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯à®’பà¯à®ªà¯à®•à¯à®•à¯Šà®£à¯à®Ÿà¯ உரிமதà¯à®¤à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•à®…னைதà¯à®¤à¯ வேணà¯à®Ÿà¯à®•à¯‹à®³à¯à®•à®³à¯à®…னைதà¯à®¤à¯ மாதிரிகளà¯à®…னà¯à®®à®¤à®¿à®¤à¯à®¤à¯ தொடரà¯à®•à®‡à®²à¯à®²à®¾à®µà®¿à®Ÿà¯à®Ÿà®¾à®²à¯, Network-level கணகà¯à®•à¯à®ªà¯ பகà¯à®•à®¤à¯à®¤à®¿à®²à¯ எபà¯à®ªà¯‹à®¤à¯ வேணà¯à®Ÿà¯à®®à®¾à®©à®¾à®²à¯à®®à¯ உரிமதà¯à®¤à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®•à¯ கொளà¯à®³à®²à®¾à®®à¯.தொகை%sலிரà¯à®¨à¯à®¤à¯ %s (பணம௠செலà¯à®¤à¯à®¤à®¿à®¯) பதிபà¯à®ªà®¿à®©à¯ தானியஙà¯à®•à®¿ பதிவிறகà¯à®•à®®à¯à®®à¯, நிறà¯à®µà¯à®¤à®²à¯à®®à¯ %sல௠ஆரமà¯à®ªà®®à®¾à®•à¯à®®à¯. இதை நீஙà¯à®•à®³à¯‡ செயà¯à®¯ விரà¯à®®à¯à®ªà®¿à®©à®¾à®²à¯ ரதà¯à®¤à¯ செயà¯à®¯à¯à®®à¯ படà¯à®Ÿà®©à¯ˆ à®…à®´à¯à®¤à¯à®¤à®µà¯à®®à¯. உபயோகிபà¯à®ªà®¾à®³à®°à®¿à®©à¯ பீடà¯à®Ÿà®¾à®µà¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•à¯ˆà®¯à®¿à®²à¯, பà¯à®¤à®¿à®¯ தவற௠உரà¯à®µà®¾à®•à®¿à®¯à¯à®³à¯à®³à®¤à¯.எனà¯à®©à®¤à¯†à®©à¯à®±à¯‡ தெரியாத ஒர௠தவற௠நேரà¯à®¨à¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà®¤à¯à®Žà®šà¯à®šà®°à®¿à®•à¯à®•à¯ˆ: %sன௠மà¯à®©à¯à®©à¯‹à®Ÿà¯à®Ÿ Beta பதிபà¯à®ªà®¿à®©à¯ மேமà¯à®ªà®Ÿà¯à®Ÿ வடிவம௠பழைய பதிபà¯à®ªà®¿à®©à¯ மீத௠நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯. அனாமதேய பினà¯à®©à¯‚டà¯à®Ÿà®®à¯à®®à¯€à®¤à®®à¯à®³à¯à®³ அனைதà¯à®¤à¯ தளஙà¯à®•à®³à®¿à®©à¯ மீதà¯à®®à¯ பிரயோகிகà¯à®•à®µà®²à¯ˆà®ªà¯à®ªà®¿à®©à¯à®©à®²à®¿à®©à¯ அனைதà¯à®¤à¯ தளஙà¯à®•à®³à®¿à®©à¯ மீதà¯à®®à¯ பிரயோகிகà¯à®•Affiliate ஆக விணà¯à®£à®ªà¯à®ªà®¿à®¯à¯à®™à¯à®•à®³à¯à®…னைதà¯à®¤à¯ Freemius தகவலையà¯à®®à¯ அழிகà¯à®• விரà¯à®ªà¯à®ªà®®à®¾?மேலே தொடர விரà¯à®ªà¯à®ªà®®à®¾?வாடிகà¯à®•à¯ˆà®¯à®¾à®³à®°à¯ 30 நாடà¯à®•à®³à¯à®•à¯à®•à¯ பணம௠திரà¯à®®à¯à®ªà®ªà¯ பெறலாம௠Refund எனà¯à®ªà®¤à®¾à®²à¯ உஙà¯à®•à®³à¯à®•à¯à®•à¯ லாபப௠பஙà¯à®•à¯€à®Ÿà¯ 30 நாடà¯à®•à®³à¯à®•à¯à®•à¯à®ªà¯ பிறகே கிடைகà¯à®•à¯à®®à¯.à®®à¯à®©à¯à®©à®°à¯‡ தெரிவ௠செயà¯à®¤à®¿à®°à¯à®¨à¯à®¤à®¾à®²à¯ மடà¯à®Ÿà¯à®®à¯‡ தானியஙà¯à®•à®¿ நிறà¯à®µà¯à®¤à®²à¯ நடைபெறà¯à®®à¯.%sல௠தானாக பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•à®¿à®±à®¤à¯à®¤à®¾à®©à®¿à®¯à®™à¯à®•à®¿ நிறà¯à®µà¯à®¤à®²à¯à®‰à®¤à¯à®¤à¯‡à®š மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà¯†à®£à¯à®…டி தூளà¯Affiliate ஆகà¯à®™à¯à®•à®³à¯à®ªà¯€à®Ÿà¯à®Ÿà®¾à®µà®šà¯‚லà¯à®ªà®¿à®²à¯ & இனà¯à®µà®¾à®¯à¯à®¸à¯à®¤à®Ÿà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯Blog IDஅமைபà¯à®ªà¯à®•à¯‚டà¯à®Ÿà¯à®¤à¯à®¤à®¿à®Ÿà¯à®Ÿà®®à¯à®¤à¯Šà®´à®¿à®²à®¿à®©à¯ பெயரà¯à®ªà¯à®¤à¯ உரிமம௠வாஙà¯à®•à¯à®™à¯à®•à®³à¯à®‰à®°à®¿à®®à®®à¯ வாஙà¯à®•License Key காணவிலà¯à®²à¯ˆà®¯à®¾?ரதà¯à®¤à¯%s ரதà¯à®¤à¯ செயà¯à®• & தொடரà¯à®•à®¨à®¾à®©à¯ %s஠இநà¯à®¤ தளதà¯à®¤à®¿à®²à¯‹ அலà¯à®²à®¤à¯ பிற தளதà¯à®¤à®¿à®²à¯‹ உபயோகிகà¯à®• விரà¯à®®à¯à®ªà®µà®¿à®²à¯à®²à¯ˆ எனà¯à®ªà®¤à®¾à®²à¯ %sகà¯à®•à¯ உதவியோ, பாதà¯à®•à®¾à®ªà¯à®ªà¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯‹ தேவையிலà¯à®²à¯ˆ. %s஠ரதà¯à®¤à¯ செயà¯à®¯à®µà¯à®®à¯.%s ரதà¯à®¤à¯ செயà¯à®¯à®µà®¾?நிறà¯à®µà¯à®¤à®²à¯ˆ ரதà¯à®¤à¯à®šà¯†à®¯à¯à®šà®¨à¯à®¤à®¾à®µà¯ˆ ரதà¯à®¤à¯ செயà¯à®µà¯†à®³à¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ ரதà¯à®¤à¯ செயà¯à®•à®°à®¤à¯à®¤à®¾à®©à®¤à¯%s ரதà¯à®¤à®¾à®•à®¿à®±à®¤à¯%s ரதà¯à®¤à®¾à®•à®¿à®±à®¤à¯...சநà¯à®¤à®¾ ரதà¯à®¤à®¾à®•à®¿à®±à®¤à¯à®µà¯†à®³à¯à®³à¯‹à®Ÿà¯à®Ÿà®¤à¯à®¤à¯ˆ ரதà¯à®¤à¯ செயà¯à®¤à®¾à®²à¯ அனைதà¯à®¤à¯ விலையà¯à®³à¯à®³ வசதிகளà¯à®®à¯ நிறà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®®à¯. சரியா?உரிமம௠மாறà¯à®±à®‰à®°à®¿à®®à¯ˆ மாறà¯à®±à®®à¯à®¤à®¿à®Ÿà¯à®Ÿà®®à¯ மாறà¯à®±Checkoutஊரà¯API Cache நீகà¯à®•Clear Updates Transientsபிளகà¯à®‡à®©à¯à®©à¯ˆ அநாமதேயமாக பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ இஙà¯à®•à¯‡ கிளிக௠செயà¯à®¯à®µà¯à®®à¯%s கà¯à®±à®¿à®¤à¯à®¤ மதிபà¯à®ªà¯€à®Ÿà¯ & விமரà¯à®šà®©à®™à¯à®•à®³à¯ˆ கிளிக௠செயà¯à®¤à¯ காணà¯à®•à®•à®¿à®³à®¿à®•à¯ செயà¯à®¤à¯ %dன௠மà¯à®´à¯à®…ளவ௠திரைநகல௠காணà¯à®•à®¤à®¯à®¾à®°à®¿à®ªà¯à®ªà¯à®•à®³à¯Codeஒதà¯à®¤à®¿à®šà¯ˆà®µà¯ உயரà¯à®¨à®¿à®²à¯ˆà®¤à¯Šà®Ÿà®°à¯à®ªà¯à®‰à®¤à®µà®¿à®¯à¯ˆ அணà¯à®•à®µà¯à®®à¯à®¤à¯Šà®Ÿà®°à¯à®ªà¯ கொளà¯à®³à¯à®™à¯à®•à®³à¯à®ªà®™à¯à®•à¯†à®Ÿà¯à®¤à¯à®¤à¯‹à®°à¯%s஠செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤ à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ.நாடà¯Cron மாதிரிதேதிசெயலà¯à®¨à®¿à®±à¯à®¤à¯à®¤à¯à®‰à®°à®¿à®®à®¤à¯à®¤à¯ˆ செயலà¯à®¨à®¿à®±à¯à®¤à¯à®¤%s஠செயலà¯à®¨à®¿à®±à¯à®¤à¯à®¤à®¿à®©à®¾à®²à¯‹, அகறà¯à®±à®¿à®©à®¾à®²à¯‹ பிற தளஙà¯à®•à®³à®¿à®²à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ வாயà¯à®ªà¯à®ªà®¿à®°à¯à®¨à¯à®¤à¯à®®à¯, உரிமம௠தானாகவே செயலிழகà¯à®•à¯à®®à¯.உரிமதà¯à®¤à¯ˆ செயலà¯à®¨à®¿à®±à¯à®¤à¯à®¤à¯à®µà®¤à®¾à®©à®¤à¯, அனைதà¯à®¤à¯ விலையà¯à®³à¯à®³ வசதிகளையà¯à®®à¯ நிறà¯à®¤à¯à®¤à®¿à®µà®¿à®Ÿà¯à®®à¯. ஆனாலà¯à®®à¯ பிற தளஙà¯à®•à®³à®¿à®²à¯ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à®¾à®®à¯. தொடரலாமா?செயலà¯à®¨à®¿à®±à¯à®¤à¯à®¤à¯Debug Logதள நிரà¯à®µà®¾à®•à®¿à®•à®³à¯à®•à¯à®•à®¾à®© சிறபà¯à®ªà®¾à®³à®°à¯à®…னைதà¯à®¤à¯ கணகà¯à®•à¯à®•à®³à¯ˆà®¯à¯à®®à¯ அழிகà¯à®•à®µà®¿à®ªà®°à®™à¯à®•à®³à¯%s ரதà¯à®¤à¯à®šà¯†à®¯à¯à®¯ வேணà¯à®Ÿà®¾à®®à¯ - அதறà¯à®•à¯ உதவியை அணà¯à®•à®µà¯à®®à¯, பாதà¯à®•à®¾à®ªà¯à®ªà¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯à®•à®³à¯ˆà®ªà¯ பெறவà¯à®®à¯ விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯‡à®©à¯.License Key இலà¯à®²à¯ˆà®¯à®¾?இநà¯à®¤ பிளகà¯à®‡à®©à¯à®©à¯à®•à¯à®•à¯ நனà¯à®•à¯Šà®Ÿà¯ˆ தாரà¯à®™à¯à®•à®³à¯à®‰à®™à¯à®•à®³à¯ திடà¯à®Ÿà®®à¯ கீழà¯à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯à®ªà®¤à®¿à®µà®¿à®±à®•à¯à®•à¯%s பதிபà¯à®ªà¯ˆ பதிவிறகà¯à®•à®²à®¾à®®à¯%sன௠அணà¯à®®à¯ˆà®¯ பதிபà¯à®ªà¯ˆà®ªà¯ பதிவிறகà¯à®•à®²à®¾à®®à¯à®ªà¯à®¤à®¿à®¯ பதிபà¯à®ªà¯ˆ பதிவிறகà¯à®•à®²à®¾à®®à¯à®ªà®¤à®¿à®µà®¿à®±à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯à®ªà¯à®¤à®¿à®¯ %s EU GDPRன௠படி %s மேறà¯à®ªà®¾à®°à¯à®µà¯ˆ விதிகளாலà¯, ஆடà¯à®šà¯‡à®ªà®•à®° தகவலà¯à®•à¯à®•à¯ எதிரான உஙà¯à®•à®³à¯ நிலையை உறà¯à®¤à®¿ செயà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à¯ :)எஙà¯à®•à®³à¯ affiliate திடà¯à®Ÿ விதிமà¯à®±à¯ˆ மீறல௠காரணமாக உஙà¯à®•à®³à¯ affiliate கணகà¯à®•à¯ˆ தறà¯à®•à®¾à®²à®¿à®•à®®à®¾à®• தடை செயà¯à®•à®¿à®±à¯‹à®®à¯. கேளà¯à®µà®¿à®•à®³à¯ இரà¯à®¨à¯à®¤à®¾à®²à¯ உதவியை தொடரà¯à®ªà¯ கொளà¯à®³à®µà¯à®®à¯.மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ நடைபெறà¯à®®à¯à®ªà¯‹à®¤à¯‡ இனà¯à®©à¯à®®à¯ %d தளஙà¯à®•à®³à®¿à®²à¯ உரிமம௠செயலà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®²à¯ இலà¯à®²à¯ˆ எனà¯à®±à¯ அறிகிறோமà¯.மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ நடைபெறà¯à®®à¯à®ªà¯‹à®¤à¯‡ Networkலà¯à®²à¯à®³à¯à®³ %s தளஙà¯à®•à®³à¯ உஙà¯à®•à®³à¯ கவனிபà¯à®ªà¯ˆà®•à¯ கோரà¯à®•à®¿à®©à¯à®±à®© எனà¯à®±à®±à®¿à®•à®¿à®±à¯‹à®®à¯.மினà¯à®©à®žà¯à®šà®²à¯à®®à®¿à®©à¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•à®µà®°à®¿à®®à¯à®Ÿà®¿à®µà¯%s஠எநà¯à®¤à¯†à®¨à¯à®¤ தளஙà¯à®•à®³à®¿à®²à¯ à®®à¯à®©à¯à®©à®¿à®²à¯ˆà®ªà¯ படà¯à®¤à¯à®¤à¯à®µà¯€à®°à¯à®•à®³à¯‹ அநà¯à®¤à®¤à¯ தளஙà¯à®•à®³à®¿à®©à¯ பெயரà¯à®•à®³à¯ˆ உளà¯à®³à®¿à®Ÿà¯à®™à¯à®•à®³à¯.தரம௠உயரà¯à®¤à¯à®¤à¯à®¤à®²à®¿à®©à¯ போத௠நீஙà¯à®•à®³à¯ உளà¯à®³à®¿à®Ÿà¯à®Ÿ மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®¤à¯ தநà¯à®¤à®¾à®²à¯, license key஠மீணà¯à®Ÿà¯à®®à¯ அனà¯à®ªà¯à®ªà¯à®•à®¿à®±à¯‹à®®à¯.தவறà¯à®šà¯†à®°à¯à®µà®°à®¿à®Ÿà®®à¯ இரà¯à®¨à¯à®¤à¯ தவறà¯à®šà¯ செயà¯à®¤à®¿ வநà¯à®¤à®¿à®°à¯à®•à¯à®•à®¿à®±à®¤à¯.காலாவதியானதà¯%sல௠காலாவதியாகிறதà¯à®®à¯‡à®²à®¤à®¿à®• தளஙà¯à®•à®³à¯à®¤à®¯à®¾à®°à®¿à®ªà¯à®ªà¯à®•à®³à¯ˆ சநà¯à®¤à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ மேலதிக தளஙà¯à®•à®³à¯.FileFilterWordpress.orgயின௠வழிகாடà¯à®Ÿà¯ நெறிமà¯à®±à¯ˆà®•à®³à¯à®ªà®Ÿà®¿, உஙà¯à®•à®³à¯ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ தà¯à®µà®™à¯à®•à¯à®®à¯à®®à¯à®©à¯ நாஙà¯à®•à®³à¯ கேடà¯à®Ÿà¯à®•à¯ கொளà¯à®µà®¤à¯†à®²à¯à®²à®¾à®®à¯, உஙà¯à®•à®³à¯ பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯à®¤à¯ தகவலை நாஙà¯à®•à®³à¯ பினà¯à®¤à¯Šà®Ÿà®° எஙà¯à®•à®³à¯ˆ அனà¯à®®à®¤à®¿à®•à¯à®•à¯à®®à¯ தெரிவை தெரிவ௠செயà¯à®¯à¯à®™à¯à®•à®³à¯ எனà¯à®ªà®¤à¯‡. இத௠%s஠அனà¯à®®à®¤à®¿à®¤à¯à®¤à¯ தகவலை %sகà¯à®•à¯ அனà¯à®ªà¯à®ªà®šà¯à®šà¯†à®¯à¯à®¤à¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯à®•à¯à®•à¯ உதவà¯à®®à¯. மறà¯à®±à¯à®®à¯ உஙà¯à®•à®³à¯ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®¤à¯à®¤à¯ˆ உறà¯à®¤à®¿à®šà¯†à®¯à¯à®¯à¯à®®à¯.விலையிலà¯à®²à¯ˆà®µà®¿à®²à¯ˆà®¯à®¿à®²à¯à®²à®¾ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯à®µà®¿à®²à¯ˆà®¯à®¿à®²à¯à®²à®¾ பதிபà¯à®ªà¯Freemius APIFreemius தவறà¯à®¨à¯€à®•à¯à®•à®¿ Debugபà¯à®³à®•à¯à®‡à®©à¯ à®®à¯à®•à¯à®•à®¿à®¯ கோபà¯à®ªà¯ˆ Freemius SDKவால௠கணà¯à®Ÿà®±à®¿à®¯ à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ. தயவà¯à®šà¯†à®¯à¯à®¤à¯ பினà¯à®µà®°à¯à®®à¯ செயà¯à®¤à®¿à®¯à¯à®Ÿà®©à¯ sdk@freemius.comகà¯à®•à¯ மினà¯à®©à®žà¯à®šà®²à¯ அனà¯à®ªà¯à®ªà®µà¯à®®à¯Freemius நிலைமà¯à®´à¯à®ªà¯à®ªà¯†à®¯à®°à¯Functionதானியஙà¯à®•à®¿ சநà¯à®¤à®¾ பà¯à®¤à¯à®ªà¯à®ªà®¿à®¤à¯à®¤à®²à¯à®•à¯à®•à¯à®®à¯ லாபப௠பஙà¯à®•à¯€à®Ÿà¯ பெறà¯à®™à¯à®•à®³à¯.%sன௠பீடà¯à®Ÿà®¾ பதிபà¯à®ªà¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ˆà®ªà¯ பெறà¯à®™à¯à®•à®³à¯.License key உளà¯à®³à®¤à®¾?வணகà¯à®•à®®à¯. %sன௠மà¯à®•à®µà®°à¯ திடà¯à®Ÿà®®à¯ கà¯à®±à®¿à®¤à¯à®¤à¯ உஙà¯à®•à®³à¯à®•à¯à®•à¯à®¤à¯ தெரியà¯à®®à®¾? %s஠நீஙà¯à®•à®³à¯ விரà¯à®®à¯à®ªà®¿à®©à®¾à®²à¯, நீஙà¯à®•à®³à¯à®®à¯ à®®à¯à®•à®µà®°à®¾à®•à®¿ பணம௠ஈடà¯à®Ÿà®²à®¾à®®à¯!%s஠எநà¯à®¤à®³à®µà¯ விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à¯? %d-நாள௠விலையிலà¯à®²à®¾ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®¤à¯à®¤à®¿à®²à¯ %sன௠விலையà¯à®³à¯à®³ வசதிகளை சோதிதà¯à®¤à¯à®ªà¯ பாரà¯à®™à¯à®•à®³à¯.பதிவேறà¯à®±à¯à®¤à®²à¯ மறà¯à®±à¯à®®à¯ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®¤à®²à¯ எபà¯à®ªà®Ÿà®¿?எஙà¯à®•à®³à¯ˆ நீஙà¯à®•à®³à¯ எபà¯à®ªà®Ÿà®¿ à®®à¯à®©à¯à®©à®¿à®²à¯ˆà®ªà¯ படà¯à®¤à¯à®¤à¯à®µà¯€à®°à¯à®•à®³à¯?இதறà¯à®•à¯à®®à¯‡à®²à¯ பணம௠செலà¯à®¤à¯à®¤à®®à®¾à®Ÿà¯à®Ÿà¯‡à®©à¯à®‡à®¤à¯ˆ எபà¯à®ªà®Ÿà®¿ உபயோகிபà¯à®ªà®¤à¯ எனà¯à®±à¯ எனகà¯à®•à¯à®ªà¯ பà¯à®°à®¿à®¯à®µà®¿à®²à¯à®²à¯ˆà®Žà®©à¯ தனிபà¯à®ªà®Ÿà¯à®Ÿ தகவலை உஙà¯à®•à®³à¯‹à®Ÿà¯ பகிர விரà¯à®®à¯à®ªà®µà®¿à®²à¯à®²à¯ˆ.எனகà¯à®•à¯ வேற௠ஒர௠நலà¯à®² %s கிடைதà¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà®¤à¯à®Žà®©à¯ திடà¯à®Ÿà®¤à¯à®¤à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®¯ பினà¯à®©à¯à®®à¯, என௠உரிமம௠%s எனà¯à®ªà®¤à®¾à®•à®µà¯‡ காடà¯à®Ÿà¯à®•à®¿à®±à®¤à¯.இனி எனகà¯à®•à¯ %s தேவையிலà¯à®²à¯ˆà®•à¯à®±à¯à®•à®¿à®¯ காலதà¯à®¤à®¿à®±à¯à®•à¯ மடà¯à®Ÿà¯à®®à¯ %s போதà¯à®®à¯à®à®Ÿà®¿à®‡à®¤à¯ˆ கிளிக௠செயà¯à®¤à®¾à®²à¯, இநà¯à®¤ à®®à¯à®Ÿà®¿à®µà¯ தள நிரà¯à®µà®¾à®•à®¿à®•à®³à¯à®•à¯à®•à¯ அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®®à¯.à®à®©à¯ நீஙà¯à®•à®³à¯ %s எனà¯à®ªà®¤à¯ˆ எஙà¯à®•à®³à¯à®•à¯à®•à¯à®¤à¯ தெரிவியà¯à®™à¯à®•à®³à¯à®‰à®™à¯à®•à®³à¯ %s கணகà¯à®•à®¿à®©à¯ உரிமையை %sகà¯à®•à¯ மாறà¯à®±à®¿à®Ÿ விரà¯à®®à¯à®ªà®¿à®©à®¾à®²à¯ உரிமை மாறà¯à®±à®®à¯ படà¯à®Ÿà®©à¯ˆ à®…à®´à¯à®¤à¯à®¤à®µà¯à®®à¯.அநà¯à®¤à®¤à¯ தளஙà¯à®•à®³à®¿à®²à¯à®®à¯ %s஠உபயோகிகà¯à®• விரà¯à®®à¯à®ªà®¿à®©à®¾à®²à¯, கீழே License Key உளà¯à®³à®¿à®Ÿà¯à®Ÿà¯ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ˆ à®…à®´à¯à®¤à¯à®¤à®µà¯à®®à¯.à®®à¯à®•à¯à®•à®¿à®¯à®®à®¾à®© மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ அறிவிபà¯à®ªà¯%sலà¯à®’à®°à¯à®µà¯‡à®³à¯ˆ %s இநà¯à®¤ தளதà¯à®¤à®¿à®²à¯‹ அலà¯à®²à®¤à¯ பிற தளதà¯à®¤à®¿à®²à¯‹ உபயோகிகà¯à®•à®µà®¿à®²à¯à®²à¯ˆ எனà¯à®±à®¾à®²à¯ %s஠ரதà¯à®¤à¯ செயà¯à®¯ விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾?விலையிலà¯à®²à®¾ பதிபà¯à®ªà¯ˆ நிறà¯à®µà®²à®¾à®®à¯à®µà®¿à®²à¯ˆà®¯à®¿à®²à¯à®²à®¾ பதிபà¯à®ªà®¿à®©à¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ˆ நிறà¯à®µà®²à®¾à®®à¯à®¨à®¿à®±à¯à®µà®²à®¾à®®à¯à®®à¯‡à®®à¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ˆ நிறà¯à®µà®²à®¾à®®à¯%s: பிளகà¯à®‡à®©à¯ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯module ID தவறானதà¯.தவறான தள விவர சேரà¯à®ªà¯à®ªà¯à®‡à®©à¯à®µà®¾à®¯à¯à®¸à¯Is Activeஉஙà¯à®•à®³à¯ உரிமம௠செயலà¯à®ªà®¾à®Ÿà¯à®Ÿà¯à®•à¯à®•à¯ வரவிலà¯à®²à¯ˆà®¯à¯†à®© தோனà¯à®±à¯à®•à®¿à®±à®¤à¯.உரிமதà¯à®¤à®¿à®©à¯ செயலà¯à®¨à®¿à®±à¯à®¤à¯à®¤à®®à¯ தோலà¯à®µà®¿ அடைநà¯à®¤à®¤à¯à®ªà¯‹à®²à¯ தெரிகிறதà¯.வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®¤à¯à®¤à®¿à®²à¯ நீஙà¯à®•à®³à¯ இலà¯à®²à¯ˆ எனà¯à®ªà®¤à®¾à®²à¯, அதை ரதà¯à®¤à¯à®šà¯†à®¯à¯à®¯à®¤à¯ தேவையிலà¯à®²à¯ˆ :)நீஙà¯à®•à®³à¯ இனà¯à®©à¯à®®à¯ %s திடà¯à®Ÿà®¤à¯à®¤à®¿à®²à¯‡à®¯à¯‡ இரà¯à®ªà¯à®ªà®¤à®¾à®•à®¤à¯ தெரிகிறதà¯. நீஙà¯à®•à®³à¯ திடà¯à®Ÿà®¤à¯à®¤à¯ˆ மாறà¯à®±à®¿à®¯ பினà¯à®©à®°à¯ இபà¯à®ªà®Ÿà®¿ இரà¯à®¨à¯à®¤à®¾à®²à¯, அத௠எஙà¯à®•à®³à¯ தவறà¯. மனà¯à®©à®¿à®•à¯à®•à®µà¯à®®à¯. உஙà¯à®•à®³à¯ தளதà¯à®¤à®¿à®±à¯à®•à¯ உரிமம௠à®à®¤à¯à®®à¯ இலà¯à®²à¯ˆ எனà¯à®ªà®¤à¯ போல௠தெரிகிறதà¯.சரிபாரà¯à®•à¯à®•à¯à®®à¯ வகையினஙà¯à®•à®³à®¿à®²à¯ à®à®¤à¯‹ ஒனà¯à®±à¯ தவறà¯à®ªà¯‹à®²à¯ தெரிகிறதà¯. உஙà¯à®•à®³à¯ Public Key, Secret Key & User ID ஆகியவறà¯à®±à¯ˆ சரிபாரà¯à®¤à¯à®¤à¯ மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®µà¯à®®à¯.நான௠எதிரà¯à®ªà®¾à®°à¯à®¤à¯à®¤à®¤à¯ இதà¯à®µà®²à¯à®².பீடà¯à®Ÿà®¾ பதிபà¯à®ªà¯ சோதனையில௠சேரவà¯à®®à¯%sன௠ஆடà¯-ஆன௠தகவலை வெளியிலà¯à®³à¯à®³ சரà¯à®µà®°à¯ மூலம௠எடà¯à®•à¯à®•à®¿à®±à¯‹à®®à¯ எனà¯à®ªà®¤à¯ˆ அறியவà¯à®®à¯.Keyஎனà¯à®© வேலை செயà¯à®¯à®µà®¿à®²à¯à®²à¯ˆ எனà¯à®ªà®¤à¯ˆ விளகà¯à®•à®®à®¾à®• சொனà¯à®©à®¾à®²à¯, அதை நாஙà¯à®•à®³à¯ சரி செயà¯à®µà¯‹à®®à¯.காரணம௠எதà¯à®µà¯†à®©à¯à®±à¯ சொனà¯à®©à®¾à®²à¯ எஙà¯à®•à®³à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®•à¯ கொளà¯à®µà¯‹à®®à¯.கடைசிகடைசி மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯à®•à®Ÿà¯ˆà®šà®¿ உரிமமà¯à®šà®®à¯€à®ªà®¤à¯à®¤à®¿à®¯ விலையிலà¯à®²à®¾ பதிபà¯à®ªà¯ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯à®šà®®à¯€à®ªà®¤à¯à®¤à®¿à®¯ பதிபà¯à®ªà¯ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯à®®à¯‡à®²à¯à®®à¯ அறியநீளமà¯à®‰à®°à®¿à®®à®®à¯à®‰à®°à®¿à®® ஒபà¯à®ªà®¨à¯à®¤à®®à¯License KeyLicense keyLicense key காலியாக உளà¯à®³à®¤à¯.வாழà¯à®¨à®¾à®³à¯%s஠விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾? எஙà¯à®•à®³à¯ Ambassador ஆக பணியாறà¯à®±à®¿ பணம௠பெறலாம௠:-)Load DB OptionLocalhostLogLoggerசெயà¯à®¤à®¿à®µà®´à®¿à®®à¯à®±à¯ˆMigrate Options to Networkஅலைபேசி செயலிகளà¯ModuleModule PathModule மாதிரி%s கà¯à®±à®¿à®¤à¯à®¤ மேலதிக தகவலà¯à®ªà¯†à®¯à®°à¯Network BlogNetwork பயனரà¯à®ªà¯à®¤à®¿à®¯à®¤à¯à®ªà¯à®¤à®¿à®¯ பதிபà¯à®ªà¯ கிடைகà¯à®•à®¿à®±à®¤à¯à®ªà¯à®¤à®¿à®¯ விலையிலà¯à®²à®¾ பதிபà¯à®ªà¯ (%s) நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯à®ªà¯à®¤à®¿à®¯ பதிபà¯à®ªà¯ (%s) நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯à®šà¯†à®¯à¯à®¤à®¿à®•à¯à®•à®Ÿà®¿à®¤à®®à¯à®…டà¯à®¤à¯à®¤à¯à®‡à®²à¯à®²à¯ˆà®à®Ÿà®¿ இலà¯à®²à¯ˆ%sகà¯à®•à¯ எநà¯à®¤à®•à¯ கடபà¯à®ªà®¾à®Ÿà¯à®®à¯ இலà¯à®²à¯ˆ - எபà¯à®ªà¯‹à®¤à¯à®®à¯ ரதà¯à®¤à¯ செயà¯à®¯à®²à®¾à®®à¯!%s நாடà¯à®•à®³à¯à®•à¯à®•à¯ எநà¯à®¤à®•à¯ கடபà¯à®ªà®¾à®Ÿà¯à®®à¯ இலà¯à®²à¯ˆ - எபà¯à®ªà¯‹à®¤à¯à®®à¯ ரதà¯à®¤à¯ செயà¯à®¯à®²à®¾à®®à¯!கடன௠அடà¯à®Ÿà¯ˆ தேவையிலà¯à®²à¯ˆà®•à®¾à®²à®¾à®µà®¤à®¿à®¯à®¾à®•à®¾à®¤à¯à®•à®¾à®²à®¾à®µà®¤à®¿à®¯à®¾à®•à®¾à®¤à®¤à¯%sன௠எநà¯à®¤à®¤à¯ திடà¯à®Ÿà®™à¯à®•à®³à®¿à®²à¯à®®à¯ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ இலà¯à®²à¯ˆ.O.Kஉஙà¯à®•à®³à¯ உரிமம௠மà¯à®Ÿà®¿à®¨à¯à®¤à®¤à¯à®®à¯ நீஙà¯à®•à®³à¯ அனைதà¯à®¤à¯ விலையிலà¯à®²à®¾ வசதிகளையà¯à®®à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®•à¯ கொளà¯à®³ à®®à¯à®Ÿà®¿à®¯à¯à®®à¯. ஆனால௠%s வசதிகளை அணà¯à®• இயலாதà¯.மீணà¯à®Ÿà¯à®®à¯ உரிமதà¯à®¤à¯ˆ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®©à®¾à®²à¯ தவிர, உரிமம௠காலாவதியானால௠%s பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯.தெரிவ௠செயà¯à®¤à¯†à®°à®¿à®µà¯ˆ அகறà¯à®±à¯"%s"஠சிறபà¯à®ªà®¾à®©à®¤à®¾à®•à¯à®• தேரà¯à®µà¯ செயà¯à®¯à¯à®™à¯à®•à®³à¯à®®à®±à¯à®±à®µà¯ˆà®‰à®°à®¿à®®à¯ˆà®¯à®¾à®³à®°à¯ மினà¯à®©à®žà¯à®šà®²à¯à®‰à®°à®¿à®®à¯ˆà®¯à®¾à®³à®°à¯ IDஉரிமையாளர௠பெயரà¯PCI compliantவிலையà¯à®³à¯à®³ ஆடà¯à®†à®©à¯ Freemiusல௠வரிசைபà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯ படà¯à®Ÿà®¿à®°à¯à®•à¯à®• வேணà¯à®Ÿà¯à®®à¯.PayPal கணகà¯à®•à®¿à®©à¯ மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•à®µà®°à®¿à®ªà®£à®®à¯ செலà¯à®¤à¯à®¤à®²à¯à®•à®³à¯à®ªà®£à®®à¯ பெறà¯à®¤à®²à¯ USDயில௠மாதாமாதம௠PayPal மூலம௠பெறலாமà¯.திடà¯à®Ÿà®®à¯%s திடà¯à®Ÿà®®à¯ இலà¯à®²à¯ˆ. வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ தà¯à®µà®™à¯à®• இயலாதà¯.%s திடà¯à®Ÿà®¤à¯à®¤à®¿à®±à¯à®•à¯ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ கிடையாதà¯.திடà¯à®Ÿ IDஎஙà¯à®•à®³à¯ˆ இஙà¯à®•à¯ அணà¯à®•à®²à®¾à®®à¯à®ªà®¿à®©à¯à®µà®°à¯à®®à¯ செயà¯à®¤à®¿à®¯à¯‹à®Ÿà¯ எஙà¯à®•à®³à¯ˆà®¤à¯ தொடரà¯à®ªà¯ கொளà¯à®³à¯à®™à¯à®•à®³à¯%s஠பதிவிறகà¯à®•à®²à®¾à®®à¯.உஙà¯à®•à®³à¯ மினà¯à®©à®žà¯à®šà®²à¯à®•à¯à®•à¯ வநà¯à®¤ License Key஠உளà¯à®³à®¿à®Ÿà¯à®™à¯à®•à®³à¯:இணைய தள அலà¯à®²à®¤à¯ சமூக ஊடக வரà¯à®•à¯ˆà®¯à®¾à®³à®°à¯ எணà¯à®£à®¿à®•à¯à®•à¯ˆ, மினà¯à®©à®žà¯à®šà®²à¯ சநà¯à®¤à®¾à®¤à®¾à®°à®°à¯à®•à®³à¯, பினà¯à®¤à¯Šà®Ÿà®°à¯à®µà¯‹à®°à¯ போனà¯à®± பà¯à®³à¯à®³à®¿à®µà®¿à®µà®°à®™à¯à®•à®³à¯ தரà¯à®•. (நாஙà¯à®•à®³à¯ ரகசியம௠காபà¯à®ªà¯‹à®®à¯)மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ˆ à®®à¯à®Ÿà®¿à®¤à¯à®¤à¯à®µà¯ˆà®•à¯à®• பினà¯à®µà®°à¯à®®à¯ வழிமà¯à®±à¯ˆà®¯à¯ˆà®ªà¯ பினà¯à®ªà®±à¯à®±à®µà¯à®®à¯à®ªà®¾à®¤à¯à®•à®¾à®ªà¯à®ªà¯ & மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯, விளகà¯à®•à®µà¯à®°à¯ˆ மறà¯à®±à¯à®®à¯ தளà¯à®³à¯à®ªà®Ÿà®¿ விவரஙà¯à®•à®³à¯ˆ உஙà¯à®•à®³à¯à®•à¯à®•à¯ நாஙà¯à®•à®³à¯ அனà¯à®ªà¯à®ª விரà¯à®®à¯à®ªà®¿à®©à®¾à®²à¯ எஙà¯à®•à®³à¯ˆà®¤à¯ தொடரà¯à®ªà¯ கொளà¯à®³à¯à®™à¯à®•à®³à¯.தயவà¯à®šà¯†à®¯à¯à®¤à¯ கவனிகà¯à®•à®µà¯à®®à¯. ரதà¯à®¤à¯à®šà¯†à®¯à¯à®¤ பிறக௠மீணà¯à®Ÿà¯à®®à¯ பà¯à®¤à®¿à®¯ சநà¯à®¤à®¾/பà¯à®¤à¯à®ªà¯à®ªà®¿à®¤à¯à®¤à®²à¯à®•à¯à®•à¯ பழைய விலையை எஙà¯à®•à®³à®¾à®²à¯ வசூலிகà¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯. விலை ஆணà¯à®Ÿà¯à®•à¯à®•à¯Šà®°à¯ à®®à¯à®±à¯ˆ உயரà¯à®®à¯. நீஙà¯à®•à®³à¯ இனி பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®• விரà¯à®®à¯à®ªà®¿à®©à®¾à®²à¯ பà¯à®¤à®¿à®¯ விலையை செலà¯à®¤à¯à®¤à®µà¯‡à®£à¯à®Ÿà¯à®®à¯.%s஠எபà¯à®ªà®Ÿà®¿ à®®à¯à®©à¯à®©à®¿à®²à¯ˆà®ªà¯ படà¯à®¤à¯à®¤à¯à®µà¯€à®°à¯à®•à®³à¯ எனà¯à®± விவரம௠தரவà¯à®®à¯. (தயவà¯à®šà¯†à®¯à¯à®¤à¯ கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà¯à®Ÿà¯à®šà¯ சொலà¯à®²à®µà¯à®®à¯)உஙà¯à®•à®³à¯ à®®à¯à®´à¯à®ªà¯ பெயரைத௠தரவà¯à®®à¯.பà¯à®³à®•à¯à®‡à®©à¯à®ªà®¿à®³à®•à¯à®‡à®©à¯ à®®à¯à®•à®ªà¯à®ªà¯à®ªà¯à®ªà®•à¯à®•à®®à¯à®ªà®¿à®³à®•à¯à®‡à®©à¯ IDபிளகà¯à®‡à®©à¯ நிறà¯à®µà¯à®¤à®²à¯Changelogவிளகà¯à®•à®®à¯FAQவசதிகள௠& விலைநிறà¯à®µà¯à®¤à®²à¯à®ªà®¿à®± கà¯à®±à®¿à®ªà¯à®ªà¯à®•à®³à¯à®•à®°à¯à®¤à¯à®¤à¯à®°à¯ˆà®•à®³à¯à®µà®¿à®²à¯ˆà®¯à¯à®³à¯à®³ நிரல௠இலà¯à®²à®¾à®¤à®¤à®¾à®²à¯ பிளகà¯à®‡à®©à¯ "Serviceware" எனபà¯à®ªà®Ÿà¯à®®à¯.பிளகà¯à®‡à®©à¯à®•à®³à¯à®ªà®¿à®³à®•à¯à®‡à®©à¯ & தீம௠SyncPremium%s விலையà¯à®³à¯à®³ பதிபà¯à®ªà¯ வெறà¯à®±à®¿à®•à®°à®®à®¾à®• செயலà¯à®ªà®¾à®Ÿà¯à®Ÿà¯à®•à¯à®•à¯ வநà¯à®¤à®¤à¯.விலையà¯à®³à¯à®³ ஆடà¯-ஆன௠பதிபà¯à®ªà¯ à®à®±à¯à®•à®©à®µà¯‡ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.விலையà¯à®³à¯à®³ பதிபà¯à®ªà¯à®µà®¿à®²à¯ˆà®¯à¯à®³à¯à®³ பதிபà¯à®ªà¯ à®à®±à¯à®•à®©à®µà¯‡ செயலில௠உளà¯à®³à®¤à¯.விலை விவரமà¯à®¤à®©à®¿à®¯à¯à®°à®¿à®®à¯ˆà®•à¯ கொளà¯à®•à¯ˆà®•à®³à¯à®¤à¯Šà®Ÿà®°à¯à®•Process IDசெயலிலà¯à®¤à®¯à®¾à®°à®¿à®ªà¯à®ªà¯à®•à®³à¯à®¤à®¿à®Ÿà¯à®Ÿà®¤à¯à®¤à®¿à®©à¯ சà¯à®°à¯à®•à¯à®•à®®à¯à®®à¯à®©à¯à®©à®¿à®²à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ வழிமà¯à®±à¯ˆà®•à®³à¯à®®à®¾à®¨à®¿à®²à®ªà¯ பரபà¯à®ªà¯Public Keyஉரிமம௠வாஙà¯à®•à¯à®™à¯à®•à®³à¯à®®à¯‡à®²à¯à®®à¯ வாஙà¯à®•à¯à®•à®‰à®Ÿà®©à®Ÿà®¿ பினà¯à®©à¯‚டà¯à®Ÿà®®à¯à®’தà¯à®•à¯à®•à¯€à®Ÿà¯à®šà¯†à®¯à®²à¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ மினà¯à®©à®žà¯à®šà®²à¯ˆ மீணà¯à®Ÿà¯à®®à¯ அனà¯à®ªà¯à®ªà¯à®•à®Žà®™à¯à®•à®³à¯ %sகà¯à®•à¯ பà¯à®¤à®¿à®¯ வாடிகà¯à®•à¯ˆà®¯à®¾à®³à®°à¯à®•à®³à¯ˆ பரிநà¯à®¤à¯à®°à¯ˆ செயà¯à®¤à¯, ஒவà¯à®µà¯Šà®°à¯ விறà¯à®ªà®©à¯ˆà®•à¯à®•à¯à®®à¯ %s லாபப௠பஙà¯à®•à¯€à®Ÿà®¾à®•à®ªà¯ பெறலாமà¯.உரிமதà¯à®¤à¯ˆ பà¯à®¤à¯à®ªà¯à®ªà®¿à®¯à¯à®™à¯à®•à®³à¯à®‰à®°à®¿à®®à®¤à¯à®¤à¯ˆ பà¯à®¤à¯à®ªà¯à®ªà®¿à®¯à¯à®™à¯à®•à®³à¯à®µà¯‡à®£à¯à®Ÿà¯à®•à¯‹à®³à¯à®•à®³à¯WordPress பதிபà¯à®ªà¯ˆ வேணà¯à®Ÿà¯à®•à®¿à®±à®¤à¯à®®à¯à®Ÿà®¿à®µà¯SDKSDK Path%s சேமிகà¯à®•à®²à®¾à®®à¯à®ªà®Ÿà¯à®Ÿà®¿à®¯à®²à®¿à®Ÿà¯à®Ÿ Cronsதிரை நகலà¯à®•à®³à¯à®®à¯à®•à®µà®°à®¿ மூலம௠தேடSecret Keyபாதà¯à®•à®¾à®ªà¯à®ªà®¾à®© HTTPS %s பகà¯à®•à®®à¯, வெளி à®®à¯à®•à®µà®°à®¿à®¯à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ இயஙà¯à®•à¯à®•à®¿à®±à®¤à¯à®‰à®™à¯à®•à®³à¯ சநà¯à®¤à®¾ ரதà¯à®¤à¯ செயà¯à®µà®¤à®¿à®²à¯ ஒர௠தொழிலà¯à®¨à¯à®Ÿà¯à®ªà®•à¯ கோளாறà¯. மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®µà¯à®®à¯.94%match உஙà¯à®•à®³à¯ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ ரதà¯à®¤à¯ செயà¯à®µà®¤à®¿à®²à¯ ஒர௠தொழிலà¯à®¨à¯à®Ÿà¯à®ªà®•à¯ கோளாறà¯. மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®µà¯à®®à¯à®ªà¯à®¤à®¿à®¯ பதிபà¯à®ªà¯ உஙà¯à®•à®³à¯à®•à¯à®•à¯à®•à¯ கிடைதà¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà®¤à¯ போல௠தெரிகிறதà¯.நாடà¯à®Ÿà¯ˆà®¤à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•License key அனà¯à®ªà¯à®ªà¯à®•Set DB OptionSimulate Network UpgradeSimulate Trial Promotionஒர௠தள உரிமமà¯à®‡à®£à¯ˆà®¯à®¤à®³ à®à®Ÿà®¿à®¤à®³à®®à¯ தெரிவ௠செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.தளஙà¯à®•à®³à¯à®•à®Ÿà®¨à¯à®¤à®¿à®Ÿà¯ & %sSlugசமூக ஊடகஙà¯à®•à®³à¯ (Facebook, Twitter etc.)தவறà¯à®•à¯à®•à¯ வரà¯à®¨à¯à®¤à¯à®•à®¿à®±à¯‹à®®à¯. எஙà¯à®•à®³à¯à®•à¯à®•à¯ ஒர௠வாயà¯à®ªà¯à®ªà¯à®¤à¯ தநà¯à®¤à®¾à®²à¯ உஙà¯à®•à®³à¯à®•à¯à®•à¯ உதவக௠காதà¯à®¤à®¿à®°à¯à®•à¯à®•à®¿à®±à¯‹à®®à¯.மனà¯à®©à®¿à®•à¯à®•à®µà¯à®®à¯... இனà¯à®©à¯Šà®°à¯ பயனாளர௠இதே மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•à®µà®°à®¿à®¯à¯à®Ÿà®©à¯ à®à®±à¯à®•à®©à®µà¯‡ பதிவ௠செயà¯à®¤à®¿à®°à¯à®•à¯à®•à®¿à®±à®¾à®°à¯.தà¯à®µà®•à¯à®•à®®à¯à®µà¯†à®³à¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ தà¯à®µà®•à¯à®•à¯à®Žà®©à¯ விலையிலà¯à®²à®¾ %s஠தà¯à®µà®•à¯à®•à®µà¯à®®à¯à®®à®¾à®¨à®¿à®²à®®à¯à®šà®®à®°à¯à®ªà¯à®ªà®¿ & %sசநà¯à®¤à®¾à®‰à®¤à®µà®¿à®‰à®¤à®µà®¿ மையமà¯Sync Data From ServerTax / VAT IDசேவை நிபநà¯à®¤à®©à¯ˆà®•à®³à¯à®Žà®™à¯à®•à®³à¯ affiliate திடà¯à®Ÿà®¤à¯à®¤à®¿à®±à¯à®•à¯ விணà¯à®£à®ªà¯à®ªà®¿à®¤à¯à®¤à®¤à®±à¯à®•à®¾à®• நனà¯à®±à®¿. எதிரà¯à®ªà®¾à®°à®¾ விதமாக உஙà¯à®•à®³à¯ விணà¯à®£à®ªà¯à®ªà®®à¯ தளà¯à®³à¯à®ªà®Ÿà®¿ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯. 30 நாடà¯à®•à®³à®¿à®²à¯ மீணà¯à®Ÿà¯à®®à¯ விணà¯à®£à®ªà¯à®ªà®¿à®•à¯à®•à®µà¯à®®à¯.எஙà¯à®•à®³à¯ affiliate திடà¯à®Ÿà®¤à¯à®¤à®¿à®±à¯à®•à¯ விணà¯à®£à®ªà¯à®ªà®¿à®¤à¯à®¤à®¤à®±à¯à®•à®¾à®• நனà¯à®±à®¿. உஙà¯à®•à®³à¯ விவரஙà¯à®•à®³à¯ˆ பரிசீலிதà¯à®¤à¯, 14 நாடà¯à®•à®³à®¿à®²à¯ மேலதிக தகவலோட௠தொடரà¯à®ªà¯ கொளà¯à®•à®¿à®±à¯‹à®®à¯.%s மறà¯à®±à¯à®®à¯ அதன௠ஆடà¯-ஆன௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®µà®¤à®±à¯à®•à¯ நனà¯à®±à®¿!%s பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®µà®¤à®±à¯à®•à¯ நனà¯à®±à®¿!எஙà¯à®•à®³à¯ உரà¯à®µà®¾à®•à¯à®•à®™à¯à®•à®³à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®µà®¤à®±à¯à®•à¯ நனà¯à®±à®¿!நனà¯à®±à®¿!நனà¯à®±à®¿ %s!உரிமை மாறà¯à®±à®¤à¯à®¤à¯ˆ உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®¯à®¤à®±à¯à®•à¯ நனà¯à®±à®¿. இறà¯à®¤à®¿ ஒபà¯à®ªà¯à®¤à®²à¯à®•à¯à®•à®¾à®• %sகà¯à®•à¯ இபà¯à®ªà¯‹à®¤à¯ ஒர௠மினà¯à®©à®žà¯à®šà®²à¯ அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.%s எனத௠இணையதளதà¯à®¤à¯ˆ செயலிழகà¯à®• வைதà¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà®¤à¯%s வேலை செயà¯à®¯à®µà®¿à®²à¯à®²à¯ˆ%s நான௠எதிரà¯à®ªà®¾à®°à¯à®¤à¯à®¤à®¤à¯ போல௠இலà¯à®²à¯ˆ%s நலà¯à®²à®¤à¯à®¤à®¾à®©à¯. ஆனாலà¯, எனகà¯à®•à¯ தேவைபà¯à®ªà®Ÿà¯à®®à¯ வசதி இதில௠இலà¯à®²à¯ˆ%s சரிவர வேலை செயà¯à®¯à®µà®¿à®²à¯à®²à¯ˆ%s திடீரென நினà¯à®±à¯à®µà®¿à®Ÿà¯à®Ÿà®¤à¯à®¨à®¿à®±à¯à®µà®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯. சில நிமிடஙà¯à®•à®³à¯ காதà¯à®¤à®¿à®°à¯à®•à¯à®•à®µà¯à®®à¯. இநà¯à®¤à®ªà¯ பகà¯à®•à®¤à¯à®¤à¯ˆ Refresh செயà¯à®¯à®µà¯‡à®£à¯à®Ÿà®¾à®®à¯.பெயர௠மாறà¯à®±à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯. Slug உடனான folder, பிளகà¯à®‡à®©à¯ பேகà¯à®•à®¿à®²à¯ இலà¯à®²à¯ˆ.%sன௠மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ à®®à¯à®Ÿà®¿à®¨à¯à®¤à®¤à¯à®¤à¯€à®®à¯à®¤à¯€à®®à¯ மாறà¯à®±à®®à¯à®¤à¯€à®®à¯à®•à®³à¯%sன௠%s கிடைகà¯à®•à®¿à®±à®¤à¯.%sன௠பà¯à®¤à®¿à®¯ பதிபà¯à®ªà¯ இபà¯à®ªà¯‹à®¤à¯ கிடைகà¯à®•à®¿à®±à®¤à¯.இநà¯à®¤ பிளகà¯à®‡à®©à¯ உஙà¯à®•à®³à¯ WordPress பதிபà¯à®ªà¯à®Ÿà®©à¯ ஒதà¯à®¤à®¿à®šà¯ˆà®µà®¾à®©à®¤à¯ எனà¯à®±à¯ கà¯à®±à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ.இநà¯à®¤ பிளகà¯à®‡à®©à¯ உஙà¯à®•à®³à¯ தறà¯à®ªà¯‹à®¤à¯ˆà®¯ WordPress பதிபà¯à®ªà¯à®Ÿà®©à¯ சோதிகà¯à®•à®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ.நேர à®®à¯à®¤à¯à®¤à®¿à®°à¯ˆà®¤à®²à¯ˆà®ªà¯à®ªà¯à®®à¯Šà®¤à¯à®¤à®®à¯à®¨à®•à®°à¯à®µà¯†à®³à¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯à®®à®¾à®¤à®¿à®°à®¿Filesystem அணà¯à®• இயலவிலà¯à®²à¯ˆ. உஙà¯à®•à®³à¯ உளà¯à®³à¯€à®Ÿà¯ சரியா என சோதிகà¯à®•à®µà¯à®®à¯.பலà¯à®¤à®³ உரிமமà¯à®…ளவிலà¯à®²à®¾ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯à®•à®³à¯à®…ளவிலà¯à®²à®¾ லாபப௠பஙà¯à®•à¯€à®Ÿà¯.%s தளஙà¯à®•à®³à¯ வரைமேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®‰à®°à®¿à®®à®®à¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®®à¯‡à®®à¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯, அறிவிபà¯à®ªà¯à®•à®³à¯, வணிக செயà¯à®¤à®¿à®•à®³à¯. Spam இலà¯à®²à¯ˆà®®à¯‡à®®à¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®ªà®¤à®¿à®µà®¿à®±à®•à¯à®•à®¿à®¯ பதிபà¯à®ªà¯ˆ பதிவேறà¯à®±à®¿ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à®¾à®®à¯W00tஉபயோகிபà¯à®ªà®¾à®³à®°à¯ à®à®Ÿà®¿à®ªà®¯à®©à®°à¯à®•à®³à¯Valueஉறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ மினà¯à®©à®žà¯à®šà®²à¯ %sகà¯à®•à¯ அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. பாரà¯à®•à¯à®•à®µà¯à®®à¯. 5 நிமிடதà¯à®¤à®¿à®²à¯ மினà¯à®©à®žà¯à®šà®²à¯ வரவிலà¯à®²à¯ˆ எனà¯à®±à®¾à®²à¯ Spamல௠பாரà¯à®•à¯à®•à®µà¯à®®à¯.உறà¯à®¤à®¿à®šà¯†à®¯à¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯à®®à®¿à®©à¯à®©à®žà¯à®šà®²à¯ சரிபாரà¯à®¤à¯à®¤à®¿à®Ÿà¯à®™à¯à®•à®³à¯%s பதிபà¯à®ªà¯ வெளியாகிவிடà¯à®Ÿà®¤à¯.விபரஙà¯à®•à®³à¯ˆà®ªà¯ பாரà¯à®™à¯à®•à®³à¯à®µà®¿à®²à¯ˆà®¯à¯à®³à¯à®³ வசதிகள௠எனà¯à®©à®µà¯†à®©à¯à®±à¯ காணà¯à®™à¯à®•à®³à¯à®Žà®šà¯à®šà®°à®¿à®•à¯à®•à¯ˆà®‡à®¨à¯à®¤ மினà¯à®©à®žà¯à®šà®²à®¿à®©à¯ பதிவில௠எநà¯à®¤ உரிமமà¯à®®à¯ இலà¯à®²à¯ˆ. தஙà¯à®•à®³à¯ மினà¯à®©à®žà¯à®šà®²à¯ சரியானதா?உஙà¯à®•à®³à¯ மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®•à¯ காணவிலà¯à®²à¯ˆ. நீஙà¯à®•à®³à¯ அளிதà¯à®¤à®¤à¯ சரியானதா?. %s, %sகà¯à®•à¯ சில சà¯à®µà®¾à®°à®¸à¯à®¯à®™à¯à®•à®³à¯ˆ உரà¯à®µà®¾à®•à¯à®•à®¿à®¯à®¿à®°à¯à®•à¯à®•à®¿à®±à¯‹à®®à¯Freemius network-level integration஠அறிமà¯à®•à®®à¯ செயà¯à®µà®¤à®¿à®²à¯ பேரà¯à®µà®•à¯ˆ அடைகிறோமà¯.இணையதளமà¯, மினà¯à®©à®žà¯à®šà®²à¯ மறà¯à®±à¯à®®à¯ சமூக ஊடக பà¯à®³à¯à®³à®¿ விவரஙà¯à®•à®³à¯ (விரà¯à®®à¯à®ªà®¿à®©à®¾à®²à¯ தரலாமà¯)நீஙà¯à®•à®³à¯ எனà¯à®© எதிரà¯à®ªà®¾à®°à¯à®¤à¯à®¤à¯€à®°à¯à®•à®³à¯?எனà¯à®© வசதி?உஙà¯à®•à®³à¯ %s எனà¯à®©?எனà¯à®© விலை உஙà¯à®•à®³à¯à®•à¯à®•à¯ வசதியாக இரà¯à®•à¯à®•à¯à®®à¯?நீஙà¯à®•à®³à¯ எனà¯à®© எதிரà¯à®ªà®¾à®°à¯à®•à¯à®•à®¿à®±à¯€à®°à¯à®•à®³à¯?%sன௠பெயர௠எனà¯à®©?%s஠எஙà¯à®•à¯ எபà¯à®ªà®Ÿà®¿ à®®à¯à®©à¯à®©à®¿à®²à¯ˆà®ªà¯ படà¯à®¤à¯à®¤à¯à®µà¯€à®°à¯à®•à®³à¯?WordPress.org பிளகà¯à®‡à®©à¯ பகà¯à®•à®®à¯à®®à¯‡à®®à¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿ பதிபà¯à®ªà®¿à®²à¯ தொடர விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾?ஆமà¯à®†à®®à¯ - %sநீஙà¯à®•à®³à¯ à®à®±à¯à®•à®©à®µà¯‡ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ பாரà¯à®¤à¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà¯€à®°à¯à®•à®³à¯‡.%2$s திடà¯à®Ÿà®¤à¯à®¤à®¿à®©à¯ %1$s-நாள௠விலையிலà¯à®²à®¾ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®¤à¯à®¤à¯ˆà®¤à¯ தà¯à®µà®•à¯à®• இனà¯à®©à¯à®®à¯ 1 கிளிக௠மடà¯à®Ÿà¯à®®à¯‡.நலà¯à®²à®¤à¯... மகிழà¯à®šà¯à®šà®¿à®¨à¯€à®™à¯à®•à®³à¯ %s஠வெளà¯à®³à¯‹à®Ÿà¯à®Ÿ நிலையில௠உபயோகிதà¯à®¤à¯à®•à¯ கொணà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®¿à®±à¯€à®°à¯à®•à®³à¯.இனà¯à®©à¯à®®à¯ à®’à®°à¯à®ªà®Ÿà®¿ à®…à®°à¯à®•à®¿à®²à¯ - %sநீஙà¯à®•à®³à¯ %sன௠வசதிகளை பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ à®®à¯à®Ÿà®¿à®¯à¯à®®à¯. ஆனால௠%s பாதà¯à®•à®¾à®ªà¯à®ªà¯ & மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ மறà¯à®±à¯à®®à¯ உதவியை அணà¯à®• இயலாதà¯.விலையà¯à®³à¯à®³ பதிபà¯à®ªà¯ˆ அணà¯à®• உஙà¯à®•à®³à®¿à®Ÿà®®à¯ உரிமம௠இலà¯à®²à¯ˆ.உஙà¯à®•à®³à®¿à®Ÿà®®à¯ %sன௠உரிமம௠உளà¯à®³à®¤à¯à®‰à®™à¯à®•à®³à¯ %s மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.விடà¯à®Ÿà¯à®µà®¿à®Ÿà¯à®Ÿà¯€à®°à¯à®•à®³à¯, ஆனாலà¯à®®à¯ நீஙà¯à®•à®³à¯ எநà¯à®¤ தகவலையà¯à®®à¯ பகிர வேணà¯à®Ÿà®¿à®¯à®¤à®¿à®²à¯à®²à¯ˆ %sதெரிநà¯à®¤à¯†à®Ÿà¯à®ªà¯à®ªà¯ மடà¯à®Ÿà¯à®®à¯‡à®‰à®™à¯à®•à®³à¯ பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ˆà®ªà¯ பினà¯à®¤à¯Šà®Ÿà®° எஙà¯à®•à®³à¯à®•à¯à®•à¯ நீஙà¯à®•à®³à¯ அளிதà¯à®¤ அனà¯à®®à®¤à®¿à®¯à®¾à®©à®¤à¯, %s஠மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤ உதவà¯à®®à¯.உஙà¯à®•à®³à¯ பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ˆà®ªà¯ பினà¯à®¤à¯Šà®Ÿà®° எஙà¯à®•à®³à¯à®•à¯à®•à¯ நீஙà¯à®•à®³à¯ அளிதà¯à®¤ அனà¯à®®à®¤à®¿à®¯à®¾à®©à®¤à¯, எஙà¯à®•à®³à¯ உரà¯à®µà®¾à®•à¯à®•à®¤à¯à®¤à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤ உதவà¯à®®à¯.உஙà¯à®•à®³à¯ %s ஆடà¯-ஆன௠திடà¯à®Ÿà®®à¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.உஙà¯à®•à®³à¯ %s விலையிலà¯à®²à®¾ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ ரதà¯à®¤à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.%s திடà¯à®Ÿà®¤à¯à®¤à®¿à®²à¯ உஙà¯à®•à®³à¯ கணகà¯à®•à®¿à®©à¯ செயலà¯à®ªà®¾à®Ÿà¯ தà¯à®µà®™à¯à®•à®¿à®¯à®¤à¯.%sகà¯à®•à®¾à®© உஙà¯à®•à®³à¯ Affiliate விணà¯à®£à®ªà¯à®ªà®®à¯ à®à®±à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯. உளà¯à®¨à¯à®´à¯ˆà®¨à¯à®¤à¯ %sல௠உஙà¯à®•à®³à¯ affiliate areaவை அணà¯à®•à®µà¯à®®à¯.உஙà¯à®•à®³à¯ affiliate கணகà¯à®•à¯ தறà¯à®•à®¾à®²à®¿à®•à®®à®¾à®• இடைநிறà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.உஙà¯à®•à®³à¯ மினà¯à®©à®žà¯à®šà®²à¯ சரிபாரà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ - நனà¯à®±à®¿!உஙà¯à®•à®³à¯ விலையிலà¯à®²à®¾ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ à®®à¯à®Ÿà®¿à®¨à¯à®¤à®¤à¯. %3$s஠தொடரà¯à®¨à¯à®¤à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ %1$s %2$sஇவறà¯à®±à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯.உஙà¯à®•à®³à¯ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ à®®à¯à®Ÿà®¿à®¨à¯à®¤à®¤à¯. ஆனாலà¯à®®à¯ பிற விலையிலà¯à®²à®¾ சேவைகளைத௠தொடரலாமà¯.உஙà¯à®•à®³à¯ உரிமம௠ரதà¯à®¤à®¾à®©à®¤à¯. இதில௠தவறேதà¯à®®à¯ உணரà¯à®¨à¯à®¤à®¾à®²à¯ உடனடியாக எஙà¯à®•à®³à¯ உதவியை அணà¯à®•à®µà¯à®®à¯.உஙà¯à®•à®³à¯ உரிமம௠மà¯à®Ÿà®¿à®¨à¯à®¤à®¤à¯. %3$s஠தொடரà¯à®¨à¯à®¤à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ %1$s %2$s இவறà¯à®±à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯.உஙà¯à®•à®³à¯ உரிமம௠மà¯à®Ÿà®¿à®¨à¯à®¤à®¤à¯. எனினà¯à®®à¯ நீஙà¯à®•à®³à¯ %sன௠வசதிகளைத௠தொடரலாமà¯. எனினà¯à®®à¯, தொடர௠மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ மறà¯à®±à¯à®®à¯ உதவிகà¯à®•à¯ உஙà¯à®•à®³à¯ உரிமதà¯à®¤à¯ˆà®ªà¯ பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•à®µà¯à®®à¯.உஙà¯à®•à®³à¯ உரிமம௠மà¯à®Ÿà®¿à®¨à¯à®¤à®¤à¯. ஆனாலà¯à®®à¯ %sன௠விலையிலà¯à®²à®¾à®ªà¯ பதிபà¯à®ªà¯ˆ எனà¯à®±à¯à®®à¯ தொடரலாமà¯. உஙà¯à®•à®³à¯ உரிமம௠செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.உஙà¯à®•à®³à¯ உரிமம௠செயலà¯à®¨à®¿à®±à¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯, %s திடà¯à®Ÿà®¤à¯à®¤à®¿à®±à¯à®•à¯ மாறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à¯€à®°à¯à®•à®³à¯.உஙà¯à®•à®³à¯ பெயர௠à®à®±à¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.உஙà¯à®•à®³à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ திடà¯à®Ÿà®®à¯ தà¯à®µà®™à¯à®•à®¿à®¯à®¤à¯.உஙà¯à®•à®³à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ திடà¯à®Ÿà®®à¯ %sகà¯à®•à¯ மாறியதà¯.உஙà¯à®•à®³à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®¤à¯à®¤ திடà¯à®Ÿà®®à¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.உஙà¯à®•à®³à¯ சநà¯à®¤à®¾ ரதà¯à®¤à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯. உஙà¯à®•à®³à¯ %s திடà¯à®Ÿà®®à¯ %s அனà¯à®±à¯ காலாவதியாகிறதà¯.உஙà¯à®•à®³à¯ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ தà¯à®µà®™à¯à®•à®¿à®¯à®¤à¯ZIP / தபால௠கà¯à®±à®¿à®¯à¯€à®Ÿà¯Right onசெயலà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®²à¯%s இலà¯à®²à®¾à®®à®²à¯ %s இயஙà¯à®•à®¾à®¤à¯à®ªà¯à®³à®•à¯à®‡à®©à¯ இலà¯à®²à®¾à®®à®²à¯ %s இயஙà¯à®•à®¾à®¤à¯Heads upஅனà¯à®®à®¤à®¿%s இரà¯à®•à¯à®•à®¿à®±à®¤à¯à®šà¯†à®¯à®²à¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•à®¿à®±à®¤à¯à®µà®°à¯à®Ÿà®®à¯APIபோயà¯à®¤à¯ தொலைதவறை சோதிகà¯à®•à®¿à®±à®¤à¯à®µà®¾à®´à¯à®¤à¯à®¤à¯à®•à¯à®•à®³à¯à®¤à®Ÿà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯à®‡à®£à¯ˆà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯à®…ணà¯à®®à¯ˆà®¯ பதிபà¯à®ªà¯ˆ பதிவிறகà¯à®•à®…ணà¯à®®à¯ˆà®¯ விலையிலà¯à®²à®¾ பதிபà¯à®ªà¯ˆ பதிவிறகà¯à®•à®®à®¾à®¤à®¾à®®à®¾à®¤à®®à¯à®•à®¾à®²à®¾à®µà®¤à®¿à®µà®´à®¿à®®à®¿à®©à¯à®©à®žà¯à®šà®²à¯ அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯à®®à®¾à®¤à®®à¯à®†à®£à¯à®Ÿà¯à®†à®£à¯à®Ÿà¯à®•à¯à®•à®¾à®£à¯à®Ÿà¯à®’à®°à¯à®®à¯à®±à¯ˆà®¤à®¿à®Ÿà¯à®Ÿà®®à¯No SecretSDK பதிபà¯à®ªà¯à®•à®³à¯à®‰à®°à®¿à®®à®®à¯SyncSync Licenseஉரà¯à®µà®¾à®•à¯à®•à®¿à®¯à®µà®°à¯OffOn%s அடிபà¯à®ªà®Ÿà¯ˆà®¯à®¿à®²à®¾à®©à®¤à¯à®µà®¿à®²à¯ˆà®¯à®¿à®²à¯à®²à®¾ வெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ தொடஙà¯à®•à®Ÿà¯à®Ÿà¯à®®à¯... டà¯à®®à¯à®ªà¯‹à®¯à¯à®¤à¯ தொலைபோயà¯à®¤à¯ தொலைசெயலà¯à®¨à®¿à®±à¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯delegateபாதà¯à®•à®¾à®ªà¯à®ªà¯ & மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯, விளகà¯à®•à®µà¯à®°à¯ˆ மறà¯à®±à¯à®®à¯ தளà¯à®³à¯à®ªà®Ÿà®¿ விவரஙà¯à®•à®³à¯ˆ எனகà¯à®•à¯ அனà¯à®ªà¯à®ªà®µà¯à®®à¯. %s செயà¯à®•, %s தேவையிலà¯à®²à¯ˆ%s திடà¯à®Ÿà®®à¯%s பில௠எழà¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯à®šà®¿à®±à®ªà¯à®ªà¯Heyஅரே ஓ சமà¯à®ªà¯‹!வணகà¯à®•à®®à¯ %s,நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯Yee-hawஉரிமமà¯à®¤à®³à®™à¯à®•à®³à¯msபà¯à®¤à®¿à®¯ பீடà¯à®Ÿà®¾ பதிபà¯à®ªà¯à®ªà¯à®¤à®¿à®¯ பதிபà¯à®ªà¯à®‰à®±à¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆà®µà®¿à®²à¯ˆà®µà®¿à®²à¯ˆ விவரமà¯à®ªà®¤à®¿à®ªà¯à®ªà¯secபாதà¯à®•à®¾à®ªà¯à®ªà¯ & மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯, விளகà¯à®•à®µà¯à®°à¯ˆ மறà¯à®±à¯à®®à¯ தளà¯à®³à¯à®ªà®Ÿà®¿ விவரஙà¯à®•à®³à¯ˆ எனகà¯à®•à¯ அனà¯à®ªà¯à®ªà®µà¯à®®à¯.கடநà¯à®¤à®¿à®Ÿà¯Hmmவெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯ தà¯à®µà®™à¯à®•à®²à®¾à®®à¯à®šà®¨à¯à®¤à®¾switching%sன௠அணà¯à®®à¯ˆà®¯ பதிபà¯à®ªà¯ இதோவெளà¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯à®µà¯†à®³à¯à®³à¯‹à®Ÿà¯à®Ÿà®®à¯à®…ழிதரமிறகà¯à®•à¯à®¤à®¿à®°à¯à®¤à¯à®¤à¯à®®à®±à¯ˆà®¤à¯à®¤à®¿à®Ÿà¯à®¤à¯†à®°à®¿à®µà¯ செயà¯à®¤à¯†à®°à®¿à®µà¯ˆ அகறà¯à®±à¯à®µà®¾à®™à¯à®•à¯à®•à®•à®¾à®Ÿà¯à®Ÿà¯à®•à®Ÿà®¨à¯à®¤à®¿à®Ÿà¯à®®à¯‡à®®à¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯‡à®®à¯à®ªà®Ÿà¯à®¤à¯à®¤à¯%s à®®à¯à®©à¯à®ªà¯freemius/languages/freemius-he_IL.mo000064400000117061146725417150013505 0ustar00Þ•Ì|eÜp&Sq&%Å& ë& ÷&'6 '´A'_ö'#V(z( ”( ¡( «(¶(½(Å(Î(Ö(Hß((),)4)D)L) U)a)r)ˆ)&™)-À)î) * **1*D*K*5S*‰*‘* ¡* «*'·*ß* ø* ++ +ž'+Æ+Ù+"õ+,25,!h,aŠ,ì,þ,-$-,-@-H-Q-Y- ^-l-‰--¤- ¸- Å-YÏ-).8. I.U.^.c.(s.1œ.%Î.:ô.//4/E/M/ ]/ h/u/‹/ “// ¢/­/”À/ U0 b0l0„0˜0 0º0Ð0Ù0í0 1 (1—31Ë1 Ñ1ß1Yã1a=2Ÿ2¥2Å2 Í2 Û2;é2%3*3þ1304 54 @4 M4Z4ji4Ô4 ã4í43ö4*5~>5U½56/6H6)c6-6»6SÏ6#7';7c77f7gž78 8%8 E8Q8d8w8 81‰8.»8Oê8:9Aº9yü92v:©:aÉ:+;B/;,r;Ÿ; ¤; ±;¾;Ü; õ;<< < <'<=<4F<{< Š<”<˜<Ÿ<§< ®<º< Á< Í<Ù<ó< ø<= == <=G=L=O=%U=+{=§= ¿= Í=/Ú= >m>|>ƒ>‹> ‘>> ¦> ±>)¿>é>?4?D?5I?(?¨?°?-Ç?õ?U @È_@1(A[ZA¶AÕAÜA ìAöA(B*.B"YB1|B+®B*ÚB&C,C4CJC.RCC‘C±C¹C ÈC ÓCÞCçC÷C D DD.D4DWMD ¥D³D¼D×DÞDâDëDóD EE !E5,ElbE&ÏEöEF F$F=FQFYF _FiF&nFL•FfâFIG OG[GlG rG ~G‹G “G¡G ·GÄG•ÕG–kHI)"I LI WI\bI¿IÔIçICJJJ`J…€J-K4K :KGK'NKMvKGÄK LLL"L'L-LE2LxL‹LL´LÃLÊL*ÙLM* M^7M–MžM¤MdªMN N%N >NKN^NifNWÐN"(O6KO‚O —O¥O-¶OäOP&P*?PjPnP$wPMœPêP/üP,Q>LQ‹Q&¢QZÉQ.$R.SR9‚RZ¼R3S<KSPˆSUÙSš/TKÊT(UG?U#‡U)«U$ÕU)úU$V6V;SV6V>ÆVW W&WFW$\WW›W·WÓW&ñW*XCXZXxX3‘XÅXÚXðXYY*9Y1dY–Y²Y#ÆYêYZZ (Z4ZTZkZ €ZZN–ZåZ["[=[M[^[1o[¡[µ[ Å[ Ò[ Ý[ê[ \C\R\QW\©\ ¹\Ã\Þ\ ñ\ý\ ] ] ] ,] 9] G] Q] [] g] t])]#«a(Ïaøa b b6 b´Wb_ c5lc¢c ¼c ÊcÖc æc ôcd d dH(dqd ud€d ”d ¡d ¬d¸d$ÏdôdO e8\e•e °eºeÓeèeûef5 f @f Kf Yfcf'vf$žfÃfÕfçfgÔ gßgBùg+}#}£} µ}/Â} ò}mý}k~r~z~~—~­~¿~)Õ~ÿ~4+ ``k>Ì €&€B:€}€m˜€ÈFÏ[‚#r‚–‚Ÿ‚ ³‚½‚Ñ‚ ç‚ò‚ ƒ )ƒ4ƒNƒ ]ƒjƒ€ƒ.ˆƒ·ƒ*у üƒ „ %„ 0„ ;„H„X„j„}„‘„©„6¯„Wæ„>…V…_…z………… ”…¢…²…Æ…ß…5ñ…'†4§†܆ î† ‡‡<‡W‡ g‡ r‡~‡&’‡k¹‡f%ˆŒˆ ’ˆ&³ˆÚˆ îˆúˆ ‰‰ $‰E‰L‰•b‰–ø‰<ŠAÌŠ‹ ‹‚,‹¯‹΋ß‹Cý‹AŒ%TŒ®zŒ-) Wb x%…G«Bó 6Ž @ŽKŽQŽ XŽeŽElŽ ²Ž ÓŽôŽ 'S?“8œÕÚîýd hs§'¿çiïWY‘"±‘6Ô‘ ’’4’7F’~’’&¥’5Ì’““(“M9“‡“/›“Ë“Xë“D”$_”Š„”5•IE•8•ZÈ•3#–<W–{”–_—šp—K ˜'W˜>˜¾˜/Þ˜'™.6™e™ €™&‹™A²™ô™š š š*š1š 5š @š KšYš bšmš Œš —š¢š«š ¾šËšÔš Ýš ëšöš› ›-›<›V›]›f›o› ‚› £› ®› ¹›Æ›yÏ› IœWœ uœƒœŠœ “œžœ §œ²œµœÅœ Μۜäœuèœ^e l $— ¼ÉÐÙâëò úž žžž %žˆüº‘Iš“²b=»‚†éÆÂãQ¢×°o@í?^©µ©²·N5|9mñ,ÍM4À«ù1;§î–ƒ</$]l´&‰ä…}úáÅn.*§[ÇqfpB+Å Øe  ¯ŠDžmÕ¤pþ4É3S{]*-=t T'—»˜jð‡à:'ÕhÌP‘ìEP›¸5b´>"L®!Êݱ,”’K)"—„&ÒQž•¬~WXÞÙŽwöGz€±k™Œˆ³_è>aÇ+êYXMÎ¥SvÄl-[¬ŸJ¡­6s ’$@iCßâ¦cx‹cLZ”OÓ.%‹1Fªë¾t¶jWõo\­z¼‰A07I£9J˜8ŒÊ¡rçVƒ<ÏKÁ}RÃóÈ£Ödœ³Ÿµ¢y›É¥ÜY È «÷CËÛ¶u(Šn#®ý RB2Ú7øHÑ0œUZ8ÔFÀOTa#Vrк^(ÿô…3„k¹¨G° DU¤gšfhsHwE ¯ïq_¾ûu¸ªx?eyÁ¹ /‡i™ òŽ{!½2‚æÄ:¿|¦d%€A·`vN;¨å)6~ “¿–\`˽†g¼ÌÆ%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is the new owner of the account.%s minimum payout amount.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s tracking cookie after the first visit to maximize earnings potential.APIAccountAccount DetailsActionsActivateActivate %sActivate %s PlanActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre you sure you want to delete all Freemius data?Are you sure you want to proceed?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBillingBlockingBlog IDBodyBusiness nameCan't find your license key?CancelCancel InstallationCancel SubscriptionCancel TrialCancelledCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanCheckoutCityClear API CacheClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeDateDeactivateDeactivate LicenseDeactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDelegate to Site AdminsDelete All AccountsDetailsDon't have a license key?Donate to this pluginDownloadDownload %s VersionDownload the latest %s versionDownload the latest versionDownloadedDue to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.EmailEmail addressEndEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used for the upgrade below and we will resend you the license key.ErrorError received from the server:ExpiredExpires in %sExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.FreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFull nameFunctionGet commission for automated subscription renewals.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!How do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I can't pay for it anymoreI couldn't understand how to make it workI don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf you have a moment, please let us know why you are %sIf you would like to give up the ownership of the %s's account to %s click the Change Ownership button.In %sInstall Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInvalid module ID.InvoiceIs ActiveIt looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's a temporary %s - I'm troubleshooting an issueIt's not what I was looking forJust letting you know that the add-ons information of %s is being pulled from an external server.KeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense KeyLicense keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerMessageMethodMobile appsModuleModule PathModule TypeMore information about %sNameNetwork UserNewNew Version AvailableNewer Version (%s) InstalledNewsletterNextNoNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Opt InOpt OutOtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium versionPremium version already active.PricingPrivacy PolicyProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicenseQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRequestsRequires WordPress VersionResultSDKSDK PathSave %sScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSimulate Network UpgradeSingle Site LicenseSite IDSitesSkip & %sSlugSocial media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart TrialStart my free %sStateSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a new version of %s available.This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.TimestampTitleTotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser IDUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We made a few tweaks to the %s, %sWebsite, email, and social media statistics (optional)What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?Would you like to proceed with the update?YesYes - %sYou already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou do not have a valid license to access the premium version.You have a %s license.You have successfully updated your %s.You might have missed it, but you don't have to share any data and can just %s the opt-in.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismissdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,interjection expressing joy or exuberanceYee-hawlike websitesSitesmillisecondsmsnot verifiednounPricenounPricingproduct versionVersionsecondssecsend me security & feature updates, educational content and offers.skipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialswitchingthe latest %s version heretrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Vova Feldman , 2017-2018,2022 Language-Team: Hebrew (Israel) (http://www.transifex.com/freemius/wordpress-sdk/language/he_IL/) Language: he_IL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3; X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js ×”×©×œ× ×”×¤×¢×œ×ª "%s" עכשיוההרחבה %s נרכשה בהצלחה.%s התקנות%s Licensesלפני %s%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s הינו ×”×‘×¢×œ×™× ×”×—×“ של חשבון ×–×”.%s minimum payout amount.%s ומעלהדרוג %s%s דרוגי×%s שניותכוכב %s%s כוכבי××¤×¢× %s%s פעמי×%s tracking cookie after the first visit to maximize earnings potential.APIחשבוןפרטי חשבוןפעולותהפעלהActivate %sהפעל חבילה %sהפעלת גירסה ×—×™× ×מיתהפעלת רישיוןהפעלת רישיון על כל ×”××ª×¨×™× ×”×ª×œ×•×™×™× ×•×”×¢×•×ž×“×™×.הפעלת רישיון על כל ×”××ª×¨×™× ×‘×¨×©×ª.הפעל ×ת ההרחבהActivatedהרחבות עבור %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.כתובתכתובת %sAffiliate×פילי×ציהAfter your free %s, pay as little as %sהסכמה והפעלת רישיוןכל הבקשותכל הסוגי××פשר\×™ והמשכ\יסכו×הורדה והתקנה ×וטומטית של %s (גרסה בתשלו×) מ-%2$s תתחיל בעוד %3$s. ×× ×‘×¨×¦×•× ×š לבצע ×ת ההתקנה ידנית - לחץ על כפתור הביטול עכשיו.פידבק ×× ×•× ×™×ž×™×™×™×©×•× ×¢×œ כל ×”××ª×¨×™× ×”×ª×œ×•×™×™× ×•×”×¢×•×ž×“×™×.×™×™×©×•× ×¢×œ כל ×”××ª×¨×™× ×‘×¨×©×ª.Apply to become an affiliateAre you sure you want to delete all Freemius data?×”×× ×ת/×” בטוח רוצה להמשיך?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.עדכן ×וטומטית בעוד %sהתקנה ×וטומטיתדירוג ממוצע×דירBecome an affiliateבילינגBlockingמזהה בלוגBody×©× ×¢×¡×§×”×× ×ינך ×ž×•×¦× ×ת מפתח הרישיון?בטלבטל התקנהבטל מנויביטבוטלביטול הניסיון ×™×—×¡×•× ×ž×™×™×“ ×ת הפיטצ'×¨×™× ×©×”×™× × ×‘×ª×©×œ×•×. ×”×× ×‘×¨×¦×•× ×š בכל ×–×ת להמשיך?שינוי רישיוןעדכון בעלותשינוי חבילהCheckoutעירניקוי מטמון ×”-APIClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dמוצרי×CodeCompatible up toContactצור קשריצירת קשרתורמי××œ× × ×™×ª×Ÿ להפעיל ×ת %s.מדינהCron Typeת×ריךכיבוישיחרור רישיוןביטול הרישיון ×™×—×¡×•× ×ת כל הפיטצ'×¨×™× ×©×‘×ª×©×œ×•× ×ך ×™×פשר להפעיל ×ת הרישיון על ×תר ×חר. ×”×× ×ª×¨×¦×• להמשיך בכל ×–×ת?די×קטיבציהDebug Log×”×צלה למנהלי ×”×תרי×מחיקת כל החשבונותפרטי××”×× ×ין ברשותך מפתח רישיון?×ª×¨×•× ×œ×ª×•×¡×£×”×•×¨×“×”×”×•×¨×“ גרסת %sהורד\×™ ×ת גרסת ×”-%s העדכניתהורד ×ת הגרסה ×”×חרונהDownloadedDue to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.דו×"לכתובת דו×"לEndEnter the domain of your website or other websites from where you plan to promote the %s.הזן ×ת כתובת הדו×ל ש×יתה שידרגת כדי לקבל ×ת הרישיון שוב.שגי×ההוחזרה שגי××” מהשרת:פג תוקףפג תוקף בעוד %sExtra DomainsExtra domains where you will be marketing the product from.קובץפילטרFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.×—×™× ×ניסיון ×—×™× ×גירסה ×—×™× ×מיתFreemius APIניפוי תקלות פרימיוסFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.מצב פרימיוסFull nameפונקציהGet commission for automated subscription renewals.×”×× ×‘×¨×©×•×ª×š רישיון?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!How do you like %s so far? Test all our %s premium features with a %d-day free trial.×יך להעלות ולהפעיל?How will you promote us?×× ×™ ×œ× ×™×›×•×œ/×” להמשיך ×œ×©×œ× ×¢×œ ×–×”×œ× ×”×¦×œ×—×ª×™ להבין ×יך ×œ×’×¨×•× ×œ×–×” לעבוד×× ×™ ×œ× ×והב ×ת הרעיון של שיתוף מידע ×יתכ×מצ×תי %s יותר טובשידרגתי ×ת החשבון שלי ×בל כש×× ×™ מנסה לבצע סנכרון לרישיון החבילה נש×רת %s.I no longer need the %sI only needed the %s for a short periodמזההIf you have a moment, please let us know why you are %sIf you would like to give up the ownership of the %s's account to %s click the Change Ownership button.בעוד %sהתקן גרסה ×—×™× ×מית עכשיוהתקן עדכון גרסה ×—×™× ×מית עכשיוהתקן עכשיוהתקן עדכון במיידימזהה המודול ×œ× ×ª×§× ×™.חשבוניתה×× ×¤×¢×™×œ× ×¨××” ×©×œ× × ×™×ª×Ÿ להפעיל ×ת הרישיון.נר××” שניתוק הרישיון נכשל.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.נר××” ל×תר עדיין ×ין רישיון פעיל.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.×–×” %s זמני - ×× ×™ מנסה לפתור בעיהחיפשתי משהו ×חרJust letting you know that the add-ons information of %s is being pulled from an external server.Key×× × ×©×ª×¤\×™ מה ×œ× ×¢×‘×“ כדי שנוכל לתקן ×–×ת עבור ×ž×©×ª×ž×©×™× ×¢×ª×™×“×™×™×...×× × ×©×ª×£ ×ת הסיבה כדי שנוכל להשתפר.Lastעודכן ל×חרונהרישיון ×חרוןגרסה ×—×™× ×מית עדכנית הותקנההגרסה ×”×חרונה הותקנהLearn moreLengthרישיוןLicense Keyמפתח רישיוןמפתח הרישיון ריק.לכל ×”×—×™×™×Like the %s? Become our ambassador and earn cash ;-)Load DB Optionשרת לוק×ליLogLoggerהודעהMethodMobile appsמודולModule Pathסוג מודולמידע נוסף ×ודות %sש×משתמש רשתחדשיש גרסה חדשהגרסה חדשה (%s) הותקנהניוסלטרNextל××ין מזההNo commitment for %s - cancel anytime×œ×œ× ×”×ª×—×™×™×‘×•×ª ל-%s ימין - בטלו בכל רגע!×œ× × ×“×¨×© כרטיס ×שר××™×œ×œ× ×ª×¤×•×’×”Non-expiringNone of the %s's plans supports a trial period.×וקייOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Opt InOpt Out×חרמייל הבעלי×מזהה הבעלי××©× ×”×‘×¢×œ×™×עומד בתקן PCIPaid add-on must be deployed to Freemius.PayPal account email addressתשלומי×Payouts are in USD and processed monthly via PayPal.חבילההחבילה %s ××™× ×” קיימת, לכן, ×œ× × ×™×ª×Ÿ להתחיל תקופת ניסיון.תוכנית %s ××™× ×” תומכת בתקופת ניסיון.Plan ID×× × ×¦×•×¨ ×יתנו קשר ×›×ן×× × ×¦×•×¨ ×יתנו קשר יחד ×¢× ×”×”×•×“×¢×” הב××”:× × ×œ×”×•×¨×™×“ ×ת %s.×× × ×”×–×Ÿ ×ת הרישיון שקיבלת לתיבת הדו×ל שלך ל×חר השלמת הרכישה.Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).× × ×œ×‘×¦×¢ ×ת ×”×¦×¢×“×™× ×”×‘××™× ×œ×”×©×œ×ž×ª השידרוגPlease provide details on how you intend to promote %s (please be as specific as possible).× × ×œ×ž×œ× ×ת שמך המל×.תוסףעמוד התוסףPlugin IDהתקנת תוסףלוג שינויי×תי×ורש×לות נפוצותפיטצ'×¨×™× ×•×ž×—×™×¨×™×התקנההיערות נוספותביקורותתוספי×Plugins & Themes SyncPremiumPremium %s version was successfully activated.גירסת פרימיו×הגרסה ×‘×ª×©×œ×•× ×›×‘×¨ פעילה.מחירוןמדיניות פרטיותProcess IDProcessingמוצרי×Program SummaryPromotion methodsפרובינציהמפתח פומביקניית רישיוןQuotaשליחה חוזרת של מייל ×”×קטיבציהRefer new customers to our %s and earn %s commission on each successful sale you refer!חידוש רישיוןRequestsRequires WordPress VersionResultSDK×ž×™×§×•× SDKשמירת %sScheduled Cronsצילומי מסךחפש לפי כתובתמפתח סודיSecure HTTPS %s page, running from an external domainנר××” שיש תקלה זמנית המונעת ×ת ביטול הניסיון. ×× × × ×¡×• שוב בעוד כמה דקות.נר××” שיש לך ×ת הגרסה ×”×חרונה.בחר מדינהשליחת מפתח רישיוןSet DB Optionסמלוץ עדכון לרשתרשיון ל×תר ×חדמזהה ×תר×תרי×דלג ו%sמזהה כתובתSocial media (Facebook, Twitter, etc.)×ž×¦×˜×¢×¨×™× ×¢×œ חוסר הנעימות, ×נחנו ×›×ן כדי לעזור ×× ×ª×פשר\×™ ×–×ת.Sorry, we could not complete the email update. Another user with the same email is already registered.Startהתחל תקופת ניסיוןהתחל ×ת %s הניסיון שלימחוז/מדינהSubmit & %s×ž× ×•×™×ª×ž×™×›×”×¤×•×¨×•× ×ª×ž×™×›×”×¡× ×›×¨×•×Ÿ מידע מהשרתח.פ.תנ××™ השירותThank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.×נו ×ž×•×“×™× ×œ×š על היותך כמשתמש של %s!×נו ×ž×•×“×™× ×œ×š על השימוש ×‘×ž×•×¦×¨×™× ×©×œ× ×•!תודה רבה!תודה %s!תודה על ×ישור ביצוע החלפת הבעלות. הרגע נשלח מייל ל-%s כדי לקבל ×ישור סופי.×”%s הרס לי ×ת ×”×תרה%s ×œ× ×¢×‘×“×”%s ×œ× ×¢×‘×“ כמצופהThe %s is great, but I need specific feature that you don't support×”%s ×œ× ×¢×•×‘×“×”%s הפסיק פת××•× ×œ×¢×‘×•×“×ª×”×œ×™×š ההתקנה התחיל ויכול לקחת מספר דקות לסיו×. ×× × ×”×ž×ª×™× ×• בסבלנות עד ×œ×¡×™×•× ×ž×‘×œ×™ לרענן ×ת הדפדפן.The upgrade of %s was successfully completed.תבניתהחלפת תֵמָהתבניותיש גרסה חדשה עבור ×”%s.התוסף ×œ× ×¡×•×ž×Ÿ כתו×× ×œ×’×¨×¡×ª הוורדפרס שלך.תוסף ×–×” ×œ× × ×‘×“×§ ×¢× ×’×¨×¡×ª הוורדפרס שלך.TimestampכותרתTotalכפרניסיוןסוגUnable to connect to the filesystem. Please confirm your credentials.רשיונות ×œ×œ× ×”×’×‘×œ×”×¢×“×›×•× ×™× ×œ×œ× ×”×’×‘×œ×”Unlimited commissions.עד %s ×תרי×עדכןעדכון רישיוןעדכוני×, הכרזות, הודעות שיווקיות, ×œ×œ× ×“×•×ר זבלשדרגהעלה\×™ והפעיל\×™ ×ת הגרסה שהורדתישמזהה משתמשמשתמשי×ValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.מ×ומת×מת כתובת דו×"לגרסה %s הושקה.×¤×¨×˜×™× × ×•×¡×¤×™×צפה בפיטצ'×¨×™× ×©×‘×ª×©×œ×•×WarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We made a few tweaks to the %s, %sWebsite, email, and social media statistics (optional)למה ציפית?××™×–×” פיטצ'ר?מה ×”%s שלך?מה המחיר שכן תרגיש\×™ בנוח לשל×?מה חיפשת?What's the %s's name?Where are you going to promote the %s?×”×× ×‘×¨×¦×•× ×š להמשיך ×¢× ×”×¢×™×“×›×•×Ÿ?כןYes - %sהניסיון כבר נוצל בעבר.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.×ת\×” מסודר!You are already running the %s in a trial mode.You are just one step away - %s×ין ברשותך רישיון בר תוקף לשימוש בגרסת הפרימיו×.יש לך רישיון %s.עידכנת בהצלחה ×ת ×”%s.×ולי פספסת ×ת ×–×” ×בל ×ינך חייב\ת לשתף כל מידע ×יתנו, ביכולתך %s על שיתוף המידע.חבילת ההרחבה %s שודרגה בהצלחה.תקופת הניסיון החינמית של %s בוטלה בהצלחה.חשבונך הופעל בהצלחה ×¢× ×—×‘×™×œ×ª %s.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!תקופת הניסיון שלך הסתיימה. הפיטצ'×¨×™× ×”×—×™× ××ž×™×™× ×¢×“×™×™×Ÿ × ×™×ª× ×™× ×œ×©×™×ž×•×©.רשיונך בוטל. ×× ×œ×“×¢×ª×š זו טעות, × × ×œ×™×¦×•×¨ קשר ×¢× ×”×ª×ž×™×›×”.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.הרישיון הופעל בהצלחה.רישיונך נותק בהצלחה, חזרת לחבילת %sשמך עודכן בהצלחה.החבילה עודכנה בהצלחה ×ל %s.החבילה שודרגה בהצלחה.הניסיון שלך הופעל בהצלחה.מיקוד / ×ª× ×“×•×רמעולה%s ×œ× ×™×›×•×œ לעבוד ×œ×œ× %s.ההרחבה %s ××™× ×” יכולה לפעול ×œ×œ× ×”×ª×•×¡×£.לתשמות לבך×פשרנש×רו %sמפעילשנהAPIסגירהדיבוגמזל טובחסו×מחוברהורד גרסה ×חרונהחודשיתפוגהנתיבשולח דו×"לחודשי××©× ×ª×™×©× ×ª×™×¤×¢× ×חתחבילה×ין מפתח סודיגרס×ות SDKרישיוןסינכרוןסינכרן רישיוןAuthorכבוידלוקמבוסס על %sהתחלת ניסיון ×—×™× ×סגירהסגירהdeactivating×”×צל%s×ל%2$s תשלחו לי עדכוני ×בטחה, פיטצ'רי×, תוכן חינוכי, ומידע על מבצעי×.חבילה %sמחוייב על בסיס %s×”×›×™ טובהיי×ופסהיי %s,יששש×תרי×ms×œ× ×ž×ומתמחירמחירוןגרסהsecתשלחו לי עדכוני ×בטחה ופיטצ'רי×, תוכן חינוכי, ומידע ×ודות מבצעי×.דלג×ממהתחל תקופת ניסיוןswitchingגרסת ×”-%s ×”×חרונה ×›×ןניסיוןמחקשנמךערוךהסתרOpt InOpt Outרכישההצגדלגעדכןשדרגלפני %sfreemius/languages/index.php000064400000000127146725417150012165 0ustar00,l, ,‹,š,¯,Â,É,5Ñ,-- - )-'5-]- v- ƒ--ož-.ž.´.Ç."ã./2#/!V/ax/0Ú/ 0040C0K0_0g0p0x0 }0‹0¨0¯0Ã0 ×0 ä0Yî0H1W1 h1t1}1‚1’1(«11Ô1%2:,2g2l2}2…2 •2  2­2Ã2 Ë2Õ2 Ú2å2”ø2 3 š3¤3¼3Ð3Ø3ò344%4D4 `4—k4[5f_5Æ5 Ì5Ú5YÞ5a86š6 6À6 È6 Ö6;ä6 7%7þ,7+8 08 ;8 H8U8jd8Ï8 Þ8è83ñ8%9~99U¸9:*:C:)^:-ˆ:¶:SÊ:;'6;^;Ma;7¯;gç;pO<À<Æ<ß< ÿ< ==4=G= O=1Y=.‹=Oº= >AŠ>yÌ>F?af?È?BÌ?,@<@ A@ N@[@y@ ’@@¤@ ¬@ ¸@Ä@Ú@4ã@A 'A1A5AL&CLLjLf·LM $M0MAM GM SM`M hMvM ŒM™M•ªM–@N/×NO)'O QO \O\gOÄOÙOìOC POPeP……Pd Q-pQžQ ¤Q±Q'¸QMàQG.R vR€R†RŒR‘R—REœRâRõRSS-S4S*CSnS*vS^¡STTTdTyT ‚TT ¨TµTÈTiÐTW:U"’UBµU6øU/V DVRV-cV‘V¯V&ÅVìVW W$WM8W†W/˜WÈW>èW'X&>XZeXTÀXRY.hY.—Y9ÆYZZ3[Z<ZbÌZP/[U€[_Ö[š6\KÑ\(]GF]#Ž])²]$Ü])^+^=^Z^;o^6«^>â^!_'_B_b_$x__·_Ó_ï_& `*4`7_`—`®`Ì`3å`a.aDa\apa*a1¸aêab#b>bZblb |bˆb¨b¿b ÔbábNêb9cXcvc‘c¡c²c1Ãcõc d d &d 1d>d VdCbd¦dQ«dýd ee2e EeQe `e je te €e e ›e ¥e ¯e »e ÈeÕe3si6§iÞióij jk$jéj–zk$l6lTlllul~l „l lœl¢ln¨lmk)m•m™m©m¿m ÏmÙmîm$n,nEHnZŽnénoo +oLo ko xoa…oço îoûopE'p'mp•p±pÇp¡ÝpqȆqOr3nrQ¢r$ôrAs%[sjsTìsAtTtmt ‰t”t ³t½t ÐtÝtät1ëtu*-u3Xu!Œu®u ¾u_vxvŽvžv´v¸vBØvEwAawK£wïw ÿw' x1x8xNxUx!qx“x—x¦x ­x·xáÓx µy¿y!Òy!ôyz:z$Xz}z'z"¸zÛzúzÛ{}ï{†m|ô|ú|}ƒ}œ›} 8~3B~ v~ƒ~–~T¯~ I!k€r€‹€ ¤€±€¹Ç€šªT±+‚Á2‚cô‚'Xƒ6€ƒ$·ƒ<܃0„$J„ˆo„ø„%…6…T9…MŽ…mÜ…›J†æ†6í†?$‡d‡$€‡(¥‡"· ñ‡û‡9ˆ9<ˆovˆÇæˆH®‰÷‰*•ŠWÀŠ‹~‹Bž‹á‹ è‹õ‹EŒ*TŒŒ’Œ™Œ©Œ¿Œ$ÕŒúŒ] !k — ›¥ µ$Âç÷Ž)ŽEŽLŽhŽ„Ž'‹ŽK³ŽBÿŽBX \fK|BÈ3 ?R>b¡ž¥D‘T‘ g‘q‘„‘ ”‘¡‘U¾‘.’ C’CM’ ‘’H›’<ä’ !“9.“Hh“-±“^ß“â>”Z!•½|•:–-Ê–ø–$—-—$@— e—r—y—}—— — ³—fÀ—'˜$7˜\˜Hl˜Wµ˜ ™H,™ u™™ž™®™¾™Ô™ð™ š š #š0švOšÆšßš&òš› › $› 2›?›W›s› ‰›B“›uÖ›$Lœ qœ~œ!œB¿œ$ '34 hu ‡;”iЫ:žæžížŸŸ !Ÿ-Ÿ IŸVŸ'rŸšŸ ªŸà·Ÿ¶˜ >O¡/Ž¡<¾¡!û¡¢8¢*¸¢!ã¢-£]3£‘£'°£ÀØ£«™¤3E¥ y¥ƒ¥ “¥;¥qÙ¥tK¦À¦ Ö¦ ã¦ð¦ô¦ §]§l§…§!¤§Ƨاߧ9ø§2¨KH¨ ”¨¡¨ ±¨¾¨—¨ Z©g©1w©©©¹©Ø©Ÿß©™ª.«yH«Z«"¬@¬ W¬;x¬"´¬׬Aõ¬)7­a­h­0o­l ­ ®;$® `®f®*è®0¯’D¯eׯr=°N°°Bÿ°=B±•€±K²Nb²´±²rf³‡Ù³®a´óµr¶3w¶T«¶3·44·9i·3£·×· ê·ô·?û·K;¸‡¸Ž¸ •¸ Ÿ¸¬¸°¸´¸ »¸ȸ ظå¸ì¸6 ¹B¹ F¹S¹Z¹m¹q¹x¹¹ †¹¹¬¹À¹й×¹ð¹÷¹þ¹ º!º3º:º AºNºUº Õº⺠òºüº » » $» 1»>» A»K» R»\»l»up» æ»ó»ú» ¼1¼O¼_¼f¼|¼ ƒ¼¼¼°¼·¼ ¾¼˼Ò¼è¼G4@v_‹‹¿À(¹±ŸÇI)j`f258zEBq ý§d£ ¡Y•~Aòh"ÜÛÆaÕv‚°„/ÍûÝÁ  Xaă€7¾Ujã|—žXgsWT+“y9\@ÓÀÿ'y3ÎõK–ªÙ‰¸æ}Ö _ùËDê-7[è ìpHÜh‘Šáq\ošs¨“/Ò rkúFâO¦š)ЈiRYÂÞ®üw´<2±¥FÑ­+†²UB=‰H:l‡¢G’=Án¹”’¶ààM`€1²;³6â0˜Ù^P-xœ'Ú® ŸÒ¢%tÈ?Ç™‡u™Ã}µ6ˆðžÞÉkÊK5.» S¦1óm³ØfÅW¾LÄ¿µƒÛEª‚¼ÉÈ<ätNÔw«·½0·ï*!Í"ŽløÖþ­N×;§#.¥g¨ZôÓ•!©«QA¼´JÆ[bZ— ̤R›ni¶JИî÷8L&M](>ÌCcPzŒ¤c>ëÑ&ä?ñ3V]ߎÚ,eQöϜʖuŒ,Š4×ØCç¡‘S*%”m#¯ºé|á°d{…e:¯Ô›x…I{DVºÏŸ9Î¬å» í¬„bß^ †£ Õ~ÃrTOo$ãpÝ© $˽%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is the new owner of the account.%s minimum payout amount.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.APIAccountAccount DetailsActionsActivateActivate %sActivate %s PlanActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre you sure you want to delete all Freemius data?Are you sure you want to proceed?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBillingBlockingBlog IDBodyBusiness nameCan't find your license key?CancelCancel InstallationCancel SubscriptionCancel TrialCancelledCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanCheckoutCityClear API CacheClear Updates TransientsClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeDateDeactivateDeactivate LicenseDeactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDelegate to Site AdminsDelete All AccountsDetailsDon't have a license key?Donate to this pluginDownloadDownload %s VersionDownload the latest %s versionDownload the latest versionDownloadedDue to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.During the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEndEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used for the upgrade below and we will resend you the license key.ErrorError received from the server:ExpiredExpires in %sExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.FreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFull nameFunctionGet commission for automated subscription renewals.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!How do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I can't pay for it anymoreI couldn't understand how to make it workI don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.In %sInstall Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid module ID.InvoiceIs ActiveIt looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's not what I was looking forJust letting you know that the add-ons information of %s is being pulled from an external server.KeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense KeyLicense keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerMessageMethodMobile appsModuleModule PathModule TypeMore information about %sNameNetwork BlogNetwork UserNewNew Version AvailableNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Opt InOpt OutOtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProcess IDProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicenseQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRequestsRequires WordPress VersionResultSDKSDK PathSave %sScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSimulate Network UpgradeSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSocial media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart TrialStart my free %sStateSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a new version of %s available.This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.TimestampTitleTotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser IDUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We made a few tweaks to the %s, %sWe're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress.org Plugin PageYesYes - %sYou already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou do not have a valid license to access the premium version.You have a %s license.You have successfully updated your %s.You might have missed it, but you don't have to share any data and can just %s the opt-in.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onactive add-onActiveaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismissdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,interjection expressing joy or exuberanceYee-hawlike websitesSitesmillisecondsmsnot verifiednounPricenounPricingproduct versionVersionsecondssecsend me security & feature updates, educational content and offers.skipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialswitchingthe latest %s version heretrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Tomohyco Tsunoda, 2018 Language-Team: Japanese (http://www.transifex.com/freemius/wordpress-sdk/language/ja/) Language: ja MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js ã™ãã« "%s" 有効化を完了ã—ã¦ãã ã•ã„%s ã®ã‚¢ãƒ‰ã‚ªãƒ³ã®æ”¯æ‰•ã„ãŒå®Œäº†ã—ã¾ã—ãŸã€‚%sインストール%sラインセス%s å‰%sã¨ãã®ã‚¢ãƒ‰ã‚ªãƒ³ã‚«ã‚¹ã‚¿ãƒžãƒ¼ãŒæ–°è¦ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’購入ã™ã‚‹ã”ã¨ã«%sã®ã‚³ãƒŸãƒƒã‚·ãƒ§ãƒ³ãŒç™ºç”Ÿã—ã¾ã™ã€‚%s ã®ç„¡æ–™è©¦ç”¨ãŒæ­£å¸¸ã«ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œã¾ã—ãŸã€‚ アドオンã¯ãƒ—レミアムãªã®ã§ã€è‡ªå‹•çš„ã«ç„¡åŠ¹åŒ–ã•ã‚Œã¾ã—ãŸã€‚ å°†æ¥ä½¿ç”¨ã—ãŸã„å ´åˆã¯ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’購入ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚%s ã¯ãƒ—レミアムã®ã¿ã®ã‚¢ãƒ‰ã‚ªãƒ³ã§ã™ã€‚ãã®ãƒ—ラグインを有効化ã™ã‚‹å‰ã«ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’購入ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚%s ã¯æ–°ã—ã„オーナーã§ã™ã€‚%sãŠæ”¯æ‰•ã„ã®æœ€ä½Žé‡‘é¡%sã¾ãŸã¯ãれ以上%s評価%s評価%s秒%sスター%sスター%s回%s回%såˆå›žã®è¨ªå•å¾Œã€ã‚¯ãƒƒã‚­ãƒ¼ã‚’トラッキングã—ã¦åŽç›Šã®å¯èƒ½æ€§ã‚’最大化ã—ã¾ã—ょã†ã€‚%sã®æœ‰æ–™æ©Ÿèƒ½%sã“ã“をクリックã—ã¦%s ライセンスを有効化ã—ãŸã„サイトをé¸æŠžã—ã¦ãã ã•ã„。APIアカウントアカウント詳細アクション有効化%sを有効化ã™ã‚‹%s プランを有効化フリーãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’有効化ライセンスを有効化ä¿ç•™ä¸­ã®ã‚µã‚¤ãƒˆã™ã¹ã¦ã§ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’有効ã«ã™ã‚‹ã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã«ã‚ã‚‹ã™ã¹ã¦ã®ã‚µã‚¤ãƒˆã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’有効ã«ã™ã‚‹ã€‚ã“ã®ã‚¢ãƒ‰ã‚ªãƒ³ã‚’有効化有効化済ã¿%s ã®ã‚¢ãƒ‰ã‚ªãƒ³ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã®ã‚¢ãƒ‰ã‚ªãƒ³%sドメインåを追加ã™ã‚‹ã‚¢ãƒ‰ã‚ªãƒ³ã‚¢ãƒ‰ã‚ªãƒ³ã‚¢ãƒ‰ã‚ªãƒ³ãŒ WordPress.org ã‹ Freemius ã«ãƒ‡ãƒ—ロイã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ä½æ‰€ä½æ‰€æ¬„ %dアフィリエイトアフィリエイト無料㮠%s ã®å¾Œã¯ã€ã‚ãšã‹ %s ã ã‘ãŠæ”¯æ‰•ãã ã•ã„。åŒæ„ã—ã¦ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’有効化ã™ã¹ã¦ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã™ã¹ã¦ã®ã‚¿ã‚¤ãƒ—許å¯ã—ã¦ç¶šã‘ã‚‹ã¾ãŸã¯ã€ä»Šã™ãスキップã—ã¦ã€%sã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ¬ãƒ™ãƒ«ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãƒšãƒ¼ã‚¸ã§ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’有効ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ç·é¡%sã‹ã‚‰ %s (有料版) ã®è‡ªå‹•ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã¨è‡ªå‹•ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãŒ%sã§é–‹å§‹ã—ã¾ã™ã€‚手動ã§è¡Œã†å ´åˆã¯ä»Šã™ãã«ã‚­ãƒ£ãƒ³ã‚»ãƒ«ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。匿åã®ãƒ•ã‚£ãƒ¼ãƒ‰ãƒãƒƒã‚¯ä¿ç•™ä¸­ã®ã‚µã‚¤ãƒˆã™ã¹ã¦ã«å映ã•ã›ã‚‹ã€‚ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã«ã‚ã‚‹ã™ã¹ã¦ã®ã‚µã‚¤ãƒˆã«å¯¾ã—ã¦å映ã•ã›ã‚‹ã€‚アフィリエイトã«å¿œå‹Ÿã™ã‚‹ã»ã‚“ã¨ã†ã«å…¨ã¦ã® Freemius データを削除ã—ã¾ã™ã‹?本当ã«ç¶šè¡Œã—ã¦ã„ã„ã§ã™ã‹?30日間ã®è¿”金期間ãŒã‚ã‚‹ãŸã‚ã€ã‚³ãƒŸãƒƒã‚·ãƒ§ãƒ³ã®ãŠæ”¯æ‰•ã„ã¯30日以é™ã«ãªã‚Šã¾ã™ã€‚自動インストールã¯ã‚ªãƒ—トインã—ãŸãƒ¦ãƒ¼ã‚¶ã®ã¿ã§å‹•ä½œã—ã¾ã™ã€‚%s ã«è‡ªå‹•æ›´æ–°è‡ªå‹•ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã®å¹³å‡ã™ã”ã„!アフィリエイトã«ãªã‚‹è«‹æ±‚書ブロッキングブログ ID本文商å·ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã‹?キャンセルインストールをキャンセルã™ã‚‹ã‚µãƒ–スクリプションをキャンセルã™ã‚‹ãƒˆãƒ©ã‚¤ã‚¢ãƒ«ã‚’キャンセルキャンセルトライアルをキャンセルã™ã‚‹ã¨ã™ãã«ã™ã¹ã¦ã®ãƒ—レミアム機能ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒã§ããªããªã‚Šã¾ã™ã€‚本当ã«å®Ÿè¡Œã—ã¾ã™ã‹?ライセンスを変更オーナーを変更プラン変更ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆå¸‚API キャッシュをクリアアップデートã®ãƒˆãƒ©ãƒ³ã‚¸ã‚¨ãƒ³ãƒˆã‚’クリアーã«ã™ã‚‹åŒ¿åã§ãƒ—ラグインを使用ã™ã‚‹ã«ã¯ã“ã¡ã‚‰ã‚’クリッククリックã—ã¦%sã®è©•ä¾¡ã‚’ã—ã¦ã„るレビューを観るクリックã—ã¦ãƒ•ãƒ«ã‚µã‚¤ã‚ºã®ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã‚·ãƒ§ãƒƒãƒˆã‚’見る %dプロダクトコード互æ›æ€§ã®ã‚る最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³é€£çµ¡ã‚µãƒãƒ¼ãƒˆã«é€£çµ¡é€£çµ¡ã‚³ãƒ³ãƒˆãƒªãƒ“ューター%s を有効化ã§ãã¾ã›ã‚“。国Cron タイプ日付無効化ライセンスを無効化ライセンスを無効化ã™ã‚‹ã¨ã™ã¹ã¦ã®ãƒ—レミアム機能ãŒä½¿ãˆãªããªã‚Šã¾ã™ãŒã€ä»–ã®ã‚µã‚¤ãƒˆã§ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’有効ã«ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚本当ã«å®Ÿè¡Œã—ã¾ã™ã‹ï¼Ÿç„¡åŠ¹åŒ–デãƒãƒƒã‚°ãƒ­ã‚°ã‚µã‚¤ãƒˆç®¡ç†è€…ã«å§”ä»»ã™ã‚‹å…¨ã¦ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除詳細ライセンスキーをãŠæŒã¡ã§ã¯ã‚ã‚Šã¾ã›ã‚“ã‹?ã“ã®ãƒ—ラグインã«å¯„付ã™ã‚‹ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰%s ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンロード最新㮠%s をダウンロード最新版をダウンロードダウンロード済ã¿ã‚¢ãƒ•ã‚£ãƒªã‚¨ã‚¤ãƒˆè¦ç´„é•åã«ã‚ˆã‚Šã€ã‚¢ãƒ•ã‚£ãƒªã‚¨ã‚¤ãƒˆã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’一時的ã«å‡çµã•ã›ã¦ã„ãŸã ãã¾ã—ãŸã€‚ã”質å•ç­‰ãŒã‚ã‚Šã¾ã—ãŸã‚‰ã€ã‚µãƒãƒ¼ãƒˆã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。アップデートã®å‡¦ç†ä¸­ã«%dサイトãŒãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®æœ‰åŠ¹åŒ–ãŒä¿ç•™ä¸­ã§ã‚ã‚‹ã“ã¨ã‚’検知ã—ã¾ã—ãŸã€‚アップデートã®å‡¦ç†ä¸­ã«ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯å†…ã®%dサイトãŒå¯¾å¿œå¾…ã¡ã«ãªã£ã¦ã„ã‚‹ã“ã¨ã‚’検知ã—ã¾ã—ãŸã€‚Emailメールアドレス終了%sã®ãƒ—ロモーションを行ã†äºˆå®šã®ã‚ãªãŸã®ã‚µã‚¤ãƒˆã‚„ä»–ã®ã‚µã‚¤ãƒˆã®ãƒ‰ãƒ¡ã‚¤ãƒ³åを入力ã—ã¦ãã ã•ã„。アップグレードã«ä½¿ç”¨ã—ãŸãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’下ã«å…¥åŠ›ã—ã¦ãã ã•ã„。ãã†ã™ã‚Œã°ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’ãŠé€ã‚Šã—ã¾ã™ã€‚エラーサーãƒãƒ¼ã‹ã‚‰ã‚¨ãƒ©ãƒ¼ã‚’å—ä¿¡ã—ã¾ã—ãŸã€‚期é™åˆ‡ã‚Œ%s ã§æœŸé–“終了追加ã®ãƒ‰ãƒ¡ã‚¤ãƒ³åプロダクトフォームã®ãƒžãƒ¼ã‚±ãƒ†ã‚£ãƒ³ã‚°ã‚’è¡Œã†è¿½åŠ ãƒ‰ãƒ¡ã‚¤ãƒ³å。ファイルフィルターWordPress.orgã®ã‚¬ã‚¤ãƒ‰ãƒ©ã‚¤ãƒ³ã«æº–æ‹ ã™ã‚‹ãŸã‚ã€ãƒˆãƒ©ã‚¤ã‚¢ãƒ«ã‚’開始ã™ã‚‹å‰ã«ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¨é‡è¦ã§ãªã„サイト情報ã®ã‚ªãƒ—トインã€æ›´æ–°ã®ç¢ºèªã‚„トライアルã®çŠ¶æ…‹ç¢ºèªã®ãŸã‚ã«%sãŒ%sã«å¯¾ã—ã¦å®šæœŸçš„ã«ãƒ‡ãƒ¼ã‚¿ã‚’é€ä¿¡ã™ã‚‹è¨±å¯ã‚’得るよã†ã«è¨­å®šã—ã¦ãã ã•ã„。無料フリートライアルフリーãƒãƒ¼ã‚¸ãƒ§ãƒ³Freemius APIFreemius デãƒãƒƒã‚°Freemius SDK ãŒãƒ—ラグインã®ãƒ¡ã‚¤ãƒ³ãƒ•ã‚¡ã‚¤ãƒ«ã‚’見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ç¾åœ¨ã®ã‚¨ãƒ©ãƒ¼ã‚’æ·»ãˆã¦ sdk@freemius.com ã«é€£çµ¡ã—ã¦ãã ã•ã„。Freemius ステータスフルãƒãƒ¼ãƒ æ©Ÿèƒ½ã‚µãƒ–スクリプションã®è‡ªå‹•æ›´æ–°ã§ã‚³ãƒŸãƒƒã‚·ãƒ§ãƒ³ã‚’å¾—ã¾ã—ょã†ã€‚ライセンスキーã¯ãŠæŒã¡ã§ã™ã‹?ã“ã‚“ã«ã¡ã¯ã€‚%sã«ã‚¢ãƒ•ã‚£ãƒªã‚¨ã‚¤ãƒˆãƒ—ログラムãŒã‚ã‚‹ã®ã¯ã”存知ã§ã—ãŸã‹ï¼Ÿã€€%sãŒãŠå¥½ããªã‚‰ã€ç§ãŸã¡ã®ã‚¢ãƒ³ãƒã‚µãƒ€ãƒ¼ã«ãªã£ã¦å ±é…¬ã‚’å¾—ã¾ã—ょã†ï¼%s ã¯ã©ã†ã§ã™ã‹? ç§ãŸã¡ã®å…¨ã¦ã® %s ã®ãƒ—レミアム機能をãŠè©¦ã—ãã ã•ã„。アップロードã¨æœ‰åŠ¹åŒ–ã®æ–¹æ³•ã©ã®ã‚ˆã†ã«æˆ‘々をプロモートã—ã¾ã™ã‹ï¼Ÿã‚‚ã†æ‰•ã†ã“ã¨ãŒã§ãã¾ã›ã‚“ã©ã†ã—ãŸã‚‰å‹•ä½œã™ã‚‹ã‹åˆ†ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚自分ã®æƒ…報を共有ã—ãŸãã‚ã‚Šã¾ã›ã‚“より良ㄠ%sを見ã¤ã‘ã¾ã—ãŸã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’アップグレードã—ã¾ã—ãŸãŒã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’åŒæœŸã—よã†ã¨ã™ã‚‹ã¨ãƒ—ラン㌠%s ã®ã¾ã¾ã§ã™ã€‚%sã¯ã‚‚ã†ä¸è¦ã§ã™çŸ­æœŸé–“ã ã‘ %s㌠必è¦ã§ã™ã€‚ID決定をサイトã®ç®¡ç†è€…ã«å§”ä»»ã™ã‚‹ã«ã¯ã‚¯ãƒªãƒƒã‚¯ã—ã¦ãã ã•ã„。ãŠæ™‚é–“ãŒã‚ã‚Œã°ã€ãªãœ%sã™ã‚‹ã®ã‹ç†ç”±ã‚’æ•™ãˆã¦ãã ã•ã„。%sã®æ‰€æœ‰æ¨©ã‚’%sã¸è­²ã‚ŠãŸã„å ´åˆã¯ã€æ‰€æœ‰æ¨©ã®å¤‰æ›´ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。ã“れらã®ã‚µã‚¤ãƒˆã§%sを使ã†å ´åˆã¯ã€ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’入力ã—ã€ã‚¢ã‚¯ãƒ†ã‚£ãƒ™ãƒ¼ã‚·ãƒ§ãƒ³ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。%s 内フリーãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’今ã™ãインストールフリーãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®æ›´æ–°ã‚’今ã™ãインストール今ã™ãインストール今ã™ã更新をインストールインストール中プラグイン: %sモジュール ID ãŒä¸æ­£ã§ã™è«‹æ±‚書有効ライセンスã®æœ‰åŠ¹åŒ–ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ライセンスã®ç„¡åŠ¹åŒ–ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã™ã§ã«ãƒˆãƒ©ã‚¤ã‚¢ãƒ«ãƒ¢ãƒ¼ãƒ‰ã§ã¯ãªã„よã†ãªã®ã§ã€ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã™ã‚‹å¿…è¦ã¯ã‚ã‚Šã¾ã›ã‚“ :)ã¾ã  %s プランã®ã‚ˆã†ã§ã™ã€‚ã‚‚ã—アップグレードやプランã®å¤‰æ›´ã‚’ã—ãŸã®ãªã‚‰ã€ã“ã¡ã‚‰ã§ä½•ã‚‰ã‹ã®å•é¡ŒãŒç™ºç”Ÿã—ã¦ã„るよã†ã§ã™ã€‚申ã—訳ã‚ã‚Šã¾ã›ã‚“。サイトã¯æœ‰åŠ¹ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’æŒã£ã¦ã„ãªã„よã†ã§ã™ã€‚èªè¨¼ãƒ‘ラメータã®1ã¤ãŒé–“é•ã£ã¦ã„るよã†ã§ã™ã€‚ 公開éµã€ç§˜å¯†éµã€ãƒ¦ãƒ¼ã‚¶ãƒ¼IDã‚’æ›´æ–°ã—ã¦ã€ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。探ã—ã¦ã„ãŸã‚‚ã®ã§ã¯ã‚ã‚Šã¾ã›ã‚“%s ã®ã‚¢ãƒ‰ã‚ªãƒ³ã«é–¢ã™ã‚‹æƒ…å ±ã¯ã€å¤–部サーãƒãƒ¼ã‹ã‚‰å–å¾—ã•ã‚Œã¾ã™ã€‚キー将æ¥ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãŸã‚ã«ä¿®æ­£ã§ãるよã†ã€ä½•ãŒå‹•ä½œã—ãªã‹ã£ãŸã®ã‹ã©ã†ã‹å…±æœ‰ã—ã¦ãã ã•ã„…改善ã§ãるよã†ã€ã©ã†ã‹ç†ç”±ã‚’æ•™ãˆã¦ãã ã•ã„。最終最終更新最新ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹æœ€æ–°ã®ãƒ•ãƒªãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã—ãŸæœ€æ–°ç‰ˆãŒã‚¤ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã—ãŸè©³ç´°ã¯ã“ã¡ã‚‰é•·ã•ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ãŒç©ºã§ã™ã€‚ライフタイム%sã¯æ°—ã«å…¥ã‚Šã¾ã—ãŸã‹ï¼Ÿã€€ã‚¢ãƒ³ãƒã‚µãƒ€ãƒ¼ã«ãªã£ã¦å ±é…¬ã‚’å¾—ã¾ã—ょㆠ;-)DB オプションを読ã¿è¾¼ã‚€localhostグロガーメッセージメソッドモãƒã‚¤ãƒ«ã‚¢ãƒ—リケーションモジュールモジュールã®ãƒ‘スモジュールタイプ%s ã«é–¢ã™ã‚‹è©³ç´°æƒ…å ±åå‰ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ–ログãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ¦ãƒ¼ã‚¶æ–°è¦æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚ã‚Šã¾ã™æ–°ã—ã„フリーãƒãƒ¼ã‚¸ãƒ§ãƒ³ (%s) ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã—ãŸæ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ (%s) ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã—ãŸãƒ‹ãƒ¥ãƒ¼ã‚¹ãƒ¬ã‚¿ãƒ¼æ¬¡ã„ã„ãˆID ãŒã‚ã‚Šã¾ã›ã‚“%s ã®æ‹˜æŸã¯ã‚ã‚Šã¾ã›ã‚“。ã„ã¤ã§ã‚‚キャンセルã§ãã¾ã™ã€‚%s 日以内ã§ã‚ã‚Œã°ã„ã¤ã§ã‚‚キャンセルã§ãã¾ã™ã€‚クレジットカードã¯å¿…è¦ã‚ã‚Šã¾ã›ã‚“。有効期é™ãªã—期é™ã®ãªã„%sã®ãƒ—ランã«ã¯ãƒˆãƒ©ã‚¤ã‚¢ãƒ«æœŸé–“ã¯ã‚ã‚Šã¾ã›ã‚“。O.K一度ライセンスã®æœŸé™ãŒåˆ‡ã‚Œã‚‹ã¨ã€ãƒ•ãƒªãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®åˆ©ç”¨ã¯å¯èƒ½ã§ã™ãŒã€%sã®æ©Ÿèƒ½ã‚’使ã†ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚オプトインオプトアウトãã®ä»–所有者㮠Emailオーナー ID所有者åPCI コンプライアント有料アドオン㯠Freemius ã«ãƒ‡ãƒ—ロイã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚PayPal アカウントã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹æ”¯æ‰•ã„ãŠæ”¯æ‰•ã„㯠USD ã‹ã¤ PayPal 経由ã§æ¯Žæœˆè¡Œã‚ã‚Œã¾ã™ã€‚プラン%s プランã¯å­˜åœ¨ã—ãªã„ãŸã‚ã€è©¦ç”¨ã‚’開始ã§ãã¾ã›ã‚“。%s プランã«ã¯ãƒˆãƒ©ã‚¤ã‚¢ãƒ«æœŸé–“ã¯ã‚ã‚Šã¾ã›ã‚“。プラン IDã“ã¡ã‚‰ã§ç§ãŸã¡ã«é€£çµ¡ã‚’ã¨ã£ã¦ãã ã•ã„。以下ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¨ã¨ã‚‚ã«ç§ãŸã¡ã«é€£çµ¡ã‚’ãã ã•ã„。%s をダウンロードã—ã¦ãã ã•ã„。購入後ã™ãã«ãƒ¡ãƒ¼ãƒ«ã§å—ã‘å–ã£ãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’入力ã—ã¦ãã ã•ã„:関係ã®ã‚るウェブサイトやソーシャルメディアã®çµ±è¨ˆã‚’æä¾›ã—ã¦ãã ã•ã„。例: サイトã®æœˆé–“訪å•è€…æ•°ã€Emailã®è³¼èª­è€…æ•°ã€ãƒ•ã‚©ãƒ­ãƒ¯ãƒ¼æ•°ç­‰ (機密情報ã¨ã—ã¦å–り扱ã„ã¾ã™)アップグレードを完了ã™ã‚‹ã«ã¯ä»¥ä¸‹ã®æ‰‹é †ã‚’完了ã•ã›ã¦ãã ã•ã„。セキュリティや機能ã®ã‚¢ãƒƒãƒ—デートã€å­¦ç¿’用用コンテンツã€ãŠã‚ˆã³ã‚ªãƒ•ã‚¡ãƒ¼ã«ã¤ã„ã¦ãŠå•ã„åˆã‚ã›ã‚’希望ã•ã‚Œã‚‹å ´åˆã¯ã€ãŠçŸ¥ã‚‰ã›ãã ã•ã„。ã©ã®ã‚ˆã†ã«%sをプロモートã™ã‚‹ã¤ã‚‚ã‚Šãªã®ã‹ã€è©³ç´°ã‚’ãŠçŸ¥ã‚‰ã›ãã ã•ã„ (ã§ãã‚‹ã ã‘具体的ã«ãŠé¡˜ã„ã—ã¾ã™)フルãƒãƒ¼ãƒ ã‚’入力ã—ã¦ãã ã•ã„。プラグインプラグインã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ãƒ—ラグイン IDプラグインã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å¤‰æ›´å±¥æ­´èª¬æ˜ŽFAQ機能 & 料金インストールãã®ä»–ã®è¨˜è¿°ãƒ¬ãƒ“ュープラグインã¯ãƒ—レミアムコードãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãªã„「サービスウェアã€ã§ã™ã€‚プラグインプラグインã¨ãƒ†ãƒ¼ãƒžã‚’åŒæœŸãƒ—レミアムプレミアムãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® %sã¯æœ‰åŠ¹åŒ–ã«æˆåŠŸã—ã¾ã—ãŸã€‚プレミアムアドオンãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯ã™ã§ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ¸ˆã¿ã§ã™ã€‚プレミアムãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ—レミアムãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯ã™ã§ã«æœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚料金表プライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼ãƒ—ロセス IDプロダクトプログラム概è¦ãƒ—ロモーション方法県・州・çœå…¬é–‹éµãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’購入クォータ有効化メールをå†é€ä¿¡æ–°è¦ã‚«ã‚¹ã‚¿ãƒžãƒ¼ã«ç§ãŸã¡ã®%sを紹介ã—ã¦ã€å£²ã‚Šä¸Šã’ã”ã¨ã«%sã®ã‚³ãƒŸãƒƒã‚·ãƒ§ãƒ³ã‚’å¾—ã¾ã—ょã†ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’更新リクエスト数必è¦ãª WordPress ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³çµæžœSDKSDK ã®ãƒ‘ス%s ã‚’ä¿å­˜ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ« Cronスクリーンショットä½æ‰€ã§æ¤œç´¢ã™ã‚‹ç§˜å¯†éµå¤–部ドメインã§å®Ÿè¡Œä¸­ã®ã‚»ã‚­ãƒ¥ã‚¢ãª HTTPS %sページトライアルã®ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã«ä¸€æ™‚çš„ãªå•é¡ŒãŒã‚ã‚Šã¾ã—ãŸã€‚数分後ã«å†åº¦ãŠè©¦ã—ãã ã•ã„。最新版をå–å¾—ã§ãã¾ã—ãŸã€‚国をé¸æŠžãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚­ãƒ¼ã‚’é€ä¿¡DB オプションを設定ã™ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¢ãƒƒãƒ—グレードをシミュレートã™ã‚‹ã‚·ãƒ³ã‚°ãƒ«ã‚µã‚¤ãƒˆãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚µã‚¤ãƒˆ IDサイトã®ã‚ªãƒ—トインã«æˆåŠŸã—ã¾ã—ãŸã€‚サイト数スキップã¨%sスラッグソーシャルメディア(Facebookã€Twitterã€ãã®ä»–)ã”迷惑をãŠã‹ã‘ã—ã¦ã™ã„ã¾ã›ã‚“。もã—機会をã„ãŸã ã‘ãŸã‚‰ãŠæ‰‹ä¼ã„ã‚’ã—ã¾ã™ã€‚メールアドレスã®ã‚¢ãƒƒãƒ—デートを完了ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã™ã§ã«åŒã˜ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ç™»éŒ²ã—ã¦ã„るよã†ã§ã™ã€‚開始トライアルを開始無料㮠%s を開始州é€ä¿¡ã¨%sサブスクリプションサãƒãƒ¼ãƒˆã‚µãƒãƒ¼ãƒˆãƒ•ã‚©ãƒ¼ãƒ©ãƒ ã‚µãƒ¼ãƒãƒ¼ã‹ã‚‰ã®ãƒ‡ãƒ¼ã‚¿ã‚’åŒæœŸç¨Žé‡‘ / VAT ID利用è¦ç´„アフィリエイトアカウントã«å¿œå‹Ÿã„ãŸã ãã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚残念ãªãŒã‚‰ç¾æ™‚点ã§ã¯ç”³è«‹ã‚’å—ç†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚30日後ã«æ”¹ã‚ã¦ãŠç”³è¾¼ã¿ãã ã•ã„。アフィリエイトプログラムã«å¿œå‹Ÿã„ãŸã ãã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚14日以内ã«ãŠç”³ã—è¾¼ã¿è©³ç´°ã‚’レビューã—ã€æ”¹ã‚ã¦ã”連絡ã„ãŸã—ã¾ã™ã€‚%sã¨ã‚¢ãƒ‰ã‚ªãƒ³ã®ã”利用ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ï¼%sã®ã”利用ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ï¼ãƒ—ロダクトã®ã”利用ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ï¼ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ï¼ã‚ã‚ŠãŒã¨ã† $s ã•ã‚“!所有権ã®å¤‰æ›´ã‚’確èªã—ã¦ã„ãŸã ãã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚ %s ã«æ‰¿èªãƒ¡ãƒ¼ãƒ«ãŒé€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚%s ã®å½±éŸ¿ã§ã‚µã‚¤ãƒˆã‚’å´©ã‚Œã¾ã—ãŸ%s ãŒå‹•ä½œã—ã¾ã›ã‚“ã§ã—ãŸ%sãŒæœŸå¾…通りã«å‹•ãã¾ã›ã‚“ã§ã—㟠%s ã¯ç´ æ™´ã‚‰ã—ã„ã®ã§ã™ãŒã€ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„ã‚る機能ãŒå¿…è¦ã§ã™%s ãŒå‹•ä½œã—ã¦ã„ã¾ã›ã‚“%s ã®å‹•ä½œãŒçªç„¶åœæ­¢ã—ã¾ã—ãŸã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ—ロセスãŒé–‹å§‹ã•ã‚Œã€æ•°åˆ†ã§å®Œäº†ã—ã¾ã™ã€‚完了ã¾ã§ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。ページã®ãƒªãƒ•ãƒ¬ãƒƒã‚·ãƒ¥ãªã©ã¯è¡Œã‚ãªã„ã§ãã ã•ã„。リモートプラグインパッケージã«ã¯ã€ç›®çš„ã®ã‚¹ãƒ©ãƒƒã‚°ã‚’å«ã‚€ãƒ•ã‚©ãƒ«ãƒ€ãŒå«ã¾ã‚Œã¦ã„ãªã„ãŸã‚ã€ãƒªã­ãƒ¼ãƒ ãŒæ©Ÿèƒ½ã—ã¾ã›ã‚“ã§ã—ãŸã€‚%s ã®ã‚¢ãƒƒãƒ—グレードãŒå®Œäº†ã—ã¾ã—ãŸã€‚テーマテーマ変更テーマ%sã®å…¥æ‰‹å¯èƒ½ãªæ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚ã‚Šã¾ã™ã“ã®ãƒ—ラグインã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚ŒãŸ WordPress ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«äº’æ›æ€§ãŒã‚ã‚Šã¾ã›ã‚“。ã“ã®ãƒ—ラグインã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚ŒãŸ WordPress ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯æ¤œè¨¼ã•ã‚Œã¦ã„ã¾ã›ã‚“。タイムスタンプタイトルトータル町トライアルタイプファイルシステムã«æŽ¥ç¶šã§ãã¾ã›ã‚“。視覚情報を確èªã—ã¦ãã ã•ã„。無制é™ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ç„¡åˆ¶é™ã®ã‚¢ãƒƒãƒ—デート無制é™ã®ã‚³ãƒŸãƒƒã‚·ãƒ§ãƒ³ã€‚%sサイトã¾ã§æ›´æ–°ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’æ›´æ–°æ›´æ–°ã€ç™ºè¡¨ã€ãƒžãƒ¼ã‚±ãƒ†ã‚£ãƒ³ã‚°ã€ã‚¹ãƒ‘ムãªã—アップグレードダウンロードã—ãŸãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’アップロードã—ã¦æœ‰åŠ¹åŒ–ã‚„ã£ãŸãƒ¼ãƒ¦ãƒ¼ã‚¶ãƒ¼ IDユーザー値%s ã«ç¢ºèªãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã—ã¾ã—ãŸã€‚ã‚‚ã—5分以内ã«ãã‚ŒãŒå±Šã‹ãªã„å ´åˆã€è¿·æƒ‘メールボックスを確èªã—ã¦ãã ã•ã„。èªè¨¼æ¸ˆã¿èªè¨¼ãƒ¡ãƒ¼ãƒ«ãƒãƒ¼ã‚¸ãƒ§ãƒ³ %s をリリースã—ã¾ã—ãŸã€‚詳細を表示有料ã®æ©Ÿèƒ½ã‚’表示ã™ã‚‹è­¦å‘Šãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«é–¢é€£ä»˜ã‘られãŸæœ‰åŠ¹ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。メールアドレスãŒæ­£ã—ã„ã‹ç¢ºèªã—ã¦ãã ã•ã„。システムã§ã¯ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚メールアドレスãŒæ­£ã—ã„ã‹ç¢ºèªã—ã¦ãã ã•ã„。プラグインを微調整ã—ã¾ã™ã€ %s, %sFreeminus ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãƒ¬ãƒ™ãƒ«ã®ã‚¤ãƒ³ãƒ†ã‚°ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’ã”紹介ã§ãã‚‹ã“ã¨ã«èˆˆå¥®ã—ã¦ã„ã¾ã™ã€‚ウェブサイトã€Email ã¾ãŸã¯ã‚½ãƒ¼ã‚·ãƒ£ãƒ«ãƒ¡ãƒ‡ã‚£ã‚¢ã®çµ±è¨ˆ (オプション)何を期待ã—ã¦ã„ã¾ã—ãŸã‹?何ã®æ©Ÿèƒ½ã§ã™ã‹?自分㮠%s ã¯ãªã‚“ã§ã™ã‹? 支払ã£ã¦ã‚‚よã„ã¨æ€ã†ä¾¡æ ¼ã¯ã„ãらã§ã™ã‹?探ã—ã¦ã„ãŸã®ã¯ä½•ã§ã™ã‹?%sã®åå‰ã¯ä½•ã§ã™ã‹ï¼Ÿ%sã®ãƒ—ロモーションを行ã†ã‚µã‚¤ãƒˆã¯ã©ã“ã§ã™ã‹ï¼ŸWordPress.org ã®ãƒ—ラグインページã¯ã„ã¯ã„以å‰ã™ã§ã«è©¦ç”¨ç‰ˆã‚’利用ã—ã¾ã—ãŸã€‚%2$s プランã®%1$s日間ã®ãƒ•ãƒªãƒ¼ãƒˆãƒ©ã‚¤ã‚¢ãƒ«ã‚’開始ã™ã‚‹ã¾ã§ã‚ã¨ãƒ¯ãƒ³ã‚¯ãƒªãƒƒã‚¯ã§ã™ã€‚ã™ã¹ã¦å®Œç’§ã§ã™!ã™ã§ã«%sをトライアルモードã§åˆ©ç”¨ä¸­ã§ã™ã€‚ã‚‚ã†ã‚ã¨ã‚ãšã‹ã§ã™ - %sプレミアムãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãる有効ãªãƒ©ã‚¤ã‚»ãƒ³ã‚¹æŒã£ã¦ã„ã¾ã›ã‚“。%s ライセンスをæŒã£ã¦ã„ã¾ã™ã€‚%s ã®ã‚¢ãƒƒãƒ—デートãŒæˆåŠŸã—ã¾ã—ãŸã€‚見逃ã—ã¦ã„ãŸã‹ã‚‚ã—ã‚Œã¾ã›ã‚“ãŒã€ã©ã‚“ãªæƒ…報も共有ã™ã‚‹å¿…è¦ã¯ãªãã€ã‚ªãƒ—トインを $s ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ %sã®æ”¹å–„ã«å½¹ç«‹ã¤ä½¿ç”¨çŠ¶æ³ã®ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã«ã™ã§ã«ã‚ªãƒ—トインã—ã¦ã„ã¾ã™ã€‚プロダクトã®æ”¹å–„ã«å½¹ç«‹ã¤ä½¿ç”¨çŠ¶æ³ã®ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã«ã™ã§ã«ã‚ªãƒ—トインã—ã¦ã„ã¾ã™ã€‚%s ã®ã‚¢ãƒ‰ã‚ªãƒ³ã®ãƒ—ランã®ã‚¢ãƒƒãƒ—グレードãŒå®Œäº†ã—ã¾ã—ãŸã€‚%s ã®ãƒ•ãƒªãƒ¼ãƒˆãƒ©ã‚¤ã‚¢ãƒ«ã¯ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œã¾ã—ãŸã€‚アカウント㌠%s プランã§æœ‰åŠ¹åŒ–ã§ãã¾ã—ãŸã€‚%sã®ã‚¢ãƒ•ã‚£ãƒªã‚¨ã‚¤ãƒˆç”³è«‹ã¯å—ç†ã•ã‚Œã¾ã—ãŸï¼ã€€æ¬¡ã®ãƒªãƒ³ã‚¯ã‹ã‚‰ã‚¢ãƒ•ã‚£ãƒªã‚¨ã‚¤ãƒˆã‚¨ãƒªã‚¢ã«ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ãã ã•ã„:%sアフィリエイトアカウントã¯ä¸€æ™‚çš„ã«åœæ­¢ã•ã‚Œã¾ã—ãŸã€‚ã‚ãªãŸã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®æ‰¿èªãŒå®Œäº†ã—ã¾ã—ãŸã€‚ã™ã”ã„ï¼ãƒ•ãƒªãƒ¼ãƒˆãƒ©ã‚¤ã‚¢ãƒ«æœŸé–“ãŒçµ‚了ã—ã¾ã—ãŸã€‚%1$s %3$sã«é‚ªé­”ã•ã‚Œãšã«åˆ©ç”¨ã‚’継続ã™ã‚‹ã«ã¯ï¼Œä»Šã™ã %2$s ã®ã‚¢ãƒƒãƒ—グレードを行ã£ã¦ãã ã•ã„。フリートライアル期間ãŒçµ‚了ã—ã¾ã—ãŸã€‚ç„¡æ–™ã§ä½¿ãˆã‚‹æ©Ÿèƒ½ã¯å¼•ã続ã利用å¯èƒ½ã§ã™ã€‚ライセンスã¯ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œã¾ã—ãŸã€‚ã‚‚ã—ãã‚ŒãŒé–“é•ã„ã ã¨æ€ã†ãªã‚‰ã‚µãƒãƒ¼ãƒˆã«é€£çµ¡ã—ã¦ãã ã•ã„。ライセンスã®æœ‰åŠ¹æœŸé™ãŒåˆ‡ã‚Œã¾ã—ãŸã€‚ %1$s %3$sã«é‚ªé­”ã•ã‚Œãšã«åˆ©ç”¨ã‚’継続ã™ã‚‹ã«ã¯ï¼Œä»Šã™ã%2$sアップグレードを行ã£ã¦ãã ã•ã„。ライセンスã¯æœ‰åŠ¹æœŸé™ãŒãã‚Œã¾ã—ãŸã€‚%s ã®æ©Ÿèƒ½ã‚’引ã続ã利用ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ãŸã ã—ã€ã‚¢ãƒƒãƒ—デートやサãƒãƒ¼ãƒˆã‚’ã†ã‘ã‚‹ã«ã¯ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’アップデートã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ライセンスã®æœ‰åŠ¹æœŸé™ãŒåˆ‡ã‚Œã¾ã—ãŸã€‚ç„¡æ–™ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®%s ã¯å¼•ã続ã利用ã§ãã¾ã™ã€‚ライセンスã®æœ‰åŠ¹åŒ–ãŒæˆåŠŸã—ã¾ã—ãŸã€‚ライセンスã®ç„¡åŠ¹åŒ–ãŒå®Œäº†ã—ã¾ã—ãŸã€‚%s プランã«æˆ»ã‚Šã¾ã—ãŸã€‚åå‰ã®ã‚¢ãƒƒãƒ—デートãŒæˆåŠŸã—ã¾ã—ãŸã€‚プラン㮠%s ã¸ã®å¤‰æ›´ãŒæˆåŠŸã—ã¾ã—ãŸã€‚プランã®ã‚¢ãƒƒãƒ—グレードãŒæˆåŠŸã—ã¾ã—ãŸã€‚トライアル版ã®åˆ©ç”¨ã‚’開始ã—ã¾ã—ãŸã€‚ZIP / 郵便番å·ãã†ã æœ‰åŠ¹%s ã¯ã€%s ãŒç„¡ã„ã¨å®Ÿè¡Œã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。%s ã¯ã€ãƒ—ラグインãŒç„¡ã„ã¨å®Ÿè¡Œã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。警告許å¯ã‚㨠%s有効化中年APIå´ä¸‹ãƒ‡ãƒãƒƒã‚°ãŠã‚ã§ã¨ã†ãƒ–ロック接続最新版をダウンロード最新ã®ãƒ•ãƒªãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンロード月期é™åˆ‡ã‚Œãƒ‘スメールé€ä¿¡ä¸­æœˆå¹´æ¬¡æ¯Žå¹´ä¸€åº¦ãƒ—ラン秘密éµãŒã‚ã‚Šã¾ã›ã‚“SDK ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãƒ©ã‚¤ã‚»ãƒ³ã‚¹åŒæœŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã‚’åŒæœŸä½œè€…オフオン%sを基ã«ãƒ•ãƒªãƒ¼ãƒˆãƒ©ã‚¤ã‚¢ãƒ«ã‚’開始å´ä¸‹å´ä¸‹ç„¡åŠ¹åŒ–中代表セキュリティã¨æ©Ÿèƒ½ã®ã‚¢ãƒƒãƒ—デートã€å­¦ç¿’用コンテンツやオファーを%sé€ã‚‰ãªã„ã§ãã ã•ã„%s。%s プラン%s ã¸ã®è«‹æ±‚ベストヘイãŠã£ã¨ãŠãŠã„ %s ã•ã‚“ã€ãƒ¤ãƒƒãƒ›ãƒ¼ã‚µã‚¤ãƒˆæ•°ms未èªè¨¼æ–™é‡‘料金表ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç§’セキュリティã¨æ©Ÿèƒ½ã®ã‚¢ãƒƒãƒ—デートã€å­¦ç¿’用コンテンツやオファーをé€ã£ã¦ãã ã•ã„。スキップãµã‚€ãƒˆãƒ©ã‚¤ã‚¢ãƒ«ã‚’開始変更中最新㮠%s ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯ã“ã¡ã‚‰ã§ã™ã€‚トライアル削除ダウングレード編集éžè¡¨ç¤ºã‚ªãƒ—トインオプトアウト購入表示スキップ更新アップグレード%s å‰freemius/languages/freemius-da_DK.mo000064400000206740146725417150013472 0ustar00Þ•¡$‹,*X8Y8^8Ad8¢¦8nI92¸9Zë9hF:d¯:S;%h; Ž; š;¦;­;¥À;6f<´<_R=²=Ò=#é= >%'> M> Z> d>o>v>~>‡>>@˜>HÙ>"?O5?M…?jÓ?›>@Ú@Þ@ý@A%AŒ5AÂAÊA ÓAßAðABB&,B-SBB –B B¯BÄB×BÞB5æBC$C 4C >C'JCrC ‹C ˜C¢Co³C#Dž*DGÉDTEfE©…E/FBF"^FF(žF2ÇF!úF>Ga[G+½G0éGH,HCHRHZHnHsH{HŽH—HŸH¤H «H ·HÅH ×HEãHy)I£IÀIÇI’ÛI nJyJJ ¡J ®J ¸JÆJ×JYóJMK\K mK yK…KŽK“K£K ¼K(ÇK1ðK%"L:HLƒL ˆL–L§L¯L ¿L ÊL×LíL õL7ÿL7M 5]mt]gâ]pJ^»^Õ^yÛ^U_n_ Ž_š_­_ Ã_ä_%÷_ `>`F`c`z` ˜`&¢`•É`1_a.‘aOÀabAbÒbyòb2lcŸc¿caÕc 7dDd[dB_d,¢dÏd Ôd ádîd e %e0e7e?e Qe \ehe xe„eše4£eØe çeñeõeüefff'f7f Rf^f ef qf}f—f,œf Éf Öfãf¡g¤g¨g ¾g!Êgìg hhhh%1hWh%]h+ƒh¯h Çh Õh/âhimi~„ij jujÛˆj¡dklm*m 0muDuW]u µuÃuÚuãuøuv/v6v:vCvKvQv avmv v5ŠvsÀvl4w&¡wÈw×w èw öwyy4yHyPyly ry|y y=y&ËyLòyf?z¦z ¬z ¸zÄzÕzÛz êzõz üz {{ {+{ A{N{¯_{•|–¥|%<}/b}’})²} Ü} ç}\ò}˜O~è~ý~C/s‰©…ÁmG€xµ€d.-“Á ÇÔÛ'ú¬"‚MÏ‚Gƒ,eƒ’ƒ ¨ƒ²ƒ¦¸ƒS_„ ³„‘T…çæ…ΆÔ†Ù†߆Eä†*‡=‡O‡f‡u‡|‡*‹‡¶‡*¾‡é‡ø‡ˆ ˆˆdˆzˆ ƒˆˆ ©ˆ·ˆʈâˆúˆ‰'‰ B‰O‰b‰ij‰WÔ‰n,Š¤›Š"@‹ƒc‹Bç‹6*Œ=aŒŸŒ ´ŒÂŒ-ÓŒ&5/\Œ#¦*ÊõùŽ Ž/4ŽQdŽU¶ŽD $QMvÄ/Öo&>–Õ ì& ‘<4‘Dq‘Z¶‘€’T’’Rç’.:“.i“˜“-ª”;Ø”9•ZN•3©•<Ý•b–P}–UΖ_$—š„—K˜(k˜G”˜#ܘ%™)&™$P™Šu™Uš)Vš€š’š¯šÇš;Üš6›>O›Ž›”›¯›Ï›$å› œ$œ@œ\œ&zœ*¡œ7Ìœ93R†›±ÉÝ*ú1%žWžsž#‡ž«žÇžÙž éžõžŸ,ŸAŸUŸZŸ _ŸlŸNuŸÄŸãŸ  , = N S Y 1t ¦ ®  Ò  ã  ï  ü  ¡¡¡5¡ >¡ L¡9X¡C’¡Ö¡Û¡ ë¡ ø¡¢¢7¢=¢ P¢\¢ k¢ u¢ ¢ ‹¢ ˜¢ ¦¢ °¢ º¢ Æ¢ Ó¢ºà¢›¦Ÿ¦A¤¦¢æ¦n‰§ø§Z¨h\¨dŨ!*©0L©}© ©œ©¥©¥¸©6^ª´•ª_J«ª«Ê«á«¬%¬@¬ Q¬^¬m¬ u¬ €¬Œ¬”¬@¬HÞ¬'­O=­M­jÛ­›F®â®æ®ï®ø® þ®Œ ¯ ™¯¤¯ ¬¯·¯ǯ߯ö¯,°/2°b° |°†°š°´° Ê° Ö°5ã°±!± 1± ;±%G±m±‡± ›±¦±o¸±(²ž/²GβT³k³©…³/´%?´'e´´(­´1Ö´$µ>-µalµ+ε5úµ0¶C¶[¶s¶x¶Š¶¶ ˜¶¤¶­¶µ¶º¶ Á¶ Ͷ׶ é¶Eõ¶y;·#µ·Ù·â·’ú· ¸š¸°¸ĸ Û¸ æ¸ô¸¹Y¹ w¹„¹ “¹ ž¹ «¹¶¹ ¹¹ǹà¹)é¹1º/Eº uºº „º’º¤º¬º ¼º ǺÔºìº ñº7ûº3» 8»B»xS»”Ì» a¼n¼”~¼%½9½I½R½5b½˜½X³½t ¾¾ž¾¶¾˾Ô¾é¾"ý¾ ¿ =¿¹H¿—ÀšÀ[©ÀfÁlÁ sÁÁ–Á°ÁµÁYÉÁ_#ÂnƒÂòÂÃÃ/Ã8à GÃRÃ1bÔØÃþŸÃOžÄîÄõÄ Å Å&Åj5Å Å5²Å èÅóÅ3üÅ20ÆAcÆ¥Ç~½Ç:<ÈowÈçÈÉ#É$9É<^ÉI›É8åÉÊc4Ê!˜Ê&ºÊáÊgäÊMLË7šË>ÒËmÌgÌpçÌ"XÍ{ÍyÍûÍ*Î BÎOÎgÎ ~ΟÎ%²Î ØÎùÎÏÏ6ÏTÏ&]Ï•„Ï1Ð5LÐ\‚ÐßÐ>_ÑžÑy¾Ñ28ÒkÒˆÒa¡Ò ÓÓ'ÓW.Ó6†Ó½ÓÄÓÕÓ"åÓÔ $Ô.Ô6Ô =Ô JÔ TÔaÔ qÔ~Ô”Ô4œÔÑÔ åÔïÔóÔúÔÕÕÕ !Õ-Õ HÕSÕ YÕ cÕmÕ„Õ,‰Õ ¶ÕÄÕÔÕ¡óÕ•Ö˜Ö °Ö%¼ÖâÖ × ×××%,×R×.[×4Š×¿× Ý× ë×1ù×+Øm/Ø~ØÙ$Ùu,ÙÛ¢Ù¡~Ú Û!(ÜJÜPÜgÜ oÜyÜ)ˆÜ²Ü ÑÜ:ÜÜÝ@Ý,]ÝŠÝ’Ý)¡ÝËÝ>áÝ6 ÞÈWÞ; ß…\ßâß[ÿà [á|áƒá ’áœá °á ½áÉáÍá âá ïá ûáNâVâ#^â‚â'Šâ,²âßâïâãã(ã 1ã;ã DãNã^ãrãzã ‹ã —ã¢ã²ã¸ãWÕã -ä:äNä]äräŒä¨ä±äµä½äÅäÊäÞäíä å5åsDål¸å0%æ Væaæsæ ‡æ“ç°çÉç Üçèç ýçèè !è=-è'kèP“èhäèMéSéeéyéŽé“é¢é³é ¸é ÂéÍé Õéâé þé êÅê•áê–wë%ì84ìmì)‡ì ±ì¼ìdÄì˜)íÂíÛíëíL îVî#eî‰î…¡îm'ïx•ïdð"sð–ð ›ð¥ð¬ð$Ëð¬ððUñKóñ,?òlò ‚òŽò¦”òS;ó ó‘0ôçÂôªõ°õ ³õÁõEÆõ ö"ö<öSögöoö2~ö±ö)ºö äö ðö úö÷÷d÷ {÷‡÷˜÷ ¶÷Ä÷×÷ï÷øø4ø Oø\øqøtzø_ïønOù¤¾ù+cú}úB û>Pû=ûÍûáûòû,ü2üGü^ü/xü¨ü#Âü#æü ý ýý3ý/FýQvýUÈýDþ(cþOŒþ Üþ/éþÿo8ÿ>¨ÿçÿüÿ"<>D{YÀ€S›Tï.D5s©-»;é'%ZM3¨8ÜbTx_Íe-–“X*ƒ9£Ýû"<Š[Uæ< Z k r ˆ Ž ¦ Å Ì  Ó  Þ è ì ð  ö      /  O Z c  g u x €  ˆ – ›  ¯ ½  Ä Ð  ã í ñ õ   % + ? D  I U Q^ °  ¸ Æ Í Ñ Õ Ý â  è ô ü      + < A H Q  Y  c q 9u L¯  ü    ( 0 J  h  v „  ‰ “ › ¡ © ± ¶  º Æ Î × ؾÀyl~|Ÿ'§€ñ4Žm”f‘ýÃ*“f-/¨ŒÝÞi#¡$£÷Ÿ†MèÉ}ª#à:’  YÝ*ߊD5uàiý^‘]‚L³yptÍw;xFœk|¿K³3ž Ÿ!Pt'”o.Y¨g‡_ûø8½,!Ù@ÅvhBΙf,²Õ0``Åj… é%ù7?Û–6°êCú¦Œz9™k¹ù¡zœ¦J[,h†ܤæ42e­SWÐB¸ÎîXr6ëÀ2ÒçJj“ôíìLˆƒ|ñÙø â"c<€(Ï:Ö{@ „6Z±ál‡»p½o\/ü†žºÔ^+š-nA˜l5%wا"T0=\O7õÜEÍnP‹)<Jv¼Çs&Žqé?ƸóuNyA}˜Ž{FE‰·;#¥¢µOè8žþ‰ã =öü_{F¥÷D«±´ŠSLDM3ÿaqRG´v 5¬Q[ ÒrIú­îÞ„ÓSZg>å%©$Ì®]Uš~9T« u2cÄŒGKª×n;’~ãg¾Úá®Áo…$U€Oß0ƒXë)£a í+—–ÃmQ‹_s1Zxä›GÑp ÛË:”Ïÿ^ô·ò`QÕ¯Âì‘êmöNYº ©&ˆ9œWÈ!R& [ó…xjÊïæòÌqÁdä‡bÉ4‹Ôâ>3?‚BÐ]ˆç—\t'eA¢Ú¡bõšH¬Ç/dR»=“>w)að eHƒÄÆX}sKNŠ¹C+V*ï×.¶@傶c™(r °1 "ð•E‰Ë <I¤—TÈd˜ûÊ I²U1›H-¿V„V•8 W–ziP.kb(•Ö¯ þC’ÓMµѼ›h7HmmW00t %s to access version %s security & feature updates, and support. The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"The ", e.g.: "The plugin"The %s's%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is my client's email address%s is my email address%s is the new owner of the account.%s minimum payout amount.%s opt-in was successfully completed.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.Click here to learn more about updating PHP.A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.APIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsAccount is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.ActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.An unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred while trying to toggle the license's white-label mode.An unknown error has occurred.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre both %s and %s your email addresses?Are you sure you want to delete all Freemius data?Are you sure you want to proceed?Are you sure you would like to proceed with the disconnection?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Associate with the license owner's account.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBetaBillingBilling & InvoicesBlockingBlog IDBodyBundleBundle PlanBusiness nameBuy a license nowBuy licenseBy changing the user, you agree to transfer the account ownership to:By disconnecting the website, previously shared diagnostic data about %1$s will be deleted and no longer visible to %2$s.Can't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanChange UserCheckoutCityClear API CacheClear Updates TransientsClick hereClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCommunicationCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeCurrent %s & SDK versions, and if active or uninstalledDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDebug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.Delegate to Site AdminsDelete All AccountsDetailsDiagnostic InfoDiagnostic data will no longer be sent from %s to %s.Disabling white-label modeDisconnecting the website will permanently remove %s from your User Dashboard's account.Don't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload Paid VersionDownload the latest %s versionDownload the latest versionDownloadedDue to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.Duplicate WebsiteDuring the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEmail address updateEnabling white-label modeEndEnter email addressEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used during the purchase and we will resend you the license key.Enter the email address you've used for the upgrade below and we will resend you the license key.Enter the new email addressErrorError received from the server:ExpiredExpires in %sExtensionsExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.For delivery of security & feature updates, and license management, %s needs toFreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFreemius is our licensing and software updates engineFull nameFunctionGet commission for automated subscription renewals.Get updates for bleeding edge Beta versions of %s.Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!Homepage URL & title, WP & PHP versions, and site languageHow do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I Agree - Change UserI can't pay for it anymoreI couldn't understand how to make it workI don't know what is cURL or how to install it, help me!I don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.If you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you skip this, that's okay! %1$s will still work just fine.If you wish to cancel your %1$s plan's subscription instead, please navigate to the %2$s and cancel it there.If you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid clone resolution action.Invalid module ID.Invalid new user ID or email address.Invalid site details collection.InvoiceIs %2$s a duplicate of %4$s?Is %2$s a new website?Is %2$s the new home of %4$s?Is ActiveIs active, deactivated, or uninstalledIs this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.It looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It requires license activation.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's a temporary %s - I'm troubleshooting an issueIt's not what I was looking forJoin the Beta programJust letting you know that the add-ons information of %s is being pulled from an external server.Keep SharingKeep automatic updatesKeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense IDLicense KeyLicense issues?License keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerLong-Term DuplicateMessageMethodMigrateMigrate LicenseMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNames, slugs, versions, and if active or notNetwork BlogNetwork UserNever miss an important updateNever miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.NewNew Version AvailableNew WebsiteNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo - just deactivateNo - only move this site's data to %sNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to get email notifications for security & feature updates, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please enter the license key to enable the debug mode:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires PHP VersionRequires WordPress VersionReset Deactivation SnoozingResultSDKSDK PathSave %sSavedScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSharing diagnostic data with %s helps to provide functionality that's more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to.Simulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSnooze & %sSo you can reuse the license when the %s is no longer active.Social media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart DebugStart TrialStart my free %sStateStay ConnectedStop DebugSubmitSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank for giving us the chance to fix it! A message was just sent to our technical staff. We will get back to you as soon as we have an update to %s. Appreciate your patience.Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you for updating to %1$s v%2$s!Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe following products'The installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$sThe products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$sThe remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn't work, contact the %s's author with the following:This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.This plugin requires a newer version of PHP.This will allow %s toTimestampTitleTo avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.To ensure compatibility and avoid conflicts with your installed plugins and themes.To enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.To provide additional functionality that's relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.TotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUser DashboardUser IDUser keyUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View %s StateView Basic %s InfoView Basic Profile InfoView Basic Website InfoView Diagnostic InfoView License EssentialsView Plugins & Themes ListView detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We couldn't load the add-ons list. It's probably an issue on our side, please try to come back in few minutes.We have introduced this opt-in so you never miss an important update and help us make the %s more compatible with your site and better at doing what you need it to.We made a few tweaks to the %s, %sWe'll make sure to contact your hosting company and resolve the issue. You will get a follow-up email to %s once we have an update.We're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)Welcome to %s! To get started, please enter your license key:What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress & PHP versions, site language & titleWordPress.org Plugin PageWould you like to merge %s into %s?Would you like to proceed with the update?YesYes - %sYes - both addresses are mineYes - do your thingYes - move all my data and assets from %s to %sYes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s.Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.Yes, %2$s is a new and different website that is separate from %4$s.You already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have purchased a %s license.You have successfully updated your %s.You marked this website, %s, as a temporary duplicate of %s.You marked this website, %s, as a temporary duplicate of these sitesYou might have missed it, but you don't have to share any data and can just %s the opt-in.You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s.Your %s license was successfully deactivated.Your WordPress user's: first & last name, and email addressYour account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$sYour subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onactivate a license hereactive add-onActiveaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismisscomplete the opt-indatadaysdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,hourhoursinstalled add-onInstalledinterjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew Beta versionnew versionnot verifiednounPricenounPricingoptionalproduct versionVersionproductsrevert it nowsecondssecseems like the key you entered doesn't match our records.send me security & feature updates, educational content and offers.skipstart the trialsubscriptionswitchingthe above-mentioned sitesthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Joachim Jensen, 2019-2020,2022 Language-Team: Danish (Denmark) (http://www.transifex.com/freemius/wordpress-sdk/language/da_DK/) Language: da_DK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js HmmW00t %s to access version %s security & feature updates, and support. The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$sThe %s's%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.Færdiggør aktivering af "%s" nuBetalingen for tilføjelsen %s blev gennemført.%s installeringer1%s licenser%s siden%s og tilføjelser%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is my client's email address%s is my email address%s er den nye ejer af kontoen.%s minimum payout amount.%s opt-in was successfully completed.%s eller højere%s vurdering%s vurderinger1%s sek%s stjerne%s stjerner%s gang%s gange%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's betalte features%sClick here%s to choose the sites where you'd like to activate the license on.Click here to learn more about updating PHP.A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.API←➤KontoKontodetaljerAccount is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again.HandlingerAktiverAktiver %sAktiver %s planAktiver funktioner i %sAktiver gratis versionAktiver licensAkiver licens pÃ¥ alle afventende websteder.Aktiver licens pÃ¥ alle websteder i netværket.Aktiver denne tilføjelseAktiveretTilføjelser til %sTilføjelser til modul %sTilføj andet domæneTilføjelseTilføjelserAdd-on must be deployed to WordPress.org or Freemius.AdresseAdresselinje %dAffiliateAffiliationEfter dine gratis %s er prisen kun %sAccepter & aktiver licensAlle forespørgslerAlle typerTillad & FortsætAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.BeløbAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.An unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred while trying to toggle the license's white-label mode.Der skete en ukendt fejl.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonym feedbackAnvend pÃ¥ alle afventende websteder.Anvend pÃ¥ alle websteder i netværket.Ansøg om at blive en affiliateAre both %s and %s your email addresses?Er du sikker pÃ¥, du vil slette al Freemius data?Er du sikker pÃ¥, du vil fortsætte?Are you sure you would like to proceed with the disconnection?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Associate with the license owner's account.Auto-installation fungerer kun for tilmeldte brugere.Auto-fornyer om %sAutomatisk installeringGennemsnitlig vurderingSejtBliv en affiliateBetaBetalingFaktureringBlokererBlog-IDBodyBundleBundle PlanFirmanavnKøb en licens nuKøb licensBy changing the user, you agree to transfer the account ownership to:By disconnecting the website, previously shared diagnostic data about %1$s will be deleted and no longer visible to %2$s.Kan du ikke finde din licensnøgle?AnnullerAnnuller %s og fortsætCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Annuller %s?Annuller installeringAnnuller abonnementAnnuller prøveperiodeAnnulleretAnnullerer %sAnnullerer %s...Annullerer abonnementetCancelling the trial will immediately block access to all premium features. Are you sure?Skift licensSkift ejerskabSkift planSkift brugerUdtjekningByRyd API-cacheClear Updates TransientsKlik herKlik her for at benytte pluginnet anonymtClick to see reviews that provided a rating of %sKlik for at vise skærmbillede %d i fuld skærmProdukterKodeCommunicationKompatibel op tilKontaktKontakt supportKontakt osBidragsydereKunne ikke aktivere %s.LandCron TypeCurrent %s & SDK versions, and if active or uninstalledDatoDeaktiverDeaktiver licensDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeaktiveringFejlfindingslogDebug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.Uddeleger til webstedsadministratorerSlet alle kontiDetaljerDiagnostic InfoDiagnostic data will no longer be sent from %s to %s.Disabling white-label modeDisconnecting the website will permanently remove %s from your User Dashboard's account.Don't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Har du ikke en licensnøgle?Donér til dette pluginNedgraderer din planDownloadDownload 1%s versionHent betalt versionDownload den seneste version af %sDownload den seneste versionDownloadetDue to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.Kopier webstedDuring the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.E-mailE-mailadresseEmail address updateEnabling white-label modeSlutEnter email addressEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used during the purchase and we will resend you the license key.Indtast e-mailadressen, som du benyttede ved opgraderingen, nedenfor og vi vil gensende licensnøglen til dig.Enter the new email addressFejlFejl modtager fra serveren:UdløbetUdløber om %sExtensionsEkstra domænerAndre domæner du vil markedsføre produktet fra.FilFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.For delivery of security & feature updates, and license management, %s needs toGratisGratis prøveperiodeGratis versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius tilstandFreemius is our licensing and software updates engineFulde navnFunktionGet commission for automated subscription renewals.Get updates for bleeding edge Beta versions of %s.Great, please install cURL and enable it in your php.ini file. In addition, search for the 'disable_functions' directive in your php.ini file and remove any disabled methods starting with 'curl_'. To make sure it was successfully activated, use 'phpinfo()'. Once activated, deactivate the %s and reactivate it back again.Har du en licensnøgle?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!Homepage URL & title, WP & PHP versions, and site languageHvad synes du om %s indtil videre? Test alle vores premium funktioner i %s med en %d-dags gratis prøveperiode.Upload og aktivering, hvordan?Hvordan vil du promovere os?I Agree - Change UserJeg kan ikke længere betale for detJeg forstod ikke, hvordan jeg skulle fÃ¥ det til at fungere.Jeg ved ikke hvad cURL er, eller hvordan jeg installerer det. Hjælp mig!Jeg har ikke lyst til at dele mine informationer med jerJeg fandt et bedre %sJeg har opgraderet min konto, men nÃ¥r jeg forsøger at synkronisere licensen, forbliver planen %s.Jeg har ikke længere brug for %sJeg behøvede kun %s i en kort periodeIDIf this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.If you click it, this decision will be delegated to the sites administrators.Hvis du har tid, sÃ¥ lad os venligst vide hvorfor du %sIf you skip this, that's okay! %1$s will still work just fine.If you wish to cancel your %1$s plan's subscription instead, please navigate to the %2$s and cancel it there.If you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Vigtig meddelelse til opgradering:Om %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Installer gratis version nuInstaller opdatering til gratis version nuInstaller nuInstaller opdatering nuInstallerer plugin: %sInvalid clone resolution action.Ugyldigt modul-ID.Invalid new user ID or email address.Invalid site details collection.FakturaIs %2$s a duplicate of %4$s?Er %2$s et nyt websted?Is %2$s the new home of %4$s?Er aktivIs active, deactivated, or uninstalledIs this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.Det ser ud til, at licensen ikke kunne aktiveres.Det ser ud til, at licens-deaktiveringen mislykkedes.Det lader ikke til du er i en prøveperiode længere, sÃ¥ der er ikke noget at annullere :-)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.Det ser ud til, at dit websted endnu ikke har en aktiv licens.It requires license activation.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's a temporary %s - I'm troubleshooting an issueDet er ikke, hvad jeg søgteDeltag i beta-programmetJust letting you know that the add-ons information of %s is being pulled from an external server.Keep SharingKeep automatic updatesNøgleVær venlig at dele hvad der ikke virkede sÃ¥ vi kan rette det for kommende brugere....Fortæl os venligst Ã¥rsagen, sÃ¥ vi kan forbedre det.SidsteSenest opdateretSeneste licenseSeneste gratis version installeretSeneste version installeretLæs mereLængdeLicensLicensaftaleLicens-IDLicensnøgleLicense issues?LicensnøgleLicensnøglen er tom.LivstidLike the %s? Become our ambassador and earn cash ;-)Hent DB-indstillingLocalhostLogLoggerLong-Term DuplicateBeskedMetodeFlytFlyt licensMigrate Options to NetworkMobil-appsModulModul-stiModultypeMere information om %sNavnNames, slugs, versions, and if active or notNetværksblogNetværksbrugerNever miss an important updateNever miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.NyNy version tilgængeligNyt webstedNyere gratis version (%s) installeretNyere version (%s) installeretNyhedsbrevNæsteNejNej - bare deaktiverNo - only move this site's data to %sIntet IDIngen bindinger i %s - annuller nÃ¥r som helstIngen bindinger i %s dage - annuller nÃ¥r som helst!Betalingskort ikke pÃ¥krævetUdløber ikkeUdløber ikkeIngen af %s's planer understøtter prøveperiode.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.TilmeldFrameldOpt in to get email notifications for security & feature updates, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info.Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.Accepter for at gøre "%s" bedre!AndetE-mailadresse for ejerEjer-IDEjer-navnPCI-kompatibelPaid add-on must be deployed to Freemius.E-mailadresse til PayPal-kontoBetalingerUdbetalinger er i USD og behandles hver mÃ¥ned via PayPal.PlanPlan %s eksisterer ikke og kan derfor ikke starte prøveperiode.Plan %s understøtter ikke en prøveperiode.Plan-IDKontakt os herKontakt os venligst med følgende besked:Download venligst %s.Indtast licensnøglen, du modtog i e-mailen lige efter købet:Please enter the license key to enable the debug mode:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Følg venligst disse trin for at færdiggøre opgraderingenLad os vide, om vi har lov til at kontakte dig med sikkerheds- og feature-opdateringer, informativt indhold og lejlighedsvise tilbud:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Indtast venligst dit fulde navn.PluginPlugin-webstedPlugin-IDPlugin-installeringÆndringslogBeskrivelseFAQFunktioner og priserInstalleringAndre noterAnmeldelserPlugin is a "Serviceware" which means it does not have a premium code version.PluginsSynkronisering af plugins og temaerPremiumPremium-versionen af %s blev aktiveret.Premium tilføjelse er allerede installeret.Premium versionPremium version allerede aktiv.PriserPrivatlivspolitikFortsætProces-IDArbejderProdukterProgramoversigtPromoveringsmetoderProvinsOffentlig nøgleKøb licensKøb flereHurtig feedbackKvoteGensend e-mail om aktiveringRefer new customers to our %s and earn %s commission on each successful sale you refer!Forny licensForny din licens nuForespørgslerRequires PHP VersionKræver WordPress-versionReset Deactivation SnoozingResultatSDKSDK-stiSpar %sGemtPlanlagte cron jobsSkærmbillederSøg efter adressePrivat nøgleSecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Det ser ud til, at du har den seneste udgivelse.Vælg landSend licensnøgleSæt DB-indstillingSharing diagnostic data with %s helps to provide functionality that's more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to.Simuler netværksopgraderingSimulate Trial PromotionEnkelt site licensWebsteds-IDWebsted er tilmeldt.WebstederSpring over & %sKortnavnUdsæt & %sSo you can reuse the license when the %s is no longer active.Sociale medier (Facebook, Twitter osv.)Vi beklager ulejligheden, og vi er her for at hjælpe, hvis du giver os chancen.Beklager, vi kunne ikke opdatere e-mailen. Der er allerede registreret en anden bruger med samme e-mail.StartStart fejlfindingStart prøveperiodeStart mine gratis %sStatStay ConnectedStop fejlfindingSendSend & %sAbonnementSupportSupportforumSynkroniser data fra serverMoms / VAT IDServicevilkÃ¥rTak fordi du giver os en chance for at fixe det! En besked er lige blevet sendt til vores tekniske personale. Vi vil vende tilbage, sÃ¥ snart der er nyt om %s. Vi sætter pris pÃ¥ din tÃ¥lmodighed.Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you for updating to %1$s v%2$s!Mange tak for, at du benytter %s og tilhørende add-ons!Tak fordi du benytter %s!Mange tak for at benytte vores produkter!Mange tak!Tak %s!Tak fordi du bekræftede skift af ejerskab. En e-mail er blevet sendt til %s for sidste godkendelse.The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license.%s ødelagde min webside%s virkede ikke%s virkede ikke som forventet%s er godt, men jeg har brug for en specifik feature, som ikke understøttes%s virker ikke%s stoppede pludseligt med at virkeThe following products'The installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$sThe products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$sThe remote plugin package does not contain a folder with the desired slug and renaming did not work.Opgraderingen af %s blev fuldendt.TemaTemaskiftTemaerThere is a %s of %s available.En ny version af %s er tilgængelig.There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn't work, contact the %s's author with the following:Dette plugin er ikke markeret som kompatibel med din nuværende version af WordPress.Dette plugin er ikke blevet testet med din nuværende version af WordPress.This plugin requires a newer version of PHP.This will allow %s toTidsstempelTitelTo avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.To ensure compatibility and avoid conflicts with your installed plugins and themes.To enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.To provide additional functionality that's relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.TotalByPrøveperiodeTypeUnable to connect to the filesystem. Please confirm your credentials.Ubegrænsede licenserUbegrænsede opdateringerUbegrænset provision.Op til %s webstederOpdaterOpdater licensOpdateringer, annonceringer, marketing, ingen spamOpgraderUpload og aktiver den downloadede versionBrugerpanelBruger-IDBrugernøgleBrugereVærdiVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerificeretVerificer e-mailVersion %s er blevet udgivet.View %s StateView Basic %s InfoView Basic Profile InfoView Basic Website InfoView Diagnostic InfoView License EssentialsView Plugins & Themes ListVis detaljerVis betalte featuresAdvarselVi kan ikke finde nogen aktive licenser knyttet til den e-mailadresse, er du sikker pÃ¥, det er den rigtige adresse?Vi kunne ikke finde din e-mailadresse i systemet, er du sikker pÃ¥, det er den rigtige adresse?We couldn't load the add-ons list. It's probably an issue on our side, please try to come back in few minutes.We have introduced this opt-in so you never miss an important update and help us make the %s more compatible with your site and better at doing what you need it to.Vi har foretaget nogle rettelser til %s, %sVi vil kontakte din udbyder og løse problemet. NÃ¥r vi har opdatinger i sagen, vil vi følge op med en email til dig pÃ¥ %s.We're excited to introduce the Freemius network-level integration.Websted, e-mail, og statistikker for sociale medier (valgfrit)Welcome to %s! To get started, please enter your license key:Hvad forventede du?Hvilken feature?Angiv venligst %s?Hvilken pris ville du foretrække at betale?Hvad ledte du efter?Hvad er navnet pÃ¥ %s?Hvor vil du promovere %s?WordPress & PHP versions, site language & titleWordPress.org Plugin-sideWould you like to merge %s into %s?Vil du fortsætte med opdateringen?JaJa - %sYes - both addresses are mineJa - fortsæt bareYes - move all my data and assets from %s to %sYes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s.Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.Yes, %2$s is a new and different website that is separate from %4$s.Du har allerede brugt din prøveperiode.Du er 1 klik fra at begynde din %1$s dages gratis prøveperiode af planen %2$s.Det var det!Du benytter allerede %s under en prøveperiode.Du mangler kun ét skridt - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.Du har ikke en gyldig licens til at benytte premium-versionen.Du har en %s licens.Du har købt en licens til %s.Opdatering af %s blev gennemført.You marked this website, %s, as a temporary duplicate of %s.You marked this website, %s, as a temporary duplicate of these sitesDu har mÃ¥ske overset det, men du behøver ikke at dele data og kan blot %s tilmeldingen.You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s.Du er allerede tilmeldt vores brugssporing, hvilket hjælper os med at forbedre %s.Du er allerede tilmeldt vores brugssporing, hvilket hjælper os med at forbedre dem.Your %s Add-on plan was successfully upgraded.Din gratis prøveperiode for %s er blevet annulleret.Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s.Your %s license was successfully deactivated.Your WordPress user's: first & last name, and email addressDin konto blev aktiveret med planen %s.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Din e-mailadresse er blevet verificeret - du er FOR SEJ!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Din gratis prøveperiode er udløbet. Du kan stadig benytte alle de gratis features.Din licens er blevet annulleret. Hvis du mener, dette er en fejl, sÃ¥ kontakt venligst support.Din licens er udløbet. %1$sOpgrader nu%2$s for at fortsætte med at benytte %3$s uden forstyrrelser.Din licens er udløbet. Du kan stadig benytte alle funktionerne i %s, men du bliver nødt til at fornye din licens for at fÃ¥ opdateringer og support.Din licens er udløbet. Du kan stadig fortsætte med at benytte den gratis udgave af %s.Din licens er blevet aktiveret.Din licens blev deaktiveret, du er tilbage pÃ¥ planen %s.Dit navn er blevet opdateret.Din plan er blevet aktiveret.Din plan er blevet ændret til %s.Din plan er blevet opgraderet.Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist %2$sYour subscription was successfully cancelled. Your %s plan license will expire in %s.Din prøveperiode er begyndt.ZIP / PostnummerSÃ¥danaktiver en licens herAktiv%s virker ikke uden %s.%s virker ikke uden pluginnet.Se hertillad%s tilbageAktivererÃ¥rAPIFjernFejlfindingTillykkeBlokeretForbundetDownload senesteDownload seneste gratis versionMÃ¥nedligtUdløberStiSender e-mailmdÃ…rligtÃ…rligtEngangsbeløbPlanIngen privat nøgleSDK-versionerLicensSynkroniserSynkroniser licensForfatterFraTilbaseret pÃ¥ %sStart gratis prøveperiodeFjernFjerncomplete the opt-indatadagedeaktivererdelegérsend %sIKKE%s sikkerheds- og feature-opdateringer, informativt indhold og tilbud.%s PlanFaktureret %sBedsteHeyUpsHey %s,timetimerInstalleretYee-hawlicensWebstedermsny beta-versionny versionikke verificeretPrisPriservalgfritVersionprodukterrevert it nowsekseems like the key you entered doesn't match our records.send mig sikkerheds- og feature-opdateringer, informativt indhold og tilbud.spring overstart prøveperiodenabonnementskifterthe above-mentioned sitesden seneste version af %s herprøveperiodePrøveperiodeSletNedgraderRedigerSkjulTilmeldFrameldKøbVisSpring overOpdaterOpgrader%s sidenfreemius/languages/freemius-it_IT.mo000064400000164362146725417150013543 0ustar00Þ•eD5l&@3AA3¢ƒ3n&42•4ZÈ4h#5dŒ5Sñ5%E6 k6 w6ƒ6Š6¥66C7´z7_/88¯8#Æ8ê8 9 9 9&9-959>9F9@O9H9Ù9Oì9j<:›§:C;G;f;†;Ž;ž;¦; ¯;»;Ì;á;÷;&<-/<]< r<|<‹< <³<º<5Â<ø<= = ='&=N= g= t=~=o=ÿ=ž>G¥>Tí>B?©a? @@":@]@(z@2£@!Ö@aø@+ZA0†A·AÉAàAïA÷A BBB+B4Bcy¢y ¹y&Úy<zD>zZƒzTÞzR3{.†{.µ{ä{-ö|9$}Z^}3¹}<í}b*~P~UÞ~_4š”K/€({€G¤€#ì€%)6$`U…)Û‚‚4‚L‚;a‚6‚>Ô‚ƒƒ4ƒTƒ$jƒƒ©ƒŃáƒ&ÿƒ*&„7Q„‰„ „¾„3ׄ … …6…N…b…*…1ª…Ü…ø…# †0†L†^† n†z†š†±†Ɔˆ І݆Næ†5‡T‡r‡‡‡®‡¿‡ćʇ1凈ˆ3ˆCˆ Tˆ `ˆ mˆ xˆ…ˆŽˆ¦ˆ ¯ˆ ½ˆ9ɈC‰G‰QL‰ž‰ ®‰ »‰ʼn߉ú‰Š ŠŠ .Š 8Š BŠ NŠ [Š iŠ sŠ }Š ‰Š –Šæ£ŠKŠŽ¦ÖŽ€}þgXl_Å"%‘.H‘w‘ ˆ‘“‘™‘Óª‘:~’¼¹’Uv“Ì“é“)”%0”V”e”t”ƒ” Š” ””ž”§”^°”[•k•B‹•|Ε£K–ï–ó–ü–— —#—*— 1—;—P—n—‡—,–—.×ò—˜ ˜˜3˜M˜T˜<Z˜ —˜¡˜ ³˜ ½˜+ʘö˜™ %™2™tF™»™¢Ã™MfšY´š"›´1›æ›"÷›#œ">œ+aœ7œÅœgäœ)LSvÊãü žž.ž 3ž@žSž\ždž ižvž‹ž¢žF´ž#ûžŸ'Ÿ¥=Ÿ ãŸïŸ   3 = Q e € ¡¡ #¡ 0¡>¡D¡'V¡ ~¡-‰¡I·¡@¢B¢K¢R¢e¢n¢ ƒ¢ Ž¢#›¢¿¢ Ç¢Ô¢ Ù¢ã¢}õ¢‘s£¤ ¤¤¼¤Û¤÷¤#¥|$¥¡¥!À¥â¥ü¥¦¦<¦\¦ v¦¦€¦§'§ϧvÞ§wU¨ͨÓ¨㨠þ¨©$©J@©€‹©" ª/ª6ªRª Zªfª7xª°ªµª$¼ªá«ê«ù« ¬¬„'¬¬¬9¾¬ ø¬­?­;O­‹­{¦­h"®#‹®¯®Ä®Ü®!ó®)¯?¯^Y¯¸¯+Ò¯þ¯†°Iˆ°)Ò°]ü°lZ±#DZë±^ñ±!P²#r² –²£²À²(Ù²³-³F³e³m³‹³¢³ Á³›Ë³0g´<˜´fÕ´–<µ=Óµ&¶~8¶A·¶ ù¶·J3·~·[…·/á·¸¸-¸#<¸ `¸ ¸ Ž¸˜¸ ¸ ²¸½¸Ò¸ç¸ù¸ ¹A#¹e¹ {¹…¹‰¹¹ ª¹´¹»¹¹Ô¹ð¹º ºº*ºGº LºYºhºnº ‰º'”º%¼º ⺠íºøº*ûº &»,0»C]»"¡»Ä»Õ»4廼ƒ¼u¡¼ ½!½#5½Y½_½r½‚½ ”½=¢½འÿ½I ¾S¾XY¾-²¾à¾é¾%ø¾ ¿[*¿C†¿¬Ê¿5wÀ„­À 2ÁSSÂ*§ÂÒÂÙ íÂ÷ à Ã&Ã*à Cà Qà \ÃUgýÃÄÃãÃ7ëÃ-#ÄQÄbÄ€Ä‡ÄžÄ §Ä ³ÄÀÄÉÄÜÄ ðÄúÄ ÅÅ/ÅCÅ'IÅ[qÅÍÅÝÅ øÅ!Æ"$Æ GÆQÆ UÆ bÆoÆwÆ ŠÆ•Æ©Æ@¸Æ|ùÆnvÇ-åÇÈ%È=ÈTÈqÈ‡È  È¬ÈÉÈ ÎÈÙÈ ÞÈ9ìÈ(&ÉQOÉ¡É/Ê 5Ê#AÊeÊvÊ |ÊˆÊ ŽÊ ™Ê¥Ê®ÊÀÊÞÊ÷Ê¡ ˧®Ë'VÌ~Ì(˜ÌÁÌ ÉÌzÔÌOÍgÍ&wÍHžÍçÍ*÷Í"Ω6Îà΋`ÏuìÏ7bКРŸÐ«Ð°Ð*ÍÐUøÐINÑ ˜Ñ¢Ñ¦©ÑPÒ WÒaÒpÒ@uÒ¶ÒÉÒâÒúÒ ÓÓ*#Ó NÓ%\Ó‚ÓˆÓ —Ó ¡Ó¯Ó¶Ó‘½Ó OÔZÔ#iÔÔ¡ÔÀÔ{ÇÔgCÕs«Õ%ÖMEÖ8“Ö8ÌÖ××1×$D×i×ט×"±×Ô×#ë×ØØ#Ø*>ØKiØ>µØ2ôØj'Ù’Ù'¢ÙÊÙ…éÙEoÚµÚÈÚ&ÛÚ=ÛG@Û}ˆÛFÜCMÜ<‘ÜDÎÜÝ3Þ?IÞi‰Þ@óÞH4ßh}ßgæß\Nàe«àÇáWÙá/1âJaâ.¬â,Ûâ-ã*6ã]aã4¿ãôãøãüãä ä';ä cänä wä „ää•ä™ä  äªäºäÃäÌä"æä ååå 'å3å8å @å LåVå\å kåxå €åŒå£å ªåµå ¼å#Éåíåôåûåæææ_&æ†æ æœæ¥æ©æ­æµæ¹æ ½æÈæÎæÖæÛæÞæòæççç ç(ç1ç:çIçFMçR”çççíç#ñçè$è,èKèhènè}è …èè˜è ¡è«è¿èÈèÏèÕè ÞèìèÅã‹jÜd½,y¬<<"<Ìè ßNF;å*ŒYn¯GÕ"É…CÕ“ i%ÛS7MÙÿ°=ÿPÃL®4ÄXó¢:wƉîD¡6:™ñ,H¾|¾‘õ–Z(F“öú/A!9'XX6¼ Dº Þr­a-meúOTr/±¤šuu2CÀng¥Wv ª&[d²‡hH´¦•»K'®Ô¿¡Tëo3Gv9·A@±ÒF›_Q\{UlVùÓN9ƒô»ý1N]RôxÂãÐ&b¥¸[}Où0©· Ë^pjäÐéé„š8(â.ýø©5¿#GRÝþµÝµ¶¯3Ô!iQò Qfþ†£ è 0ÑÊoœ‚Ç ’2m °¤™{OEï íZTŸ¸2Ü3ì«ÚcÄ] ÍðP e ?Ãy›×”VêE¨õ-ȈS¹ߎægD"¹U$CEêSK7zÚaØÓâÁ„É ˜]à˜À@!‘x=˨%€^;ðkB’Y >?¶z­Ž8;³sRV6œí`‡•£s>_…}ÆPwŸ€ÍØMÖböìa.+äÇ[ f-Öl—d#`–Œå0ϺLU÷ ñ@\Ï)Yû²$§ˆ¦×¬qeÛZóø|cžŠ8+ƒ‰~æÎ4«#=¼‹”žJ*BÊü.k :Èt$JWàŠª‚´Þ\ÑÁp'áçL*Ù>)IÌçqá÷h/tKbų%ë(5^?&W4AüûIM½—)~1ÎBò†H`§7î5ïJ_I+Òc¢1, %s to access version %s security & feature updates, and support. The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box. The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s"The ", e.g.: "The plugin"The %s's%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s.%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first).%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is my client's email address%s is my email address%s is the new owner of the account.%s minimum payout amount.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours.A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder.APIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.An unknown error has occurred while trying to set the user's beta mode.An unknown error has occurred while trying to toggle the license's white-label mode.An unknown error has occurred.An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre both %s and %s your email addresses?Are you sure you want to delete all Freemius data?Are you sure you want to proceed?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Associate with the license owner's account.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBetaBillingBilling & InvoicesBlockingBlog IDBodyBundle PlanBusiness nameBuy a license nowBuy licenseBy changing the user, you agree to transfer the account ownership to:Can't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanChange UserCheckoutClear API CacheClear Updates TransientsClick hereClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDebug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the "Stop Debug" link.Delegate to Site AdminsDelete All AccountsDetailsDisabling white-label modeDon't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload Paid VersionDownload the latest %s versionDownload the latest versionDownloadedDue to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.Duplicate WebsiteDuring the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEmail address updateEnabling white-label modeEndEnter email addressEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used for the upgrade below and we will resend you the license key.Enter the new email addressErrorError received from the server:ExpiredExpires in %sExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.FreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFreemius is our licensing and software updates engineFull nameFunctionGet commission for automated subscription renewals.Get updates for bleeding edge Beta versions of %s.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!How do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I Agree - Change UserI can't pay for it anymoreI couldn't understand how to make it workI don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s.If you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid clone resolution action.Invalid module ID.Invalid new user ID or email address.Invalid site details collection.InvoiceIs %2$s a duplicate of %4$s?Is %2$s a new website?Is %2$s the new home of %4$s?Is ActiveIs this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin.It looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It requires license activation.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's a temporary %s - I'm troubleshooting an issueIt's not what I was looking forJoin the Beta programJust letting you know that the add-ons information of %s is being pulled from an external server.KeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense IDLicense KeyLicense issues?License keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerLong-Term DuplicateMessageMethodMigrateMigrate LicenseMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNetwork BlogNetwork UserNewNew Version AvailableNew WebsiteNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo - only move this site's data to %sNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please enter the license key to enable the debug mode:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicensePurchase MoreQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires WordPress VersionReset Deactivation SnoozingResultSDKSDK PathSave %sSavedScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSimulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSnooze & %sSo you can reuse the license when the %s is no longer active.Social media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart DebugStart TrialStart my free %sStateStop DebugSubmitSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe following products'The installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$sThe products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$sThe remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.TimestampTitleTo enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:TotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser DashboardUser IDUser keyUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We couldn't load the add-ons list. It's probably an issue on our side, please try to come back in few minutes.We made a few tweaks to the %s, %sWe're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)Welcome to %s! To get started, please enter your license key:What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress.org Plugin PageWould you like to merge %s into %s?Would you like to proceed with the update?YesYes - %sYes - both addresses are mineYes - move all my data and assets from %s to %sYes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development.Yes, %2$s is a new and different website that is separate from %4$s.You already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have purchased a %s license.You have successfully updated your %s.You marked this website, %s, as a temporary duplicate of %s.You marked this website, %s, as a temporary duplicate of these sitesYou might have missed it, but you don't have to share any data and can just %s the opt-in.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s.Your %s license was successfully deactivated.Your account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully activated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onactivate a license hereactive add-onActiveaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismissdatadaysdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,hourhoursinstalled add-onInstalledinterjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew Beta versionnew versionnot verifiednounPricenounPricingoptionalproduct versionVersionproductsrevert it nowsecondssecseems like the key you entered doesn't match our records.send me security & feature updates, educational content and offers.skipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialsubscriptionswitchingthe above-mentioned sitesthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Leo Fajardo , 2022 Language-Team: Italian (Italy) (http://www.transifex.com/freemius/wordpress-sdk/language/it_IT/) Language: it_IT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2; X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js %sper accedere alla versione%s per aggiornamenti, funzionalità e supporto.Il %s %slink per scaricare%s, la licenza e le istruzioni d'installazione sono state inviate a %s. Se non trovi l'email entro 5 minuti cerca nella cartella dello spam.La versione a pagamento di %1$sè già installata. Attiva questione versione per iniziare ad usare le funzionalità di %2$s.%3$sIl %s%1$s è entrato in modalità sicurezza perché è stato rilevato che %2$s è una copia esatta di %3$s./%1$sfermerà tutti i pagamenti ricorrenti futuri e il tuo piano %2$sche scadrà in %3$s.%1$s fermerà subito tutti i futuri pagamenti ricorrenti e il tuo piano licenza scadrà in %s.,Completa l'attivazione di "%s" oraL' add-on %s è stato acquistato con successo.%s Installazioni%s Licenze%s fa%se i suoi addon%s con aggiornamenti automatici di sicurezza e funzionalità con le funzionalità a pagamento manterrà il funzionamento senza interruzioni fino a %s (o quando la licenza scade, oppure quello che avviene prima).%scommissione quando un utente acquista una nuova lcienza.Il periodo di prova gratuito %s è stato annullato con successo. Siccome l'add-on è premium, è stato disattivato automaticamente. Se vorrai usarlo in futuro, dovrai comprare una licenza.%s è un add-on premium. Devi comprare una licenza prima di poter attivare il plugin.%s è il mio indirizzo email%s è il mio indirizzo email%s è il nuovo proprietario dell'account.%s quantità minima per il pagamento.%s o superiore%s valutazione%s valutazioni%s sec%s stella%s stelle%s volta%s volte%sper accedere alla versione %sper aggiornamenti di sicurezza, nuove funzionalità e supporto.%s cookie di tracciamento dopo che la prima visita per massimizzare i margini di guadagno. Funzionalità a pagamento di %s%sClicca qui%s per scegliere i siti dove vuoi attivare la licenza.Un email di conferma è stata inviata a %s. Il proprietario dell'email deve confermare l'aggiornamento nelle prossime 4 ore.Una email di conferma è stata inviata a %s. Puoi confermare l'aggiornamento nelle prossime 4 ore. Se non puoi trovare l'email verifica la tua cartella dello spam.API←➤AccountDettagli dell'accountAzioniAttivaAttiva %sAttivare il piano %sAttiva le funzionalità di %sAttiva versione gratuitaAttiva licenzaAttiva le licenze su tutti i siti in attesa.Attiva la licenza su tutti i siti del network.Attivare questo addonAttivatoAdd-on per %sAddon del modulo %sAggiungi un altro dominioAdd-onAddonL'add-on dev'essere distribuito da WordPress.org o Freemius.IndirizzoRiga indirizzo %dAffiliatiAffiliazioneDopo il tuo %s gratuito, paghi solamente %sAccetta e attiva la licenzaTutte le richiesteTutti i tipiConsenti & ContinuaIn caso puoi saltare per adesso e attivare la licenza successivamente nella tua pagina di attivazione network di %s.ImportoUn download con installazione automatica di %s (versione a pagamento) da %s inizierà in %s. Se preferisci farlo manualmente, fai clic sul pulsante per annullare.Un errore sconosciuto è avvenuto durante l'attivazione della modalità beta.Un errore sconosciuto è avvenuto mentre si passava alla licenza in modalità whitelabel.Un errore sconosciuto è avvenuto.Un aggiornamento per la versione Beta sostituirà la versione installata di %scon l'ultima versione Beta, utilizzare con attenzione e non su siti in produzione. Sei stato avvisato!Feedback anonimoApplica su tutti i siti in attesa.Applica su tutti i siti della rete.Applica per diventare un affiliatoSono entrambi %s e %s tuoi indirizzi email?Sei sicuro di voler eliminare tutti i dati di Freemius?Sei sicuro di voler procedere?Ci riserviamo 30 giorni in caso di rimborsi, paghiamo le commissioni se sono più vecchie di 30 giorni.Associa con il proprietario della licenzaL'installazione automatica funziona solo per gli utenti che hanno dato il consenso.Rinnovo automatico in %sInstallazione automaticaValutazione mediaFantasticoDiventa un affiliatoBetaFatturazioneRicevute e FattureBloccatoBlog IDBodyPiano BundleNome della compagniaCompra una licenza oraCompra la licenzaCambiando l'utente accetti di trasferire la proprietà dell'account a:Non trovi la tua chiave di licenza?AnnullaAnnulla %s & ProseguiAnnulla %s, non ho bisogno di aggiornamenti di funzionalità e sicurezza o supporto per %sperché non ho intenzione di usare %ssu questo sito o qualunque altro sito.Annulla %s?Annulla installazioneAnnulla sottoscrizioneAnnulla prova gratuitaAnnullatoCancellazione di %sCancellazione %s...Cancella la sottoscrizioneCancellando il periodo di prova gratuito bloccherai immediatamente l'accesso a tutte le funzionalità premium. Vuoi continuare?Cambia licenzaCambia ProprietarioCambia pianoCambia utenteCassaElimina cache APISvuota le Transient degli aggiornamentiClicca quiFai clic qui per usare il plugin anonimamenteFai clic per vedere le recensioni che hanno fornito una valutazione di %sFare clic per visualizzare lo screenshot in grandi dimensioni %dProdottiCodiceCompatibile fino aContattiContatta il supportoContattaciContributoriNon é stato possibile attivare %s.NazioneTipo di CronDataDisattivaDisattiva licenzaDisattivare o disinstallare %s che disabiliterà automaticamente la licenza, che permetterà di utilizzarla in un altro sito.Disattiva la tua licenza bloccando tutte le funzionalità premium ma potrai attivare la licenza su un altro sito. Sei sicuro di voler continuare?DisattivazioneDebug LogLa modalità Debug è stata attivata con successo e sarà disattivata automaticamente in 60 minuti. Puoi disattivarla prima cliccando sul link "Ferma Debug".Delega ai proprietari del sitoEliminare tutti gli accountDettagliDisabilita la modalità white labelNon annullare %s, sono interessato in ottenere gli aggiornamenti di sicurezza, nuove funzionalità o contattare il supporto.Non hai una chiave di licenza?Fai una donazione a questo pluginTorna al piano precedenteDownloadScarica la versione %sScarica la versione a pagamentoScarica l'ultima versione di %sScarica l'ultima versioneScaricatoCausa la %sDirettiva per la protezione dei Dati Europea (GDPR)%sabbiamo adeguato i requisiti che fornisci per il consenso, confermando che accetti di lasciare i dati.A causa della violazione dei nostri termini di affiliazione abbiamo deciso di bloccare temporaneamente il tuo account affiliativo. Se hai domande contatta il supporto.Sito duplicatoDurante la procedura di aggiornamento abbiamo individuato%d sito/i che sono in attesa della attivazione della licenza.Durante la procedura di aggiornamenti abbiamo individuato %s sito/i del network che sono in attesa di un tuo controllo.EmailIndirizzo emailAggiorna l'indirizzo emailAbilita la modalità white labelFineInserisci l'indirizzo emailInserisci il dominio del tuo sito o altri siti da dove vuoi promuovere %s.Inserisci qui sotto l'indirizzo email che hai usato per registrare l'aggiornamento e ti invieremo di nuovo la chiave di licenza.Inserisci il nuovo indirizzo emailErroreErrore ricevuto dal server:ScadutoScade in %sDomini aggiuntiviDomini aggiuntivi dove ci sarà il modulo promozionale.FileFiltroPer essere accettato del regolamento WordPress.org, prima di attivare il periodo di prova devi accettare di condividere informazioni come il tuo utente e dati non sensibili. Permettendo a %s di inviare dati periodicamente a %s per verificare gli aggiornamenti e approvare il periodo di prova.GratuitoProva gratuitaVersione gratuitaFreemius APIDebug FreemiusL'SDK di Freemius non è riuscito a trovare il file principale del plugin. Per favore contatta sdk@freemius.com riportando l'errore.Stato di FreemiusFreemius è il nostro servizio di licenze e aggiornamentiNome completoFunzioneOttieni delle commissioni dal sistema automatizzato di rinnovo.Ottieni gli aggiornamenti per le nuove versioni Beta di %s.Hai una chiave di licenza?Ciao, sai che %s ha il programma di affiliazione? Se ti piace %s puoi diventare un nostro ambasciatore e guadagnare denaro!Come sta andando con %s? Prova tutte le funzionalità premium di %s con una prova gratuita di %d giorni.Come faccio a caricare ed attivare?Come ci promuoverai?Accetto - Cambia utenteNon posso piú pagarloNon capisco come farlo funzionareNon voglio condividere i miei dati con teHo trovato un migliore %sHo aggiornato il mio account, ma quando cerco di sincronizzare la licenza, il piano rimane %s.Non ho più bisogno di %sHo avuto bisogno di %s per un breve periodoIDSe questo è un duplicato a lungo termine per mantenere gli aggiornamenti automatico e funzionalità a pagamento dopo %s, verifica %s.Se fai clic questa decisione sarà delegata agli amministratori del sito.Se hai un attimo, facci sapere perché %sPuoi abbandonare la proprietà dell'account %s a %scliccando il pulsante Cambia proprietario.Se vuoi utilizzare %s su questi siti, inserisci la tua licenza sotto e fai clic sul pulsante di attivazione.Avviso Importante di aggiornamento:In %sIn caso NON hai pianificato di usare %s su questo sito (o ogni altro sito) vuoi cancellare %s?Installa la versione gratuita oraInstalla l'ultima versione gratuitaInstalla oraInstalla l'aggiornamento oraInstallazione plugin: %sAzione di risoluzione del clone fallita.ID modulo non valida.Nuovo utente ID o indirizzo email non valido.Raccolta dati siti non valida.Fattura%2$s è un duplicato di %4$s?%2$s è un nuovo sito?%2$s è la nuova home di %4$s?è attivaSi tratta di un sito di un cliente?%sse vuoi puoi nascondere informazioni sensibili come la tua email, licenza, prezzi e indirizzi dalla tua bacheca di WP.Sembra che la licenza non possa essere attivata.Sembra che la disattivazione della licenza non sia riuscita.Sembra che tu non stia più usando la prova gratuita, quindi non c'è niente che tu debba annullare :)Sembra che tu sia ancora usando il piano %s. Se hai effettuato un upgrade o cambiato il piano, è probabile che ci sia un problema nei nostri sistemi.Sembra che il tuo sito non disponga di alcuna licenza attiva.Richiede la attivazione della licenza.Sembra che uno dei parametri di autenticazione sia sbagliato. Aggiorna la tua chiave pubblica, Secret Key & User ID e riprova.È una %s temporanea. Sto solo cercando di risolvere un problema.Non é quello che stavo cercandoEntra nel programma BetaLe informazioni sugli add-on di %s vengono scaricate da un server esterno.ChiaveCondividi cosa non ha funzionato in modo da migliorare il prodotto per gli utenti futuri...Spiegandoci il motivo ci aiuterai a migliorare.UltimoUltimo aggiornamentoUltima licenzaUltima versione gratuita installataVersione più recente installataScopri altroLunghezzaLicenzaLicense AgreementLicense IDChiave della licenzaProblemi di licenza?Chiave di licenzaLa chiave licenza è vuota.Tutta la vitaTi piace %s? Diventa il nostro ambasciatore e guadagna denaro ;-)Carica opzioni del DBLocalhostLogLoggerDuplicato a lungo termineMessaggioMetodoSpostaSposta la licenzaMigra le opzioni al NetworkApplicazioni mobileModuloPercorso moduloTipo di moduloUlteriori informazioni su %sNomeNetwork BlogUtente NetworkNuovoNuova versione disponibileNuovo sitoNuova versione gratuita (%s) installataVersione più recente (%s) installataNewsletterSuccessivoNoNo sposta solo i dati di questo sito su %sNessun IDNessun impegno con %s - cancella quando vuoiNessun impegno per %s giorni - puoi annullare in qualsiasi momento!Nessuna carta di credito richiestaNessuna scadenzaNon in scadenzaNessuno dei piani di %ssupporta il periodo di prova.OKQuando la tua licenza scadrà, potrai comunque continuare a usare la versione gratuita, ma NON avrai accesso alle funzionalità %s.Quando la tua licenza scadrà non potrai più usare %s, a meno che lo attivi di nuovo con una licenza premium valida.IscrivitiCancella iscrizioneAbilita "%s" per renderlo migliore!AltroEmail proprietarioID proprietarioNome proprietarioPCI compliantGli add-on a pagamento devono essere distribuiti da Freemius.Indirizzo account email PaypalPagamentiI pagamenti sono in Dollari Americani e processati mensilmente da PayPal.PianoIl piano %s non esiste, per questo motivo non è possibile iniziare il periodo di prova.Il piano %s non supporta il periodo di prova.ID PianoContattaci quiContattaci con il seguente messaggio:Scarica %s.Per favore inserisci la chiave di licenza che hai ricevuto via mail subito dopo l'acquisto:Inserisci la chiave della licenza per abilitare la modalità Debug:Facci sapere ogni sito o statistiche social valide, es: visite uniche mensili, numero di sottoscrizioni email, follower ecc (tratteremo queste informazioni come riservate).Segui i passi seguenti per completare l'aggiornamentoFacci sapere se vuoi essere contattato per aggiornamenti di sicurezza e di funzionalità, contenuti formativi e offerte occasionali:Si prega di notare che non saremo in grado di garantire lo stesso prezzo per rinnovi/sottoscrizioni dopo la cancellazione. Se scegli di rinnovare l'abbonamento manualmente in futuro, dopo un aumento del prezzo, che di solito avviene una volta l'anno, ti verrà addebitato il nuovo prezzo.Fornisci i dettagli su come intendi promuovere %s. (sii più esplicativo possibile)Per favore inserisci il tuo nome completo.PluginHomepage del pluginPlugin IDInstallazione del pluginChangelogDescrizioneFAQCaratteristiche & prezziInstallazioneAltre noteRecensioniIl plugin è un "Serviceware", quindi non dispone di una versione del codice Premium.PluginSincronizzazione plugin e temiPremiumLa versione 1%s Permium è stata attivata con successo.Versione Premium dell'add-on già installata.Versione premiumVersione Premium già attiva.PrezziPolitica sulla privacyProseguiID processoElaborazioneProdottiSommario programmaMetodi promozionaliProvinciaChiave pubblicaAcquista licenzaContinua a comprareSuggerimenti rapidiQuotaInvia nuovamente l'email di attivazioneComunica nuovi clienti al nostro %s e guadagna %s di commissione per ogni vendita avvenuta!Rinnova licenzaRinnova la tua licenza oraRichiesteRichiede la versione di WordPressResetta l'avviso di disattivazioneRisultatoSDKPercorso SDKRisparmia %sSalvatoAzioni programmateScreenshotCerca per indirizzoChiave segretaPagina sicura su protocollo HTTPS %s eseguita su dominio esternoSembra che stai avendo dei problemi temporanei con la cancellazione della sottoscrizione. Prova nuovamente tra pochi minuti.Stiamo avendo qualche problema temporaneo con l'annullamento del periodo di prova. Riprova tra qualche minuto.Sembra che tu abbia la versione più recente.Seleziona NazioneInvia chiave di licenzaImposta opzione del DBSimula aggiornamento networkSimula la prova TrialLicenza per sito singoloID del sitoSito accettato con successo.SitiSalta & %sSlugSilenzia e %sPuoi riutilizzare la licenza quando %s non è piu attivo.Social network (Facebook, Twitter, ecc.)Siamo spiacenti per l'inconveniente e siamo qui per aiutarti con il tuo permesso.Siamo spiacenti, non siamo riusciti a completare l'aggiornamento via email. Un altro utente con lo stesso indirizzo email è già registrato.AvviaAvvia DebugInizia il periodo di prova gratuitoInizia la mia %sStatoFerma DebugInviaInvia e %sSottoscriviSupportoForum di supportoSincronizza i dati dal serverNumero Partita Iva o VATTermini del ServizioGrazie per la partecipazione al nostro programma di affiliazione, sfortunatamente abbiamo valutato di rifiutare la tua richiesta. Prova nuovamente fra 30 giorni.Grazie per la partecipazione al nostro programma di affiliazione, valuteremo la tua richiesta durante i prossimi 14 giorni e ti contatteremo per maggiori informazioni.Grazie per utilizzare %se i suoi addon!Grazie per utilizzare %s!Grazie per utilizzare i nostri prodotti!Grazie!Grazie %s!Grazie per aver confermato il cambiamento del proprietario. Un' email è stata appena inviata a %s per la conferma finale.%s ha rotto il mio sito%s non funziona%s non ha funzionato come mi aspettavo%s è ottimo ma ho bisogno di una funzionalità specifica non supportata%s non funziona%s ha improvvisamente smesso di funzionareI prodotti seguentiIl processo d'installazione è iniziato e potrebbe impiegare alcuni minuti per completarsi. Attendi finchè non ha finito, assicurandoti di non ricaricare questa pagina.Il prodotto sottostante è stato messo in modalità sicurezza perchè abbiamo notato che %2$s è una copia esatta di %3$s: %1$sIl prodotto sottostante è stato messo in modalità sicurezza perchè abbiamo notato che %2$s è una copia esatta di questi siti %3$s: %1$sIl pacchetto remoto del plugin non contiene una cartella con lo slug desiderato e la rinominazione non ha funzionato.L'aggiornamento di %s è stato completato con successo.TemaCambio temaTemiC'è un %sdi %s disponibile.C'è una nuova versione di %s disponibile.Questo plugin non è stato segnato come compatibile con la tua versione di WordPress.Questo plugin non è stato testato con la versione corrente di WordPress.TimestampTitoloAbilita la modalità Debug, inserisci la chiave segreta del proprietario della licenza (UserID = %d), che puoi trovare nella sezione "Profilo" della dashboard utente:TotaleCittadinaProva gratuitaTipoImpossibile accedere al filesystem. Conferma le tue credenziali.Licenze illimitateAggiornamenti IllimitatiCommissioni illimitate.Fino a %s sitiAggiornaAggiorna licenzaAggiornamenti, annunci, marketing, no spamAggiornamentoCarica e attiva la versione scaricataForteBacheca UtenteID utenteChiave utenteUtentiValoreL'email di verifica è stata inviata a %s. Se dopo 5 minuti non è ancora arrivata, per favore controlla nella tua casella di posta indesiderata.VerificatoVerifica emailLa versione %s é stata rilasciata.Visualizza dettagliVedi funzionalità a pagamentoAvvisoNon siamo riusciti a trovare alcuna licenza attiva associata al tuo indirizzo email, sei sicuro che sia l'indirizzo giusto?Non siamo riusciti a trovare il tuo indirizzo email nel sistema, sei sicuro che sia l'indirizzo giusto?Non possiamo caricare la lista degli addon. Probabilmente è un nostro problema, prova di nuovo fra qualche minuto.Abbiamo fatto alcune migliore a %s,%sSiamo felici di presentarvi il supporto al sistema multi network di Freemius.Siti, email e statistiche dei social network (opzionali)Benvenuto nel %s! Per iniziare inserisci la tua licenza:Che cosa ti aspettavi?Quale funzionalitá?Qual è il tuo %s?Che prezzo ritieni opportuno pagare?Che cosa stai cercando?Qual è il nome di %s?Dove vuoi promuovere %s?Pagina dei plugin di WordPress.orgVuoi fondere %s in %s?Vuoi procedere con l'aggiornamento?SiSI - %sSi entrambi gli indirizzi sono mieiSi muovi tutti i miei e risorse da %s a %sSi, %2$s è un duplicato di %4$s per il motivo di test, staging o sviluppo.Si %2$s è un nuovo e sito differente che è separato da %4$s.Hai già utilizzato una prova gratuita in passato.Sei a un clic di distanza dall'iniziare il tuo periodo di prova gratuito di %1$s giorni per il piano %2$s.Sei fantastico!Stai già usando %s in modalità prova.Sei a un passo dalla fine - %sPuoi continuare ad utilizzare le funzionalità%sma non avrai accesso agli aggiornamenti di sicurezza, nuove funzionalità o supporto.Non disponi di una licenza valida per accedere alla versione Premium.Hai la licenza %s.Hai la licenza %s.Hai aggiornato con successo il tuo %s.Hai segnato questo sito, %s, come duplicato temporaneo di %s.Hai marchiato questo sito, %s, come duplicato temporaneo di questi sitiPotresti non averci fatto caso, ma non sei obbligato a condividere i tuoi dati e puoi semplicemente %s la tua partecipazione.Hai già accettato il tracciamento d'uso, ci aiuterà a migliorare %s.Hai già accettato il tracciamento d'uso che ci aiuta a migliorare.Il piano del tuo add-on %s è stato aggiornato con successo.Il tuo periodo di prova gratuito %s è stato annullato con successo.La tua licenza%s è stata segnata come white label per nascondere informazioni sensibili dalla bacheca di WP (es: la tua email, licenza, prezzi e indirizzi). Se vuoi tornare indietro puoi farlo semplicemente tramite%s. Se è stato un errore guarda anche %s.La tua licenza%s è stata disattivata con successo.Il tuo account è stato attivato correttamente con il piano %s.La tua applicazione di affiliazione per %s è stata accettata! Accedi alla tua area di affiliazione a %s.Il tuo account di affiliazione è stato sospeso temporaneamente.Il tuo indirizzo email è stato verificato con successo - SEI UN GRANDE!La tua versione prova è scaduta.%1$s aggiorna ora %2$s per continuare ad usare %3$s senza interruzioni.La tua versione di prova gratuita è scaduta. Puoi continuare ad usare tutte le funzionalità gratuite.La tua licenza è stata cancellata. Se credi sia un errore, per favore contatta il supporto.La tua licenza è scaduta. %1$saggiorna ora %2$sper continuare ad utilizzare %3$s senza interruzioni.La licenza è scaduta. È comunque possibile continuare a utilizzare tutte le funzionalità di %s, ma sarà necessario rinnovare la licenza per continuare a ricevere gli aggiornamenti ed il supporto.La tua licenza è scaduta. Puoi continuare ad usare la versione gratuita %s per sempre.La tua licenza è stata attivata correttamente.La tua licenza é stata disattivata con successo, sei tornato al piano %s.Il tuo nome è stato aggiornato correttamente.Il tuo piano è stato attivato con successo.Il piano è stato cambiato con successo a %s.Il piano è stato aggiornato con successo.La tua sottoscrizione è stata cancellata con successo. La licenza del piano %sscadrà in %s.La versione di prova è stata avviata correttamente.CAPSìattiva una licenza quiAttiva%s non può funzionare senza %s.%s non può funzionare senza il plugin.Attenzionepermetti%s rimanentiAttivazioneannoAPIChiudiDebuggingCongratulazioniBloccatoConnessoScarica l'ultima versioneScarica l'ultima versione gratuitaMensilmenteScadenzaPercorsoInvio emailmeseAnnualeAnnualmenteUna voltaPianoNessuna chiaveVersioni SDKLicenzaSincronizzaSincronizza la licenzaAutoreNon attivoAttivobasato su %sInizia il periodo di prova gratuitoChiudiChiudidatagiornidisattivazione in corsodelega%snon %s mi invierà aggiornamenti di funzionalità e sicurezza, contenuti formativi e offerte.Piano %sFatturato %sMiglioreHeyOpsHey %s,oraoreInstallatoEvvailicenzaSitimsnuova versione Betanuova versionenon verificatoPrezzoPrezziopzionaleVersioneprodottitorna indietrosecsembra che la chiave che hai inserito non risulti nei nostri registri.inviami aggiornamenti di funzionalità e sicurezza, contenuti formativi e offerte.saltaUhmInizia il periodo di prova gratuitosottoscrizionepassa ai siti menzionati sopra stantel'ultima versione %s é quìprovaProva gratuitaEliminaDowngradeModificaNascondiIscrivitiCancella iscrizioneAcquistoMostraSaltaAggiornaAggiornamento%s fafreemius/languages/freemius-ru_RU.mo000064400000137767146725417150013600 0ustar00Þ•­„ Aìð#Sñ#%E$ k$ w$ƒ$6Š$´Á$_v%#Ö%ú% & !& +&6&=&E&N&V&H_&¨&¬&´&Ä&Ì& Õ&á&ò&'' .'8'G'\'o'v'5~'´' Ä' Î''Ú'( ( ((2(C(žJ(é(ü(2)!L)an)0Ð)****9*A*U*]*f* k*y*–**±* Å* Ò*YÜ*6+E+ V+b+k+p+(€+1©+%Û+,,,, /, :,G,], e,o, t,, ’, Ÿ,©,½,Å,ß,õ,þ,-1- M-—X-ð- ö-.Y.ab.Ä.Ê.ê. ò. /;/J/O/þV/U0 Z0 e0 r00jŽ0ù0 1131O1~c1Uâ182T2m2)ˆ2-²2à2Sô2H3'`3ˆ37‹3gÃ3+4 14=4P4f4y4 41‹4.½4Oì4<5A¼5yþ5x6a˜6ú6Bþ6,A7n7 s7 €77 ¦7±7¸7 À7 Ì7Ø74á78 %8/838:8B8 I8U8 \8 h8t8Ž8“8—8 ´8¿8Ä8%Ê8+ð89 49 B9/O99mƒ9ñ9ø9: :):>:[:4d:™:5ž:(Ô:ý:;-;J;U^;È´;1}<[¯< =*=1= A=K=(Z=*ƒ="®=1Ñ=+>*/>&Z>N>Ð>Ø>î>.ö>)%?O?_??‡? –? ¡?¬?¼?Î? ×?â?ó?ù?W@j@s@Ž@•@™@¢@ª@ º@ Æ@5Ñ@lA&tA›AªA »AÉAÝAåA ëAõA&úAL!BfnBÕB ÛBçBøB þB C C C 6CCC•TC–êC D\ŒDéDþDEC0EtEŠE…ªEd0F-•FÃF ÉFÖFMÝFG+G sG}GƒG‰GŽG”GE™GßGòGHH*H1H*@HkH*sH^žHýHI IdIvI IŒI ¥I²IÅIiÍIW7J"J6²JéJ þJ K-KKKiK&K¦KÀK$ÉKMîKžLÝL&ôLZM.vM.¥M9ÔMZN3iN<NUÚNš0OKËO(PG@P#ˆP)¬P$ÖP)ûP%Q7Q;TQ6Q>ÇQR!RAR$WR|R–R²RÎR&ìR*S>SUSsS3ŒSÀSÕSëSTT*4T1_T‘T­T#ÁTåTUU #U/UOUfU {UˆU§UÅUàUðUV1VDVXV hV uV €VV ¥VQ±VW WW8W KWWW fW pW zW †W “W ¡W «W µW ÁW ÎWJÛW6&\D]\¢\¹\Î\^æ\pE]š¶^EQ_4—_Ì_ß_ð_``'`>` M`ÆX`a#a ?aMa_aya"•a;¸a)ôa5bTblb$‹b6°b$çb" c]/c c®c½ciÕcD?d„d›d*«dÖdìd f6*fWaf>¹føfÿg6h0¸héhii6iSimi Ši@«i ìi$úi"j/BjrjùŒj"†k3©kÝk øk llb.lx‘le mpmwmm9¯mémûm0n HnVn jntn.’nÁn0Øn& o0o7CoB{o¾o Îo3ïo,#pPp!bp"„q"§q Êq•Öqõlr bsos/‹sB»s9þsx8t±t ºtYÈt"w98w"rw •w-¢w´Ðw…x¡xµxyÅx5?yúuyåpz6V{9{;Ç{^|Qb|´|¸Ò|,‹}:¸}ó}rö}°i~" 3C%w  ¾È_ÚT:€T€wä€l\‚µÉ‚(ƒ°¨ƒ Y„Ùc„h=…¦…(º…$ã…6†?† Y†g†"y†!œ†'¾†bæ†4I‡"~‡ ¡‡;‡þ‡ ˆ(ˆ GˆTˆkˆ'€ˆ¨ˆ ¯ˆ=»ˆùˆ ‰‰w%‰z‰BŠ9[Š•Šb«Š‹ò‹Œ4#Œ XŒeŒTvŒ9ËŒUj…dŽ!zŽNœŽkëŽ)W¹ž;vÚ‘²Q’A“ F“/T“„“"—“ º“Û“/í“1”O”c” €”‰Ž”•@(•i•Qy•JË•–;3– o–5y–¯– Ä–3å–$—>— R—^—,}—Aª—ì—}˜,˜º˜͘ јÞ˜)ò˜™ 7™qC™èµ™Ožšîš4 ›6@›(w› › ¨›¶›(Л8ù› 2œ×Óœ «*¸+ã žž/žCž:bžž5µžëžÕýŸÓ ×å %½¡ã¡4þ¡§3¢Û¢8ô¢ñ-£­¤Bͤ ¥*¥I¥oY¥nÉ¥8¦U¦ g¦ r¦“¦²¦—¹¦.Q§2€§;³§ï§¨!¨K:¨†¨L¥¨ò¨ú¨©©ä/©ª9,ª/fª$–ª8»ªôªí«µ¬T¶¬‡ ­1“­ Å­æ­Pü­%M®s®5“®/É® ù®I¯×M¯!%°GG°8°…È°'N±.v±Ü¥±9‚²`¼²t³ˆ’³T´|p´Òí´HÀµÚ ·Lä·‰1¸:»¸Nö¸GE¹>¹ ̹Ú¹#í¹;ºMº_ºtºˆºžº¢º!²ºÔºïº ».»N» b» ƒ»T»â»û» ¼)¼:¼U¼l¼}¼!¼,±¼ Þ¼é¼ý¼½)&½P½`½p½ ˆ½•½ ­½ »½ɽѽí½ õ½¾ ¾&¾:¾ C¾Q¾X¾*`¾‹¾-¥¾Ó¾ñ¾¿¿7¿I¿e¿ {¿ˆ¿š¿¯¿Á¿ß¿~ö>ŒÇ0Z'5Š-yºI`¡Go£´Šzì­¨qˆµw}#•Y¬c“êRùWFžpf‹X™Á`.KŸá—òl4?lÜwª«2U@•÷¿°+_zô6.³j¥S¼×(rÒ,=’e*ÿ;$G,ND'§a˜ßo{x7dhLœ­íŒ®¹hÕžX‰6k" þ‚Ä©ÎM(s[‘ð‹x 2_î䛯g#dSU ’ ïȽm0^EQ-jN!û!åeÂ"¢„ÆëH4óéY…]“@ &v|7Tæ{cJs+v”>«*ŽZ 38Ú$Ì™yɦ[^\š»§†¥–õ3n·:1t9J¾ p„Ï&šQuAœ1–˜ Ž\â¦|¢)f²›iÔ±9FÍ£BÅIrÝ~çÑPCW:‡ƒPEBãÙ‘=‚8Dà Vk€}Þúˆüƒ…/€O©RO‡a—)Ÿ¨/iØÀM¬ubqb‰ èªV<ý<mñL¤t5ø¡àË]Р%¶;ÛnKCÓ¸†gA ʤH ”?Ö%T%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is the new owner of the account.%s minimum payout amount.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s tracking cookie after the first visit to maximize earnings potential.APIAccountAccount DetailsActionsActivateActivate %sActivate %s PlanActivate Free VersionActivate LicenseActivate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.Address Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.Anonymous feedbackApply to become an affiliateAre you sure you want to delete all Freemius data?Are you sure you want to proceed?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBillingBlockingBodyBusiness nameCan't find your license key?CancelCancel InstallationCancel SubscriptionCancel TrialCancelledCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanCheckoutCityClear API CacheClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeDateDeactivateDeactivate LicenseDeactivationDebug LogDelete All AccountsDetailsDon't have a license key?Donate to this pluginDownloadDownload %s VersionDownload the latest %s versionDownload the latest versionDownloadedDue to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.EmailEmail addressEndEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used for the upgrade below and we will resend you the license key.ErrorError received from the server:ExpiredExpires in %sExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.FreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFull nameFunctionGet commission for automated subscription renewals.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!How do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I can't pay for it anymoreI couldn't understand how to make it workI don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf you have a moment, please let us know why you are %sIf you would like to give up the ownership of the %s's account to %s click the Change Ownership button.In %sInstall NowInstall Update NowInstalling plugin: %sInvalid module ID.InvoiceIs ActiveIt looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's not what I was looking forJust letting you know that the add-ons information of %s is being pulled from an external server.KeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Version InstalledLearn moreLengthLicenseLicense KeyLicense keyLifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerMessageMethodMobile appsModuleModule PathModule TypeMore information about %sNameNewNewer Version (%s) InstalledNewsletterNextNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Opt InOpt OutOtherPCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProcess IDProcessingProgram SummaryPromotion methodsProvincePublic KeyPurchase LicenseQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!RequestsRequires WordPress VersionResultSDKSDK PathSave %sScheduled CronsScreenshotsSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSingle Site LicenseSite IDSitesSkip & %sSlugSocial media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart TrialStart my free %sStateSubmit & %sSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThis plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.TimestampTitleTotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser IDUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We made a few tweaks to the %s, %sWebsite, email, and social media statistics (optional)What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress.org Plugin PageYes - %sYou already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou do not have a valid license to access the premium version.You have a %s license.You have successfully updated your %s.You might have missed it, but you don't have to share any data and can just %s the opt-in.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismissdeactivatinge.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,interjection expressing joy or exuberanceYee-hawlike websitesSitesmillisecondsmsnot verifiednounPricenounPricingproduct versionVersionsecondssecsomething somebody says when they are thinking about what you have just said.Hmmstart the trialswitchingthe latest %s version heretrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Leo Fajardo , 2021 Language-Team: Russian (Russia) (http://www.transifex.com/freemius/wordpress-sdk/language/ru_RU/) Language: ru_RU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3); X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js Закончить активацию %s ÑÐµÐ¹Ñ‡Ð°Ñ ÐŸÐ¾ÐºÑƒÐ¿ÐºÐ° %s плагина уÑпешно ÑоÑтоÑлаÑÑŒ%s уÑтановок %s лицензий %s тому назад %s вознаграждениÑ, еÑли клиент купит новую лицензию.БеÑплатный период Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ %s закончилÑÑ. Этот плагин ÑвлÑетÑÑ Ð¿Ñ€ÐµÐ¼Ð¸ÑƒÐ¼ продуктом и он был деактивирован автоматичеÑки. ЕÑли Ð’Ñ‹ планируете дальнейшее его иÑпользование, пожалуйÑта купите лицензию. %s ÑвлÑетÑÑ Ð¿Ñ€ÐµÐ¼Ð¸ÑƒÐ¼ продуктом. Ðеобходимо купить лицензию перед активацией плагина. %Ñ ÑвлÑетÑÑ Ð½Ð¾Ð²Ñ‹Ð¼ владельцем аккаунта%s Ð¼Ð¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ñумма выплаты %s или выше%s оценка %s оценки %s Ñекунд %звездочка %s звездочки %s Ð²Ñ€ÐµÐ¼Ñ %s раз %s данные cookies предоÑтавлÑÑŽÑ‚ÑÑ Ð¿Ð¾Ñле первого поÑещениÑ, чтобы макÑимально увеличить вероÑтноÑÑ‚ÑŒ заработка. APIЛичный кабинет ДеталиДейÑÑ‚Ð²Ð¸Ñ Ðктивировать Ðктивировать %sÐктивируйте план %sÐктивировать беÑплатную верÑию?Ðктивировать лицензиюÐктивируйте Ñтот функционал Ðктивирован Функционал Ð´Ð»Ñ %sФункционал Ð¼Ð¾Ð´ÑƒÐ»Ñ %sДобавьте другое доменное Ð¸Ð¼Ñ Ð¤ÑƒÐ½ÐºÑ†Ð¸Ð¾Ð½Ð°Ð» плагина ÐаÑтройки плагина Функционал должен быть заÑвлен на WordPress.org или Freemius Поле Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑа %dПартнерПартнерÑтво ПоÑле Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð’Ð°ÑˆÐµÐ³Ð¾ беÑплатного %s, платите вÑего лиш %sСоглаÑитьÑÑ Ð¸ активировать лицензию Ð’Ñе запроÑÑ‹ Ð’Ñе типыРазрешить и продолжитьКоличеÑтво ÐвтоматичеÑкое Ñкачивание и уÑтановка %s ( платной верÑии) %s начнетÑÑ Ñ‡ÐµÑ€ÐµÐ· %s. ЕÑли Ð’Ñ‹ хотите вÑе Ñделать в ручном режиме, нажмите на кнопку "Отменить" ÑейчаÑ. Ðнонимный отзыв Подать заÑвку на партнерÑтво Ð’Ñ‹ уверенны, что хотите удалить вÑе данные Freemius?Ð’Ñ‹ уверены, что хотите продолжить?Мы выделÑем 30 дней Ð´Ð»Ñ Ð¿Ð¾ÑÑ‚ÑƒÐ¿Ð»ÐµÐ½Ð¸Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‚Ð¾Ð² и поÑтому Ð²Ð¾Ð·Ð½Ð°Ð³Ñ€Ð°Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð¿Ð»Ð°Ñ‡Ð¸Ð²Ð°ÑŽÑ‚ÑÑ Ð·Ð° покупки, которые были Ñовершены более чем 30 дней назад.Ðвто уÑтановка работает только Ð´Ð»Ñ Ð·Ð°Ñ€ÐµÐ³Ð¸Ñтрированных пользователей.ÐвтоматичеÑкое продление в %sÐвтоматичеÑÐºÐ°Ñ ÑƒÑтановка Средний рейтинг Отлично!Стать партнеромСиÑтема оплаты Блокирование ОÑÐ½Ð¾Ð²Ð½Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ Ðазвание бизнеÑа Ðе можете найти лицензионный ключ? Отмена Отменить уÑтановку Отменить подпиÑку Отменить теÑтовый период Ðннулирована Отказ от Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‚ÐµÑтовым периодом автоматичеÑки блокирует доÑтуп ко вÑем премиум возможноÑÑ‚Ñм. Ð’Ñ‹ уверены, что хотите отказатьÑÑ?Изменить лицензию Сменить владельца лицензии Изменить план Оплата Город ОчиÑтить кÑш APIÐажмите здеÑÑŒ, чтобы пользоватьÑÑ Ð¿Ð»Ð°Ð³Ð¸Ð½Ð¾Ð¼ анонимно. Ðажмите, чтобы поÑмотреть отзывы, которые Ñформировали рейтинг %sКликните, чтобы поÑмотреть Ñнимок %d на широком Ñкране. КодСовмеÑтима Ñ Ð¡Ð²ÑжитеÑÑŒ Ñ Ð½Ð°Ð¼Ð¸Ð¡Ð²ÑзатьÑÑ Ñо Ñлужбой поддержкиКонтакты Контрибьюторы Ðевозможно активировать %sСтрана Тип задачиДата Деактивировать Деактивировать лицензию ДеактивациÑЖурнал уÑÑ‚Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº Удалить вÑе аккаунтыДетальнейУ Ð’Ð°Ñ Ð½ÐµÑ‚ лицензионного ключа?ИнвеÑтировать в разработку плагина Скачать Скачайте верÑию %sСкачайте поÑледнюю верÑию %sСкачай поÑледнюю верÑиюЗагружен Из-за Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸Ñ ÑƒÑловий партнерÑтва мы вынуждены временно заблокировать Ваш аккаунт. ЕÑли у Ð’Ð°Ñ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ»Ð¸ вопроÑÑ‹, пожалуйÑта, обратитеÑÑŒ в Ñлужбу поддержки. Электронный Ð°Ð´Ñ€ÐµÑ Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ñ‹Ð¹ Ð°Ð´Ñ€ÐµÑ ÐšÐ¾Ð½ÐµÑ† Введите домен Вашего Ñайта или других Ñайтов на которых Ð’Ñ‹ намерены продвигать %s.Введите ниже Ð°Ð´Ñ€ÐµÑ Ñвоей Ñлектронной почты, которую Ð’Ñ‹ иÑпользовали Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ð¹ и мы Вам отправим повторно Ваш лицензионный ключ. ОшибкаОшибка ÑервераСрок дейÑÑ‚Ð²Ð¸Ñ Ð·Ð°ÐºÐ¾Ð½Ñ‡Ð¸Ð»ÑÑ ÐžÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ðµ Ñрока Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· %sДополнительные доменные имена Дополнительные доменные имена, где Ð’Ñ‹ будете продвигать продукт. ФайлФильтр Ð’ ÑоответÑтвии Ñ Ñ€ÑƒÐºÐ¾Ð²Ð¾Ð´Ñтвом WordPress.org, перед началом теÑтового периода мы проÑим, чтобы Ð’Ñ‹ приÑоединилиÑÑŒ к нашему ÑообщеÑтву предоÑтавив информацию о Вашем Ñайте и также Ваши личные данные, тем Ñамым разрешив %s периодичеÑки отправлÑÑ‚ÑŒ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð½Ð° %s Ð´Ð»Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ð¹ об обновлениÑÑ… и Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð’Ð°ÑˆÐµÐ³Ð¾ теÑтового периода. БеÑÐ¿Ð»Ð°Ñ‚Ð½Ð°Ñ Ð‘ÐµÑплатный период Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð‘ÐµÑÐ¿Ð»Ð°Ñ‚Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Freemius APIИÑправление ошибок FreemiusFreemius SDK не удалоÑÑŒ найти оÑновной файл плагина. ПожалуйÑта, ÑвÑжитеÑÑŒ Ñ sdk@freemius.com Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ ошибкой.CоÑтоÑние Freemius Полное имÑÐ¤ÑƒÐ½ÐºÑ†Ð¸Ñ ÐŸÐ¾Ð»ÑƒÑ‡Ð°Ð¹ вознаграждение за автоматичеÑкие Ð¿Ñ€Ð¾Ð´Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ. У Ð’Ð°Ñ ÐµÑÑ‚ÑŒ лицензионный ключ?Привет! Знали ли Ð’Ñ‹, что %s предоÑтавлÑет реферальную программу? ЕÑли Вам нравитÑÑ %s, Ð’Ñ‹ можете Ñтать нашим предÑтавителем и зарабатывать!Тебе нравитÑÑ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÑŒÑÑ %s? ВоÑпользуйÑÑ Ð²Ñеми нашими премиум возможноÑÑ‚Ñми на протÑжении %d - дневного теÑтового периода. Как загрузить и активировать?Как Ð’Ñ‹ намерены продвигать наÑ?Я больше не могу оплачивать Ñто. Я не могу понÑÑ‚ÑŒ как Ñделать так, чтобы оно работалоЯ не хочу делитьÑÑ Ð»Ð¸Ñ‡Ð½Ð¾Ð¹ информацией Ñ Ð’Ð°Ð¼Ð¸Ð¯ нашел лучший %sЯ провел апгрейд аккаунта, но при попытке Ñинхронизировать лицензию, мой тарифный план не менÑетÑÑ. %s больше не понадобитÑÑ.%s требовалаÑÑŒ на короткое времÑIDЕÑли у Ð’Ð°Ñ ÐµÑÑ‚ÑŒ времÑ, пожалуйÑта, Ñообщите причину почему Ð’Ñ‹ %sЕÑли Ð’Ñ‹ передаете права Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð¾Ð¼ %s %s нажмите кнопку " Сменить права иÑпользованиÑ"Ð’ %sУÑтановить ÑÐµÐ¹Ñ‡Ð°Ñ ÐŸÑ€Ð¾Ð²ÐµÑти Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÑÐµÐ¹Ñ‡Ð°Ñ Ð£Ñтановка плагина: %sÐеверный ID модулÑСчет активный ВероÑтно возникли трудноÑти Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸ÐµÐ¹ лицензии. ВероÑтно Ð´ÐµÐ°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ð¸ не ÑоÑтоÑлаÑÑŒ. Возможно, Ваш теÑтовый период уже закончилÑÑ. ВероÑтно Ð’Ñ‹ вÑе еще пользуетеÑÑŒ ÑервиÑом ÑоглаÑно плану %s. ЕÑли Ð’Ñ‹ обновлÑли или менÑли Ñвой тарифный план, то вероÑтно ÑущеÑтвуют какие-то трудноÑти ÑвÑзанные Ñ Ð’Ð°ÑˆÐ¸Ð¼ программным обеÑпечением. Извините. ВероÑтно Ваш Ñайт не иÑпользует активную лицензию ÑейчаÑ. ВероÑтно один из параметров ÑвлÑетÑÑ Ð½ÐµÐ²ÐµÑ€Ð½Ñ‹Ð¼. Обновите Ñвой Public Key, Secret Key&User ID и повторите попытку.Это не то, что Ñ Ð¸Ñкал. Сообщаем, что Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ дополнительных наÑтройках %s предоÑтавлÑетÑÑ Ñо Ñтороннего Ñервера. Ключ ПожалуйÑта, Ñообщите о функционале, который не работает, чтобы мы Ñмогли иÑправить его Ð´Ð»Ñ Ð´Ð°Ð»ÑŒÐ½ÐµÐ¹ÑˆÐµÐ³Ð¾ иÑпользованиÑ. ПожалуйÑта, укажите причину, чтобы мы могли иÑправитьÑÑ. ПоÑледний ПоÑледнее обновление ПоÑледнÑÑ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ ÐŸÐ¾ÑледнÑÑ Ð²ÐµÑ€ÑÐ¸Ñ ÑƒÑтановленаУзнать большеДлинна Ð›Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð›Ð¸Ñ†ÐµÐ½Ð·Ð¸Ð¾Ð½Ð½Ñ‹Ð¹ ключ Лицензионный ключÐа беÑÑрочный период Вам нравитÑÑ %s? Стань нашим партнером и зарабатывай ;-)Загрузить опцию базы данных Локальный хоÑтинг Журнал изменений Программа ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ Сообщение Метод Мобильные Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÐœÐ¾Ð´ÑƒÐ»ÑŒÐŸÑƒÑ‚ÑŒ Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¢Ð¸Ð¿ Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð‘Ð¾Ð»ÑŒÑˆÐµ информации о %sИмÑÐовое Более Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ %s уÑтановлена РаÑÑылка Следующий No IDБез обÑзательÑтв платить %s - аннулируй пользование в любое Ð²Ñ€ÐµÐ¼Ñ Ð‘ÐµÑплатное пользование на протÑжении %s дней. Отмена в любое времÑ. Ðе требуютÑÑ Ð´Ð°Ð½Ð½Ñ‹Ðµ платежной картыБеÑÑрочный период Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð‘ÐµÑÑрочный Тарифные планы %s не предуÑматривают теÑтовый период. O.K.По окончанию Ñрока дейÑÑ‚Ð²Ð¸Ñ Ð’Ð°ÑˆÐµÐ¹ лицензии, Ð’Ñ‹ Ñможете пользоватьÑÑ Ð±ÐµÑплатной верÑией, но у Ð’Ð°Ñ Ð½Ðµ будет доÑтупа к возможноÑÑ‚Ñм %s. ПриÑоединитьÑÑОтказатьÑÑ Ð¾Ñ‚ иÑпользованиÑДругиеЖалоба PCIПлатный функционал должен быть заÑвлен в FreemiusЭлектронный Ð°Ð´Ñ€ÐµÑ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð° PayPalПлатежиВыплаты производÑÑ‚ÑÑ Ð² долларах СШРчерез PayPal.Тарифный план Тарифного плана %s не ÑущеÑтвует, поÑтому Ð’Ñ‹ не можете начать теÑтовый период. Тарифный план %s не предуÑматривает теÑтового периода. ID тарифного плана ПожалуйÑта, напишите нам Ñообщение здеÑÑŒ. ПожалуйÑта, напишите нам Ñообщение Ñледующего ÑодержаниÑ:ПожалуйÑта, Ñкачайте %sПожалуйÑта введите лицензионный ключ, который Ð’Ñ‹ получили на Ñлектронный Ð°Ð´Ñ€ÐµÑ Ñразу поÑле покупки. ПожалуйÑта, предоÑтавьте ÑоответÑтвенную ÑтатиÑтику вебÑайта или Ñтраницы Ñоциальных Ñетей, например, количеÑтво уникальных поÑетителей, количеÑтво подпиÑчиков, читателей, Ñ‚. д. ( Ñта Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ÑтанетÑÑ ÐºÐ¾Ð½Ñ„Ð¸Ð´ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð¾Ð¹). ПожалуйÑта, пройдите Ñти шаги Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы произвеÑти апгрейдПожалуйÑта, предоÑтавьте макÑимально детальную информацию о том, как Ð’Ñ‹ планируете продвигать %s.ПожалуйÑта, введите Ваше полное имÑПлагин Ð“Ð»Ð°Ð²Ð½Ð°Ñ Ñтраница плагина ID плагина УÑтановка плагина Журнал изменений ОпиÑание ЧаÑто задаваемые вопроÑÑ‹ Функционал&тарифные планы УÑтановка Другие заметки Отзывы Плагин ÑвлÑетÑÑ 'ServiÑeware'. Это означает, что он не имеет премиум верÑию кода. Плагины Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ð»Ð°Ð³Ð¸Ð½Ð¾Ð² и шаблонов Премиум Премиум верÑÐ¸Ñ %s была уÑпешно активирована. Премиум верÑÐ¸Ñ Ð¿Ð»Ð°Ð³Ð¸Ð½Ð° была уÑтановленаПремиум верÑÐ¸Ñ ÐŸÑ€ÐµÐ¼Ð¸ÑƒÐ¼ верÑÐ¸Ñ ÑƒÐ¶Ðµ активированаЦены Политика КонфиденциальноÑтиID процеÑÑа Обработка данных Краткое опиÑание программы Методы Ð¿Ñ€Ð¾Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ ÐŸÑ€Ð¾Ð²Ð¸Ð½Ñ†Ð¸Ñ Public Key Купите лицензию Выделенный объем памÑтиОтправить пиÑьмо активации еще раз Порекомендуй %s новым пользователÑм и зарабатывай %s c каждой уÑпешной продажи. ЗапроÑÑ‹ Ðеобходима верÑÐ¸Ñ WordPress РезультатSDKпуть SDKÐ­ÐºÐ¾Ð½Ð¾Ð¼Ð¸Ñ %sСпланированные задачиСнимки Ñкрана Secret Key БезопаÑÐ½Ð°Ñ Ñтраница HTTPS %s воÑпроизводитÑÑ Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ реÑурÑа К Ñожалению у Ð½Ð°Ñ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ»Ð¸ трудноÑти Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¾Ð¹ Вашего теÑтового периода. ПожалуйÑта, повторите попытку через неÑколько минут.ВероÑтно, Ð’Ñ‹ пользуетеÑÑŒ поÑледней верÑиейВыбрать Ñтрану Отправить лицензионный ключУÑтановить опцию базы данных Ð›Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð½Ð° один Ñайт Site IDСайтов ПропуÑтить & %sОпиÑÐ°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ‡Ð°ÑÑ‚ÑŒ URL Социальные Ñети ( Facebook, Twitter, etc.)Извините за неудобÑтво. Мы будем рады помочь, еÑли Ð’Ñ‹ нам предоÑтавите Ñту возможноÑÑ‚ÑŒ. Извините, нам не удалоÑÑŒ обновить Ñлектронный адреÑ. Другой пользователь Ñ Ñ‚Ð°ÐºÐ¸Ð¼ же адреÑом уже был зарегиÑтрирован. ÐачалоÐачать теÑтовый периодÐачать мой беÑплатный %sШтат Отправить&%sПоддержка Форум поддержки Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… Ñ Ñервера ID налога/ÐДС ПользовательÑкое ÑоглашениеСпаÑибо за подачу заÑвки на партнерÑтво. К Ñожалению, мы принÑли решение отказать Вам в Ñтой возможноÑти. ПожалуйÑта, повторите попытку через 30 дней. СпаÑибо за подачу заÑвки на партнерÑтво. Мы раÑÑмотрим Ваши данные на протÑжении Ñледующих 14 дней и ÑвÑжемÑÑ Ñ Ð’Ð°Ð¼Ð¸. СпаÑибо %sСпаÑибо, что подтвердили изменение прав иÑпользованиÑ. Вам отправлено пиÑьмо на %s Ð´Ð»Ñ Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ подтверждениÑ. %s повредила мой Ñайт%s не Ñработала%s не Ñработала как ожидалоÑÑŒ%s Ð¾Ñ‚Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑ‚ÑŒ, но мне нужен определенный функционал, который вы не поддерживаете. %s не работает%s внезапно переÑтала работать ПроцеÑÑ ÑƒÑтановки уже начат и может занÑÑ‚ÑŒ неÑколько минут. ПожалуйÑта, подождите Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ñ†ÐµÑÑа и не обновлÑйте Ñту Ñтраницу. Удаленный пакет плагинов не Ñодержит папку Ñ Ð½ÑƒÐ¶Ð½Ñ‹Ð¼ опиÑанием URL и Ñмена имени не Ñрабатывает. Обновление %s было уÑпешно завершеноШаблон Переключатель шаблона Шаблоны Этот плагин не отмечен как ÑовмеÑтимый з Вашей верÑией WordPress Этот плагин не был теÑтирован Ñ Ð’Ð°ÑˆÐµÐ¹ текущей верÑией WordPress. Маркер времени Ðазвание ИтогоÐаÑеленный пункт ТеÑтовый период ТипÐевозможно приÑоединитьÑÑ Ðº ÑиÑтеме файлов. ПожалуйÑта, подтвердите Ñвои данные. ÐÐµÐ¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð½Ð°Ñ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ðеограниченные Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ðеограниченное вознаграждение до %s Ñайтов Обновить Обновить лицензиюÐовоÑти, объÑвлениÑ, маркетинг, без ÑпамаСделать апгрейд Загрузите и активируйте Ñкачанную верÑиюВау!User ID Пользователи Значение ПиÑьмо подтверждение было только что отправлено на %s. ЕÑли Ð’Ñ‹ не получите его через 5 минут, пожалуйÑта, проверьте папку Ñпам.Подтвержден Подтвердите Ñлектронный Ð°Ð´Ñ€ÐµÑ Ð ÐµÐ»Ð¸Ð· верÑии %s ÑоÑтоÑлÑÑ. Смотреть детальней ПроÑмотр платных возможноÑтейПредупреждение ÐÐºÑ‚Ð¸Ð²Ð½Ð°Ñ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð²Ñ‹Ð´Ð°Ð½Ð½Ð°Ñ Ð½Ð° Ñтот Ñлектронный Ð°Ð´Ñ€ÐµÑ Ð½Ðµ была найдена. Ð’Ñ‹ уверены, что предоÑтавили правильный Ñлектронный адреÑ?К Ñожалению, Ваш почтовый Ð°Ð´Ñ€ÐµÑ Ð½Ðµ найден в ÑиÑтеме. Ð’Ñ‹ уверены, что предоÑтавили правильный адреÑ? Мы уÑовершенÑтвовали в %s, %s Ð´Ð»Ñ Ð»ÑƒÑ‡ÑˆÐµÐ¹ работы ВебÑайт, Ñлектронный Ð°Ð´Ñ€ÐµÑ Ð¸ ÑтатиÑтика Ñоциальных Ñетей (не обÑзательно)Каковы были Ваши ожиданиÑ? Какой функционал?Какой Ваш %s?ÐšÐ°ÐºÐ°Ñ ÑтоимоÑÑ‚ÑŒ была бы Ð´Ð»Ñ Ð’Ð°Ñ Ð¿Ñ€Ð¸ÐµÐ¼Ð»ÐµÐ¼Ð¾Ð¹? Что именно Ð’Ñ‹ ищите? Какое название %s?Где Ð’Ñ‹ намерены продвигать %s?Страница плагинов WordPress.orgДа - %sÐ’Ñ‹ уже иÑпользовали Ваш теÑтовый периодВы уже на раÑÑтоÑнии одного клика от начала Вашего беÑплатного %1$s - дневного теÑтового периода по тарифному плану %2$s. Ð’Ñе прошло хорошо!Ð’Ñ‹ уже пользуетеÑÑŒ теÑтовой верÑией %s Вам оÑталоÑÑŒ ÑовÑем немножко %sУ Ð’Ð°Ñ Ð½ÐµÑ‚ необходимых лицензионных прав Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€ÐµÐ¼Ð¸ÑƒÐ¼ верÑиейУ Ð’Ð°Ñ ÐµÑÑ‚ÑŒ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ %s.Ð’Ñ‹ уÑпешно обновили Ваш %sВозможно, Ð’Ñ‹ не обратили внимание, но Ð’Ñ‹ не обÑзаны делитьÑÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ð¼Ð¸ данными и можете проÑто %s кнопку "ПриÑоединитьÑÑ". Ваш %s план был уÑпешно обновленВаш беÑплатный теÑтовый период был уÑпешно отменен. Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ была уÑпешно активирована ÑоглаÑно плану %sВаша заÑвка на партнерÑтво Ñ %s принÑта! Войдите в Ваш кабинет партнера на %sВаш партнерÑкий аккаунт временно недоÑтупен. Ваш Ñлектронный Ð°Ð´Ñ€ÐµÑ Ð±Ñ‹Ð» уÑпешно подтвержден и Ð’Ñ‹ проÑто молодец!Ваша Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð±Ñ‹Ð»Ð° аннулирована. ЕÑли Ð’Ñ‹ Ñчитаете, что Ñто ошибка, пожалуйÑта ÑвÑжитеÑÑŒ Ñ Ð½Ð°ÑˆÐµÐ¹ Ñлужбой поддержки. Срок дейÑÑ‚Ð²Ð¸Ñ Ð’Ð°ÑˆÐµÐ¹ лицензии закончен. Ð’Ñ‹ можете продолжать пользоватьÑÑ Ð²Ñеми возможноÑÑ‚Ñми %s продлив Вашу лицензию. Ð’Ñ‹ также будете получать доÑтуп к обновлениÑм и поддержке. Срок дейÑÑ‚Ð²Ð¸Ñ Ð’Ð°ÑˆÐµÐ¹ лицензии закончилÑÑ. Ð’Ñ‹ можете продолжать пользоватьÑÑ Ð±ÐµÑплатной верÑией %s на беÑÑрочной оÑнове.Ваша Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð±Ñ‹Ð»Ð° уÑпешно активирована. Ваша Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð±Ñ‹Ð»Ð° уÑпешно деактивирована и Ð’Ñ‹ Ñнова пользуетеÑÑŒ планом %s.Ваше Ð¸Ð¼Ñ Ð±Ñ‹Ð»Ð¾ уÑпешно обновленоВаш тарифный план был уÑпешно изменен на %s.Ваш тарифный план был уÑпешно изменен. Ваш теÑтовый период уÑпешно Ð½Ð°Ñ‡Ð°Ñ‚Ð˜Ð½Ð´ÐµÐºÑ Ð’Ñе верно!%s не работает без %s.%s не может работать без плагина. Внимание!ОÑталоÑÑŒ %s ÐÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð½Ð° один год APIЗакрыть УÑтранение ошибокПоздравлениÑ! Заблокировано Соединено Скачать поÑледнюю верÑиюПомеÑÑчно Срок Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÐŸÑƒÑ‚ÑŒ Электронное пиÑьмо отправлÑетÑÑ Ð’Ð°Ð¼ на почту на один меÑÑцЕжегодно Один раз в год Один раз Тарифный план Ðет Ñекрета ВерÑии SDKÐ›Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ð¸ ÐвторВыключить Включить ОÑнован на %sÐачни теÑтовый период!Закрыть Закрыть Ð”ÐµÐ°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ %s план Оплачивать %sЛучший Привет!УпÑ!ЗдравÑтвуйте %sУра!Сайтов Ð¼Ñ Ð½Ðµ подтвержден СтоимоÑÑ‚ÑŒ ЦеныВерÑÐ¸Ñ ÑекХм...Ðачать теÑтовый периодПереключение ПоÑледнÑÑ Ð²ÐµÑ€ÑÐ¸Ñ %s здеÑьТеÑтовый периодУдалитьПонизить план Редактировать СпрÑтать ПриÑоединитÑÑ ÐžÑ‚Ð¿Ð¸ÑатьÑÑ ÐšÑƒÐ¿Ð¸Ñ‚ÑŒÐŸÐ¾ÐºÐ°Ð·Ð°Ñ‚ÑŒ ПропуÑтитьОбновить Сделать апгрейд%s тому назад freemius/languages/freemius-fr_FR.mo000064400000140331146725417150013517 0ustar00Þ•T½Œ €+A+SÃ+%, =, I,U,\,6o,´¦,_[-#»-ß- ù- . ..".*.3.;.@D.H….Î.Oá.1/5/T/t/|/Œ/”/ /©/º/Ï/å/&ö/-0K0 `0j0y0Ž0¡0¨05°0æ0î0 þ0 1'1<1 U1 b1l1o}1í1žô1“2¦2"Â2å223!53aW30¹3ê3ü34"4*4>4F4O4W4 \4j4 |4ˆ4¥4¬4’À4 S5^5r5 †5 “5 5«5¼5YØ526A6 R6^6g6l6|6(•61¾6%ð6:7Q7V7g7o7 7 Š7—7­7 µ7¿7 Ä7Ï7xâ7”[8 ð8 ý89939t;9°9Ê9à9ö9ÿ9:2: N:—Y:[ñ:fM;´; º;È;YÌ;a&<ˆ<Ž<®< ¶< Ä<;Ò<==þ=> > )> 6>C>jR>½> Ì>Ö>3ß>?~'?U¦?ü?@1@)L@-v@¤@S¸@ A'$ALAMOA7AgÕAp=B®BÈByÎBHCaC CC C¶C ÉCêC òC1üC..DO]D­DA-EyoEéEa FkFBoF,²FßF äF ñFþFG 5G@GGGOG aG mGyGG4˜GÍG ÜGæGêGñGùGH H'H .H :HFH`H eH rHHƒH!™H»H ØHãHèHëH%ñH+ICI [I iI/vI¦ImªI~J—JžJ¦JÂJ ÈJÔJ ÝJ èJ)öJ K=K4FK{K5€K(¶KßKçK-þK,LU@LÈ–L1_M~‘MN[-O‰O¨O¯O ¿OÉO(ØO*P",P1OP+P*­P&ØPNÿPNQVQlQ.tQ)£QÍQÝQýQRR R 'R2R;RKR]R fRqR‚R‘R—RW°R SS-S6SQSXS\SeSmS }S‰S ›S5¦SsÜSlPT&½TäTóT UU+UDUXU`U|U ‚UŒU&‘UL¸UfVlV rV~VV •V ¡V®V ¶VÄV ÚVçV•øV–ŽW/%XUX)uX ŸX ªX\µXY'Y:YCYYY³Y…ÓYdYZ-¾ZìZ òZÿZ['%[MM[G›[ ã[í[ó[ù[þ[\E \O\b\t\‹\š\¡\*°\Û\*ã\^]m]u]{]d]æ] ï]ü] ^"^5^i=^W§^"ÿ^B"_6e_œ_ ±_¿_-Ð_þ_`&2`Y`s`w`$€`M¥`ó`/a5aoUa>Åab&bZBbTbRòb.Ec.tc9£cZÝc38d<ldb©dP eU]e_³ešfK®f(úfG#g#kg)g$¹gUÞg)4h^hph;h6Éh>i?iEi`i€i$–i»iÕiñi j&+j*Rj7}jµjÌjêj3k7kLkbkzkŽk*«k1Ökl$l#8l\lxlŠl šl¦lÆlÝl òlÿlNmWmvm”m¯m¿mÐm1ámnn/n ?n Kn Xn cnpn ˆn”nQ™nën ûn oo-o3o FoRo ao ko uo o Žo œo ¦o °o ¼o ÉoúÖohÑs":t!]tt t œt¦t>¸tÌ÷tbÄu*'vRv rv }v ‰v–v v ¨v´v¼viÄvZ.w‰wW©wxxxxx1x9x AxLxbx‚xžx1±x1ãxy(y0y@yUyoyvyB~yÁyÉy Úy æy*òyz:zNz]z~szòz¼úz·{&Ë{-ò{! |FB|!‰|}«|X)}#‚}¦} ¿} Ì}×} ë}÷}~~ ~~;~+O~{~ƒ~Áœ~ ^k‚—³»Ìànùh€{€—€ª€³€¹€$Ì€/ñ€2!9TŽ—œ°¸Ï Þì‚ ‚‚ ‚(‚x?‚¦¸‚_ƒ nƒ&xƒŸƒºƒšÃƒ$^„!ƒ„¥„À„Ñ„%í„"… 6…¿D…s†mx†æ† ì†ú†dþ†ƒc‡ç‡,#ˆ2ˆOLˆœˆ¤ˆT«ˆŠ ŠŠ 'Š4ŠxHŠÁŠ ÓŠߊKèŠ4‹T‹]ä‹!BŒ*dŒŒ0®Œ2ߌg.–1°âPå;6ŽqrŽˆäŽ(m–ž( 7I$–»×/ð ‘ (‘22‘9e‘UŸ‘Ÿõ‘5•’ªË’ v“O—“ç“sì“M`”®”¶”Í”/ß”•,•;•D•L•_•o••œ•?£•-ã• –––&–.–"7–Z–o–v––#Ÿ–ÖÇ–×–í–#õ–5— O— p—{—ƒ— ‡—6“—>Ê— ˜&˜7˜4G˜|˜ˆ€˜ˆ ™ ’™ž™%®™Ô™Ú™ñ™šš7)šaš €šPŠšÛšTãš18›j›{›1—›É›Xä›ê=œ:(°c]žnrŸ$០    -  D  N Z ^  x …  ™ Z¦ ¡) ¡3¡7;¡5s¡©¡¹¡Ø¡ß¡ ý¡¢¢,¢5¢K¢b¢ j¢x¢Œ¢¡¢§¢xÅ¢>£#W£{£„£ ¡£«£¯£Æ£Õ£ç£ù£ ¤>¤‚\¤€ß¤-`¥Ž¥ž¥0¼¥"í¥¦-¦<¦D¦_¦ e¦q¦*v¦[¡¦oý¦m§ t§‚§›§ ¡§ ®§º§§.Ó§¨! ¨³-¨¯á¨-‘©¿©(Þ©ª ªzª•ª­ª&ǪYîªH«,`«©«}7¬3µ¬é¬ð¬­ ­.-­a\­G¾­ ®®®®"®3®Y8®’®¬®Æ®ß® ñ®þ®/¯ H¯1U¯‡¯¯ —¯¤¯…«¯ 1°;°%M°s°"…° ¨°x²°j+±0–±SDZP²l²Š²£²&·²Þ²ô²* ³7³T³X³.a³c³ô³0 ´;´­Z´FµOµ"nµ‘µd!¶b†¶)é¶/·=C·k·6í·D$¸Ži¸wø¸gp¹wع«PºYüº$V»P{»Ì»-ë»(¼WB¼(š¼ ü ϼ#Û¼*ÿ¼ *½ 8½B½Q½e½l½p½ w½½½ ˜½"¢½+Žñ½ ù½¾ ¾"¾'¾.¾5¾>¾F¾^¾n¾ v¾ƒ¾›¾¢¾¦¾ ©¾¶¾о×¾Þ¾ í¾qø¾ j¿ u¿¿†¿Š¿¿—¿¿¥¿«¿®¿ ¿¿Í¿Ó¿Ú¿â¿æ¿í¿ñ¿ À À%ÀDÀJÀ [À eÀrÀzÀ ÀÀÀ¥À®À µÀ ÂÀ ÏÀ äm‡4=ˆ˜b~& 6£}°A+sìB®ŸuÑÕ[#¼HÜ _ï>€8Bè•‚öò <n…š_ÔοõÈS¤dÌr¨ Ú†±ªkÙT­5—^dMD×µ”‹:N„ëoÉ”ã(ÜÓô* Øbžuü¦Kÿ>„EêÖeâpÀ%Ž"TP 32ñª“ó~9$ûÇŠ’x©WŒàÆ;à·C°^zD|L=Š¯´Çs´jÒQæ¬ìÕJUIkXY–›Z¯Uðý÷™9§¡‘Å5]tÛô\Ÿt×»Fîh÷ÑÛ£ˆ!ʾ:¥@¼µ7whƒí {ÐŽ-p-åÏ&m¤fG…c• ÁNš/<KqCé¸ÞV½èÍÃðßR¶1Œúõ%Í¥»y“.@OSÅlgxþ þëäWR¸‡ýL)²Äù¡î§'a¹Æ4ºç¬$ØÏz–[Ë\ï2Ó{lçcÂGÚ8M‚óœ²øFQÖÞåÃ6(aË`«ÝÀæÌЀžf?A;±«oí ú}ÝHáÁ+?Ei¨›È7/XÔ¹‹3á,|*곑rÿÉOÒPJò#ü ‰VÊ]‰ùÄY˜¢ßy™Â0¦1¾`—g·ƒñ'©)œö½v,¿"ûκZ†ã0¶.ewÙqi!âI’ ¢vé³­øj®n %s to access version %s security & feature updates, and support.%s - plugin name. As complete "PluginX" activation nowComplete "%s" Activation Now%s Add-on was successfully purchased.%s Installs%s Licenses%s ago%s and its add-ons%s commission when a customer purchases a new license.%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license.%s is a premium only add-on. You have to purchase a license first before activating the plugin.%s is the new owner of the account.%s minimum payout amount.%s or higher%s rating%s ratings%s sec%s star%s stars%s time%s times%s to access version %s security & feature updates, and support.%s tracking cookie after the first visit to maximize earnings potential.%s's paid features%sClick here%s to choose the sites where you'd like to activate the license on.APIASCII arrow left icon←ASCII arrow right icon➤AccountAccount DetailsActionsActivateActivate %sActivate %s PlanActivate %s featuresActivate Free VersionActivate LicenseActivate license on all pending sites.Activate license on all sites in the network.Activate this add-onActivatedAdd Ons for %sAdd Ons of module %sAdd another domainAdd-OnAdd-OnsAdd-on must be deployed to WordPress.org or Freemius.AddressAddress Line %dAffiliateAffiliationAfter your free %s, pay as little as %sAgree & Activate LicenseAll RequestsAll TypesAllow & ContinueAlternatively, you can skip it for now and activate the license later, in your %s's network-level Account page.AmountAn automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now.Anonymous feedbackApply on all pending sites.Apply on all sites in the network.Apply to become an affiliateAre you sure you want to delete all Freemius data?Are you sure you want to proceed?As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days.Auto installation only works for opted-in users.Auto renews in %sAutomatic InstallationAverage RatingAwesomeBecome an affiliateBillingBlockingBlog IDBodyBusiness nameBuy a license nowBuy licenseCan't find your license key?CancelCancel %s & ProceedCancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.Cancel %s?Cancel InstallationCancel SubscriptionCancel TrialCancelledCancelling %sCancelling %s...Cancelling the subscriptionCancelling the trial will immediately block access to all premium features. Are you sure?Change LicenseChange OwnershipChange PlanCheckoutCityClear API CacheClear Updates TransientsClick here to use the plugin anonymouslyClick to see reviews that provided a rating of %sClick to view full-size screenshot %dClone resolution admin notice products list labelProductsCodeCompatible up toContactContact SupportContact UsContributorsCouldn't activate %s.CountryCron TypeDateDeactivateDeactivate LicenseDeactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?DeactivationDebug LogDelegate to Site AdminsDelete All AccountsDetailsDon't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.Don't have a license key?Donate to this pluginDowngrading your planDownloadDownload %s VersionDownload the latest %s versionDownload the latest versionDownloadedDue to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.During the update process we detected %d site(s) that are still pending license activation.During the update process we detected %s site(s) in the network that are still pending your attention.EmailEmail addressEndEnter the domain of your website or other websites from where you plan to promote the %s.Enter the email address you've used for the upgrade below and we will resend you the license key.ErrorError received from the server:ExpiredExpires in %sExtra DomainsExtra domains where you will be marketing the product from.FileFilterFor compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.FreeFree TrialFree versionFreemius APIFreemius DebugFreemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error.Freemius StateFull nameFunctionGet commission for automated subscription renewals.Have a license key?Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!How do you like %s so far? Test all our %s premium features with a %d-day free trial.How to upload and activate?How will you promote us?I can't pay for it anymoreI couldn't understand how to make it workI don't like to share my information with youI found a better %sI have upgraded my account but when I try to Sync the License, the plan remains %s.I no longer need the %sI only needed the %s for a short periodIDIf you click it, this decision will be delegated to the sites administrators.If you have a moment, please let us know why you are %sIf you would like to give up the ownership of the %s's account to %s click the Change Ownership button.If you'd like to use the %s on those sites, please enter your license key below and click the activation button.Important Upgrade Notice:In %sIn case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?Install Free Version NowInstall Free Version Update NowInstall NowInstall Update NowInstalling plugin: %sInvalid module ID.Invalid site details collection.InvoiceIs ActiveIt looks like the license could not be activated.It looks like the license deactivation failed.It looks like you are not in trial mode anymore so there's nothing to cancel :)It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry.It looks like your site currently doesn't have an active license.It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again.It's not what I was looking forJust letting you know that the add-ons information of %s is being pulled from an external server.KeyKindly share what didn't work so we can fix it for future users...Kindly tell us the reason so we can improve.LastLast UpdatedLast licenseLatest Free Version InstalledLatest Version InstalledLearn moreLengthLicenseLicense AgreementLicense KeyLicense keyLicense key is empty.LifetimeLike the %s? Become our ambassador and earn cash ;-)Load DB OptionLocalhostLogLoggerMessageMethodMigrate Options to NetworkMobile appsModuleModule PathModule TypeMore information about %sNameNetwork BlogNetwork UserNewNew Version AvailableNewer Free Version (%s) InstalledNewer Version (%s) InstalledNewsletterNextNoNo IDNo commitment for %s - cancel anytimeNo commitment for %s days - cancel anytime!No credit card requiredNo expirationNon-expiringNone of the %s's plans supports a trial period.O.KOnce your license expires you can still use the Free version but you will NOT have access to the %s features.Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.Opt InOpt OutOpt in to make "%s" better!OtherOwner EmailOwner IDOwner NamePCI compliantPaid add-on must be deployed to Freemius.PayPal account email addressPaymentsPayouts are in USD and processed monthly via PayPal.PlanPlan %s do not exist, therefore, can't start a trial.Plan %s does not support a trial period.Plan IDPlease contact us herePlease contact us with the following message:Please download %s.Please enter the license key that you received in the email right after the purchase:Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential).Please follow these steps to complete the upgradePlease let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.Please provide details on how you intend to promote %s (please be as specific as possible).Please provide your full name.PluginPlugin HomepagePlugin IDPlugin InstallPlugin installer section titleChangelogPlugin installer section titleDescriptionPlugin installer section titleFAQPlugin installer section titleFeatures & PricingPlugin installer section titleInstallationPlugin installer section titleOther NotesPlugin installer section titleReviewsPlugin is a "Serviceware" which means it does not have a premium code version.PluginsPlugins & Themes SyncPremiumPremium %s version was successfully activated.Premium add-on version already installed.Premium versionPremium version already active.PricingPrivacy PolicyProceedProcess IDProcessingProductsProgram SummaryPromotion methodsProvincePublic KeyPurchase LicenseQuick FeedbackQuotaRe-send activation emailRefer new customers to our %s and earn %s commission on each successful sale you refer!Renew licenseRenew your license nowRequestsRequires WordPress VersionResultSDKSDK PathSave %sScheduled CronsScreenshotsSearch by addressSecret KeySecure HTTPS %s page, running from an external domainSeems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes.Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes.Seems like you got the latest release.Select CountrySend License KeySet DB OptionSimulate Network UpgradeSimulate Trial PromotionSingle Site LicenseSite IDSite successfully opted in.SitesSkip & %sSlugSocial media (Facebook, Twitter, etc.)Sorry for the inconvenience and we are here to help if you give us a chance.Sorry, we could not complete the email update. Another user with the same email is already registered.StartStart TrialStart my free %sStateSubmit & %sSubscriptionSupportSupport ForumSync Data From ServerTax / VAT IDTerms of ServiceThank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information.Thank you so much for using %s and its add-ons!Thank you so much for using %s!Thank you so much for using our products!Thank you!Thanks %s!Thanks for confirming the ownership change. An email was just sent to %s for final approval.The %s broke my siteThe %s didn't workThe %s didn't work as expectedThe %s is great, but I need specific feature that you don't supportThe %s is not workingThe %s suddenly stopped workingThe installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page.The remote plugin package does not contain a folder with the desired slug and renaming did not work.The upgrade of %s was successfully completed.ThemeTheme SwitchThemesThere is a %s of %s available.There is a new version of %s available.This plugin has not been marked as compatible with your version of WordPress.This plugin has not been tested with your current version of WordPress.TimestampTitleTotalTownTrialTypeUnable to connect to the filesystem. Please confirm your credentials.Unlimited LicensesUnlimited UpdatesUnlimited commissions.Up to %s SitesUpdateUpdate LicenseUpdates, announcements, marketing, no spamUpgradeUpload and activate the downloaded versionUsed to express elation, enthusiasm, or triumph (especially in electronic communication).W00tUser IDUsersValueVerification mail was just sent to %s. If you can't find it after 5 min, please check your spam box.VerifiedVerify EmailVersion %s was released.View detailsView paid featuresWarningWe can't see any active licenses associated with that email address, are you sure it's the right address?We couldn't find your email address in the system, are you sure it's the right address?We made a few tweaks to the %s, %sWe're excited to introduce the Freemius network-level integration.Website, email, and social media statistics (optional)What did you expect?What feature?What is your %s?What price would you feel comfortable paying?What you've been looking for?What's the %s's name?Where are you going to promote the %s?WordPress.org Plugin PageYesYes - %sYou already utilized a trial before.You are 1-click away from starting your %1$s-day free trial of the %2$s plan.You are all good!You are already running the %s in a trial mode.You are just one step away - %sYou can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.You do not have a valid license to access the premium version.You have a %s license.You have successfully updated your %s.You might have missed it, but you don't have to share any data and can just %s the opt-in.You've already opted-in to our usage-tracking, which helps us keep improving the %s.You've already opted-in to our usage-tracking, which helps us keep improving them.Your %s Add-on plan was successfully upgraded.Your %s free trial was successfully cancelled.Your account was successfully activated with the %s plan.Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s.Your affiliation account was temporarily suspended.Your email has been successfully verified - you are AWESOME!Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your free trial has expired. You can still continue using all our free features.Your license has been cancelled. If you think it's a mistake, please contact support.Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions.Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support.Your license has expired. You can still continue using the free %s forever.Your license was successfully activated.Your license was successfully deactivated, you are back to the %s plan.Your name was successfully updated.Your plan was successfully changed to %s.Your plan was successfully upgraded.Your subscription was successfully cancelled. Your %s plan license will expire in %s.Your trial has been successfully started.ZIP / Postal Codea positive responseRight onaddonX cannot run without pluginY%s cannot run without %s.addonX cannot run...%s cannot run without the plugin.advance notice of something that will need attention.Heads upallowas 5 licenses left%s leftas activating pluginActivatingas annual periodyearas application program interfaceAPIas close a windowDismissas code debuggingDebuggingas congratulationsCongratsas connection blockedBlockedas connection was successfulConnectedas download latest versionDownload Latestas download latest versionDownload Latest Free Versionas every monthMonthlyas expiration dateExpirationas file/folder pathPathas in the process of sending an emailSending emailas monthly periodmoas once a yearAnnualas once a yearAnnuallyas once a yearOnceas product pricing planPlanas secret encryption key missingNo Secretas software development kit versionsSDK Versionsas software licenseLicenseas synchronizeSyncas synchronize licenseSync Licenseas the plugin authorAuthoras turned offOffas turned onOnbased on %scall to actionStart free trialclose a windowDismissclose windowDismissdeactivatingdelegatedo %sNOT%s send me security & feature updates, educational content and offers.e.g. Professional Plan%s Plane.g. billed monthlyBilled %se.g. the best productBestexclamationHeyexclamationOopsgreetingHey %s,interjection expressing joy or exuberanceYee-hawlicenselike websitesSitesmillisecondsmsnew versionnot verifiednounPricenounPricingproduct versionVersionsecondssecskipsomething somebody says when they are thinking about what you have just said.Hmmstart the trialsubscriptionswitchingthe latest %s version heretrialtrial periodTrialverbDeleteverbDowngradeverbEditverbHideverbOpt InverbOpt OutverbPurchaseverbShowverbSkipverbUpdateverbUpgradex-ago%s agoProject-Id-Version: WordPress SDK Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues PO-Revision-Date: 2023-04-19 18:31+0530 Last-Translator: Boris Colombier , 2018 Language-Team: French (France) (http://www.transifex.com/freemius/wordpress-sdk/language/fr_FR/) Language: fr_FR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2; X-Poedit-Basepath: .. X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c X-Poedit-SourceCharset: UTF-8 X-Generator: Poedit 3.2.2 X-Poedit-SearchPath-0: . X-Poedit-SearchPathExcluded-0: *.js %s pour accéder aux mises à jour de sécurité et de fonctionnalités de la version %s, et au support.Compléter "%s" Activer MaintenantL'Add-on %s a bien été acheté.%s Installations%s LicencesIl y a %s%s et ses add-onsCommission de %s quand un client achète une nouvelle licence.La période d'essai du %s a bien été annulé. L'add-on a été désactivé car il ne fonctionne qu'avec la version premium. Si vous souhaitez l'utiliser ultérieurement, vous devrez acheter une licence.%sest un add-on pour la version premium. Vous devez acheter une licence avant d'activer le plugin.%s est le nouveau propriétaire du compte.Montant de paiement minimum %s.%s ou plus%s notation%snotations %s sec%s étoile%s étoiles%s fois%s fois%s pour permettre les mises à jour de sécurité et de fonctionnalités de la version %s, et le support.Cookie de tracking de %s après la première visite pour maximiser les potentiels de gain.Fonctionnalités payantes de %s%sCliquez ici %s pour choisir les sites sur lesquels vous souhaitez activer la licence.API←➤CompteDétails du compteActionsActiverActiver %sActiver la formule %sActiver les fonctionnalités %sActivez la version gratuiteActiver la licenceActiver la licence sur tous les sites en attente.Activer la licence sur tous les sites du réseau.Activer cet add-onActivéAdd Ons pour %sAdd Ons du module %sAjouter une autre adresseAdd-OnAdd-OnsLes add-ons doivent être déposés sur WordPress.org ou Freemius.AdresseAdresse ligne %dAffiliationAffiliationAprès vos %s gratuits, payez seulement %sValider & Activer la licenceToutes les demandesTous les typesAutoriser & ContinuerÉventuellement, vous pouvez l'ignorer pour l'instant et activer la licence plus tard, sur votre page de compte du réseau %s.MontantUn téléchargement et une installation automatique de %s (version premium) de %s va commencer dans %s. Si vous voulez le faire manuellement, cliquez sur le bouton d'annulation maintenant.Commentaire anonymeActiver sur tous les sites en attente.Effectuer sur tous les sites dans le réseau.Postuler pour devenir un affiliéÊtes-vous sûr de vouloir supprimer toutes les données de Freemius ?Êtes-vous de vouloir continuer ?Comme nous bloquons sur 30 jours pour les remboursements éventuels, seules sont payées les commissions de plus de 30 jours.L'installation automatique ne fonctionne que pour les utilisateurs qui se sont inscrits.Renouvellements automatique dans %sInstallation automatiqueNote moyenneFormidableDevenir un affiliéFacturationBloquantBlog IDBodyRaison socialeAcheter une licence maintenantAcheter une licenceVous ne trouvez pas votre clef de licence ?AnnulerAnnuler %s et poursuivreAnnuler %s - Je n'ai plus besoin de mises à jour de sécurité et de fonctionnalités, ni de support pour %s parce que je n'ai pas l'intention d'utiliser le %s sur ce site, ou tout autre site.Annuler %s ?Annuler l'installationAnnuler l'abonnementAnnuler la période d'essaiAnnuléAnnulation de %sAnnulation de %s...Annuler votre abonnementAnnuler la période d'essai va immédiatement bloquer les fonctionnalités premium. Souhaitez-vous continuer ?Changer la licenceChangement De PropriétaireChanger de formulePaiementVilleVider le cache APIVider les transients de mise à jourCliquer ici pour utiliser le plugin anonymementCliquez pour voir les avis avec une notation de %sCliquez pour voir la capture d'écran %d en pleine tailleProduitsCodeCompatible jusqu'àContactContacter l'AssistanceContactez NousContributeursImpossible d'activer %s.PaysType de CronDateDésactiverDésactiver la licenceDésactiver ou désinstaller le %s désactivera automatiquement la licence, que vous pourrez utiliser sur un autre site.Désactiver la licence bloquera toutes les fonctionnalités premium mais vous permettra d'activer la licence sur un autre site. Êtes-vous sûr de vouloir continuer ?DésactivationDebug LogDéléguer aux administrateurs du siteSupprimer tous les comptesDétailsNe pas annuler %s - Je veux toujours recevoir les mises à jour de sécurité et de fonctionnalités, ainsi que d'être en mesure de contacter le support.Vous n'avez pas de clef de licence ?Faire une donation pour ce pluginRétrograder votre formuleTéléchargementTélécharger la version %sTélécharger la dernière version %sTélécharger la dernière versionTéléchargéSuite à une violation de nos conditions d'affiliation, nous avons décidé de bloquer temporairement votre compte d'affilié. Si vous avez la moindre question, merci de contacter le support.Durant le processus de mise à jour nous avons détecté %d site(s) toujours en attente d'activation de la licence.Durant le processus de mise à jour nous avons détecté %s site(s) dans le réseau que vous devez vérifier.EmailAdresse emailFinIndiquez l'adresse de votre site ou d'autres sites sur lesquels vous pensez faire la promotion du %sIndiquez ci-dessous l'adresse email que vous avez utilisez pour la mise à jour et nous allons vous renvoyer le code de la licence.ErreurUne erreur a été reçu depuis le serveur :ExpiréExpire dans %sAdresses supplémentairesAdresses supplémentaires depuis lesquelles vous ferez la promotion du produit.FichierFilterPour être en accord avec les directives de WordPress.org, avant que nous commencions la période d'essai, nous vous demandons de nous permettre de récupérer votre nom d'utilisateur et des informations non sensibles du site afin de permettre au %s de communiquer avec %s pour vérifier les mises à jour et valider votre période d'essai.GratuitEssai gratuitVersion gratuiteAPI FreemiusDébuggage FreemiusLe SDK Freemius ne trouve pas le fichier principal du plugin. Merci de contacter sdk@freemius.com en indiquant l'erreur.État de FreemiusNom completFonctionObtenez des commissions pour les renouvellements automatiques d'abonnement.Vous avez une clef de licence ?Dites, savez-vous que %s propose un système de affiliation ? Si vous aimez le %s vous pouvez devenir notre ambassadeur et gagner de l'argent !Que pensez-vous de %s ? Testez nos %s fonctionnalités premium avec %d jours d'essai gratuit.Comment téléverser et activer ?Comment allez-vous faire de la promotion ?Je ne peux plus payer pour çaJe ne comprends pas comment le faire fonctionnerJe ne veux pas partager mes informations avec vousJ'ai trouvé un meilleur %sJ'ai mis à jour mon compte mais quand j'essaie de synchroniser la licence, la formule est toujours %s.Je n'ai plus besoin du %sJe n'ai besoin de %s que pour une courte périodeIDSi vous cliquez, cette décision sera déléguée aux administrateurs des sites.Si vous avez un instant, merci de nous indiquer pourquoi %sSi vous voulez transférer la propriété du compte de %s à %s cliquez sur le bouton Changement De PropriétaireSi vous voulez utiliser le %s sur ces sites, merci d'indiquer votre clé de licence ci-dessous et de cliquer sur le bouton d'activation.Information importante de mise à jour :Dans %sDans le cas où vous n'avez PAS l'intention d'utiliser ce %s sur ce site (ou tout autre site) - voulez-vous aussi annuler le %s ?Installer la version gratuite maintenantInstaller la dernière mise à jour gratuite maintenantInstaller maintenantInstaller la mise à jour maintenantInstallation du plugin : %sID du module non valide.Récupération des détails du site non valide.FactureEst actifIl semble que la licence ne puisse être activée.Il semble que la désactivation de la licence a échoué.Il semble que vous ne soyez plus en période d'essai donc il n'y a rien à annuler :)Il semble que vous soyez encore sur la formule %s. Si vous avez mis à jour ou changer votre formule, le problème est probablement de votre côté - désolé.Il semble que votre site n'ait pas de licence active.Il semble que l'un des paramètres d'authentification soit faux. Veuillez mettre à jour votre Public Key, votre Secret Key ainsi que vote User ID et essayez à nouveau.Ce n'est pas ce que je rechercheSachez que les informations de l'add-ons de %s sont issus d'un serveur externe.ClefMerci de nous indiquer ce qui ne fonctionne pas afin que nous puissions le corriger pour les futurs utilisateurs...S'il vous plait, dites nous pourquoi afin que nous puissions nous améliorer.DernierDernière mise à jourDernière licenceLa dernière version gratuite a été installéDernière Version InstalléeEn savoir plusLongueurLicenceContrat de licenceClef de licenceClef de licenceLa clé de licence est vide.À vieVous aimez %s ? Devenez notre ambassadeur et gagnez du cash ;-)Chargement des options de la base de donnéesLocalhostLogLoggerMessageMéthodeMigrer les options vers le réseauApplications mobilesModuleChemin d'accès du moduleType de modulePlus d'informations à propos de %sNomRéseau de BlogRéseau d'UtilisateurNouveauUne nouvelle version est disponibleLa nouvelle version gratuite ( %s ) a été installéNouvelle Version (%s) InstalléeNewsletterSuivantNonID manquantPas d'engagement durant %s - annuler quand vous voulezPas d'engagement durant %s jours - annuler quand vous voulez !Pas besoin de carte bancairePas d'expirationSans expirationAucune formule du %s ne propose de période d'essai.O.KUne fois la licence expirée vous pourrez toujours utiliser la version gratuite mais vous n'aurez PAS accès aux fonctionnalités de %s.Une fois votre licence expirée, vous ne pourrez plus utiliser le %s, sauf si vous l'activez à nouveau avec une licence premium valide.InscriptionDésinscriptionInscrivez-vous pour améliorer "%s" !AutreEmail du propriétaireID du propriétaireNom du propriétaireCompatible PCILes add-ons payant doivent être déposés sur FreemiusAdresse email du compte PayPalPaiementsLes paiements se font en Dollars US et sont effectués mensuellement via PayPal.FormuleLa formule %s n'existe pas, il n'est pas possible de commencer une période d'essai.La formule %s ne propose pas de période d'essai.ID de la formuleMerci de nous contacter iciMerci de nous contacter avec le message suivant :Merci de télécharger %s.Merci d'indiquer le code de licence que vous avez reçu par email juste après l'achat :N'hésitez pas à indiquer des statistiques pertinentes concernant votre site ou vos réseaux sociaux telles que le nombre de visiteurs mensuel, le nombre d'abonnés, de followers, etc... (C'est informations resteront confidentielles)Merci de suivre ces étapes pour finaliser la mise à jourMerci de nous indiquer si vous souhaitez que nous vous contactions pour les mises à jour de sécurité et de fonctionnalités, du contenu instructif et des offres spéciales :Veuillez noter que nous ne serons pas en mesure de garantir le maintien des prix actuels pour les renouvellements/nouveaux abonnements après une annulation. Si vous choisissez de renouveler l'abonnement manuellement à l'avenir, après une augmentation de prix, qui se produit généralement une fois par an, le prix mis à jour vous sera facturé.Merci d'indiquer en détail comment vous allez faire la promotion du %s (en étant aussi précis que possible)Merci d'indiquer vos prénom et nom.PluginSite Web du pluginID du pluginInstallation du PluginChangelogDescriptionFAQFonctionnalités & TarifsInstallationAutres InformationsCommentairesLe plugin est un "Serviceware" ce qui veut dire qu'il n'a pas de version premium de code.PluginsSynchronisation des plugin et des thèmesPremiumLa version premium de %s a été activée avec succès.La version premium de l'add-on est déjà installée.Version premiumVersion premium déjà active.TarifsPolitique de confidentialitéPoursuivreID du processusTraitement en coursProduitsSommaire du programmeMéthodes de promotionRégionClef publiqueAcheter une licenceCommentaires rapidesQuotaRenvoyer l'email d'activationParrainez des nouveaux clients pour notre %s et gagnez une commission de %s sur chaque vente réussie que vous affiliez.Renouvelez votre licenceRenouvelez votre licence maintenantDemandesVersion de WordPress requiseRésultatSDKChemin d'accès du SDKÉconomisez %sCrons programmésCaptures d'écranRecherche par adresseClef secrêtePage %s sécurisée HTTPS, s'exécutant sur un domaine externeIl semble que nous ayons un problème temporaire avec l'annulation de votre abonnement. Merci de réessayer dans quelques minutes.Il semble que nous ayons un problème temporaire pour annuler votre période d'essai. Merci de réessayer dans quelques minutes.Il semble que vous ayez la dernière version.Choisir le paysEnvoyer le code de la licenceMise en place des options de la base de donnéesSimuler la mise à jour du réseauSimuler la promotion d'essaiLicence 1 siteSite IDSite ajouté avec succès.SitesPasser & %sSlugRéseaux sociaux (Facebook, Twitter, etc.)Désolé pour le dérangement et nous sommes là pour vous aider si vous nous le permettez.Désolé, nous ne pouvons pas mettre à jour l'email. Il existe déjà un autre utilisateur avec cette adresse.DébutEssai gratuitCommencer ma %s gratuiteÉtatEnvoyer & %sInscriptionSupportForum de SupportSynchronisation des données depuis le serveurCode TVAConditions générales de serviceMerci d'avoir postulé à notre programme d'affiliation, malheureusement, nous avons décidé pour le moment de décliner votre dossier. Merci d'essayer à nouveau d'ici 30 jours.Merci d'avoir postulé à notre programme d'affiliation, nous regarderons votre dossier durant les 14 prochains jours et nous reviendrons vers vous avec d'autres informations.Merci beaucoup d'utiliser %s et ses add-ons !Merci beaucoup d'utiliser %s !Merci beaucoup d'utiliser nos produits !Merci !Merci %s !Merci pour la confirmation du changement de propriétaire. Un email vient d'être envoyé à %s pour la validation finale.Le %s a cassé mon siteLe %s n'a pas fonctionnéLe %s n'a pas fonctionné comme prévuLe %s est bien mais j'ai besoin de fonctionnalités spécifiques que vous ne proposez pasLe %s ne fonctionne pasLe %s a soudainement arrêté de fonctionnerL'installation a commencé et peut prendre quelques minutes pour se finir. Merci de patienter jusqu'à ce qu'elle soit terminée - veuillez ne pas rafraichir cette page.Le package du plugin à télécharger ne contient pas de dossier avec le bon slug et iln'a pas été possible de le renommer.La mise à jour du %s s'est terminée avec succès ThèmeChangement de ThèmeThèmesIl y a une %s de %s disponible.Il y a une nouvelle version disponible de %s. Ce plugin n'a pas été indiqué comme étant compatible avec votre version actuelle de WordPressCe plugin n'a pas été testé avec votre actuelle version de WordPressTimestampTitreTotalVillePériode d'essaiTypeImpossible de se connecter au système de fichiers. Merci de confirmer vos autorisations.Licences sites illimitésMises à jour illimitéesCommissions illimitées.Jusqu'à %s SitesMise à jourMettre à jour la licenceMises à jour, annonces, marketing, pas de spamMise à jourTéléverser et activer la version téléchargéeGénialUser IDUtilisateursValeurUn email de vérification vient d'être envoyé sur %s. Si vous ne le recevez pas d'ici 5 minutes, merci de vérifier dans vos spams.VérifiéVérifier l'emailLa version %s vient d'être publiée.Voir les détailsVoir les fonctionnalités payantesAttentionNous ne trouvons aucune licence active associée avec cette adresse email, êtes-vous qu'il s'agit de la bonne adresse ?Nous ne trouvons pas votre adresse mail dans notre système, êtes-vous qu'il s'agit de la bonne adresse ?Nous avons fait quelques modifications au %s, %sNous sommes impatient de vous présenter l'intégration Freemius au niveau réseau.Statistiques du site web, de l'adresse email et des réseaux sociaux (optionnel)À quoi vous attendiez-vous ?Quelle fonctionnalité ?Quel est votre %s ?Quel prix seriez-vous prêt à payer ?Que recherchez-vous ?Quel est le nom du %s ?Où allez-vous faire la promotion du %s ? Page WordPress.org du pluginOuiOui - %sVous avez déjà utilisé la période d'essai.Vous êtes à 1 clic de commencer votre période d'essai gratuite de %1$s jours de la formule %2$s.Vous êtes tout bon !Vous utilisez déjà le %s en période d'essai. Il ne reste qu'une étape - %sVous pouvez toujours profiter de toutes les fonctionnalités de %s mais vous n'aurez plus accès aux mises à jour de sécurité ou de fonctionnalités de %s, ni au support.Vous n'avez pas de licence valide pour accéder à la version premium.Vous avez une license pour %s.Votre %s a bien été mis à jour.Peut-être que cela vous a échappé mais vous n'êtes pas obligé de partager la moindre information et vous pouvez juste %s l'enregistrement.Vous avez déjà validé notre suivi d'utilisation qui nous permet de continuer à améliorer le %s.Vous avez déjà validé notre suivi d'utilisation qui nous permet de continuer à les améliorer.Votre Add-on %s a bien été mis à jour.Votre période d'essai %s a bien été annulé.Votre compte a été activé avec succès avec la formule %s.Votre dossier d'affiliation pour %s a été accepté ! Identifiez-vous dans votre espace affilié sur : %s.Votre compte affilié a été suspendu temporairement.Votre email a été vérifié avec succès - vous êtes FORMIDABLE !Votre période d'essai gratuite est terminée. %1$sFaites la mise à jour maintenant%2$s pour continuer à utiliser le %3$s sans interruption.Votre période d'essai gratuite est terminée. Vous pouvez continuer à utiliser toutes nos fonctionnalités gratuites.Votre licence a été annulé. Si vous pensez qu'il s'agit d'une erreur, merci de contacter le support.Votre licence a expiré.%1$sFaites la mise à jour maintenant%2$s pour continuer à utiliser le %3$s sans interruption.Votre licence a expiré. Vous pouvez toujours utiliser les fonctionnalités %s mais vous devrez renouveler votre licence pour recevoir les mises à jour et une assistance.Votre licence a expiré. Vous pouvez toujours utiliser la version gratuite indéfiniment.Votre licence a bien été activée.Votre licence a bien été désactivé, vous utilisez à présent la formule %s.Votre nom a été mis à jour.Votre formule a bien été modifié vers %s. Votre formule a bien été mise à jour.Votre abonnement a bien été annulé. Votre licence de la formule %s expirera dans %s.Votre période d'essai a bien démarré.Code postalDirectement%s ne peut pas fonctionner sans %s.%s ne peut pas fonctionner sans le plugin.Avertissementautoriser%s restante(s)Activation en coursannéeAPIFermerDebuggageFélicitationsBloquéConnectéTélécharger la dernière versionTélécharger la dernière version gratuiteMensuelExpirationCheminEmail en cours d'envoimoisAnnuelAnnuelUne foisFormuleClef secrète manquanteVersions du SDKLicenceSynchroniserSynchroniser la licenceAuteurOffOnBasé sur %sCommencer l'essai gratuitFermerFermerDésactivationdéléguerne %sPAS%s m'envoyer de mises à jour de sécurité ou de fonctionnalités, ni de contenu instructif, ni d'offre.Formule %s%s FacturéBestHeyOupsHey %s,YoupilicenceSitesmsNouvelle versionNon vérifiéTarifTarifsVersionsecpasserHmmcommencer la période d'essaiabonnementChangementla dernière version de %s iciessaiPériode d'essaiSupprimerRétrograderÉditerCacherInscriptionDésinscriptionAcheterAfficherPasserMise à jourMise à jourIl y a %sfreemius/languages/freemius.pot000064400000232004146725417150012711 0ustar00# Copyright (C) 2023 freemius # This file is distributed under the same license as the freemius package. msgid "" msgstr "" "Project-Id-Version: freemius\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language-Team: Freemius Team \n" "Last-Translator: Vova Feldman \n" "Report-Msgid-Bugs-To: https://github.com/Freemius/wordpress-sdk/issues\n" "X-Poedit-Basepath: ..\n" "X-Poedit-KeywordsList: get_text_inline;fs_text_inline;fs_echo_inline;fs_esc_js_inline;fs_esc_attr_inline;fs_esc_attr_echo_inline;fs_esc_html_inline;fs_esc_html_echo_inline;get_text_x_inline:1,2c;fs_text_x_inline:1,2c;fs_echo_x_inline:1,2c;fs_esc_attr_x_inline:1,2c;fs_esc_js_x_inline:1,2c;fs_esc_js_echo_x_inline:1,2c;fs_esc_html_x_inline:1,2c;fs_esc_html_echo_x_inline:1,2c\n" "X-Poedit-SearchPath-0: .\n" "X-Poedit-SearchPathExcluded-0: *.js\n" "X-Poedit-SourceCharset: UTF-8\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: includes/class-freemius.php:1748, templates/account.php:947 msgid "An update to a Beta version will replace your installed version of %s with the latest Beta release - use with caution, and not on production sites. You have been warned." msgstr "" #: includes/class-freemius.php:1755 msgid "Would you like to proceed with the update?" msgstr "" #: includes/class-freemius.php:1980 msgid "Freemius SDK couldn't find the plugin's main file. Please contact sdk@freemius.com with the current error." msgstr "" #: includes/class-freemius.php:1982, includes/fs-plugin-info-dialog.php:1517 msgid "Error" msgstr "" #: includes/class-freemius.php:2428 msgid "I found a better %s" msgstr "" #: includes/class-freemius.php:2430 msgid "What's the %s's name?" msgstr "" #: includes/class-freemius.php:2436 msgid "It's a temporary %s - I'm troubleshooting an issue" msgstr "" #: includes/class-freemius.php:2438 msgid "Deactivation" msgstr "" #: includes/class-freemius.php:2439 msgid "Theme Switch" msgstr "" #: includes/class-freemius.php:2448, templates/forms/resend-key.php:24, templates/forms/user-change.php:29 msgid "Other" msgstr "" #: includes/class-freemius.php:2456 msgid "I no longer need the %s" msgstr "" #: includes/class-freemius.php:2463 msgid "I only needed the %s for a short period" msgstr "" #: includes/class-freemius.php:2469 msgid "The %s broke my site" msgstr "" #: includes/class-freemius.php:2476 msgid "The %s suddenly stopped working" msgstr "" #: includes/class-freemius.php:2486 msgid "I can't pay for it anymore" msgstr "" #: includes/class-freemius.php:2488 msgid "What price would you feel comfortable paying?" msgstr "" #: includes/class-freemius.php:2494 msgid "I don't like to share my information with you" msgstr "" #: includes/class-freemius.php:2515 msgid "The %s didn't work" msgstr "" #: includes/class-freemius.php:2525 msgid "I couldn't understand how to make it work" msgstr "" #: includes/class-freemius.php:2533 msgid "The %s is great, but I need specific feature that you don't support" msgstr "" #: includes/class-freemius.php:2535 msgid "What feature?" msgstr "" #: includes/class-freemius.php:2539 msgid "The %s is not working" msgstr "" #: includes/class-freemius.php:2541 msgid "Kindly share what didn't work so we can fix it for future users..." msgstr "" #: includes/class-freemius.php:2545 msgid "It's not what I was looking for" msgstr "" #: includes/class-freemius.php:2547 msgid "What you've been looking for?" msgstr "" #: includes/class-freemius.php:2551 msgid "The %s didn't work as expected" msgstr "" #: includes/class-freemius.php:2553 msgid "What did you expect?" msgstr "" #: includes/class-freemius.php:3641, templates/debug.php:24 msgid "Freemius Debug" msgstr "" #: includes/class-freemius.php:4755 msgid "You have purchased a %s license." msgstr "" #: includes/class-freemius.php:4759 msgid " The %s's %sdownload link%s, license key, and installation instructions have been sent to %s. If you can't find the email after 5 min, please check your spam box." msgstr "" #: includes/class-freemius.php:4769, includes/class-freemius.php:21125, includes/class-freemius.php:24783 msgctxt "interjection expressing joy or exuberance" msgid "Yee-haw" msgstr "" #: includes/class-freemius.php:4783 msgctxt "addonX cannot run without pluginY" msgid "%s cannot run without %s." msgstr "" #: includes/class-freemius.php:4784 msgctxt "addonX cannot run..." msgid "%s cannot run without the plugin." msgstr "" #: includes/class-freemius.php:4786, includes/class-freemius.php:5978, includes/class-freemius.php:13730, includes/class-freemius.php:14469, includes/class-freemius.php:18281, includes/class-freemius.php:18394, includes/class-freemius.php:18571, includes/class-freemius.php:20856, includes/class-freemius.php:21955, includes/class-freemius.php:22971, includes/class-freemius.php:23101, includes/class-freemius.php:23231, templates/add-ons.php:57 msgctxt "exclamation" msgid "Oops" msgstr "" #: includes/class-freemius.php:5065 msgid "There was an unexpected API error while processing your request. Please try again in a few minutes and if it still doesn't work, contact the %s's author with the following:" msgstr "" #: includes/class-freemius.php:5645 msgid "Premium %s version was successfully activated." msgstr "" #: includes/class-freemius.php:5657, includes/class-freemius.php:7692 msgctxt "Used to express elation, enthusiasm, or triumph (especially in electronic communication)." msgid "W00t" msgstr "" #: includes/class-freemius.php:5672 msgid "You have a %s license." msgstr "" #: includes/class-freemius.php:5961 msgid "%s free trial was successfully cancelled. Since the add-on is premium only it was automatically deactivated. If you like to use it in the future, you'll have to purchase a license." msgstr "" #: includes/class-freemius.php:5965 msgid "%s is a premium only add-on. You have to purchase a license first before activating the plugin." msgstr "" #: includes/class-freemius.php:5974, templates/add-ons.php:186, templates/account/partials/addon.php:386 msgid "More information about %s" msgstr "" #: includes/class-freemius.php:5975 msgid "Purchase License" msgstr "" #. translators: %3$s: action (e.g.: "start the trial" or "complete the opt-in") #: includes/class-freemius.php:6971 msgid "You should receive a confirmation email for %1$s to your mailbox at %2$s. Please make sure you click the button in that email to %3$s." msgstr "" #: includes/class-freemius.php:6974 msgid "start the trial" msgstr "" #: includes/class-freemius.php:6975, templates/connect.php:218 msgid "complete the opt-in" msgstr "" #: includes/class-freemius.php:6977 msgid "Thanks!" msgstr "" #. translators: %3$s: What the user is expected to receive via email (e.g.: "the installation instructions" or "a license key") #: includes/class-freemius.php:6980 msgid "You should receive %3$s for %1$s to your mailbox at %2$s in the next 5 minutes." msgstr "" #: includes/class-freemius.php:6983 msgctxt "Part of the message telling the user what they should receive via email." msgid "the installation instructions" msgstr "" #: includes/class-freemius.php:6989 msgctxt "Part of the message telling the user what they should receive via email." msgid "a license key" msgstr "" #: includes/class-freemius.php:6997 msgid "%s to activate the license once you get it." msgstr "" #: includes/class-freemius.php:7005 msgctxt "Part of an activation link message." msgid "Click here" msgstr "" #: includes/class-freemius.php:7012 msgctxt "Part of the message that tells the user to check their spam folder for a specific email." msgid "the product's support email address" msgstr "" #: includes/class-freemius.php:7018 msgid "If you didn't get the email, try checking your spam folder or search for emails from %4$s." msgstr "" #: includes/class-freemius.php:7020 msgid "Thanks for upgrading." msgstr "" #: includes/class-freemius.php:7156 msgid "You are just one step away - %s" msgstr "" #: includes/class-freemius.php:7159 msgctxt "%s - plugin name. As complete \"PluginX\" activation now" msgid "Complete \"%s\" Activation Now" msgstr "" #: includes/class-freemius.php:7241 msgid "We made a few tweaks to the %s, %s" msgstr "" #: includes/class-freemius.php:7245 msgid "Opt in to make \"%s\" better!" msgstr "" #: includes/class-freemius.php:7691 msgid "The upgrade of %s was successfully completed." msgstr "" #: includes/class-freemius.php:10441, includes/class-fs-plugin-updater.php:1100, includes/class-fs-plugin-updater.php:1315, includes/class-fs-plugin-updater.php:1322, templates/auto-installation.php:32 msgid "Add-On" msgstr "" #: includes/class-freemius.php:10443, templates/account.php:411, templates/account.php:419, templates/debug.php:399, templates/debug.php:619 msgid "Plugin" msgstr "" #: includes/class-freemius.php:10444, templates/account.php:412, templates/account.php:420, templates/debug.php:399, templates/debug.php:619, templates/forms/deactivation/form.php:107 msgid "Theme" msgstr "" #: includes/class-freemius.php:13549 msgid "An unknown error has occurred while trying to toggle the license's white-label mode." msgstr "" #: includes/class-freemius.php:13563 msgid "Your %s license was flagged as white-labeled to hide sensitive information from the WP Admin (e.g. your email, license key, prices, billing address & invoices). If you ever wish to revert it back, you can easily do it through your %s. If this was a mistake you can also %s." msgstr "" #: includes/class-freemius.php:13568, templates/account/partials/disconnect-button.php:84 msgid "User Dashboard" msgstr "" #: includes/class-freemius.php:13569 msgid "revert it now" msgstr "" #: includes/class-freemius.php:13627 msgid "An unknown error has occurred while trying to set the user's beta mode." msgstr "" #: includes/class-freemius.php:13701 msgid "Invalid new user ID or email address." msgstr "" #: includes/class-freemius.php:13731 msgid "Sorry, we could not complete the email update. Another user with the same email is already registered." msgstr "" #: includes/class-freemius.php:13732 msgid "If you would like to give up the ownership of the %s's account to %s click the Change Ownership button." msgstr "" #: includes/class-freemius.php:13739 msgid "Change Ownership" msgstr "" #: includes/class-freemius.php:14336 msgid "Invalid site details collection." msgstr "" #: includes/class-freemius.php:14456 msgid "We couldn't find your email address in the system, are you sure it's the right address?" msgstr "" #: includes/class-freemius.php:14458 msgid "We can't see any active licenses associated with that email address, are you sure it's the right address?" msgstr "" #: includes/class-freemius.php:14756 msgid "Account is pending activation. Please check your email and click the link to activate your account and then submit the affiliate form again." msgstr "" #: includes/class-freemius.php:14870, templates/forms/premium-versions-upgrade-handler.php:47 msgid "Buy a license now" msgstr "" #: includes/class-freemius.php:14882, templates/forms/premium-versions-upgrade-handler.php:46 msgid "Renew your license now" msgstr "" #: includes/class-freemius.php:14886 msgid "%s to access version %s security & feature updates, and support." msgstr "" #: includes/class-freemius.php:17621 msgid "%s opt-in was successfully completed." msgstr "" #: includes/class-freemius.php:17635 msgid "Your account was successfully activated with the %s plan." msgstr "" #: includes/class-freemius.php:17645, includes/class-freemius.php:21566 msgid "Your trial has been successfully started." msgstr "" #: includes/class-freemius.php:18279, includes/class-freemius.php:18392, includes/class-freemius.php:18569 msgid "Couldn't activate %s." msgstr "" #: includes/class-freemius.php:18280, includes/class-freemius.php:18393, includes/class-freemius.php:18570 msgid "Please contact us with the following message:" msgstr "" #: includes/class-freemius.php:18389, templates/forms/data-debug-mode.php:162 msgid "An unknown error has occurred." msgstr "" #: includes/class-freemius.php:18931, includes/class-freemius.php:24339 msgid "Upgrade" msgstr "" #: includes/class-freemius.php:18937 msgid "Start Trial" msgstr "" #: includes/class-freemius.php:18939 msgid "Pricing" msgstr "" #: includes/class-freemius.php:19019, includes/class-freemius.php:19021 msgid "Affiliation" msgstr "" #: includes/class-freemius.php:19049, includes/class-freemius.php:19051, templates/account.php:264, templates/debug.php:366 msgid "Account" msgstr "" #: includes/class-freemius.php:19065, includes/class-freemius.php:19067, includes/customizer/class-fs-customizer-support-section.php:60 msgid "Contact Us" msgstr "" #: includes/class-freemius.php:19078, includes/class-freemius.php:19080, includes/class-freemius.php:24353, templates/account.php:134, templates/account/partials/addon.php:49 msgid "Add-Ons" msgstr "" #: includes/class-freemius.php:19114 msgctxt "ASCII arrow left icon" msgid "←" msgstr "" #: includes/class-freemius.php:19114 msgctxt "ASCII arrow right icon" msgid "➤" msgstr "" #: includes/class-freemius.php:19116, templates/pricing.php:110 msgctxt "noun" msgid "Pricing" msgstr "" #: includes/class-freemius.php:19329, includes/customizer/class-fs-customizer-support-section.php:67 msgid "Support Forum" msgstr "" #: includes/class-freemius.php:20350 msgid "Your email has been successfully verified - you are AWESOME!" msgstr "" #: includes/class-freemius.php:20351 msgctxt "a positive response" msgid "Right on" msgstr "" #: includes/class-freemius.php:20857 msgid "seems like the key you entered doesn't match our records." msgstr "" #: includes/class-freemius.php:20881 msgid "Debug mode was successfully enabled and will be automatically disabled in 60 min. You can also disable it earlier by clicking the \"Stop Debug\" link." msgstr "" #: includes/class-freemius.php:21116 msgid "Your %s Add-on plan was successfully upgraded." msgstr "" #: includes/class-freemius.php:21118 msgid "%s Add-on was successfully purchased." msgstr "" #: includes/class-freemius.php:21121 msgid "Download the latest version" msgstr "" #: includes/class-freemius.php:21239 msgid "It seems like one of the authentication parameters is wrong. Update your Public Key, Secret Key & User ID, and try again." msgstr "" #: includes/class-freemius.php:21239, includes/class-freemius.php:21636, includes/class-freemius.php:21737, includes/class-freemius.php:21824 msgid "Error received from the server:" msgstr "" #: includes/class-freemius.php:21470, includes/class-freemius.php:21742, includes/class-freemius.php:21795, includes/class-freemius.php:21902 msgctxt "something somebody says when they are thinking about what you have just said." msgid "Hmm" msgstr "" #: includes/class-freemius.php:21483 msgid "It looks like you are still on the %s plan. If you did upgrade or change your plan, it's probably an issue on our side - sorry." msgstr "" #: includes/class-freemius.php:21484, templates/account.php:136, templates/add-ons.php:250, templates/account/partials/addon.php:51 msgctxt "trial period" msgid "Trial" msgstr "" #: includes/class-freemius.php:21489 msgid "I have upgraded my account but when I try to Sync the License, the plan remains %s." msgstr "" #: includes/class-freemius.php:21493, includes/class-freemius.php:21545 msgid "Please contact us here" msgstr "" #: includes/class-freemius.php:21515 msgid "Your plan was successfully changed to %s." msgstr "" #: includes/class-freemius.php:21531 msgid "Your license has expired. You can still continue using the free %s forever." msgstr "" #: includes/class-freemius.php:21533 msgid "Your license has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions." msgstr "" #: includes/class-freemius.php:21541 msgid "Your license has been cancelled. If you think it's a mistake, please contact support." msgstr "" #: includes/class-freemius.php:21554 msgid "Your license has expired. You can still continue using all the %s features, but you'll need to renew your license to continue getting updates and support." msgstr "" #: includes/class-freemius.php:21580 msgid "Your free trial has expired. You can still continue using all our free features." msgstr "" #: includes/class-freemius.php:21582 msgid "Your free trial has expired. %1$sUpgrade now%2$s to continue using the %3$s without interruptions." msgstr "" #: includes/class-freemius.php:21628 msgid "Your server is blocking the access to Freemius' API, which is crucial for %1$s synchronization. Please contact your host to whitelist the following domains:%2$s" msgstr "" #: includes/class-freemius.php:21630 msgid "Show error details" msgstr "" #: includes/class-freemius.php:21733 msgid "It looks like the license could not be activated." msgstr "" #: includes/class-freemius.php:21775 msgid "Your license was successfully activated." msgstr "" #: includes/class-freemius.php:21799 msgid "It looks like your site currently doesn't have an active license." msgstr "" #: includes/class-freemius.php:21823 msgid "It looks like the license deactivation failed." msgstr "" #: includes/class-freemius.php:21852 msgid "Your %s license was successfully deactivated." msgstr "" #: includes/class-freemius.php:21853 msgid "Your license was successfully deactivated, you are back to the %s plan." msgstr "" #: includes/class-freemius.php:21856 msgid "O.K" msgstr "" #: includes/class-freemius.php:21909 msgid "Seems like we are having some temporary issue with your subscription cancellation. Please try again in few minutes." msgstr "" #: includes/class-freemius.php:21918 msgid "Your subscription was successfully cancelled. Your %s plan license will expire in %s." msgstr "" #: includes/class-freemius.php:21960 msgid "You are already running the %s in a trial mode." msgstr "" #: includes/class-freemius.php:21971 msgid "You already utilized a trial before." msgstr "" #: includes/class-freemius.php:21985 msgid "Plan %s do not exist, therefore, can't start a trial." msgstr "" #: includes/class-freemius.php:21996 msgid "Plan %s does not support a trial period." msgstr "" #: includes/class-freemius.php:22007 msgid "None of the %s's plans supports a trial period." msgstr "" #: includes/class-freemius.php:22056 msgid "It looks like you are not in trial mode anymore so there's nothing to cancel :)" msgstr "" #: includes/class-freemius.php:22092 msgid "Seems like we are having some temporary issue with your trial cancellation. Please try again in few minutes." msgstr "" #: includes/class-freemius.php:22111 msgid "Your %s free trial was successfully cancelled." msgstr "" #: includes/class-freemius.php:22438 msgid "Version %s was released." msgstr "" #: includes/class-freemius.php:22438 msgid "Please download %s." msgstr "" #: includes/class-freemius.php:22445 msgid "the latest %s version here" msgstr "" #: includes/class-freemius.php:22450 msgid "New" msgstr "" #: includes/class-freemius.php:22455 msgid "Seems like you got the latest release." msgstr "" #: includes/class-freemius.php:22456 msgid "You are all good!" msgstr "" #: includes/class-freemius.php:22859 msgid "Verification mail was just sent to %s. If you can't find it after 5 min, please check your spam box." msgstr "" #: includes/class-freemius.php:22999 msgid "Site successfully opted in." msgstr "" #: includes/class-freemius.php:23000, includes/class-freemius.php:24049 msgid "Awesome" msgstr "" #: includes/class-freemius.php:23016 msgid "Sharing diagnostic data with %s helps to provide functionality that's more relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the plugin should be translated and tailored to." msgstr "" #: includes/class-freemius.php:23017 msgid "Thank you!" msgstr "" #: includes/class-freemius.php:23026 msgid "Diagnostic data will no longer be sent from %s to %s." msgstr "" #: includes/class-freemius.php:23181 msgid "A confirmation email was just sent to %s. The email owner must confirm the update within the next 4 hours." msgstr "" #: includes/class-freemius.php:23183 msgid "A confirmation email was just sent to %s. You must confirm the update within the next 4 hours. If you cannot find the email, please check your spam folder." msgstr "" #: includes/class-freemius.php:23190 msgid "Thanks for confirming the ownership change. An email was just sent to %s for final approval." msgstr "" #: includes/class-freemius.php:23195 msgid "%s is the new owner of the account." msgstr "" #: includes/class-freemius.php:23197 msgctxt "as congratulations" msgid "Congrats" msgstr "" #: includes/class-freemius.php:23214 msgid "Please provide your full name." msgstr "" #: includes/class-freemius.php:23219 msgid "Your name was successfully updated." msgstr "" #: includes/class-freemius.php:23280 msgid "You have successfully updated your %s." msgstr "" #: includes/class-freemius.php:23339 msgid "Is this your client's site? %s if you wish to hide sensitive info like your email, license key, prices, billing address & invoices from the WP Admin." msgstr "" #: includes/class-freemius.php:23342 msgid "Click here" msgstr "" #: includes/class-freemius.php:23379, includes/class-freemius.php:23376 msgid "Bundle" msgstr "" #: includes/class-freemius.php:23459 msgid "Just letting you know that the add-ons information of %s is being pulled from an external server." msgstr "" #: includes/class-freemius.php:23460 msgctxt "advance notice of something that will need attention." msgid "Heads up" msgstr "" #: includes/class-freemius.php:24089 msgctxt "exclamation" msgid "Hey" msgstr "" #: includes/class-freemius.php:24089 msgid "How do you like %s so far? Test all our %s premium features with a %d-day free trial." msgstr "" #: includes/class-freemius.php:24097 msgid "No commitment for %s days - cancel anytime!" msgstr "" #: includes/class-freemius.php:24098 msgid "No credit card required" msgstr "" #: includes/class-freemius.php:24105, templates/forms/trial-start.php:53 msgctxt "call to action" msgid "Start free trial" msgstr "" #: includes/class-freemius.php:24182 msgid "Hey there, did you know that %s has an affiliate program? If you like the %s you can become our ambassador and earn some cash!" msgstr "" #: includes/class-freemius.php:24191 msgid "Learn more" msgstr "" #: includes/class-freemius.php:24377, templates/account.php:573, templates/account.php:725, templates/connect.php:221, templates/connect.php:447, includes/managers/class-fs-clone-manager.php:1295, templates/forms/license-activation.php:27, templates/account/partials/addon.php:326 msgid "Activate License" msgstr "" #: includes/class-freemius.php:24378, templates/account.php:667, templates/account.php:724, templates/account/partials/addon.php:327, templates/account/partials/site.php:273 msgid "Change License" msgstr "" #: includes/class-freemius.php:24485, templates/account/partials/site.php:170 msgid "Opt Out" msgstr "" #: includes/class-freemius.php:24487, includes/class-freemius.php:24493, templates/account/partials/site.php:49, templates/account/partials/site.php:170 msgid "Opt In" msgstr "" #: includes/class-freemius.php:24728 msgid " The paid version of %1$s is already installed. Please activate it to start benefiting the %2$s features. %3$s" msgstr "" #: includes/class-freemius.php:24738 msgid "Activate %s features" msgstr "" #: includes/class-freemius.php:24751 msgid "Please follow these steps to complete the upgrade" msgstr "" #: includes/class-freemius.php:24755 msgid "Download the latest %s version" msgstr "" #: includes/class-freemius.php:24759 msgid "Upload and activate the downloaded version" msgstr "" #: includes/class-freemius.php:24761 msgid "How to upload and activate?" msgstr "" #: includes/class-freemius.php:24796 msgid "Your plan was successfully upgraded." msgstr "" #: includes/class-freemius.php:24797 msgid "Your plan was successfully activated." msgstr "" #: includes/class-freemius.php:24927 msgid "%sClick here%s to choose the sites where you'd like to activate the license on." msgstr "" #: includes/class-freemius.php:25096 msgid "Auto installation only works for opted-in users." msgstr "" #: includes/class-freemius.php:25106, includes/class-freemius.php:25139, includes/class-fs-plugin-updater.php:1294, includes/class-fs-plugin-updater.php:1308 msgid "Invalid module ID." msgstr "" #: includes/class-freemius.php:25115, includes/class-fs-plugin-updater.php:1330 msgid "Premium version already active." msgstr "" #: includes/class-freemius.php:25122 msgid "You do not have a valid license to access the premium version." msgstr "" #: includes/class-freemius.php:25129 msgid "Plugin is a \"Serviceware\" which means it does not have a premium code version." msgstr "" #: includes/class-freemius.php:25147, includes/class-fs-plugin-updater.php:1329 msgid "Premium add-on version already installed." msgstr "" #: includes/class-freemius.php:25501 msgid "View paid features" msgstr "" #: includes/class-freemius.php:25805 msgid "Thank you so much for using %s and its add-ons!" msgstr "" #: includes/class-freemius.php:25806 msgid "Thank you so much for using %s!" msgstr "" #: includes/class-freemius.php:25812 msgid "You've already opted-in to our usage-tracking, which helps us keep improving the %s." msgstr "" #: includes/class-freemius.php:25816 msgid "Thank you so much for using our products!" msgstr "" #: includes/class-freemius.php:25817 msgid "You've already opted-in to our usage-tracking, which helps us keep improving them." msgstr "" #: includes/class-freemius.php:25836 msgid "%s and its add-ons" msgstr "" #: includes/class-freemius.php:25845 msgid "Products" msgstr "" #: includes/class-freemius.php:25852, templates/connect.php:322 msgid "Yes" msgstr "" #: includes/class-freemius.php:25853, templates/connect.php:323 msgid "send me security & feature updates, educational content and offers." msgstr "" #: includes/class-freemius.php:25854, templates/connect.php:328 msgid "No" msgstr "" #: includes/class-freemius.php:25856, templates/connect.php:330 msgid "do %sNOT%s send me security & feature updates, educational content and offers." msgstr "" #: includes/class-freemius.php:25866 msgid "Due to the new %sEU General Data Protection Regulation (GDPR)%s compliance requirements it is required that you provide your explicit consent, again, confirming that you are onboard :-)" msgstr "" #: includes/class-freemius.php:25868, templates/connect.php:337 msgid "Please let us know if you'd like us to contact you for security & feature updates, educational content, and occasional offers:" msgstr "" #: includes/class-freemius.php:26158 msgid "License key is empty." msgstr "" #: includes/class-fs-plugin-updater.php:210, templates/forms/premium-versions-upgrade-handler.php:57 msgid "Renew license" msgstr "" #: includes/class-fs-plugin-updater.php:215, templates/forms/premium-versions-upgrade-handler.php:58 msgid "Buy license" msgstr "" #: includes/class-fs-plugin-updater.php:335, includes/class-fs-plugin-updater.php:368 msgid "There is a %s of %s available." msgstr "" #: includes/class-fs-plugin-updater.php:337, includes/class-fs-plugin-updater.php:373 msgid "new Beta version" msgstr "" #: includes/class-fs-plugin-updater.php:338, includes/class-fs-plugin-updater.php:374 msgid "new version" msgstr "" #: includes/class-fs-plugin-updater.php:397 msgid "Important Upgrade Notice:" msgstr "" #: includes/class-fs-plugin-updater.php:1359 msgid "Installing plugin: %s" msgstr "" #: includes/class-fs-plugin-updater.php:1400 msgid "Unable to connect to the filesystem. Please confirm your credentials." msgstr "" #: includes/class-fs-plugin-updater.php:1582 msgid "The remote plugin package does not contain a folder with the desired slug and renaming did not work." msgstr "" #: includes/fs-plugin-info-dialog.php:542 msgid "Purchase More" msgstr "" #: includes/fs-plugin-info-dialog.php:543, templates/account/partials/addon.php:390 msgctxt "verb" msgid "Purchase" msgstr "" #: includes/fs-plugin-info-dialog.php:547 msgid "Start my free %s" msgstr "" #: includes/fs-plugin-info-dialog.php:745 msgid "Install Free Version Update Now" msgstr "" #: includes/fs-plugin-info-dialog.php:746, templates/account.php:656 msgid "Install Update Now" msgstr "" #: includes/fs-plugin-info-dialog.php:755 msgid "Install Free Version Now" msgstr "" #: includes/fs-plugin-info-dialog.php:756, templates/add-ons.php:323, templates/auto-installation.php:111, templates/account/partials/addon.php:370, templates/account/partials/addon.php:423 msgid "Install Now" msgstr "" #: includes/fs-plugin-info-dialog.php:772 msgctxt "as download latest version" msgid "Download Latest Free Version" msgstr "" #: includes/fs-plugin-info-dialog.php:773, templates/account.php:114, templates/add-ons.php:37, templates/account/partials/addon.php:30 msgctxt "as download latest version" msgid "Download Latest" msgstr "" #: includes/fs-plugin-info-dialog.php:788, templates/add-ons.php:329, templates/account/partials/addon.php:361, templates/account/partials/addon.php:417 msgid "Activate this add-on" msgstr "" #: includes/fs-plugin-info-dialog.php:790, templates/connect.php:444 msgid "Activate Free Version" msgstr "" #: includes/fs-plugin-info-dialog.php:791, templates/account.php:138, templates/add-ons.php:330, templates/account/partials/addon.php:53 msgid "Activate" msgstr "" #: includes/fs-plugin-info-dialog.php:1003 msgctxt "Plugin installer section title" msgid "Description" msgstr "" #: includes/fs-plugin-info-dialog.php:1004 msgctxt "Plugin installer section title" msgid "Installation" msgstr "" #: includes/fs-plugin-info-dialog.php:1005 msgctxt "Plugin installer section title" msgid "FAQ" msgstr "" #: includes/fs-plugin-info-dialog.php:1006, templates/plugin-info/description.php:55 msgid "Screenshots" msgstr "" #: includes/fs-plugin-info-dialog.php:1007 msgctxt "Plugin installer section title" msgid "Changelog" msgstr "" #: includes/fs-plugin-info-dialog.php:1008 msgctxt "Plugin installer section title" msgid "Reviews" msgstr "" #: includes/fs-plugin-info-dialog.php:1009 msgctxt "Plugin installer section title" msgid "Other Notes" msgstr "" #: includes/fs-plugin-info-dialog.php:1024 msgctxt "Plugin installer section title" msgid "Features & Pricing" msgstr "" #: includes/fs-plugin-info-dialog.php:1034 msgid "Plugin Install" msgstr "" #: includes/fs-plugin-info-dialog.php:1106 msgctxt "e.g. Professional Plan" msgid "%s Plan" msgstr "" #: includes/fs-plugin-info-dialog.php:1132 msgctxt "e.g. the best product" msgid "Best" msgstr "" #: includes/fs-plugin-info-dialog.php:1138, includes/fs-plugin-info-dialog.php:1158 msgctxt "as every month" msgid "Monthly" msgstr "" #: includes/fs-plugin-info-dialog.php:1141 msgctxt "as once a year" msgid "Annual" msgstr "" #: includes/fs-plugin-info-dialog.php:1144 msgid "Lifetime" msgstr "" #: includes/fs-plugin-info-dialog.php:1158, includes/fs-plugin-info-dialog.php:1160, includes/fs-plugin-info-dialog.php:1162 msgctxt "e.g. billed monthly" msgid "Billed %s" msgstr "" #: includes/fs-plugin-info-dialog.php:1160 msgctxt "as once a year" msgid "Annually" msgstr "" #: includes/fs-plugin-info-dialog.php:1162 msgctxt "as once a year" msgid "Once" msgstr "" #: includes/fs-plugin-info-dialog.php:1168 msgid "Single Site License" msgstr "" #: includes/fs-plugin-info-dialog.php:1170 msgid "Unlimited Licenses" msgstr "" #: includes/fs-plugin-info-dialog.php:1172 msgid "Up to %s Sites" msgstr "" #: includes/fs-plugin-info-dialog.php:1182, templates/plugin-info/features.php:82 msgctxt "as monthly period" msgid "mo" msgstr "" #: includes/fs-plugin-info-dialog.php:1189, templates/plugin-info/features.php:80 msgctxt "as annual period" msgid "year" msgstr "" #: includes/fs-plugin-info-dialog.php:1243 msgctxt "noun" msgid "Price" msgstr "" #: includes/fs-plugin-info-dialog.php:1291 msgid "Save %s" msgstr "" #: includes/fs-plugin-info-dialog.php:1301 msgid "No commitment for %s - cancel anytime" msgstr "" #: includes/fs-plugin-info-dialog.php:1304 msgid "After your free %s, pay as little as %s" msgstr "" #: includes/fs-plugin-info-dialog.php:1315 msgid "Details" msgstr "" #: includes/fs-plugin-info-dialog.php:1319, templates/account.php:125, templates/debug.php:232, templates/debug.php:269, templates/debug.php:518, templates/account/partials/addon.php:41 msgctxt "product version" msgid "Version" msgstr "" #: includes/fs-plugin-info-dialog.php:1326 msgctxt "as the plugin author" msgid "Author" msgstr "" #: includes/fs-plugin-info-dialog.php:1333 msgid "Last Updated" msgstr "" #: includes/fs-plugin-info-dialog.php:1338, templates/account.php:544 msgctxt "x-ago" msgid "%s ago" msgstr "" #: includes/fs-plugin-info-dialog.php:1347 msgid "Requires WordPress Version" msgstr "" #: includes/fs-plugin-info-dialog.php:1350, includes/fs-plugin-info-dialog.php:1370 msgid "%s or higher" msgstr "" #: includes/fs-plugin-info-dialog.php:1358 msgid "Compatible up to" msgstr "" #: includes/fs-plugin-info-dialog.php:1366 msgid "Requires PHP Version" msgstr "" #: includes/fs-plugin-info-dialog.php:1379 msgid "Downloaded" msgstr "" #: includes/fs-plugin-info-dialog.php:1383 msgid "%s time" msgstr "" #: includes/fs-plugin-info-dialog.php:1385 msgid "%s times" msgstr "" #: includes/fs-plugin-info-dialog.php:1396 msgid "WordPress.org Plugin Page" msgstr "" #: includes/fs-plugin-info-dialog.php:1405 msgid "Plugin Homepage" msgstr "" #: includes/fs-plugin-info-dialog.php:1414, includes/fs-plugin-info-dialog.php:1498 msgid "Donate to this plugin" msgstr "" #: includes/fs-plugin-info-dialog.php:1421 msgid "Average Rating" msgstr "" #: includes/fs-plugin-info-dialog.php:1428 msgid "based on %s" msgstr "" #: includes/fs-plugin-info-dialog.php:1432 msgid "%s rating" msgstr "" #: includes/fs-plugin-info-dialog.php:1434 msgid "%s ratings" msgstr "" #: includes/fs-plugin-info-dialog.php:1449 msgid "%s star" msgstr "" #: includes/fs-plugin-info-dialog.php:1451 msgid "%s stars" msgstr "" #: includes/fs-plugin-info-dialog.php:1463 msgid "Click to see reviews that provided a rating of %s" msgstr "" #: includes/fs-plugin-info-dialog.php:1476 msgid "Contributors" msgstr "" #: includes/fs-plugin-info-dialog.php:1517 msgid "This plugin requires a newer version of PHP." msgstr "" #: includes/fs-plugin-info-dialog.php:1526 msgid "Click here to learn more about updating PHP." msgstr "" #: includes/fs-plugin-info-dialog.php:1540, includes/fs-plugin-info-dialog.php:1542 msgid "Warning" msgstr "" #: includes/fs-plugin-info-dialog.php:1540 msgid "This plugin has not been tested with your current version of WordPress." msgstr "" #: includes/fs-plugin-info-dialog.php:1542 msgid "This plugin has not been marked as compatible with your version of WordPress." msgstr "" #: includes/fs-plugin-info-dialog.php:1561 msgid "Paid add-on must be deployed to Freemius." msgstr "" #: includes/fs-plugin-info-dialog.php:1562 msgid "Add-on must be deployed to WordPress.org or Freemius." msgstr "" #: includes/fs-plugin-info-dialog.php:1583 msgid "Newer Version (%s) Installed" msgstr "" #: includes/fs-plugin-info-dialog.php:1584 msgid "Newer Free Version (%s) Installed" msgstr "" #: includes/fs-plugin-info-dialog.php:1591 msgid "Latest Version Installed" msgstr "" #: includes/fs-plugin-info-dialog.php:1592 msgid "Latest Free Version Installed" msgstr "" #: templates/account.php:115, templates/forms/subscription-cancellation.php:96, templates/account/partials/addon.php:31, templates/account/partials/site.php:313 msgid "Downgrading your plan" msgstr "" #: templates/account.php:116, templates/forms/subscription-cancellation.php:97, templates/account/partials/addon.php:32, templates/account/partials/site.php:314 msgid "Cancelling the subscription" msgstr "" #. translators: %1$s: Either 'Downgrading your plan' or 'Cancelling the subscription' #: templates/account.php:118, templates/forms/subscription-cancellation.php:99, templates/account/partials/site.php:316 msgid "%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s." msgstr "" #: templates/account.php:119, templates/forms/subscription-cancellation.php:100, templates/account/partials/addon.php:35, templates/account/partials/site.php:317 msgid "Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price." msgstr "" #: templates/account.php:120, templates/forms/subscription-cancellation.php:106, templates/account/partials/addon.php:36 msgid "Cancelling the trial will immediately block access to all premium features. Are you sure?" msgstr "" #: templates/account.php:121, templates/forms/subscription-cancellation.php:101, templates/account/partials/addon.php:37, templates/account/partials/site.php:318 msgid "You can still enjoy all %s features but you will not have access to %s security & feature updates, nor support." msgstr "" #: templates/account.php:122, templates/forms/subscription-cancellation.php:102, templates/account/partials/addon.php:38, templates/account/partials/site.php:319 msgid "Once your license expires you can still use the Free version but you will NOT have access to the %s features." msgstr "" #. translators: %s: Plan title (e.g. "Professional") #: templates/account.php:124, templates/account/partials/activate-license-button.php:31, templates/account/partials/addon.php:40 msgid "Activate %s Plan" msgstr "" #. translators: %s: Time period (e.g. Auto renews in "2 months") #: templates/account.php:127, templates/account/partials/addon.php:43, templates/account/partials/site.php:293 msgid "Auto renews in %s" msgstr "" #. translators: %s: Time period (e.g. Expires in "2 months") #: templates/account.php:129, templates/account/partials/addon.php:45, templates/account/partials/site.php:295 msgid "Expires in %s" msgstr "" #: templates/account.php:130 msgctxt "as synchronize license" msgid "Sync License" msgstr "" #: templates/account.php:131, templates/account/partials/addon.php:46 msgid "Cancel Trial" msgstr "" #: templates/account.php:132, templates/account/partials/addon.php:47 msgid "Change Plan" msgstr "" #: templates/account.php:133, templates/account/partials/addon.php:48 msgctxt "verb" msgid "Upgrade" msgstr "" #: templates/account.php:135, templates/account/partials/addon.php:50, templates/account/partials/site.php:320 msgctxt "verb" msgid "Downgrade" msgstr "" #: templates/account.php:137, templates/add-ons.php:246, templates/plugin-info/features.php:72, templates/account/partials/addon.php:52, templates/account/partials/site.php:33 msgid "Free" msgstr "" #: templates/account.php:139, templates/debug.php:412, includes/customizer/class-fs-customizer-upsell-control.php:110, templates/account/partials/addon.php:54 msgctxt "as product pricing plan" msgid "Plan" msgstr "" #: templates/account.php:140 msgid "Bundle Plan" msgstr "" #: templates/account.php:272 msgid "Free Trial" msgstr "" #: templates/account.php:283 msgid "Account Details" msgstr "" #: templates/account.php:290, templates/forms/data-debug-mode.php:33 msgid "Start Debug" msgstr "" #: templates/account.php:292 msgid "Stop Debug" msgstr "" #: templates/account.php:299 msgid "Billing & Invoices" msgstr "" #: templates/account.php:322, templates/account/partials/addon.php:236, templates/account/partials/deactivate-license-button.php:35 msgid "Deactivate License" msgstr "" #: templates/account.php:345, templates/forms/subscription-cancellation.php:125 msgid "Are you sure you want to proceed?" msgstr "" #: templates/account.php:345, templates/account/partials/addon.php:260 msgid "Cancel Subscription" msgstr "" #: templates/account.php:374, templates/account/partials/addon.php:345 msgctxt "as synchronize" msgid "Sync" msgstr "" #: templates/account.php:389, templates/debug.php:575 msgid "Name" msgstr "" #: templates/account.php:395, templates/debug.php:576 msgid "Email" msgstr "" #: templates/account.php:402, templates/debug.php:410, templates/debug.php:625 msgid "User ID" msgstr "" #: templates/account.php:420, templates/account.php:738, templates/account.php:789, templates/debug.php:267, templates/debug.php:404, templates/debug.php:515, templates/debug.php:574, templates/debug.php:623, templates/debug.php:702, templates/account/payments.php:35, templates/debug/logger.php:21 msgid "ID" msgstr "" #: templates/account.php:427 msgid "Site ID" msgstr "" #: templates/account.php:430 msgid "No ID" msgstr "" #: templates/account.php:435, templates/debug.php:274, templates/debug.php:413, templates/debug.php:519, templates/debug.php:578, templates/account/partials/site.php:228 msgid "Public Key" msgstr "" #: templates/account.php:441, templates/debug.php:414, templates/debug.php:520, templates/debug.php:579, templates/account/partials/site.php:241 msgid "Secret Key" msgstr "" #: templates/account.php:444 msgctxt "as secret encryption key missing" msgid "No Secret" msgstr "" #: templates/account.php:471, templates/account/partials/site.php:120, templates/account/partials/site.php:122 msgid "Trial" msgstr "" #: templates/account.php:498, templates/debug.php:631, templates/account/partials/site.php:262 msgid "License Key" msgstr "" #: templates/account.php:529 msgid "Join the Beta program" msgstr "" #: templates/account.php:535 msgid "not verified" msgstr "" #: templates/account.php:544, templates/account/partials/addon.php:195 msgid "Expired" msgstr "" #: templates/account.php:602 msgid "Premium version" msgstr "" #: templates/account.php:604 msgid "Free version" msgstr "" #: templates/account.php:616 msgid "Verify Email" msgstr "" #: templates/account.php:630 msgid "Download %s Version" msgstr "" #: templates/account.php:646 msgid "Download Paid Version" msgstr "" #: templates/account.php:664, templates/account.php:927, templates/account/partials/site.php:250, templates/account/partials/site.php:272 msgctxt "verb" msgid "Show" msgstr "" #: templates/account.php:680 msgid "What is your %s?" msgstr "" #: templates/account.php:688, templates/account/billing.php:21 msgctxt "verb" msgid "Edit" msgstr "" #: templates/account.php:693, templates/forms/user-change.php:27 msgid "Change User" msgstr "" #: templates/account.php:717 msgid "Sites" msgstr "" #: templates/account.php:730 msgid "Search by address" msgstr "" #: templates/account.php:739, templates/debug.php:407 msgid "Address" msgstr "" #: templates/account.php:740 msgid "License" msgstr "" #: templates/account.php:741 msgid "Plan" msgstr "" #: templates/account.php:792 msgctxt "as software license" msgid "License" msgstr "" #: templates/account.php:921 msgctxt "verb" msgid "Hide" msgstr "" #: templates/account.php:943, templates/forms/data-debug-mode.php:31, templates/forms/deactivation/form.php:358, templates/forms/deactivation/form.php:389 msgid "Processing" msgstr "" #: templates/account.php:946 msgid "Get updates for bleeding edge Beta versions of %s." msgstr "" #: templates/account.php:1004 msgid "Cancelling %s" msgstr "" #: templates/account.php:1004, templates/account.php:1021, templates/forms/subscription-cancellation.php:27, templates/forms/deactivation/form.php:178 msgid "trial" msgstr "" #: templates/account.php:1019, templates/forms/deactivation/form.php:195 msgid "Cancelling %s..." msgstr "" #: templates/account.php:1022, templates/forms/subscription-cancellation.php:28, templates/forms/deactivation/form.php:179 msgid "subscription" msgstr "" #: templates/account.php:1036 msgid "Deactivating your license will block all premium features, but will enable activating the license on another site. Are you sure you want to proceed?" msgstr "" #: templates/account.php:1110 msgid "Disabling white-label mode" msgstr "" #: templates/account.php:1111 msgid "Enabling white-label mode" msgstr "" #: templates/add-ons.php:38 msgid "View details" msgstr "" #: templates/add-ons.php:48 msgid "Add Ons for %s" msgstr "" #: templates/add-ons.php:58 msgid "We couldn't load the add-ons list. It's probably an issue on our side, please try to come back in few minutes." msgstr "" #: templates/add-ons.php:229 msgctxt "active add-on" msgid "Active" msgstr "" #: templates/add-ons.php:230 msgctxt "installed add-on" msgid "Installed" msgstr "" #: templates/admin-notice.php:13, templates/forms/license-activation.php:243, templates/forms/resend-key.php:80 msgctxt "as close a window" msgid "Dismiss" msgstr "" #: templates/auto-installation.php:45 msgid "%s sec" msgstr "" #: templates/auto-installation.php:83 msgid "Automatic Installation" msgstr "" #: templates/auto-installation.php:93 msgid "An automated download and installation of %s (paid version) from %s will start in %s. If you would like to do it manually - click the cancellation button now." msgstr "" #: templates/auto-installation.php:104 msgid "The installation process has started and may take a few minutes to complete. Please wait until it is done - do not refresh this page." msgstr "" #: templates/auto-installation.php:109 msgid "Cancel Installation" msgstr "" #: templates/checkout.php:181 msgid "Checkout" msgstr "" #: templates/checkout.php:181 msgid "PCI compliant" msgstr "" #. translators: %s: name (e.g. Hey John,) #: templates/connect.php:127 msgctxt "greeting" msgid "Hey %s," msgstr "" #: templates/connect.php:187 msgid "Never miss an important update" msgstr "" #: templates/connect.php:195 msgid "Thank you for updating to %1$s v%2$s!" msgstr "" #: templates/connect.php:205 msgid "Allow & Continue" msgstr "" #: templates/connect.php:209 msgid "Re-send activation email" msgstr "" #: templates/connect.php:213 msgid "Thanks %s!" msgstr "" #: templates/connect.php:214 msgid "You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s." msgstr "" #: templates/connect.php:225 msgid "Welcome to %s! To get started, please enter your license key:" msgstr "" #: templates/connect.php:236 msgid "Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to." msgstr "" #. translators: %s: module type (plugin, theme, or add-on) #: templates/connect.php:245 msgid "We have introduced this opt-in so you never miss an important update and help us make the %s more compatible with your site and better at doing what you need it to." msgstr "" #: templates/connect.php:247 msgid "Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info." msgstr "" #: templates/connect.php:250 msgid "If you skip this, that's okay! %1$s will still work just fine." msgstr "" #: templates/connect.php:280 msgid "We're excited to introduce the Freemius network-level integration." msgstr "" #: templates/connect.php:283 msgid "During the update process we detected %d site(s) that are still pending license activation." msgstr "" #: templates/connect.php:285 msgid "If you'd like to use the %s on those sites, please enter your license key below and click the activation button." msgstr "" #: templates/connect.php:287 msgid "%s's paid features" msgstr "" #: templates/connect.php:292 msgid "Alternatively, you can skip it for now and activate the license later, in your %s's network-level Account page." msgstr "" #: templates/connect.php:294 msgid "During the update process we detected %s site(s) in the network that are still pending your attention." msgstr "" #: templates/connect.php:303, templates/forms/data-debug-mode.php:35, templates/forms/license-activation.php:42 msgid "License key" msgstr "" #: templates/connect.php:306, templates/forms/license-activation.php:22 msgid "Can't find your license key?" msgstr "" #: templates/connect.php:369, templates/connect.php:693, templates/forms/deactivation/retry-skip.php:20 msgctxt "verb" msgid "Skip" msgstr "" #: templates/connect.php:372 msgid "Delegate to Site Admins" msgstr "" #: templates/connect.php:372 msgid "If you click it, this decision will be delegated to the sites administrators." msgstr "" #: templates/connect.php:399 msgid "License issues?" msgstr "" #: templates/connect.php:423 msgid "For delivery of security & feature updates, and license management, %s needs to" msgstr "" #: templates/connect.php:428 msgid "This will allow %s to" msgstr "" #: templates/connect.php:443 msgid "Don't have a license key?" msgstr "" #: templates/connect.php:446 msgid "Have a license key?" msgstr "" #: templates/connect.php:454 msgid "Freemius is our licensing and software updates engine" msgstr "" #: templates/connect.php:457 msgid "Privacy Policy" msgstr "" #: templates/connect.php:459 msgid "License Agreement" msgstr "" #: templates/connect.php:459 msgid "Terms of Service" msgstr "" #: templates/connect.php:879 msgctxt "as in the process of sending an email" msgid "Sending email" msgstr "" #: templates/connect.php:880 msgctxt "as activating plugin" msgid "Activating" msgstr "" #: templates/contact.php:78 msgid "Contact" msgstr "" #: templates/debug.php:17 msgctxt "as turned off" msgid "Off" msgstr "" #: templates/debug.php:18 msgctxt "as turned on" msgid "On" msgstr "" #: templates/debug.php:24 msgid "SDK" msgstr "" #: templates/debug.php:28 msgctxt "as code debugging" msgid "Debugging" msgstr "" #: templates/debug.php:58, templates/debug.php:279, templates/debug.php:415, templates/debug.php:580 msgid "Actions" msgstr "" #: templates/debug.php:68 msgid "Are you sure you want to delete all Freemius data?" msgstr "" #: templates/debug.php:68 msgid "Delete All Accounts" msgstr "" #: templates/debug.php:75 msgid "Clear API Cache" msgstr "" #: templates/debug.php:83 msgid "Clear Updates Transients" msgstr "" #: templates/debug.php:92 msgid "Reset Deactivation Snoozing" msgstr "" #: templates/debug.php:100 msgid "Sync Data From Server" msgstr "" #: templates/debug.php:109 msgid "Migrate Options to Network" msgstr "" #: templates/debug.php:114 msgid "Load DB Option" msgstr "" #: templates/debug.php:117 msgid "Set DB Option" msgstr "" #: templates/debug.php:211 msgid "Key" msgstr "" #: templates/debug.php:212 msgid "Value" msgstr "" #: templates/debug.php:228 msgctxt "as software development kit versions" msgid "SDK Versions" msgstr "" #: templates/debug.php:233 msgid "SDK Path" msgstr "" #: templates/debug.php:234, templates/debug.php:273 msgid "Module Path" msgstr "" #: templates/debug.php:235 msgid "Is Active" msgstr "" #: templates/debug.php:263, templates/debug/plugins-themes-sync.php:35 msgid "Plugins" msgstr "" #: templates/debug.php:263, templates/debug/plugins-themes-sync.php:56 msgid "Themes" msgstr "" #: templates/debug.php:268, templates/debug.php:409, templates/debug.php:517, templates/debug/scheduled-crons.php:80 msgid "Slug" msgstr "" #: templates/debug.php:270, templates/debug.php:516 msgid "Title" msgstr "" #: templates/debug.php:271 msgctxt "as application program interface" msgid "API" msgstr "" #: templates/debug.php:272 msgid "Freemius State" msgstr "" #: templates/debug.php:276 msgid "Network Blog" msgstr "" #: templates/debug.php:277 msgid "Network User" msgstr "" #: templates/debug.php:323 msgctxt "as connection was successful" msgid "Connected" msgstr "" #: templates/debug.php:325 msgctxt "as connection blocked" msgid "Blocked" msgstr "" #: templates/debug.php:326 msgctxt "API connectivity state is unknown" msgid "Unknown" msgstr "" #: templates/debug.php:362 msgid "Simulate Trial Promotion" msgstr "" #: templates/debug.php:374 msgid "Simulate Network Upgrade" msgstr "" #: templates/debug.php:398 msgid "%s Installs" msgstr "" #: templates/debug.php:400 msgctxt "like websites" msgid "Sites" msgstr "" #: templates/debug.php:406, templates/account/partials/site.php:156 msgid "Blog ID" msgstr "" #: templates/debug.php:411 msgid "License ID" msgstr "" #: templates/debug.php:497, templates/debug.php:603, templates/account/partials/addon.php:440 msgctxt "verb" msgid "Delete" msgstr "" #: templates/debug.php:511 msgid "Add Ons of module %s" msgstr "" #: templates/debug.php:570 msgid "Users" msgstr "" #: templates/debug.php:577 msgid "Verified" msgstr "" #: templates/debug.php:619 msgid "%s Licenses" msgstr "" #: templates/debug.php:624 msgid "Plugin ID" msgstr "" #: templates/debug.php:626 msgid "Plan ID" msgstr "" #: templates/debug.php:627 msgid "Quota" msgstr "" #: templates/debug.php:628 msgid "Activated" msgstr "" #: templates/debug.php:629 msgid "Blocking" msgstr "" #: templates/debug.php:630, templates/debug.php:701, templates/debug/logger.php:22 msgid "Type" msgstr "" #: templates/debug.php:632 msgctxt "as expiration date" msgid "Expiration" msgstr "" #: templates/debug.php:660 msgid "Debug Log" msgstr "" #: templates/debug.php:664 msgid "All Types" msgstr "" #: templates/debug.php:671 msgid "All Requests" msgstr "" #: templates/debug.php:676, templates/debug.php:705, templates/debug/logger.php:25 msgid "File" msgstr "" #: templates/debug.php:677, templates/debug.php:703, templates/debug/logger.php:23 msgid "Function" msgstr "" #: templates/debug.php:678 msgid "Process ID" msgstr "" #: templates/debug.php:679 msgid "Logger" msgstr "" #: templates/debug.php:680, templates/debug.php:704, templates/debug/logger.php:24 msgid "Message" msgstr "" #: templates/debug.php:682 msgid "Filter" msgstr "" #: templates/debug.php:690 msgid "Download" msgstr "" #: templates/debug.php:706, templates/debug/logger.php:26 msgid "Timestamp" msgstr "" #: templates/secure-https-header.php:28 msgid "Secure HTTPS %s page, running from an external domain" msgstr "" #: includes/customizer/class-fs-customizer-support-section.php:55, templates/plugin-info/features.php:43 msgid "Support" msgstr "" #: includes/debug/class-fs-debug-bar-panel.php:48, templates/debug/api-calls.php:54, templates/debug/logger.php:62 msgctxt "milliseconds" msgid "ms" msgstr "" #: includes/debug/debug-bar-start.php:41 msgid "Freemius API" msgstr "" #: includes/debug/debug-bar-start.php:42 msgid "Requests" msgstr "" #: includes/managers/class-fs-clone-manager.php:839 msgid "Invalid clone resolution action." msgstr "" #: includes/managers/class-fs-clone-manager.php:1024 msgid "products" msgstr "" #: includes/managers/class-fs-clone-manager.php:1205 msgid "%1$s has been placed into safe mode because we noticed that %2$s is an exact copy of %3$s." msgstr "" #: includes/managers/class-fs-clone-manager.php:1211 msgid "The products below have been placed into safe mode because we noticed that %2$s is an exact copy of %3$s:%1$s" msgstr "" #: includes/managers/class-fs-clone-manager.php:1212 msgid "The products below have been placed into safe mode because we noticed that %2$s is an exact copy of these sites:%3$s%1$s" msgstr "" #: includes/managers/class-fs-clone-manager.php:1238 msgid "the above-mentioned sites" msgstr "" #: includes/managers/class-fs-clone-manager.php:1251 msgid "Is %2$s a duplicate of %4$s?" msgstr "" #: includes/managers/class-fs-clone-manager.php:1252 msgid "Yes, %2$s is a duplicate of %4$s for the purpose of testing, staging, or development." msgstr "" #: includes/managers/class-fs-clone-manager.php:1257 msgid "Long-Term Duplicate" msgstr "" #: includes/managers/class-fs-clone-manager.php:1262 msgid "Duplicate Website" msgstr "" #: includes/managers/class-fs-clone-manager.php:1268 msgid "Is %2$s the new home of %4$s?" msgstr "" #: includes/managers/class-fs-clone-manager.php:1270 msgid "Yes, %%2$s is replacing %%4$s. I would like to migrate my %s from %%4$s to %%2$s." msgstr "" #: includes/managers/class-fs-clone-manager.php:1271, templates/forms/subscription-cancellation.php:52 msgid "license" msgstr "" #: includes/managers/class-fs-clone-manager.php:1271 msgid "data" msgstr "" #: includes/managers/class-fs-clone-manager.php:1277 msgid "Migrate License" msgstr "" #: includes/managers/class-fs-clone-manager.php:1278 msgid "Migrate" msgstr "" #: includes/managers/class-fs-clone-manager.php:1284 msgid "Is %2$s a new website?" msgstr "" #: includes/managers/class-fs-clone-manager.php:1285 msgid "Yes, %2$s is a new and different website that is separate from %4$s." msgstr "" #: includes/managers/class-fs-clone-manager.php:1287 msgid "It requires license activation." msgstr "" #: includes/managers/class-fs-clone-manager.php:1294 msgid "New Website" msgstr "" #: includes/managers/class-fs-clone-manager.php:1319 msgctxt "Clone resolution admin notice products list label" msgid "Products" msgstr "" #: includes/managers/class-fs-clone-manager.php:1408 msgid "You marked this website, %s, as a temporary duplicate of %s." msgstr "" #: includes/managers/class-fs-clone-manager.php:1409 msgid "You marked this website, %s, as a temporary duplicate of these sites" msgstr "" #: includes/managers/class-fs-clone-manager.php:1423 msgid "%s automatic security & feature updates and paid functionality will keep working without interruptions until %s (or when your license expires, whatever comes first)." msgstr "" #: includes/managers/class-fs-clone-manager.php:1426 msgctxt "\"The \", e.g.: \"The plugin\"" msgid "The %s's" msgstr "" #: includes/managers/class-fs-clone-manager.php:1429 msgid "The following products'" msgstr "" #: includes/managers/class-fs-clone-manager.php:1437 msgid "If this is a long term duplicate, to keep automatic updates and paid functionality after %s, please %s." msgstr "" #: includes/managers/class-fs-clone-manager.php:1439 msgid "activate a license here" msgstr "" #: includes/managers/class-fs-permission-manager.php:191 msgid "View Basic Website Info" msgstr "" #: includes/managers/class-fs-permission-manager.php:192 msgid "Homepage URL & title, WP & PHP versions, and site language" msgstr "" #: includes/managers/class-fs-permission-manager.php:195 msgid "To provide additional functionality that's relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to." msgstr "" #: includes/managers/class-fs-permission-manager.php:207 msgid "View Basic %s Info" msgstr "" #: includes/managers/class-fs-permission-manager.php:210 msgid "Current %s & SDK versions, and if active or uninstalled" msgstr "" #: includes/managers/class-fs-permission-manager.php:261 msgid "View License Essentials" msgstr "" #: includes/managers/class-fs-permission-manager.php:262 msgstr "" #: includes/managers/class-fs-permission-manager.php:272 msgid "To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize." msgstr "" #: includes/managers/class-fs-permission-manager.php:284 msgid "View %s State" msgstr "" #: includes/managers/class-fs-permission-manager.php:287 msgid "Is active, deactivated, or uninstalled" msgstr "" #: includes/managers/class-fs-permission-manager.php:290 msgid "So you can reuse the license when the %s is no longer active." msgstr "" #: includes/managers/class-fs-permission-manager.php:326 msgid "View Diagnostic Info" msgstr "" #: includes/managers/class-fs-permission-manager.php:326, includes/managers/class-fs-permission-manager.php:363 msgid "optional" msgstr "" #: includes/managers/class-fs-permission-manager.php:327 msgid "WordPress & PHP versions, site language & title" msgstr "" #: includes/managers/class-fs-permission-manager.php:330 msgid "To avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to." msgstr "" #: includes/managers/class-fs-permission-manager.php:363 msgid "View Plugins & Themes List" msgstr "" #: includes/managers/class-fs-permission-manager.php:364 msgid "Names, slugs, versions, and if active or not" msgstr "" #: includes/managers/class-fs-permission-manager.php:365 msgid "To ensure compatibility and avoid conflicts with your installed plugins and themes." msgstr "" #: includes/managers/class-fs-permission-manager.php:382 msgid "View Basic Profile Info" msgstr "" #: includes/managers/class-fs-permission-manager.php:383 msgid "Your WordPress user's: first & last name, and email address" msgstr "" #: includes/managers/class-fs-permission-manager.php:384 msgid "Never miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features." msgstr "" #: includes/managers/class-fs-permission-manager.php:405 msgid "Newsletter" msgstr "" #: includes/managers/class-fs-permission-manager.php:406 msgid "Updates, announcements, marketing, no spam" msgstr "" #: templates/account/billing.php:22 msgctxt "verb" msgid "Update" msgstr "" #: templates/account/billing.php:33 msgid "Billing" msgstr "" #: templates/account/billing.php:38, templates/account/billing.php:38 msgid "Business name" msgstr "" #: templates/account/billing.php:39, templates/account/billing.php:39 msgid "Tax / VAT ID" msgstr "" #: templates/account/billing.php:42, templates/account/billing.php:42, templates/account/billing.php:43, templates/account/billing.php:43 msgid "Address Line %d" msgstr "" #: templates/account/billing.php:46, templates/account/billing.php:46 msgid "City" msgstr "" #: templates/account/billing.php:46, templates/account/billing.php:46 msgid "Town" msgstr "" #: templates/account/billing.php:47, templates/account/billing.php:47 msgid "ZIP / Postal Code" msgstr "" #: templates/account/billing.php:302 msgid "Country" msgstr "" #: templates/account/billing.php:304 msgid "Select Country" msgstr "" #: templates/account/billing.php:311, templates/account/billing.php:312 msgid "State" msgstr "" #: templates/account/billing.php:311, templates/account/billing.php:312 msgid "Province" msgstr "" #: templates/account/payments.php:29 msgid "Payments" msgstr "" #: templates/account/payments.php:36 msgid "Date" msgstr "" #: templates/account/payments.php:37 msgid "Amount" msgstr "" #: templates/account/payments.php:38, templates/account/payments.php:50 msgid "Invoice" msgstr "" #: templates/connect/permissions-group.php:31, templates/forms/optout.php:26, templates/js/permissions.php:78 msgctxt "verb" msgid "Opt Out" msgstr "" #: templates/connect/permissions-group.php:32, templates/js/permissions.php:77 msgctxt "verb" msgid "Opt In" msgstr "" #: templates/debug/api-calls.php:56 msgid "API" msgstr "" #: templates/debug/api-calls.php:68 msgid "Method" msgstr "" #: templates/debug/api-calls.php:69 msgid "Code" msgstr "" #: templates/debug/api-calls.php:70 msgid "Length" msgstr "" #: templates/debug/api-calls.php:71 msgctxt "as file/folder path" msgid "Path" msgstr "" #: templates/debug/api-calls.php:73 msgid "Body" msgstr "" #: templates/debug/api-calls.php:75 msgid "Result" msgstr "" #: templates/debug/api-calls.php:76 msgid "Start" msgstr "" #: templates/debug/api-calls.php:77 msgid "End" msgstr "" #: templates/debug/logger.php:15 msgid "Log" msgstr "" #. translators: %s: time period (e.g. In "2 hours") #: templates/debug/plugins-themes-sync.php:18, templates/debug/scheduled-crons.php:91 msgid "In %s" msgstr "" #. translators: %s: time period (e.g. "2 hours" ago) #: templates/debug/plugins-themes-sync.php:20, templates/debug/scheduled-crons.php:93 msgid "%s ago" msgstr "" #: templates/debug/plugins-themes-sync.php:21, templates/debug/scheduled-crons.php:74 msgctxt "seconds" msgid "sec" msgstr "" #: templates/debug/plugins-themes-sync.php:23 msgid "Plugins & Themes Sync" msgstr "" #: templates/debug/plugins-themes-sync.php:28 msgid "Total" msgstr "" #: templates/debug/plugins-themes-sync.php:29, templates/debug/scheduled-crons.php:84 msgid "Last" msgstr "" #: templates/debug/scheduled-crons.php:76 msgid "Scheduled Crons" msgstr "" #: templates/debug/scheduled-crons.php:81 msgid "Module" msgstr "" #: templates/debug/scheduled-crons.php:82 msgid "Module Type" msgstr "" #: templates/debug/scheduled-crons.php:83 msgid "Cron Type" msgstr "" #: templates/debug/scheduled-crons.php:85 msgid "Next" msgstr "" #: templates/forms/affiliation.php:83 msgid "Non-expiring" msgstr "" #: templates/forms/affiliation.php:86 msgid "Apply to become an affiliate" msgstr "" #: templates/forms/affiliation.php:108 msgid "Your affiliate application for %s has been accepted! Log in to your affiliate area at: %s." msgstr "" #: templates/forms/affiliation.php:123 msgid "Thank you for applying for our affiliate program, we'll review your details during the next 14 days and will get back to you with further information." msgstr "" #: templates/forms/affiliation.php:126 msgid "Your affiliation account was temporarily suspended." msgstr "" #: templates/forms/affiliation.php:129 msgid "Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days." msgstr "" #: templates/forms/affiliation.php:132 msgid "Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support." msgstr "" #: templates/forms/affiliation.php:145 msgid "Like the %s? Become our ambassador and earn cash ;-)" msgstr "" #: templates/forms/affiliation.php:146 msgid "Refer new customers to our %s and earn %s commission on each successful sale you refer!" msgstr "" #: templates/forms/affiliation.php:149 msgid "Program Summary" msgstr "" #: templates/forms/affiliation.php:151 msgid "%s commission when a customer purchases a new license." msgstr "" #: templates/forms/affiliation.php:153 msgid "Get commission for automated subscription renewals." msgstr "" #: templates/forms/affiliation.php:156 msgid "%s tracking cookie after the first visit to maximize earnings potential." msgstr "" #: templates/forms/affiliation.php:159 msgid "Unlimited commissions." msgstr "" #: templates/forms/affiliation.php:161 msgid "%s minimum payout amount." msgstr "" #: templates/forms/affiliation.php:162 msgid "Payouts are in USD and processed monthly via PayPal." msgstr "" #: templates/forms/affiliation.php:163 msgid "As we reserve 30 days for potential refunds, we only pay commissions that are older than 30 days." msgstr "" #: templates/forms/affiliation.php:166 msgid "Affiliate" msgstr "" #: templates/forms/affiliation.php:169, templates/forms/resend-key.php:23 msgid "Email address" msgstr "" #: templates/forms/affiliation.php:173 msgid "Full name" msgstr "" #: templates/forms/affiliation.php:177 msgid "PayPal account email address" msgstr "" #: templates/forms/affiliation.php:181 msgid "Where are you going to promote the %s?" msgstr "" #: templates/forms/affiliation.php:183 msgid "Enter the domain of your website or other websites from where you plan to promote the %s." msgstr "" #: templates/forms/affiliation.php:185 msgid "Add another domain" msgstr "" #: templates/forms/affiliation.php:189 msgid "Extra Domains" msgstr "" #: templates/forms/affiliation.php:190 msgid "Extra domains where you will be marketing the product from." msgstr "" #: templates/forms/affiliation.php:200 msgid "Promotion methods" msgstr "" #: templates/forms/affiliation.php:203 msgid "Social media (Facebook, Twitter, etc.)" msgstr "" #: templates/forms/affiliation.php:207 msgid "Mobile apps" msgstr "" #: templates/forms/affiliation.php:211 msgid "Website, email, and social media statistics (optional)" msgstr "" #: templates/forms/affiliation.php:214 msgid "Please feel free to provide any relevant website or social media statistics, e.g. monthly unique site visits, number of email subscribers, followers, etc. (we will keep this information confidential)." msgstr "" #: templates/forms/affiliation.php:218 msgid "How will you promote us?" msgstr "" #: templates/forms/affiliation.php:221 msgid "Please provide details on how you intend to promote %s (please be as specific as possible)." msgstr "" #: templates/forms/affiliation.php:233, templates/forms/resend-key.php:22, templates/account/partials/disconnect-button.php:92 msgid "Cancel" msgstr "" #: templates/forms/affiliation.php:235 msgid "Become an affiliate" msgstr "" #: templates/forms/data-debug-mode.php:25 msgid "Please enter the license key to enable the debug mode:" msgstr "" #: templates/forms/data-debug-mode.php:27 msgid "To enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your \"My Profile\" section of your User Dashboard:" msgstr "" #: templates/forms/data-debug-mode.php:32 msgid "Submit" msgstr "" #: templates/forms/data-debug-mode.php:36 msgid "User key" msgstr "" #: templates/forms/email-address-update.php:32 msgid "Email address update" msgstr "" #: templates/forms/email-address-update.php:33, templates/forms/user-change.php:81 msgctxt "close window" msgid "Dismiss" msgstr "" #: templates/forms/email-address-update.php:38 msgid "Enter the new email address" msgstr "" #: templates/forms/email-address-update.php:42 msgid "Are both %s and %s your email addresses?" msgstr "" #: templates/forms/email-address-update.php:50 msgid "Yes - both addresses are mine" msgstr "" #: templates/forms/email-address-update.php:57 msgid "%s is my client's email address" msgstr "" #: templates/forms/email-address-update.php:66 msgid "%s is my email address" msgstr "" #: templates/forms/email-address-update.php:75 msgid "Would you like to merge %s into %s?" msgstr "" #: templates/forms/email-address-update.php:84 msgid "Yes - move all my data and assets from %s to %s" msgstr "" #: templates/forms/email-address-update.php:94 msgid "No - only move this site's data to %s" msgstr "" #: templates/forms/email-address-update.php:292, templates/forms/email-address-update.php:298 msgid "Update" msgstr "" #: templates/forms/license-activation.php:23 msgid "Please enter the license key that you received in the email right after the purchase:" msgstr "" #: templates/forms/license-activation.php:28 msgid "Update License" msgstr "" #: templates/forms/license-activation.php:34 msgid "The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license." msgstr "" #: templates/forms/license-activation.php:39 msgid "Agree & Activate License" msgstr "" #: templates/forms/license-activation.php:204 msgid "Associate with the license owner's account." msgstr "" #: templates/forms/optout.php:44 msgid "Communication" msgstr "" #: templates/forms/optout.php:56 msgid "Stay Connected" msgstr "" #: templates/forms/optout.php:61 msgid "Diagnostic Info" msgstr "" #: templates/forms/optout.php:77 msgid "Keep Sharing" msgstr "" #: templates/forms/optout.php:82 msgid "Extensions" msgstr "" #: templates/forms/optout.php:104 msgid "Keep automatic updates" msgstr "" #: templates/forms/premium-versions-upgrade-handler.php:40 msgid "There is a new version of %s available." msgstr "" #: templates/forms/premium-versions-upgrade-handler.php:41 msgid " %s to access version %s security & feature updates, and support." msgstr "" #: templates/forms/premium-versions-upgrade-handler.php:54 msgid "New Version Available" msgstr "" #: templates/forms/premium-versions-upgrade-handler.php:75 msgctxt "close a window" msgid "Dismiss" msgstr "" #: templates/forms/resend-key.php:21 msgid "Send License Key" msgstr "" #: templates/forms/resend-key.php:58 msgid "Enter the email address you've used during the purchase and we will resend you the license key." msgstr "" #: templates/forms/resend-key.php:59 msgid "Enter the email address you've used for the upgrade below and we will resend you the license key." msgstr "" #: templates/forms/subscription-cancellation.php:37 msgid "Deactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site." msgstr "" #: templates/forms/subscription-cancellation.php:47 msgid "In case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?" msgstr "" #: templates/forms/subscription-cancellation.php:57 msgid "Cancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site." msgstr "" #: templates/forms/subscription-cancellation.php:68 msgid "Don't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support." msgstr "" #: templates/forms/subscription-cancellation.php:103 msgid "Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license." msgstr "" #: templates/forms/subscription-cancellation.php:136 msgid "Cancel %s?" msgstr "" #: templates/forms/subscription-cancellation.php:143 msgid "Proceed" msgstr "" #: templates/forms/subscription-cancellation.php:191, templates/forms/deactivation/form.php:216 msgid "Cancel %s & Proceed" msgstr "" #: templates/forms/trial-start.php:22 msgid "You are 1-click away from starting your %1$s-day free trial of the %2$s plan." msgstr "" #: templates/forms/trial-start.php:28 msgid "For compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial." msgstr "" #: templates/forms/user-change.php:26 msgid "By changing the user, you agree to transfer the account ownership to:" msgstr "" #: templates/forms/user-change.php:28 msgid "I Agree - Change User" msgstr "" #: templates/forms/user-change.php:30 msgid "Enter email address" msgstr "" #: templates/js/permissions.php:337, templates/js/permissions.php:485 msgid "Saved" msgstr "" #: templates/js/style-premium-theme.php:39 msgid "Premium" msgstr "" #: templates/js/style-premium-theme.php:42 msgid "Beta" msgstr "" #: templates/partials/network-activation.php:32 msgid "Activate license on all sites in the network." msgstr "" #: templates/partials/network-activation.php:33 msgid "Apply on all sites in the network." msgstr "" #: templates/partials/network-activation.php:36 msgid "Activate license on all pending sites." msgstr "" #: templates/partials/network-activation.php:37 msgid "Apply on all pending sites." msgstr "" #: templates/partials/network-activation.php:45, templates/partials/network-activation.php:79 msgid "allow" msgstr "" #: templates/partials/network-activation.php:48, templates/partials/network-activation.php:82 msgid "delegate" msgstr "" #: templates/partials/network-activation.php:52, templates/partials/network-activation.php:86 msgid "skip" msgstr "" #: templates/plugin-info/description.php:72, templates/plugin-info/screenshots.php:31 msgid "Click to view full-size screenshot %d" msgstr "" #: templates/plugin-info/features.php:56 msgid "Unlimited Updates" msgstr "" #: templates/account/partials/activate-license-button.php:46 msgid "Localhost" msgstr "" #: templates/account/partials/activate-license-button.php:50 msgctxt "as 5 licenses left" msgid "%s left" msgstr "" #: templates/account/partials/activate-license-button.php:51 msgid "Last license" msgstr "" #. translators: %1$s: Either 'Downgrading your plan' or 'Cancelling the subscription' #: templates/account/partials/addon.php:34 msgid "%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s." msgstr "" #: templates/account/partials/addon.php:190 msgid "Cancelled" msgstr "" #: templates/account/partials/addon.php:200 msgid "No expiration" msgstr "" #: templates/account/partials/disconnect-button.php:74 msgid "By disconnecting the website, previously shared diagnostic data about %1$s will be deleted and no longer visible to %2$s." msgstr "" #: templates/account/partials/disconnect-button.php:78 msgid "Disconnecting the website will permanently remove %s from your User Dashboard's account." msgstr "" #: templates/account/partials/disconnect-button.php:84 msgid "If you wish to cancel your %1$s plan's subscription instead, please navigate to the %2$s and cancel it there." msgstr "" #: templates/account/partials/disconnect-button.php:88 msgid "Are you sure you would like to proceed with the disconnection?" msgstr "" #: templates/account/partials/site.php:190 msgid "Owner Name" msgstr "" #: templates/account/partials/site.php:202 msgid "Owner Email" msgstr "" #: templates/account/partials/site.php:214 msgid "Owner ID" msgstr "" #: templates/account/partials/site.php:288 msgid "Subscription" msgstr "" #: templates/forms/deactivation/contact.php:19 msgid "Sorry for the inconvenience and we are here to help if you give us a chance." msgstr "" #: templates/forms/deactivation/contact.php:22 msgid "Contact Support" msgstr "" #: templates/forms/deactivation/form.php:65 msgid "Anonymous feedback" msgstr "" #: templates/forms/deactivation/form.php:71 msgid "hour" msgstr "" #: templates/forms/deactivation/form.php:76 msgid "hours" msgstr "" #: templates/forms/deactivation/form.php:81, templates/forms/deactivation/form.php:86 msgid "days" msgstr "" #: templates/forms/deactivation/form.php:106 msgid "Deactivate" msgstr "" #: templates/forms/deactivation/form.php:108 msgid "Activate %s" msgstr "" #: templates/forms/deactivation/form.php:111 msgid "Submit & %s" msgstr "" #: templates/forms/deactivation/form.php:130 msgid "Quick Feedback" msgstr "" #: templates/forms/deactivation/form.php:134 msgid "If you have a moment, please let us know why you are %s" msgstr "" #: templates/forms/deactivation/form.php:134 msgid "deactivating" msgstr "" #: templates/forms/deactivation/form.php:134 msgid "switching" msgstr "" #: templates/forms/deactivation/form.php:448 msgid "Kindly tell us the reason so we can improve." msgstr "" #: templates/forms/deactivation/form.php:478 msgid "Snooze & %s" msgstr "" #: templates/forms/deactivation/form.php:638 msgid "Yes - %s" msgstr "" #: templates/forms/deactivation/form.php:645 msgid "Skip & %s" msgstr "" #: templates/forms/deactivation/retry-skip.php:21 msgid "Click here to use the plugin anonymously" msgstr "" #: templates/forms/deactivation/retry-skip.php:23 msgid "You might have missed it, but you don't have to share any data and can just %s the opt-in." msgstr "" freemius/index.php000064400000000127146725417150010217 0ustar00plugins ) ) { $fs_active_plugins->plugins = array(); } } if ( empty( $fs_active_plugins->abspath ) ) { /** * Store the WP install absolute path reference to identify environment change * while replicating the storage. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 */ $fs_active_plugins->abspath = ABSPATH; } else { if ( ABSPATH !== $fs_active_plugins->abspath ) { /** * WordPress path has changed, cleanup the SDK references cache. * This resolves issues triggered when spinning a staging environments * while replicating the database. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 */ $fs_active_plugins->abspath = ABSPATH; $fs_active_plugins->plugins = array(); unset( $fs_active_plugins->newest ); } else { /** * Make sure SDK references are still valid. This resolves * issues when users hard delete modules via FTP. * * @author Vova Feldman (@svovaf) * @since 1.2.1.7 */ $has_changes = false; foreach ( $fs_active_plugins->plugins as $sdk_path => $data ) { if ( ! file_exists( ( isset( $data->type ) && 'theme' === $data->type ? $themes_directory : WP_PLUGIN_DIR ) . '/' . $sdk_path ) ) { unset( $fs_active_plugins->plugins[ $sdk_path ] ); if ( ! empty( $fs_active_plugins->newest ) && $sdk_path === $fs_active_plugins->newest->sdk_path ) { unset( $fs_active_plugins->newest ); } $has_changes = true; } } if ( $has_changes ) { if ( empty( $fs_active_plugins->plugins ) ) { unset( $fs_active_plugins->newest ); } update_option( 'fs_active_plugins', $fs_active_plugins ); } } } if ( ! function_exists( 'fs_find_direct_caller_plugin_file' ) ) { require_once dirname( __FILE__ ) . '/includes/supplements/fs-essential-functions-1.1.7.1.php'; } if ( ! function_exists( 'fs_get_plugins' ) ) { require_once dirname( __FILE__ ) . '/includes/supplements/fs-essential-functions-2.2.1.php'; } // Update current SDK info based on the SDK path. if ( ! isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) || $this_sdk_version != $fs_active_plugins->plugins[ $this_sdk_relative_path ]->version ) { if ( $is_theme ) { $plugin_path = basename( dirname( $this_sdk_relative_path ) ); } else { $plugin_path = plugin_basename( fs_find_direct_caller_plugin_file( $file_path ) ); } $fs_active_plugins->plugins[ $this_sdk_relative_path ] = (object) array( 'version' => $this_sdk_version, 'type' => ( $is_theme ? 'theme' : 'plugin' ), 'timestamp' => time(), 'plugin_path' => $plugin_path, ); } $is_current_sdk_newest = isset( $fs_active_plugins->newest ) && ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path ); if ( ! isset( $fs_active_plugins->newest ) ) { /** * This will be executed only once, for the first time a Freemius powered plugin is activated. */ fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); $is_current_sdk_newest = true; } else if ( version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '<' ) ) { /** * Current SDK is newer than the newest stored SDK. */ fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); if ( class_exists( 'Freemius' ) ) { // Older SDK version was already loaded. if ( ! $fs_active_plugins->newest->in_activation ) { // Re-order plugins to load this plugin first. fs_newest_sdk_plugin_first(); } // Refresh page. fs_redirect( $_SERVER['REQUEST_URI'] ); } } else { if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $fs_newest_sdk = $fs_active_plugins->newest; $fs_newest_sdk = $fs_active_plugins->plugins[ $fs_newest_sdk->sdk_path ]; $is_newest_sdk_type_theme = ( isset( $fs_newest_sdk->type ) && 'theme' === $fs_newest_sdk->type ); if ( ! $is_newest_sdk_type_theme ) { $is_newest_sdk_plugin_active = is_plugin_active( $fs_newest_sdk->plugin_path ); } else { $current_theme = wp_get_theme(); $is_newest_sdk_plugin_active = ( $current_theme->stylesheet === $fs_newest_sdk->plugin_path ); $current_theme_parent = $current_theme->parent(); /** * If the current theme is a child of the theme that has the newest SDK, this prevents a redirects loop * from happening by keeping the SDK info stored in the `fs_active_plugins` option. */ if ( ! $is_newest_sdk_plugin_active && $current_theme_parent instanceof WP_Theme ) { $is_newest_sdk_plugin_active = ( $fs_newest_sdk->plugin_path === $current_theme_parent->stylesheet ); } } if ( $is_current_sdk_newest && ! $is_newest_sdk_plugin_active && ! $fs_active_plugins->newest->in_activation ) { // If current SDK is the newest and the plugin is NOT active, it means // that the current plugin in activation mode. $fs_active_plugins->newest->in_activation = true; update_option( 'fs_active_plugins', $fs_active_plugins ); } if ( ! $is_theme ) { $sdk_starter_path = fs_normalize_path( WP_PLUGIN_DIR . '/' . $this_sdk_relative_path . '/start.php' ); } else { $sdk_starter_path = fs_normalize_path( $themes_directory . '/' . str_replace( "../{$themes_directory_name}/", '', $this_sdk_relative_path ) . '/start.php' ); } $is_newest_sdk_path_valid = ( $is_newest_sdk_plugin_active || $fs_active_plugins->newest->in_activation ) && file_exists( $sdk_starter_path ); if ( ! $is_newest_sdk_path_valid && ! $is_current_sdk_newest ) { // Plugin with newest SDK is no longer active, or SDK was moved to a different location. unset( $fs_active_plugins->plugins[ $fs_active_plugins->newest->sdk_path ] ); } if ( ! ( $is_newest_sdk_plugin_active || $fs_active_plugins->newest->in_activation ) || ! $is_newest_sdk_path_valid || // Is newest SDK downgraded. ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '>' ) ) ) { /** * Plugin with newest SDK is no longer active. * OR * The newest SDK was in the current plugin. BUT, seems like the version of * the SDK was downgraded to a lower SDK. */ // Find the active plugin with the newest SDK version and update the newest reference. fs_fallback_to_newest_active_sdk(); } else { if ( $is_newest_sdk_plugin_active && $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && ( $fs_active_plugins->newest->in_activation || ( class_exists( 'Freemius' ) && ( ! defined( 'WP_FS__SDK_VERSION' ) || version_compare( WP_FS__SDK_VERSION, $this_sdk_version, '<' ) ) ) ) ) { if ( $fs_active_plugins->newest->in_activation && ! $is_newest_sdk_type_theme ) { // Plugin no more in activation. $fs_active_plugins->newest->in_activation = false; update_option( 'fs_active_plugins', $fs_active_plugins ); } // Reorder plugins to load plugin with newest SDK first. if ( fs_newest_sdk_plugin_first() ) { // Refresh page after re-order to make sure activated plugin loads newest SDK. if ( class_exists( 'Freemius' ) ) { fs_redirect( $_SERVER['REQUEST_URI'] ); } } } } } if ( class_exists( 'Freemius' ) ) { // SDK was already loaded. return; } if ( version_compare( $this_sdk_version, $fs_active_plugins->newest->version, '<' ) ) { $newest_sdk = $fs_active_plugins->plugins[ $fs_active_plugins->newest->sdk_path ]; $plugins_or_theme_dir_path = ( ! isset( $newest_sdk->type ) || 'theme' !== $newest_sdk->type ) ? WP_PLUGIN_DIR : $themes_directory; $newest_sdk_starter = fs_normalize_path( $plugins_or_theme_dir_path . '/' . str_replace( "../{$themes_directory_name}/", '', $fs_active_plugins->newest->sdk_path ) . '/start.php' ); if ( file_exists( $newest_sdk_starter ) ) { // Reorder plugins to load plugin with newest SDK first. fs_newest_sdk_plugin_first(); // There's a newer SDK version, load it instead of the current one! require_once $newest_sdk_starter; return; } } #endregion SDK Selection Logic -------------------------------------------------------------------- #region Hooks & Filters Collection -------------------------------------------------------------------- /** * Freemius hooks (actions & filters) tags structure: * * fs_{filter/action_name}_{plugin_slug} * * -------------------------------------------------------- * * Usage with WordPress' add_action() / add_filter(): * * add_action('fs_{filter/action_name}_{plugin_slug}', $callable); * * -------------------------------------------------------- * * Usage with Freemius' instance add_action() / add_filter(): * * // No need to add 'fs_' prefix nor '_{plugin_slug}' suffix. * my_freemius()->add_action('{action_name}', $callable); * * -------------------------------------------------------- * * Freemius filters collection: * * fs_connect_url_{plugin_slug} * fs_trial_promotion_message_{plugin_slug} * fs_is_long_term_user_{plugin_slug} * fs_uninstall_reasons_{plugin_slug} * fs_is_plugin_update_{plugin_slug} * fs_api_domains_{plugin_slug} * fs_email_template_sections_{plugin_slug} * fs_support_forum_submenu_{plugin_slug} * fs_support_forum_url_{plugin_slug} * fs_connect_message_{plugin_slug} * fs_connect_message_on_update_{plugin_slug} * fs_uninstall_confirmation_message_{plugin_slug} * fs_pending_activation_message_{plugin_slug} * fs_is_submenu_visible_{plugin_slug} * fs_plugin_icon_{plugin_slug} * fs_show_trial_{plugin_slug} * * -------------------------------------------------------- * * Freemius actions collection: * * fs_after_license_loaded_{plugin_slug} * fs_after_license_change_{plugin_slug} * fs_after_plans_sync_{plugin_slug} * * fs_after_account_details_{plugin_slug} * fs_after_account_user_sync_{plugin_slug} * fs_after_account_plan_sync_{plugin_slug} * fs_before_account_load_{plugin_slug} * fs_after_account_connection_{plugin_slug} * fs_account_property_edit_{plugin_slug} * fs_account_email_verified_{plugin_slug} * fs_account_page_load_before_departure_{plugin_slug} * fs_before_account_delete_{plugin_slug} * fs_after_account_delete_{plugin_slug} * * fs_sdk_version_update_{plugin_slug} * fs_plugin_version_update_{plugin_slug} * * fs_initiated_{plugin_slug} * fs_after_init_plugin_registered_{plugin_slug} * fs_after_init_plugin_anonymous_{plugin_slug} * fs_after_init_plugin_pending_activations_{plugin_slug} * fs_after_init_addon_registered_{plugin_slug} * fs_after_init_addon_anonymous_{plugin_slug} * fs_after_init_addon_pending_activations_{plugin_slug} * * fs_after_premium_version_activation_{plugin_slug} * fs_after_free_version_reactivation_{plugin_slug} * * fs_after_uninstall_{plugin_slug} * fs_before_admin_menu_init_{plugin_slug} */ #endregion Hooks & Filters Collection -------------------------------------------------------------------- if ( ! class_exists( 'Freemius' ) ) { if ( ! defined( 'WP_FS__SDK_VERSION' ) ) { define( 'WP_FS__SDK_VERSION', $this_sdk_version ); } $plugins_or_theme_dir_path = fs_normalize_path( trailingslashit( $is_theme ? $themes_directory : WP_PLUGIN_DIR ) ); if ( 0 === strpos( $file_path, $plugins_or_theme_dir_path ) ) { // No symlinks } else { /** * This logic finds the SDK symlink and set WP_FS__DIR to use it. * * @author Vova Feldman (@svovaf) * @since 1.2.2.5 */ $sdk_symlink = null; // Try to load SDK's symlink from cache. if ( isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && is_object( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && ! empty( $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink ) ) { $sdk_symlink = $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink; if ( 0 === strpos( $sdk_symlink, $plugins_or_theme_dir_path ) ) { /** * Make the symlink path relative. * * @author Leo Fajardo (@leorw) */ $sdk_symlink = substr( $sdk_symlink, strlen( $plugins_or_theme_dir_path ) ); $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink = $sdk_symlink; update_option( 'fs_active_plugins', $fs_active_plugins ); } $realpath = realpath( $plugins_or_theme_dir_path . $sdk_symlink ); if ( ! is_string( $realpath ) || ! file_exists( $realpath ) ) { $sdk_symlink = null; } } if ( empty( $sdk_symlink ) ) // Has symlinks, therefore, we need to configure WP_FS__DIR based on the symlink. { $partial_path_right = basename( $file_path ); $partial_path_left = dirname( $file_path ); $realpath = realpath( $plugins_or_theme_dir_path . $partial_path_right ); while ( '/' !== $partial_path_left && ( false === $realpath || $file_path !== fs_normalize_path( $realpath ) ) ) { $partial_path_right = trailingslashit( basename( $partial_path_left ) ) . $partial_path_right; $partial_path_left_prev = $partial_path_left; $partial_path_left = dirname( $partial_path_left_prev ); /** * Avoid infinite loop if for example `$partial_path_left_prev` is `C:/`, in this case, * `dirname( 'C:/' )` will return `C:/`. * * @author Leo Fajardo (@leorw) */ if ( $partial_path_left === $partial_path_left_prev ) { $partial_path_left = ''; break; } $realpath = realpath( $plugins_or_theme_dir_path . $partial_path_right ); } if ( ! empty( $partial_path_left ) && '/' !== $partial_path_left ) { $sdk_symlink = fs_normalize_path( dirname( $partial_path_right ) ); // Cache value. if ( isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && is_object( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) ) { $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink = $sdk_symlink; update_option( 'fs_active_plugins', $fs_active_plugins ); } } } if ( ! empty( $sdk_symlink ) ) { // Set SDK dir to the symlink path. define( 'WP_FS__DIR', $plugins_or_theme_dir_path . $sdk_symlink ); } } // Load SDK files. require_once dirname( __FILE__ ) . '/require.php'; /** * Quick shortcut to get Freemius for specified plugin. * Used by various templates. * * @param number $module_id * * @return Freemius */ function freemius( $module_id ) { return Freemius::instance( $module_id ); } /** * @param string $slug * @param number $plugin_id * @param string $public_key * @param bool $is_live Is live or test plugin. * @param bool $is_premium Hints freemius if running the premium plugin or not. * * @return Freemius * * @deprecated Please use fs_dynamic_init(). */ function fs_init( $slug, $plugin_id, $public_key, $is_live = true, $is_premium = true ) { $fs = Freemius::instance( $plugin_id, $slug, true ); $fs->init( $plugin_id, $public_key, $is_live, $is_premium ); return $fs; } /** * @param array $module Plugin or Theme details. * * @return Freemius * @throws Freemius_Exception */ function fs_dynamic_init( $module ) { $fs = Freemius::instance( $module['id'], $module['slug'], true ); $fs->dynamic_init( $module ); return $fs; } function fs_dump_log() { FS_Logger::dump(); } } freemius/require.php000064400000006072146725417150010571 0ustar00get_slug(); $timestamp = time(); $context_params = array( 'plugin_id' => $fs->get_id(), 'public_key' => $fs->get_public_key(), 'plugin_version' => $fs->get_plugin_version(), 'mode' => 'dashboard', 'trial' => fs_request_get_bool( 'trial' ), 'is_ms' => ( fs_is_network_admin() && $fs->is_network_active() ), ); $plan_id = fs_request_get( 'plan_id' ); if ( FS_Plugin_Plan::is_valid_id( $plan_id ) ) { $context_params['plan_id'] = $plan_id; } $licenses = fs_request_get( 'licenses' ); if ( $licenses === strval( intval( $licenses ) ) && $licenses > 0 ) { $context_params['licenses'] = $licenses; } $plugin_id = fs_request_get( 'plugin_id' ); if ( ! FS_Plugin::is_valid_id( $plugin_id ) ) { $plugin_id = $fs->get_id(); } if ( $plugin_id == $fs->get_id() ) { $is_premium = $fs->is_premium(); $bundle_id = $fs->get_bundle_id(); if ( ! is_null( $bundle_id ) ) { $context_params['bundle_id'] = $bundle_id; } } else { // Identify the module code version of the checkout context module. if ( $fs->is_addon_activated( $plugin_id ) ) { $fs_addon = Freemius::get_instance_by_id( $plugin_id ); $is_premium = $fs_addon->is_premium(); } else { // If add-on isn't activated assume the premium version isn't installed. $is_premium = false; } } // Get site context secure params. if ( $fs->is_registered() ) { $site = $fs->get_site(); if ( $plugin_id != $fs->get_id() ) { if ( $fs->is_addon_activated( $plugin_id ) ) { $fs_addon = Freemius::get_instance_by_id( $plugin_id ); $addon_site = $fs_addon->get_site(); if ( is_object( $addon_site ) ) { $site = $addon_site; } } } $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( $site, $timestamp, 'checkout' ) ); } else { $current_user = Freemius::_get_current_wp_user(); // Add site and user info to the request, this information // is NOT being stored unless the user complete the purchase // and agrees to the TOS. $context_params = array_merge( $context_params, array( 'user_firstname' => $current_user->user_firstname, 'user_lastname' => $current_user->user_lastname, 'user_email' => $current_user->user_email, 'home_url' => home_url(), ) ); $fs_user = Freemius::_get_user_by_email( $current_user->user_email ); if ( is_object( $fs_user ) && $fs_user->is_verified() ) { $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( $fs_user, $timestamp, 'checkout' ) ); } } if ( $fs->is_payments_sandbox() ) { // Append plugin secure token for sandbox mode authentication. $context_params['sandbox'] = FS_Security::instance()->get_secure_token( $fs->get_plugin(), $timestamp, 'checkout' ); /** * @since 1.1.7.3 Add security timestamp for sandbox even for anonymous user. */ if ( empty( $context_params['s_ctx_ts'] ) ) { $context_params['s_ctx_ts'] = $timestamp; } } $return_url = $fs->_get_sync_license_url( $plugin_id ); $can_user_install = ( ( $fs->is_plugin() && current_user_can( 'install_plugins' ) ) || ( $fs->is_theme() && current_user_can( 'install_themes' ) ) ); $query_params = array_merge( $context_params, $_GET, array( // Current plugin version. 'plugin_version' => $fs->get_plugin_version(), 'sdk_version' => WP_FS__SDK_VERSION, 'is_premium' => $is_premium ? 'true' : 'false', 'can_install' => $can_user_install ? 'true' : 'false', 'return_url' => $return_url, ) ); $xdebug_session = fs_request_get( 'XDEBUG_SESSION' ); if ( false !== $xdebug_session ) { $query_params['XDEBUG_SESSION'] = $xdebug_session; } $view_params = array( 'id' => $VARS['id'], 'page' => strtolower( $fs->get_text_inline( 'Checkout', 'checkout' ) ) . ' ' . $fs->get_text_inline( 'PCI compliant', 'pci-compliant' ), ); fs_require_once_template('secure-https-header.php', $view_params); ?>

    freemius/templates/contact.php000064400000010211146725417150012534 0ustar00get_slug(); $context_params = array( 'plugin_id' => $fs->get_id(), 'plugin_public_key' => $fs->get_public_key(), 'plugin_version' => $fs->get_plugin_version(), ); // Get site context secure params. if ( $fs->is_registered() ) { $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( $fs->get_site(), time(), 'contact' ) ); } $query_params = array_merge( $_GET, array_merge( $context_params, array( 'plugin_version' => $fs->get_plugin_version(), 'wp_login_url' => wp_login_url(), 'site_url' => Freemius::get_unfiltered_site_url(), // 'wp_admin_css' => get_bloginfo('wpurl') . "/wp-admin/load-styles.php?c=1&load=buttons,wp-admin,dashicons", ) ) ); $view_params = array( 'id' => $VARS['id'], 'page' => strtolower( $fs->get_text_inline( 'Contact', 'contact' ) ), ); fs_require_once_template('secure-https-header.php', $view_params); $has_tabs = $fs->_add_tabs_before_content(); if ( $has_tabs ) { $query_params['tabs'] = 'true'; } ?>
    _add_tabs_after_content(); } $params = array( 'page' => 'contact', 'module_id' => $fs->get_id(), 'module_type' => $fs->get_module_type(), 'module_slug' => $slug, 'module_version' => $fs->get_plugin_version(), ); fs_require_template( 'powered-by.php', $params );freemius/templates/plugin-info/description.php000064400000004210146725417150015655 0ustar00info->selling_point_0 ) || ! empty( $plugin->info->selling_point_1 ) || ! empty( $plugin->info->selling_point_2 ) ) : ?>
      info->{'selling_point_' . $i} ) ) : ?>
    • info->{'selling_point_' . $i} ) ?>

    info->description, array( 'a' => array( 'href' => array(), 'title' => array(), 'target' => array() ), 'b' => array(), 'i' => array(), 'p' => array(), 'blockquote' => array(), 'h2' => array(), 'h3' => array(), 'ul' => array(), 'ol' => array(), 'li' => array() ) ); ?>
    info->screenshots ) ) : ?> info->screenshots ?>

    slug ) ?>

      $url ) : ?>
    freemius/templates/plugin-info/index.php000064400000000127146725417150014444 0ustar00features) && is_array($plan->features)) { foreach ( $plan->features as $feature ) { if ( ! isset( $features_plan_map[ $feature->id ] ) ) { $features_plan_map[ $feature->id ] = array( 'feature' => $feature, 'plans' => array() ); } $features_plan_map[ $feature->id ]['plans'][ $plan->id ] = $feature; } } // Add support as a feature. if ( ! empty( $plan->support_email ) || ! empty( $plan->support_skype ) || ! empty( $plan->support_phone ) || true === $plan->is_success_manager ) { if ( ! isset( $features_plan_map['support'] ) ) { $support_feature = new stdClass(); $support_feature->id = 'support'; $support_feature->title = fs_text_inline( 'Support', $plugin->slug ); $features_plan_map[ $support_feature->id ] = array( 'feature' => $support_feature, 'plans' => array() ); } else { $support_feature = $features_plan_map['support']['feature']; } $features_plan_map[ $support_feature->id ]['plans'][ $plan->id ] = $support_feature; } } // Add updates as a feature for all plans. $updates_feature = new stdClass(); $updates_feature->id = 'updates'; $updates_feature->title = fs_text_inline( 'Unlimited Updates', 'unlimited-updates', $plugin->slug ); $features_plan_map[ $updates_feature->id ] = array( 'feature' => $updates_feature, 'plans' => array() ); foreach ( $plans as $plan ) { $features_plan_map[ $updates_feature->id ]['plans'][ $plan->id ] = $updates_feature; } ?>
    $data ) : ?>
    title ?> pricing ) ) { fs_esc_html_echo_inline( 'Free', 'free', $plugin->slug ); } else { foreach ( $plan->pricing as $pricing ) { /** * @var FS_Pricing $pricing */ if ( 1 == $pricing->licenses ) { if ( $pricing->has_annual() ) { echo "\${$pricing->annual_price} / " . fs_esc_html_x_inline( 'year', 'as annual period', 'year', $plugin->slug ); } else if ( $pricing->has_monthly() ) { echo "\${$pricing->monthly_price} / " . fs_esc_html_x_inline( 'mo', 'as monthly period', 'mo', $plugin->slug ); } else { echo "\${$pricing->lifetime_price}"; } } } } ?>
    title ) ) ?> id ] ) ) : ?> id ]->value ) ) : ?> id ]->value ) ?>
    freemius/templates/plugin-info/screenshots.php000064400000001320146725417150015671 0ustar00
      $url ) : ?>
    freemius/templates/plugin-icon.php000064400000001024146725417150013327 0ustar00
    freemius/templates/add-ons.php000064400000056366146725417150012453 0ustar00get_slug(); $open_addon_slug = fs_request_get( 'slug' ); $open_addon = false; $is_data_debug_mode = $fs->is_data_debug_mode(); $is_whitelabeled = $fs->is_whitelabeled(); /** * @var FS_Plugin[] */ $addons = $fs->get_addons(); $has_addons = ( is_array( $addons ) && 0 < count( $addons ) ); $account_addon_ids = $fs->get_updated_account_addons(); $download_latest_text = fs_text_x_inline( 'Download Latest', 'as download latest version', 'download-latest', $slug ); $view_details_text = fs_text_inline( 'View details', 'view-details', $slug ); $has_tabs = $fs->_add_tabs_before_content(); $fs_blog_id = ( is_multisite() && ! is_network_admin() ) ? get_current_blog_id() : 0; ?>

    get_plugin_name() ) ) ?>

    do_action( 'addons/after_title' ) ?>

      _get_addons_plans_and_pricing_map_by_id(); $active_plugins_directories_map = Freemius::get_active_plugins_directories_map( $fs_blog_id ); ?> is_whitelabeled_by_flag() ) { $hide_all_addons_data = true; $addon_ids = $fs->get_updated_account_addons(); $installed_addons = $fs->get_installed_addons(); foreach ( $installed_addons as $fs_addon ) { $addon_ids[] = $fs_addon->get_id(); } if ( ! empty( $addon_ids ) ) { $addon_ids = array_unique( $addon_ids ); } foreach ( $addon_ids as $addon_id ) { $addon = $fs->get_addon( $addon_id ); if ( ! is_object( $addon ) ) { continue; } $addon_storage = FS_Storage::instance( WP_FS__MODULE_TYPE_PLUGIN, $addon->slug ); if ( ! $addon_storage->is_whitelabeled ) { $hide_all_addons_data = false; break; } if ( $is_data_debug_mode ) { $is_whitelabeled = false; } } } ?> get_addon_basename( $addon->id ); $is_addon_installed = file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $basename ) ); if ( ! $is_addon_installed && $hide_all_addons_data ) { continue; } $is_addon_activated = $is_addon_installed ? $fs->is_addon_activated( $addon->id ) : false; $is_plugin_active = ( $is_addon_activated || isset( $active_plugins_directories_map[ dirname( $basename ) ] ) ); $open_addon = ( $open_addon || ( $open_addon_slug === $addon->slug ) ); $price = 0; $has_trial = false; $has_free_plan = false; $has_paid_plan = false; if ( isset( $plans_and_pricing_by_addon_id[$addon->id] ) ) { $plans = $plans_and_pricing_by_addon_id[$addon->id]; if ( is_array( $plans ) && 0 < count( $plans ) ) { foreach ( $plans as $plan ) { if ( ! isset( $plan->pricing ) || ! is_array( $plan->pricing ) || 0 == count( $plan->pricing ) ) { // No pricing means a free plan. $has_free_plan = true; continue; } $has_paid_plan = true; $has_trial = $has_trial || ( is_numeric( $plan->trial_period ) && ( $plan->trial_period > 0 ) ); $min_price = 999999; foreach ( $plan->pricing as $pricing ) { $pricing = new FS_Pricing( $pricing ); if ( ! $pricing->is_usd() ) { /** * Skip non-USD pricing. * * @author Leo Fajardo (@leorw) * @since 2.3.1 */ continue; } if ( $pricing->has_annual() ) { $min_price = min( $min_price, $pricing->annual_price ); } else if ( $pricing->has_monthly() ) { $min_price = min( $min_price, 12 * $pricing->monthly_price ); } } if ( $min_price < 999999 ) { $price = $min_price; } } } if ( ! $has_paid_plan && ! $has_free_plan ) { continue; } } ?>
    • get_id() . '&plugin=' . $addon->slug . '&TB_iframe=true&width=600&height=550' ) ), esc_attr( sprintf( fs_text_inline( 'More information about %s', 'more-information-about-x', $slug ), $addon->title ) ), esc_attr( $addon->title ) ) . ' class="thickbox%s">%s'; echo sprintf( $view_details_link, /** * Additional class. * * @author Leo Fajardo (@leorw) * @since 2.2.4 */ ' fs-overlay', /** * Set the view details link text to an empty string since it is an overlay that * doesn't really need a text and whose purpose is to open the details dialog when * the card is clicked. * * @author Leo Fajardo (@leorw) * @since 2.2.4 */ '' ); ?> info ) ) { $addon->info = new stdClass(); } if ( ! isset( $addon->info->card_banner_url ) ) { $addon->info->card_banner_url = '//dashboard.freemius.com/assets/img/marketing/blueprint-300x100.jpg'; } if ( ! isset( $addon->info->short_description ) ) { $addon->info->short_description = 'What\'s the one thing your add-on does really, really well?'; } ?>
      • %s', esc_html( $is_plugin_active ? fs_text_x_inline( 'Active', 'active add-on', 'active-addon', $slug ) : fs_text_x_inline( 'Installed', 'installed add-on', 'installed-addon', $slug ) ) ); } ?>
      • title ?>
      • 0) $descriptors[] = '$' . number_format( $price, 2 ); if ($has_trial) $descriptors[] = fs_text_x_inline( 'Trial', 'trial period', 'trial', $slug ); echo implode(' - ', $descriptors); } ?>
      • info->short_description ) ? $addon->info->short_description : 'SHORT DESCRIPTION' ?>
      • is_wp_org_compliant ); $is_allowed_to_install = ( $fs->is_allowed_to_install() || $is_free_only_wp_org_compliant ); $show_premium_activation_or_installation_action = true; if ( ! in_array( $addon->id, $account_addon_ids ) ) { $show_premium_activation_or_installation_action = false; } else if ( $is_addon_installed ) { /** * If any add-on's version (free or premium) is installed, check if the * premium version can be activated and show the relevant action. Otherwise, * show the relevant action for the free version. * * @author Leo Fajardo (@leorw) * @since 2.4.5 */ $fs_addon = $is_addon_activated ? $fs->get_addon_instance( $addon->id ) : null; $premium_plugin_basename = is_object( $fs_addon ) ? $fs_addon->premium_plugin_basename() : "{$addon->premium_slug}/{$addon->slug}.php"; if ( ( $is_addon_activated && $fs_addon->is_premium() ) || file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $premium_plugin_basename ) ) ) { $basename = $premium_plugin_basename; } $show_premium_activation_or_installation_action = ( ( ! $is_addon_activated || ! $fs_addon->is_premium() ) && /** * This check is needed for cases when an active add-on doesn't have an * associated Freemius instance. * * @author Leo Fajardo (@leorw) * @since 2.4.5 */ ( ! $is_plugin_active ) ); } ?>
      • _get_latest_download_local_url( $addon->id ); ?>
      • %s', wp_nonce_url( self_admin_url( 'update.php?' . ( ( $has_paid_plan || ! $addon->is_wp_org_compliant ) ? 'fs_allow_updater_and_dialog=true&' : '' ) . 'action=install-plugin&plugin=' . $addon->slug ), 'install-plugin_' . $addon->slug ), fs_esc_html_inline( 'Install Now', 'install-now', $slug ) ); } else { echo sprintf( '%s', wp_nonce_url( 'plugins.php?action=activate&plugin=' . $basename, 'activate-plugin_' . $basename ), fs_esc_attr_inline( 'Activate this add-on', 'activate-this-addon', $addon->slug ), fs_text_inline( 'Activate', 'activate', $addon->slug ) ); } ?>
    do_action( 'addons/after_addons' ) ?>
    _add_tabs_after_content(); } $params = array( 'page' => 'addons', 'module_id' => $fs->get_id(), 'module_type' => $fs->get_module_type(), 'module_slug' => $slug, 'module_version' => $fs->get_plugin_version(), ); fs_require_template( 'powered-by.php', $params );freemius/templates/tabs-capture-js.php000064400000003356146725417150014121 0ustar00get_slug(); ?> freemius/templates/gdpr-optin-js.php000064400000004701146725417150013605 0ustar00 freemius/templates/connect.php000064400000127700146725417150012546 0ustar00get_slug(); $is_pending_activation = $fs->is_pending_activation(); $is_premium_only = $fs->is_only_premium(); $has_paid_plans = $fs->has_paid_plan(); $is_premium_code = $fs->is_premium(); $is_freemium = $fs->is_freemium(); $fs->_enqueue_connect_essentials(); /** * Enqueueing the styles in `_enqueue_connect_essentials()` is too late, as we need them in the HEADER. Therefore, inject the styles inline to avoid FOUC. * * @author Vova Feldman (@svovaf) */ echo "\n"; $current_user = Freemius::_get_current_wp_user(); $first_name = $current_user->user_firstname; if ( empty( $first_name ) ) { $first_name = $current_user->nickname; } $site_url = Freemius::get_unfiltered_site_url(); $protocol_pos = strpos( $site_url, '://' ); if ( false !== $protocol_pos ) { $site_url = substr( $site_url, $protocol_pos + 3 ); } $freemius_usage_tracking_url = $fs->get_usage_tracking_terms_url(); $freemius_plugin_terms_url = $fs->get_eula_url(); $error = fs_request_get( 'error' ); $has_release_on_freemius = $fs->has_release_on_freemius(); $require_license_key = $is_premium_only || ( $is_freemium && ( $is_premium_code || ! $has_release_on_freemius ) && fs_request_get_bool( 'require_license', ( $is_premium_code || $has_release_on_freemius ) ) ); $freemius_activation_terms_url = ($fs->is_premium() && $require_license_key) ? $fs->get_license_activation_terms_url() : $freemius_usage_tracking_url; $freemius_activation_terms_html = 'freemius.com'; if ( $is_pending_activation ) { $require_license_key = false; } if ( $require_license_key ) { $fs->_add_license_activation_dialog_box(); } $is_optin_dialog = ( $fs->is_theme() && $fs->is_themes_page() && $fs->show_opt_in_on_themes_page() ); if ( $is_optin_dialog ) { $show_close_button = false; $previous_theme_activation_url = ''; if ( ! $is_premium_code ) { $show_close_button = true; } else if ( $is_premium_only ) { $previous_theme_activation_url = $fs->get_previous_theme_activation_url(); $show_close_button = ( ! empty( $previous_theme_activation_url ) ); } } $is_network_level_activation = ( fs_is_network_admin() && $fs->is_network_active() && ! $fs->is_network_delegated_connection() ); $fs_user = Freemius::_get_user_by_email( $current_user->user_email ); $activate_with_current_user = ( is_object( $fs_user ) && ! $is_pending_activation && // If requires a license for activation, use the user associated with the license for the opt-in. ! $require_license_key && ! $is_network_level_activation ); $optin_params = $fs->get_opt_in_params( array(), $is_network_level_activation ); $sites = isset( $optin_params['sites'] ) ? $optin_params['sites'] : array(); $is_network_upgrade_mode = ( fs_is_network_admin() && $fs->is_network_upgrade_mode() ); /* translators: %s: name (e.g. Hey John,) */ $hey_x_text = esc_html( sprintf( fs_text_x_inline( 'Hey %s,', 'greeting', 'hey-x', $slug ), $first_name ) ); $activation_state = array( 'is_license_activation' => $require_license_key, 'is_pending_activation' => $is_pending_activation, 'is_gdpr_required' => true, 'is_network_level_activation' => $is_network_level_activation, 'is_dialog' => $is_optin_dialog, ); ?>
    do_action( 'connect/before', $activation_state ); ?>
    $fs->get_id(), 'size' => $size, ); fs_require_once_template( 'plugin-icon.php', $vars ); ?>
    do_action( 'connect/before_message', $activation_state ) ?>
    apply_filters( 'connect_error_esc_html', esc_html( $error ) ) ?>
    is_plugin_update() ) { echo $fs->apply_filters( 'connect-header', sprintf( '

    %s

    ', esc_html( fs_text_inline( 'Never miss an important update', 'connect-header' ) ) ) ); } else { echo $fs->apply_filters( 'connect-header_on-update', sprintf( '

    %s

    ', sprintf( esc_html( /* translators: %1$s: plugin name (e.g., "Awesome Plugin"); %2$s: version (e.g., "1.2.3") */ fs_text_inline('Thank you for updating to %1$s v%2$s!', 'connect-header_on-update' ) ), esc_html( $fs->get_plugin_name() ), $fs->get_plugin_version() ) ) ); } } ?>

    apply_filters( 'pending_activation_message', sprintf( /* translators: %s: name (e.g. Thanks John!) */ fs_text_inline( 'Thanks %s!', 'thanks-x', $slug ) . '
    ' . fs_text_inline( 'You should receive a confirmation email for %s to your mailbox at %s. Please make sure you click the button in that email to %s.', 'pending-activation-message', $slug ), $first_name, '' . $fs->get_plugin_name() . '', '' . $current_user->user_email . '', fs_text_inline( 'complete the opt-in', 'complete-the-opt-in', $slug ) ) ); } else if ( $require_license_key ) { $button_label = fs_text_inline( 'Activate License', 'activate-license', $slug ); $message = $fs->apply_filters( 'connect-message_on-premium', sprintf( fs_text_inline( 'Welcome to %s! To get started, please enter your license key:', 'thanks-for-purchasing', $slug ), '' . $fs->get_plugin_name() . '' ), $first_name, $fs->get_plugin_name() ); } else { $filter = 'connect_message'; if ( ! $fs->is_plugin_update() ) { $default_optin_message = esc_html( sprintf( /* translators: %s: module type (plugin, theme, or add-on) */ fs_text_inline( 'Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info. This will help us make the %s more compatible with your site and better at doing what you need it to.', 'connect-message', $slug ), $fs->get_module_label( true ) ) ); } else { // If Freemius was added on a plugin update, set different // opt-in message. /* translators: %s: module type (plugin, theme, or add-on) */ $default_optin_message = esc_html( sprintf( fs_text_inline( 'We have introduced this opt-in so you never miss an important update and help us make the %s more compatible with your site and better at doing what you need it to.', 'connect-message_on-update_why' ), $fs->get_module_label( true ) ) ); $default_optin_message .= '

    ' . esc_html( fs_text_inline( 'Opt in to get email notifications for security & feature updates, educational content, and occasional offers, and to share some basic WordPress environment info.', 'connect-message_on-update', $slug ) ); if ( $fs->is_enable_anonymous() ) { $default_optin_message .= ' ' . esc_html( fs_text_inline( 'If you skip this, that\'s okay! %1$s will still work just fine.', 'connect-message_on-update_skip', $slug ) ); } // If user customized the opt-in message on update, use // that message. Otherwise, fallback to regular opt-in // custom message if exists. if ( $fs->has_filter( 'connect_message_on_update' ) ) { $filter = 'connect_message_on_update'; } } $message = $fs->apply_filters( $filter, sprintf( $default_optin_message, '' . esc_html( $fs->get_plugin_name() ) . '', '' . $current_user->user_login . '', '' . $site_url . '', $freemius_activation_terms_html ), $first_name, $fs->get_plugin_name(), $current_user->user_login, '' . $site_url . '', $freemius_activation_terms_html, true ); } if ( $is_network_upgrade_mode ) { $network_integration_text = esc_html( fs_text_inline( 'We\'re excited to introduce the Freemius network-level integration.', 'connect_message_network_upgrade', $slug ) ); if ($is_premium_code){ $message = $network_integration_text . ' ' . sprintf( fs_text_inline( 'During the update process we detected %d site(s) that are still pending license activation.', 'connect_message_network_upgrade-premium', $slug ), count( $sites ) ); $message .= '

    ' . sprintf( fs_text_inline( 'If you\'d like to use the %s on those sites, please enter your license key below and click the activation button.', 'connect_message_network_upgrade-premium-activate-license', $slug ), $is_premium_only ? $fs->get_module_label( true ) : sprintf( /* translators: %s: module type (plugin, theme, or add-on) */ fs_text_inline( "%s's paid features", 'x-paid-features', $slug ), $fs->get_module_label( true ) ) ); /* translators: %s: module type (plugin, theme, or add-on) */ $message .= ' ' . sprintf( fs_text_inline( 'Alternatively, you can skip it for now and activate the license later, in your %s\'s network-level Account page.', 'connect_message_network_upgrade-premium-skip-license', $slug ), $fs->get_module_label( true ) ); }else { $message = $network_integration_text . ' ' . sprintf( fs_text_inline( 'During the update process we detected %s site(s) in the network that are still pending your attention.', 'connect_message_network_upgrade-free', $slug ), count( $sites ) ) . '

    ' . ( fs_starts_with( $message, $hey_x_text . '
    ' ) ? substr( $message, strlen( $hey_x_text . '
    ' ) ) : $message ); } } echo $message; ?>

    do_action( 'connect/after_license_input', $activation_state ); ?> - %s', $fs->get_text_inline( 'Yes', 'yes' ), $fs->get_text_inline( 'send me security & feature updates, educational content and offers.', 'send-updates' ) ); $do_not_send_updates_text = sprintf( '%s - %s', $fs->get_text_inline( 'No', 'no' ), sprintf( $fs->get_text_inline( 'do %sNOT%s send me security & feature updates, educational content and offers.', 'do-not-send-updates' ), '', '' ) ); ?>
    $fs->get_id(), 'sites' => $sites, 'require_license_key' => $require_license_key ); echo fs_get_template( 'partials/network-activation.php', $vars ); ?> do_action( 'connect/after_message', $activation_state ) ?>
    do_action( 'connect/before_actions', $activation_state ) ?> is_enable_anonymous() && ! $is_pending_activation && ( ! $require_license_key || $is_network_upgrade_mode ) ) : ?> apply_filters( 'show_delegation_option', true ) ) : ?>
    get_public_key() ) ?>
    $value ) : ?>
    do_action( 'connect/after_actions', $activation_state ) ?>
    is_permission_requested( 'newsletter' ) ) { $permissions[] = $permission_manager->get_newsletter_permission(); } $permissions = $permission_manager->get_permissions( $require_license_key, $permissions ); if ( ! empty( $permissions ) ) : ?>

    do_action( 'connect/after', $activation_state ); if ( $is_optin_dialog ) { ?>
    data-id="" data-manager-id="" data-slug="" data-type="" class=" fs-notice">
    freemius/templates/debug.php000064400000114316146725417150012202 0ustar00

    newest->version ?>

    get_option( 'ms_migration_complete', false, true ) ) : ?>
    Resolve Clone(s)
    'WP_FS__REMOTE_ADDR', 'val' => WP_FS__REMOTE_ADDR, ), array( 'key' => 'WP_FS__ADDRESS_PRODUCTION', 'val' => WP_FS__ADDRESS_PRODUCTION, ), array( 'key' => 'FS_API__ADDRESS', 'val' => FS_API__ADDRESS, ), array( 'key' => 'FS_API__SANDBOX_ADDRESS', 'val' => FS_API__SANDBOX_ADDRESS, ), array( 'key' => 'WP_FS__DIR', 'val' => WP_FS__DIR, ), array( 'key' => 'wp_using_ext_object_cache()', 'val' => wp_using_ext_object_cache() ? 'true' : 'false', ), ) ?>
    >

    plugins as $sdk_path => $data ) : ?> version ) ?> >
    version ?> plugin_path ?>
    get_option( $module_type . 's' ), FS_Plugin::get_class_name() ) ?> 0 ) : ?>

    $data ) : ?> file ); } else { $current_theme = wp_get_theme(); $is_active = ( $current_theme->stylesheet === $data->file ); if ( ! $is_active && is_child_theme() ) { $parent_theme = $current_theme->parent(); $is_active = ( ( $parent_theme instanceof WP_Theme ) && $parent_theme->stylesheet === $data->file ); } } ?> id ); $active_modules_by_id[ $data->id ] = true; } ?> has_api_connectivity(); if ( true === $has_api_connectivity && $fs->is_on() ) { echo ' style="background: #E6FFE6; font-weight: bold"'; } else { echo ' style="background: #ffd0d0; font-weight: bold"'; } } ?>> > is_on() ) { echo ' style="color: red; text-transform: uppercase;"'; } ?>>is_on() ? $on_text : $off_text ); } ?> get_network_install_blog_id(); $network_user = $fs->get_network_user(); } ?>
    id ?> version ?> title ?> file ?> public_key ?> email; } ?> has_trial_plan() ) : ?>
    is_registered() ) : ?> is_network_upgrade_mode() ) : ?>
    0 ) : ?>

    /

    $sites ) : ?> blog_id : null; if ( is_null( $site_url ) || $is_multisite ) { $site_url = Freemius::get_unfiltered_site_url( $blog_id, true, true ); } $is_active_clone = ( $site->is_clone( $site_url ) && isset( $active_modules_by_id[ $site->plugin_id ] ) ); if ( $is_active_clone ) { $has_any_active_clone = true; } ?>
    id ?> url ) ?> user_id ?> license_id) ? $site->license_id : '' ?> plan_id ) ) { if ( false === $all_plans ) { $option_name = 'plans'; if ( WP_FS__MODULE_TYPE_PLUGIN !== $module_type ) { $option_name = $module_type . '_' . $option_name; } $all_plans = fs_get_entities( $fs_options->get_option( $option_name, array() ), FS_Plugin_Plan::get_class_name() ); } foreach ( $all_plans[ $slug ] as $plan ) { $plan_id = Freemius::_decrypt( $plan->id ); if ( $site->plan_id == $plan_id ) { $plan_name = Freemius::_decrypt( $plan->name ); break; } } } echo $plan_name; ?> public_key ?> is_whitelabeled ? FS_Plugin_License::mask_secret_key_for_html( $site->secret_key ) : esc_html( $site->secret_key ); ?>
    $plugin_addons ) : ?>

    id ?> title ?> slug ?> version ?> public_key ?> secret_key ) ?>
    id ] = true; } } foreach ( $module_types as $module_type ) { /** * @var FS_Plugin_License[] $licenses */ $licenses = $VARS[ $module_type . '_licenses' ]; foreach ( $licenses as $license ) { if ( $license->is_whitelabeled ) { $users_with_developer_license_by_id[ $license->user_id ] = true; } } } ?>

    $user ) : ?>
    id ?> get_name() ?> email ?> is_verified ) ?> public_key ?> secret_key) : esc_html( $user->secret_key ) ?>
    0 ) : ?>

    id ?> plugin_id ?> user_id ?> plan_id ?> is_unlimited() ? 'Unlimited' : ( $license->is_single_site() ? 'Single Site' : $license->quota ) ?> activated ?> is_block_features ? 'Blocking' : 'Flexible' ?> is_whitelabeled ? 'Whitelabeled' : 'Normal' ?> is_whitelabeled || ! isset( $user_ids_map[ $license->user_id ] ) ) ? $license->get_html_escaped_masked_secret_key() : esc_html( $license->secret_key ); ?> expiration ?>

    #
    {$log.log_order}. {$log.type} {$log.logger} {$log.function} {$log.message_short}
    {$log.message}
    {$log.file}:{$log.line} {$log.created}
    freemius/templates/clone-resolution-js.php000064400000006624146725417150015031 0ustar00 freemius/templates/sticky-admin-notice-js.php000064400000002364146725417150015400 0ustar00 freemius/templates/powered-by.php000064400000004227146725417150013170 0ustar00is_whitelabeled() && ! $fs->apply_filters( 'hide_freemius_powered_by', false ) ) { wp_enqueue_script( 'jquery' ); wp_enqueue_script( 'json2' ); fs_enqueue_local_script( 'postmessage', 'nojquery.ba-postmessage.min.js' ); fs_enqueue_local_script( 'fs-postmessage', 'postmessage.js' ); ?>
    freemius/templates/account.php000064400000201424146725417150012545 0ustar00get_slug(); /** * @var FS_Plugin_Tag $update */ $update = $fs->has_release_on_freemius() ? $fs->get_update( false, false, WP_FS__TIME_24_HOURS_IN_SEC / 24 ) : null; if ( is_object($update) ) { /** * This logic is particularly required for multisite environment. * If a module is site activated (not network) and not on the main site, * the module will NOT be executed on the network level, therefore, the * custom updates logic will not be executed as well, so unless we force * the injection of the update into the updates transient, premium updates * will not work. * * @author Vova Feldman (@svovaf) * @since 2.0.0 */ $updater = FS_Plugin_Updater::instance( $fs ); $updater->set_update_data( $update ); } $is_paying = $fs->is_paying(); $user = $fs->get_user(); $site = $fs->get_site(); $name = $user->get_name(); $license = $fs->_get_license(); $is_license_foreign = ( is_object( $license ) && $user->id != $license->user_id ); $is_data_debug_mode = $fs->is_data_debug_mode(); $is_whitelabeled = $fs->is_whitelabeled(); $subscription = ( is_object( $license ) ? $fs->_get_subscription( $license->id ) : null ); $plan = $fs->get_plan(); $is_active_subscription = ( is_object( $subscription ) && $subscription->is_active() ); $is_paid_trial = $fs->is_paid_trial(); $has_paid_plan = $fs->apply_filters( 'has_paid_plan_account', $fs->has_paid_plan() ); $show_upgrade = ( ! $is_whitelabeled && $has_paid_plan && ! $is_paying && ! $is_paid_trial ); $trial_plan = $fs->get_trial_plan(); $is_plan_change_supported = ( ! $fs->is_single_plan() && ! $fs->apply_filters( 'hide_plan_change', false ) ); if ( $has_paid_plan ) { $fs->_add_license_activation_dialog_box(); } if ( $fs->should_handle_user_change() ) { $fs->_add_email_address_update_dialog_box(); } $ids_of_installs_activated_with_foreign_licenses = $fs->should_handle_user_change() ? $fs->get_installs_ids_with_foreign_licenses() : array(); if ( ! empty( $ids_of_installs_activated_with_foreign_licenses ) ) { $fs->_add_user_change_dialog_box( $ids_of_installs_activated_with_foreign_licenses ); } if ( $fs->is_whitelabeled( true ) || $fs->is_data_debug_mode() ) { $fs->_add_data_debug_mode_dialog_box(); } if ( fs_request_get_bool( 'auto_install' ) ) { $fs->_add_auto_installation_dialog_box(); } if ( fs_request_get_bool( 'activate_license' ) ) { // Open the license activation dialog box on the account page. add_action( 'admin_footer', array( &$fs, '_open_license_activation_dialog_box' ) ); } $show_billing = ( ! $is_whitelabeled && ! $fs->apply_filters( 'hide_billing_and_payments_info', false ) ); if ( $show_billing ) { $payments = $fs->_fetch_payments(); $show_billing = ( is_array( $payments ) && 0 < count( $payments ) ); } $has_tabs = $fs->_add_tabs_before_content(); // Aliases. $download_latest_text = fs_text_x_inline( 'Download Latest', 'as download latest version', 'download-latest', $slug ); $downgrading_plan_text = fs_text_inline( 'Downgrading your plan', 'downgrading-plan', $slug ); $cancelling_subscription_text = fs_text_inline( 'Cancelling the subscription', 'cancelling-subscription', $slug ); /* translators: %1$s: Either 'Downgrading your plan' or 'Cancelling the subscription' */ $downgrade_x_confirm_text = fs_text_inline( '%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.', 'downgrade-x-confirm', $slug ); $prices_increase_text = fs_text_inline( 'Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.', 'pricing-increase-warning', $slug ); $cancel_trial_confirm_text = fs_text_inline( 'Cancelling the trial will immediately block access to all premium features. Are you sure?', 'cancel-trial-confirm', $slug ); $after_downgrade_non_blocking_text = fs_text_inline( 'You can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.', 'after-downgrade-non-blocking', $slug ); $after_downgrade_blocking_text = fs_text_inline( 'Once your license expires you can still use the Free version but you will NOT have access to the %s features.', 'after-downgrade-blocking', $slug ); /* translators: %s: Plan title (e.g. "Professional") */ $activate_plan_text = fs_text_inline( 'Activate %s Plan', 'activate-x-plan', $slug ); $version_text = fs_text_x_inline( 'Version', 'product version', 'version', $slug ); /* translators: %s: Time period (e.g. Auto renews in "2 months") */ $renews_in_text = fs_text_inline( 'Auto renews in %s', 'renews-in', $slug ); /* translators: %s: Time period (e.g. Expires in "2 months") */ $expires_in_text = fs_text_inline( 'Expires in %s', 'expires-in', $slug ); $sync_license_text = fs_text_x_inline( 'Sync License', 'as synchronize license', 'sync-license', $slug ); $cancel_trial_text = fs_text_inline( 'Cancel Trial', 'cancel-trial', $slug ); $change_plan_text = fs_text_inline( 'Change Plan', 'change-plan', $slug ); $upgrade_text = fs_text_x_inline( 'Upgrade', 'verb', 'upgrade', $slug ); $addons_text = fs_text_inline( 'Add-Ons', 'add-ons', $slug ); $downgrade_text = fs_text_x_inline( 'Downgrade', 'verb', 'downgrade', $slug ); $trial_text = fs_text_x_inline( 'Trial', 'trial period', 'trial', $slug ); $free_text = fs_text_inline( 'Free', 'free', $slug ); $activate_text = fs_text_inline( 'Activate', 'activate', $slug ); $plan_text = fs_text_x_inline( 'Plan', 'as product pricing plan', 'plan', $slug ); $bundle_plan_text = fs_text_inline( 'Bundle Plan', 'bundle-plan', $slug ); $show_plan_row = true; $show_license_row = is_object( $license ); $site_view_params = array(); if ( fs_is_network_admin() ) { $sites = Freemius::get_sites(); $all_installs_plan_id = null; $all_installs_license_id = ( $show_license_row ? $license->id : null ); foreach ( $sites as $s ) { $site_info = $fs->get_site_info( $s ); $install = $fs->get_install_by_blog_id( $site_info['blog_id'] ); $view_params = array( 'freemius' => $fs, 'user' => $fs->get_user(), 'license' => $license, 'site' => $site_info, 'install' => $install, ); $site_view_params[] = $view_params; if ( empty( $install ) ) { continue; } if ( $show_plan_row ) { if ( is_null( $all_installs_plan_id ) ) { $all_installs_plan_id = $install->plan_id; } else if ( $all_installs_plan_id != $install->plan_id ) { $show_plan_row = false; } } if ( $show_license_row && $all_installs_license_id != $install->license_id ) { $show_license_row = false; } } } $has_bundle_license = false; if ( is_object( $license ) && FS_Plugin_License::is_valid_id( $license->parent_license_id ) ) { // Context license has a parent license, therefore, the account has a bundle license. $has_bundle_license = true; } $bundle_subscription = null; $is_bundle_first_payment_pending = false; if ( $show_plan_row && is_object( $license ) && $has_bundle_license ) { $bundle_plan_title = strtoupper( $license->parent_plan_title ); $bundle_subscription = $fs->_get_subscription( $license->parent_license_id ); $is_bundle_first_payment_pending = $license->is_first_payment_pending(); } $fs_blog_id = ( is_multisite() && ! is_network_admin() ) ? get_current_blog_id() : 0; $active_plugins_directories_map = Freemius::get_active_plugins_directories_map( $fs_blog_id ); $is_premium = $fs->is_premium(); $account_addons = $fs->get_updated_account_addons(); $installed_addons = $fs->get_installed_addons(); $installed_addons_ids = array(); /** * Store the installed add-ons' IDs into a collection which will be used in determining the add-ons to show on the "Account" page, and at the same time try to find an add-on that is activated with a bundle license if the core product is not. * * @author Leo Fajardo * * @since 2.4.0 */ foreach ( $installed_addons as $fs_addon ) { $installed_addons_ids[] = $fs_addon->get_id(); if ( $has_bundle_license ) { // We already have the context bundle license details, skip. continue; } if ( $show_plan_row && $fs_addon->has_active_valid_license() ) { $addon_license = $fs_addon->_get_license(); if ( FS_Plugin_License::is_valid_id( $addon_license->parent_license_id ) ) { // Add-on's license is associated with a parent/bundle license. $has_bundle_license = true; $bundle_plan_title = strtoupper( $addon_license->parent_plan_title ); $bundle_subscription = $fs_addon->_get_subscription( $addon_license->parent_license_id ); $is_bundle_first_payment_pending = $addon_license->is_first_payment_pending(); } } } $addons_to_show = array_unique( array_merge( $installed_addons_ids, $account_addons ) ); $is_active_bundle_subscription = ( is_object( $bundle_subscription ) && $bundle_subscription->is_active() ); $available_license = ( $fs->is_free_plan() && ! fs_is_network_admin() ) ? $fs->_get_available_premium_license( $site->is_localhost() ) : null; $available_license_paid_plan = is_object( $available_license ) ? $fs->_get_plan_by_id( $available_license->plan_id ) : null; ?>
    apply_filters( 'hide_account_tabs', false ) ) : ?>

    apply_filters( 'hide_license_key', false ) ); $profile = array(); if ( ! $is_whitelabeled ) { $profile[] = array( 'id' => 'user_name', 'title' => fs_text_inline( 'Name', 'name', $slug ), 'value' => $name ); // if (isset($user->email) && false !== strpos($user->email, '@')) $profile[] = array( 'id' => 'email', 'title' => fs_text_inline( 'Email', 'email', $slug ), 'value' => $user->email ); if ( is_numeric( $user->id ) ) { $profile[] = array( 'id' => 'user_id', 'title' => fs_text_inline( 'User ID', 'user-id', $slug ), 'value' => $user->id ); } } $profile[] = array( 'id' => 'product', 'title' => ( $fs->is_plugin() ? fs_text_inline( 'Plugin', 'plugin', $slug ) : fs_text_inline( 'Theme', 'theme', $slug ) ), 'value' => $fs->get_plugin_title() ); $profile[] = array( 'id' => 'product_id', 'title' => ( $fs->is_plugin() ? fs_text_inline( 'Plugin', 'plugin', $slug ) : fs_text_inline( 'Theme', 'theme', $slug ) ) . ' ' . fs_text_inline( 'ID', 'id', $slug ), 'value' => $fs->get_id() ); if ( ! fs_is_network_admin()) { $profile[] = array( 'id' => 'site_id', 'title' => fs_text_inline( 'Site ID', 'site-id', $slug ), 'value' => is_string( $site->id ) ? $site->id : fs_text_inline( 'No ID', 'no-id', $slug ) ); $profile[] = array( 'id' => 'site_public_key', 'title' => fs_text_inline( 'Public Key', 'public-key', $slug ), 'value' => $site->public_key ); $profile[] = array( 'id' => 'site_secret_key', 'title' => fs_text_inline( 'Secret Key', 'secret-key', $slug ), 'value' => ( ( is_string( $site->secret_key ) ) ? $site->secret_key : fs_text_x_inline( 'No Secret', 'as secret encryption key missing', 'no-secret', $slug ) ) ); } $profile[] = array( 'id' => 'version', 'title' => $version_text, 'value' => $fs->get_plugin_version() ); if ( ! fs_is_network_admin() && $is_premium ) { $profile[] = array( 'id' => 'beta_program', 'title' => '', 'value' => $site->is_beta ); } if ( $has_paid_plan || $has_bundle_license ) { if ( $fs->is_trial() ) { if ( $show_plan_row ) { $profile[] = array( 'id' => 'plan', 'title' => $plan_text, 'value' => ( is_string( $trial_plan->name ) ? strtoupper( $trial_plan->title ) : fs_text_inline( 'Trial', 'trial', $slug ) ) ); } } else { if ( $show_plan_row ) { $profile[] = array( 'id' => 'plan', 'title' => ( $has_bundle_license ? ucfirst( $fs->get_module_type() ) . ' ' : '' ) . $plan_text, 'value' => strtoupper( is_string( $plan->name ) ? $plan->title : strtoupper( $free_text ) ) ); if ( $has_bundle_license ) { $profile[] = array( 'id' => 'bundle_plan', 'title' => $bundle_plan_text, 'value' => $bundle_plan_title ); } } if ( is_object( $license ) ) { if ( ! $hide_license_key ) { $profile[] = array( 'id' => 'license_key', 'title' => fs_text_inline( 'License Key', $slug ), 'value' => $license->secret_key, ); } } } } ?> > is_verified() ) : ?> is_trial() ) : ?> is_lifetime() ) : ?> is_first_payment_pending() ) : ?> is_expired() ?> is_first_payment_pending() ) : ?> is_trial() ) : ?>
    $fs, 'slug' => $slug, 'license' => $available_license, 'plan' => $available_license_paid_plan, 'is_localhost' => $site->is_localhost(), 'install_id' => $site->id, 'class' => 'button-primary', ); fs_require_template( 'account/partials/activate-license-button.php', $view_params ); ?>
    get_unique_affix() . '_sync_license' ) ?>
    has_premium_version() ) : ?> can_use_premium_code() ) : ?>
    is_verified() ) : ?>
    has_release_on_freemius() ) : ?> secret_key ) && in_array( $p['id'], array( 'email', 'user_name' ) ) ) ) : ?>

    get_site(); if ( is_object( $site ) && ( ! is_object( $current_install ) || $current_install->id != $site->id ) ) { $fs->switch_to_blog( $current_blog_id, $site, true ); } ?>
    is_whitelabeled_by_flag() ) { $hide_all_addons_data = true; foreach ( $addons_to_show as $addon_id ) { $is_addon_installed = isset( $installed_addons_ids_map[ $addon_id ] ); $addon_info = $fs->_get_addon_info( $addon_id, $is_addon_installed ); $is_addon_connected = $addon_info['is_connected']; $fs_addon = ( $is_addon_connected && $is_addon_installed ) ? freemius( $addon_id ) : null; $is_whitelabeled = is_object( $fs_addon ) ? $fs_addon->is_whitelabeled( true ) : $addon_info['is_whitelabeled']; if ( ! $is_whitelabeled ) { $hide_all_addons_data = false; } if ( $is_data_debug_mode ) { $is_whitelabeled = false; } $addon_info_by_id[ $addon_id ] = $addon_info; } } foreach ( $addons_to_show as $addon_id ) { $is_addon_installed = isset( $installed_addons_ids_map[ $addon_id ] ); if ( $hide_all_addons_data && ! $is_addon_installed && ! file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $fs->get_addon_basename( $addon_id ) ) ) ) { continue; } $addon_view_params = array( 'parent_fs' => $fs, 'addon_id' => $addon_id, 'odd' => $odd, 'fs_blog_id' => $fs_blog_id, 'active_plugins_directories_map' => &$active_plugins_directories_map, 'is_addon_installed' => $is_addon_installed, 'addon_info' => isset( $addon_info_by_id[ $addon_id ] ) ? $addon_info_by_id[ $addon_id ] : $fs->_get_addon_info( $addon_id, $is_addon_installed ), 'is_whitelabeled' => ( $is_whitelabeled && ! $is_data_debug_mode ) ); fs_require_template( 'account/partials/addon.php', $addon_view_params ); $odd = ! $odd; } ?>

    do_action( 'after_account_details' ) ?> $VARS['id'], 'payments' => $payments ); fs_require_once_template( 'account/billing.php', $view_params ); fs_require_once_template( 'account/payments.php', $view_params ); } ?>
    _get_subscription_cancellation_dialog_box_template_params( true ); if ( ! empty( $subscription_cancellation_dialog_box_template_params ) ) { fs_require_template( 'forms/subscription-cancellation.php', $subscription_cancellation_dialog_box_template_params ); } ?> _add_tabs_after_content(); } $params = array( 'page' => 'account', 'module_id' => $fs->get_id(), 'module_type' => $fs->get_module_type(), 'module_slug' => $slug, 'module_version' => $fs->get_plugin_version(), ); fs_require_template( 'powered-by.php', $params ); freemius/templates/js/open-license-activation.php000064400000002176146725417150016250 0ustar00 freemius/templates/js/permissions.php000064400000052135146725417150014103 0ustar00 freemius/templates/js/index.php000064400000000127146725417150012631 0ustar00get_slug(); ?> freemius/templates/js/jquery.content-change.php000064400000003050146725417150015733 0ustar00 freemius/templates/ajax-loader.php000064400000000374146725417150013301 0ustar00 freemius/templates/auto-installation.php000064400000016336146725417150014566 0ustar00is_tracking_allowed() ? 'stop_tracking' : 'allow_tracking'; $title = $fs->get_plugin_title(); if ( $plugin_id != $fs->get_id() ) { $addon = $fs->get_addon( $plugin_id ); if ( is_object( $addon ) ) { $title = $addon->title . ' ' . fs_text_inline( 'Add-On', 'addon', $slug ); } } $plugin_title = sprintf( '%s', esc_html( $title ) ); $sec_countdown = 30; $countdown_html = sprintf( esc_js( /* translators: %s: Number of seconds */ fs_text_inline( '%s sec', 'x-sec', $slug ) ), sprintf( '%s', $sec_countdown ) ); fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); $params = array(); $loader_html = fs_get_template( 'ajax-loader.php', $params ); // Pass unique auto installation URL if WP_Filesystem is needed. $install_url = $fs->_get_sync_license_url( $plugin_id, true, array( 'auto_install' => 'true' ) ); ob_start(); $method = ''; // Leave blank so WP_Filesystem can populate it as necessary. $credentials = request_filesystem_credentials( esc_url_raw( $install_url ), $method, false, WP_PLUGIN_DIR, array() ); $credentials_form = ob_get_clean(); $require_credentials = ! empty( $credentials_form ); ?>

    %s', 'https://freemius.com', 'freemius.com' ), $countdown_html ) ?>

    ' freemius/templates/api-connectivity-message-js.php000064400000002016146725417150016426 0ustar00 freemius/templates/tabs.php000064400000015501146725417150012041 0ustar00get_slug(); $menu_items = $fs->get_menu_items(); $show_settings_with_tabs = $fs->show_settings_with_tabs(); $tabs = array(); foreach ( $menu_items as $priority => $items ) { foreach ( $items as $item ) { if ( ! $item['show_submenu'] ) { $submenu_name = ('wp-support-forum' === $item['menu_slug']) ? 'support' : $item['menu_slug']; if ( 'pricing' === $submenu_name && ! $fs->is_pricing_page_visible() ) { continue; } if ( ! $show_settings_with_tabs || ! $fs->is_submenu_item_visible( $submenu_name, true ) ) { continue; } } $url = $fs->_get_admin_page_url( $item['menu_slug'] ); $title = $item['menu_title']; $tab = array( 'label' => $title, 'href' => $url, 'slug' => $item['menu_slug'], ); if ( 'pricing' === $item['menu_slug'] && $fs->is_in_trial_promotion() ) { $tab['href'] .= '&trial=true'; } $tabs[] = $tab; } } ?> freemius/templates/index.php000064400000000127146725417150012215 0ustar00get_slug(); /** * @var FS_Plugin_License $license */ $license = $VARS['license']; $has_trial = $VARS['has_trial']; $subscription_cancellation_context = $has_trial ? fs_text_inline( 'trial', 'trial', $slug ) : fs_text_inline( 'subscription', 'subscription', $slug ); $plan = $fs->get_plan(); $module_label = $fs->get_module_label( true ); if ( $VARS['is_license_deactivation'] ) { $subscription_cancellation_text = ''; } else { $subscription_cancellation_text = sprintf( fs_text_inline( "Deactivating or uninstalling the %s will automatically disable the license, which you'll be able to use on another site.", 'deactivation-or-uninstall-message', $slug ), $module_label ) . ' '; } $subscription_cancellation_text .= sprintf( fs_text_inline( 'In case you are NOT planning on using this %s on this site (or any other site) - would you like to cancel the %s as well?', 'cancel-subscription-message', $slug ), ( $VARS['is_license_deactivation'] ? fs_text_inline( 'license', 'license', $slug ) : $module_label ), $subscription_cancellation_context ); $cancel_subscription_action_label = sprintf( fs_esc_html_inline( "Cancel %s - I no longer need any security & feature updates, nor support for %s because I'm not planning to use the %s on this, or any other site.", 'cancel-x', $slug ), esc_html( $subscription_cancellation_context ), sprintf( '%s', esc_html( $fs->get_plugin_title() ) ), esc_html( $module_label ) ); $keep_subscription_active_action_label = esc_html( sprintf( fs_text_inline( "Don't cancel %s - I'm still interested in getting security & feature updates, as well as be able to contact support.", 'dont-cancel-x', $slug ), $subscription_cancellation_context ) ); $subscription_cancellation_text = esc_html( $subscription_cancellation_text ); $subscription_cancellation_html = <<< HTML

    {$subscription_cancellation_text}

    HTML; $downgrading_plan_text = fs_text_inline( 'Downgrading your plan', 'downgrading-plan', $slug ); $cancelling_subscription_text = fs_text_inline( 'Cancelling the subscription', 'cancelling-subscription', $slug ); /* translators: %1$s: Either 'Downgrading your plan' or 'Cancelling the subscription' */ $downgrade_x_confirm_text = fs_text_inline( '%1$s will immediately stop all future recurring payments and your %2$s plan license will expire in %3$s.', 'downgrade-x-confirm', $slug ); $prices_increase_text = fs_text_inline( 'Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.', 'pricing-increase-warning', $slug ); $after_downgrade_non_blocking_text = fs_text_inline( 'You can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.', 'after-downgrade-non-blocking', $slug ); $after_downgrade_blocking_text = fs_text_inline( 'Once your license expires you can still use the Free version but you will NOT have access to the %s features.', 'after-downgrade-blocking', $slug ); $after_downgrade_blocking_text_premium_only = fs_text_inline( 'Once your license expires you will no longer be able to use the %s, unless you activate it again with a valid premium license.', 'after-downgrade-blocking-premium-only', $slug ); $subscription_cancellation_confirmation_message = $has_trial ? fs_text_inline( 'Cancelling the trial will immediately block access to all premium features. Are you sure?', 'cancel-trial-confirm', $slug ) : sprintf( '%s %s %s %s', sprintf( $downgrade_x_confirm_text, ($fs->is_only_premium() ? $cancelling_subscription_text : $downgrading_plan_text ), $plan->title, human_time_diff( time(), strtotime( $license->expiration ) ) ), ( $license->is_block_features ? ( $fs->is_only_premium() ? sprintf( $after_downgrade_blocking_text_premium_only, $module_label ) : sprintf( $after_downgrade_blocking_text, $plan->title ) ) : sprintf( $after_downgrade_non_blocking_text, $plan->title, $fs->get_module_label( true ) ) ), $prices_increase_text, fs_esc_attr_inline( 'Are you sure you want to proceed?', 'proceed-confirmation', $slug ) ); fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); ?> freemius/templates/forms/trial-start.php000064400000012353146725417150014506 0ustar00get_slug(); $message_header = sprintf( /* translators: %1$s: Number of trial days; %2$s: Plan name; */ fs_text_inline( 'You are 1-click away from starting your %1$s-day free trial of the %2$s plan.', 'start-trial-prompt-header', $slug ), '', '' ); $message_content = sprintf( /* translators: %s: Link to freemius.com */ fs_text_inline( 'For compliance with the WordPress.org guidelines, before we start the trial we ask that you opt in with your user and non-sensitive site information, allowing the %s to periodically send data to %s to check for version updates and to validate your trial.', 'start-trial-prompt-message', $slug ), $fs->get_module_type(), sprintf( '%s', 'https://freemius.com', 'freemius.com' ) ); $modal_content_html = <<< HTML

    {$message_header}

    {$message_content}

    HTML; fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); ?> freemius/templates/forms/data-debug-mode.php000064400000017406146725417150015163 0ustar00get_slug(); $unique_affix = $fs->get_unique_affix(); $last_license_user_id = $fs->get_last_license_user_id(); $has_last_license_user_id = FS_User::is_valid_id( $last_license_user_id ); $message_above_input_field = ( ! $has_last_license_user_id ) ? fs_text_inline( 'Please enter the license key to enable the debug mode:', 'submit-developer-license-key-message', $slug ) : sprintf( fs_text_inline( 'To enter the debug mode, please enter the secret key of the license owner (UserID = %d), which you can find in your "My Profile" section of your User Dashboard:', 'submit-addon-developer-key-message', $slug ), $last_license_user_id ); $processing_text = ( fs_esc_js_inline( 'Processing', 'processing', $slug ) . '...' ); $submit_button_text = fs_text_inline( 'Submit', 'submit', $slug ); $debug_license_link_text = fs_esc_html_inline( 'Start Debug', 'start-debug-license', $slug ); $license_or_user_key_text = ( ! $has_last_license_user_id ) ? fs_text_inline( 'License key', 'license-key' , $slug ) : fs_text_inline( 'User key', 'user-key' , $slug ); $input_html = ""; $modal_content_html = <<< HTML

    {$message_above_input_field}

    {$input_html} HTML; fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); ?> freemius/templates/forms/resend-key.php000064400000016271146725417150014311 0ustar00get_slug(); $send_button_text = fs_text_inline( 'Send License Key', 'send-license-key', $slug ); $cancel_button_text = fs_text_inline( 'Cancel', 'cancel', $slug ); $email_address_placeholder = fs_esc_attr_inline( 'Email address', 'email-address', $slug ); $other_text = fs_text_inline( 'Other', 'other', $slug ); $is_freemium = $fs->is_freemium(); $send_button_text_html = esc_html($send_button_text); $button_html = <<< HTML HTML; if ( $is_freemium ) { $current_user = Freemius::_get_current_wp_user(); $email = $current_user->user_email; $esc_email = esc_attr( $email ); $form_html = <<< HTML {$button_html} HTML; } else { $email = ''; $form_html = <<< HTML {$button_html} HTML; } $message_above_input_field = $fs->is_only_premium() ? fs_esc_html_inline( "Enter the email address you've used during the purchase and we will resend you the license key.", 'ask-for-upgrade-email-address-premium-only', $slug ) : fs_esc_html_inline( "Enter the email address you've used for the upgrade below and we will resend you the license key.", 'ask-for-upgrade-email-address', $slug ); $modal_content_html = <<< HTML

    {$message_above_input_field}

    {$form_html}
    HTML; fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); ?> freemius/templates/forms/email-address-update.php000064400000035077146725417150016242 0ustar00get_slug(); $user = $fs->get_user(); $current_email_address = $user->email; fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); ?> freemius/templates/forms/affiliation.php000064400000072314146725417150014530 0ustar00get_slug(); $user = $fs->get_user(); $affiliate = $fs->get_affiliate(); $affiliate_terms = $fs->get_affiliate_terms(); $module_type = $fs->is_plugin() ? WP_FS__MODULE_TYPE_PLUGIN : WP_FS__MODULE_TYPE_THEME; $commission = $affiliate_terms->get_formatted_commission(); $readonly = false; $is_affiliate = is_object( $affiliate ); $is_pending_affiliate = false; $email_address = ( is_object( $user ) ? $user->email : '' ); $full_name = ( is_object( $user ) ? $user->get_name() : '' ); $paypal_email_address = ''; $domain = ''; $extra_domains = array(); $promotion_method_social_media = false; $promotion_method_mobile_apps = false; $statistics_information = false; $promotion_method_description = false; $members_dashboard_login_url = 'https://users.freemius.com/login'; $affiliate_application_data = $fs->get_affiliate_application_data(); if ( $is_affiliate && $affiliate->is_pending() ) { $readonly = 'readonly'; $is_pending_affiliate = true; $paypal_email_address = $affiliate->paypal_email; $domain = $affiliate->domain; $statistics_information = $affiliate_application_data['stats_description']; $promotion_method_description = $affiliate_application_data['promotion_method_description']; if ( ! empty( $affiliate_application_data['additional_domains'] ) ) { $extra_domains = $affiliate_application_data['additional_domains']; } if ( ! empty( $affiliate_application_data['promotion_methods'] ) ) { $promotion_methods = explode( ',', $affiliate_application_data['promotion_methods'] ); $promotion_method_social_media = in_array( 'social_media', $promotion_methods ); $promotion_method_mobile_apps = in_array( 'mobile_apps', $promotion_methods ); } } else { $current_user = Freemius::_get_current_wp_user(); $full_name = trim( $current_user->user_firstname . ' ' . $current_user->user_lastname ); $email_address = $current_user->user_email; $domain = Freemius::get_unfiltered_site_url( null, true ); } $affiliate_tracking = 30; if ( is_object( $affiliate_terms ) ) { $affiliate_tracking = ( ! is_null( $affiliate_terms->cookie_days ) ? ( $affiliate_terms->cookie_days . '-day' ) : fs_text_inline( 'Non-expiring', 'non-expiring', $slug ) ); } $apply_to_become_affiliate_text = fs_text_inline( 'Apply to become an affiliate', 'apply-to-become-an-affiliate', $slug ); $module_id = $fs->get_id(); $affiliate_program_terms_url = "https://freemius.com/plugin/{$module_id}/{$slug}/legal/affiliate-program/"; $has_tabs = $fs->_add_tabs_before_content(); ?>
    is_active() ) : ?>

    %s', $members_dashboard_login_url, $members_dashboard_login_url ) ); ?>

    is_suspended() ) { $message_text = fs_text_inline( 'Your affiliation account was temporarily suspended.', 'affiliate-account-suspended', $slug ); $message_container_class = 'notice notice-warning'; } else if ( $affiliate->is_rejected() ) { $message_text = fs_text_inline( "Thank you for applying for our affiliate program, unfortunately, we've decided at this point to reject your application. Please try again in 30 days.", 'affiliate-application-rejected', $slug ); $message_container_class = 'error'; } else if ( $affiliate->is_blocked() ) { $message_text = fs_text_inline( 'Due to violation of our affiliation terms, we decided to temporarily block your affiliation account. If you have any questions, please contact support.', 'affiliate-account-blocked', $slug ); $message_container_class = 'error'; } ?>

    • has_renewals_commission() ) : ?>
    • is_session_cookie() ) ) : ?>
    • has_lifetime_commission() ) : ?>
    >

    >
    >
    >
    >

    + ...
    >

    >
    />
    />

    _add_tabs_after_content(); } $params = array( 'page' => 'affiliation', 'module_id' => $module_id, 'module_slug' => $slug, 'module_version' => $fs->get_plugin_version(), ); fs_require_template( 'powered-by.php', $params ); freemius/templates/forms/premium-versions-upgrade-metadata.php000064400000002770146725417150020771 0ustar00_get_license(); if ( ! is_object( $license ) ) { $purchase_url = $fs->pricing_url(); } else { $subscription = $fs->_get_subscription( $license->id ); $purchase_url = $fs->checkout_url( is_object( $subscription ) ? ( 1 == $subscription->billing_cycle ? WP_FS__PERIOD_MONTHLY : WP_FS__PERIOD_ANNUALLY ) : WP_FS__PERIOD_LIFETIME, false, array( 'licenses' => $license->quota ) ); } $plugin_data = $fs->get_plugin_data(); ?> freemius/templates/forms/index.php000064400000000127146725417150013343 0ustar00get_slug(); $unique_affix = $fs->get_unique_affix(); $cant_find_license_key_text = fs_text_inline( "Can't find your license key?", 'cant-find-license-key', $slug ); $message_above_input_field = fs_text_inline( 'Please enter the license key that you received in the email right after the purchase:', 'activate-license-message', $slug ); $message_below_input_field = ''; $header_title = $fs->is_free_plan() ? fs_text_inline( 'Activate License', 'activate-license', $slug ) : fs_text_inline( 'Update License', 'update-license', $slug ); if ( $fs->is_registered() ) { $activate_button_text = $header_title; } else { $message_below_input_field = sprintf( fs_text_inline( 'The %1$s will be periodically sending essential license data to %2$s to check for security and feature updates, and verify the validity of your license.', 'license-sync-disclaimer', $slug ), $fs->get_module_label( true ), "{$fs->get_plugin_title()}" ); $activate_button_text = fs_text_inline( 'Agree & Activate License', 'agree-activate-license', $slug ); } $license_key_text = fs_text_inline( 'License key', 'license-key' , $slug ); $is_network_activation = ( $fs->is_network_active() && fs_is_network_admin() && ! $fs->is_delegated_connection() ); $network_activation_html = ''; $sites_details = array(); if ( $is_network_activation ) { $all_sites = Freemius::get_sites(); $subsite_data_by_install_id = array(); $install_url_by_install_id = array(); foreach ( $all_sites as $site ) { $site_details = $fs->get_site_info( $site ); if ( FS_Clone_Manager::instance()->is_temporary_duplicate_by_blog_id( $site_details['blog_id'] ) ) { continue; } $blog_id = Freemius::get_site_blog_id( $site ); $install = $fs->get_install_by_blog_id($blog_id); if ( is_object( $install ) ) { if ( isset( $subsite_data_by_install_id[ $install->id ] ) ) { $clone_subsite_data = $subsite_data_by_install_id[ $install->id ]; $clone_install_url = $install_url_by_install_id[ $install->id ]; if ( /** * If we already have an install with the same URL as the subsite it's stored in, skip the current subsite. Otherwise, replace the existing install's data with the current subsite's install's data if the URLs match. * * @author Leo Fajardo (@leorw) * @since 2.5.0 */ fs_strip_url_protocol( untrailingslashit( $clone_install_url ) ) === fs_strip_url_protocol( untrailingslashit( $clone_subsite_data['url'] ) ) || fs_strip_url_protocol( untrailingslashit( $install->url ) ) !== fs_strip_url_protocol( untrailingslashit( $site_details['url'] ) ) ) { continue; } } if ( FS_Plugin_License::is_valid_id( $install->license_id ) ) { $site_details['license_id'] = $install->license_id; } $subsite_data_by_install_id[ $install->id ] = $site_details; $install_url_by_install_id[ $install->id ] = $install->url; } } if ( $is_network_activation ) { $vars = array( 'id' => $fs->get_id(), 'sites' => array_values( $subsite_data_by_install_id ), 'require_license_key' => true ); $network_activation_html = fs_get_template( 'partials/network-activation.php', $vars ); } } $premium_licenses = $fs->get_available_premium_licenses(); $available_licenses = array(); foreach ( $premium_licenses as $premium_license ) { $activations_left = $premium_license->left(); if ( ! ( $activations_left > 0 ) ) { continue; } $available_licenses[ $activations_left . '_' . $premium_license->id ] = $premium_license; } $total_available_licenses = count( $available_licenses ); if ( $total_available_licenses > 0 ) { $license_input_html = <<< HTML
    HTML; if ( $total_available_licenses > 1 ) { // Sort the licenses by number of activations left in descending order. krsort( $available_licenses ); $license_input_html .= ''; } else { $available_licenses = array_values( $available_licenses ); /** * @var FS_Plugin_License $available_license */ $available_license = $available_licenses[0]; $value = sprintf( "%s-Site %s License - %s", ( 1 == $available_license->quota ? 'Single' : ( $available_license->is_unlimited() ? 'Unlimited' : $available_license->quota ) ), $fs->_get_plan_by_id( $available_license->plan_id )->title, $available_license->get_html_escaped_masked_secret_key() ); $license_input_html .= <<< HTML HTML; } $license_input_html .= <<< HTML
    HTML; } else { $license_input_html = ""; } $ownership_change_option_text = fs_text_inline( "Associate with the license owner's account.", 'associate-account-with-license-owner', $slug ); $ownership_change_option_html = ""; /** * IMPORTANT: * DO NOT ADD MAXLENGTH OR LIMIT THE LICENSE KEY LENGTH SINCE * WE DO WANT TO ALLOW INPUT OF LONGER KEYS (E.G. WooCommerce Keys) * FOR MIGRATED MODULES. */ $modal_content_html = <<< HTML

    {$message_above_input_field}

    {$license_input_html} {$cant_find_license_key_text} {$network_activation_html}

    {$message_below_input_field}

    {$ownership_change_option_html} HTML; /** * Handle the ownership change option if not an add-on or if no license yet is activated for the * parent product in case of an add-on. * * @author Leo Fajardo (@leorw) * @since 2.3.2 */ $is_user_change_supported = ( ! $fs->is_addon() || ! $fs->get_parent_instance()->has_active_valid_license() ); fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); ?> get_slug(); /** * @var object[] $license_owners */ $license_owners = $VARS['license_owners']; $change_user_message = fs_text_inline( 'By changing the user, you agree to transfer the account ownership to:', 'change-user--message', $slug ); $header_title = fs_text_inline( 'Change User', 'change-user', $slug ); $user_change_button_text = fs_text_inline( 'I Agree - Change User', 'agree-change-user', $slug ); $other_text = fs_text_inline( 'Other', 'other', $slug ); $enter_email_address_placeholder_text = fs_text_inline( 'Enter email address', 'enter-email-address', $slug ); $user_change_options_html = <<< HTML
    HTML; foreach ( $license_owners as $license_owner ) { $user_change_options_html .= <<< HTML HTML; } $user_change_options_html .= <<< HTML
    HTML; $modal_content_html = <<< HTML

    {$change_user_message}

    {$user_change_options_html} HTML; fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); ?> freemius/templates/forms/optout.php000064400000023152146725417150013571 0ustar00get_slug(); $reconnect_url = $fs->get_activation_url( array( 'nonce' => wp_create_nonce( $fs->get_unique_affix() . '_reconnect' ), 'fs_action' => ( $fs->get_unique_affix() . '_reconnect' ), ) ); $plugin_title = "" . esc_html( $fs->get_plugin()->title ) . ""; $opt_out_text = fs_text_x_inline( 'Opt Out', 'verb', 'opt-out', $slug ); $permission_manager = FS_Permission_Manager::instance( $fs ); fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); fs_enqueue_local_style( 'fs_optout', '/admin/optout.css' ); fs_enqueue_local_style( 'fs_common', '/admin/common.css' ); if ( ! $permission_manager->is_premium_context() ) { $optional_permissions = array( $permission_manager->get_extensions_permission( false, false, true ) ); $permission_groups = array( array( 'id' => 'communication', 'type' => 'required', 'title' => $fs->get_text_inline( 'Communication', 'communication' ), 'desc' => '', 'permissions' => $permission_manager->get_opt_in_required_permissions( true ), 'is_enabled' => $fs->is_registered(), 'prompt' => array( $fs->esc_html_inline( "Sharing your name and email allows us to keep you in the loop about new features and important updates, warn you about security issues before they become public knowledge, and send you special offers.", 'opt-out-message_user' ), sprintf( $fs->esc_html_inline( 'By clicking "Opt Out", %s will no longer be able to view your name and email.', 'opt-out-message-clicking-opt-out' ), $plugin_title ), ), 'prompt_cancel_label' => $fs->get_text_inline( 'Stay Connected', 'stay-connected' ) ), array( 'id' => 'diagnostic', 'type' => 'required', 'title' => $fs->get_text_inline( 'Diagnostic Info', 'diagnostic-info' ), 'desc' => '', 'permissions' => $permission_manager->get_opt_in_diagnostic_permissions( true ), 'is_enabled' => $fs->is_tracking_allowed(), 'prompt' => array( sprintf( $fs->esc_html_inline( 'Sharing diagnostic data helps to provide additional functionality that\'s relevant to your website, avoid WordPress or PHP version incompatibilities that can break the website, and recognize which languages & regions the %s should be translated and tailored to.', 'opt-out-message-clicking-opt-out' ), $fs->get_module_type() ), sprintf( $fs->esc_html_inline( 'By clicking "Opt Out", diagnostic data will no longer be sent to %s.', 'opt-out-message-clicking-opt-out' ), $plugin_title ), ), 'prompt_cancel_label' => $fs->get_text_inline( 'Keep Sharing', 'keep-sharing' ) ), array( 'id' => 'extensions', 'type' => 'optional', 'title' => $fs->get_text_inline( 'Extensions', 'extensions' ), 'desc' => '', 'permissions' => $optional_permissions, ), ); } else { $optional_permissions = $permission_manager->get_license_optional_permissions( false, true ); $permission_groups = array( array( 'id' => 'essentials', 'type' => 'required', 'title' => $fs->esc_html_inline( 'Required', 'required' ), 'desc' => sprintf( $fs->esc_html_inline( 'For automatic delivery of security & feature updates, and license management & protection, %s needs to:', 'license-sync-disclaimer' ), '' . esc_html( $fs->get_plugin_title() ) . '' ), 'permissions' => $permission_manager->get_license_required_permissions( true ), 'is_enabled' => $permission_manager->is_essentials_tracking_allowed(), 'prompt' => array( sprintf( $fs->esc_html_inline( 'To ensure that security & feature updates are automatically delivered directly to your WordPress Admin Dashboard while protecting your license from unauthorized abuse, %2$s needs to view the website’s homepage URL, %1$s version, SDK version, and whether the %1$s is active.', 'premium-opt-out-message-usage-tracking' ), $fs->get_module_type(), $plugin_title ), sprintf( $fs->esc_html_inline( 'By opting out from sharing this information with the updates server, you’ll have to check for new %1$s releases and manually download & install them. Not just a hassle, but missing an update can put your site at risk and cause undue compatibility issues, so we highly recommend keeping these essential permissions on.', 'opt-out-message-clicking-opt-out' ), $fs->get_module_type(), $plugin_title ), ), 'prompt_cancel_label' => $fs->get_text_inline( 'Keep automatic updates', 'premium-opt-out-cancel' ) ), array( 'id' => 'optional', 'type' => 'optional', 'title' => $fs->esc_html_inline( 'Optional', 'optional' ), 'desc' => sprintf( $fs->esc_html_inline( 'For ongoing compatibility with your website, you can optionally allow %s to:', 'optional-permissions-disclaimer' ), $plugin_title ), 'permissions' => $optional_permissions, ), ); } $ajax_action = 'toggle_permission_tracking'; $form_id = "fs_opt_out_{$fs->get_id()}"; ?> require_permissions_js( false ) ?> freemius/templates/forms/deactivation/form.php000064400000064102146725417150015654 0ustar00get_slug(); $subscription_cancellation_dialog_box_template_params = $VARS['subscription_cancellation_dialog_box_template_params']; $show_deactivation_feedback_form = $VARS['show_deactivation_feedback_form']; $confirmation_message = $VARS['uninstall_confirmation_message']; $is_anonymous = ( ! $fs->is_registered() ); $anonymous_feedback_checkbox_html = ''; $reasons_list_items_html = ''; $snooze_select_html = ''; if ( $show_deactivation_feedback_form ) { $reasons = $VARS['reasons']; foreach ( $reasons as $reason ) { $list_item_classes = 'reason' . ( ! empty( $reason['input_type'] ) ? ' has-input' : '' ); if ( isset( $reason['internal_message'] ) && ! empty( $reason['internal_message'] ) ) { $list_item_classes .= ' has-internal-message'; $reason_internal_message = $reason['internal_message']; } else { $reason_internal_message = ''; } $reason_input_type = ( ! empty( $reason['input_type'] ) ? $reason['input_type'] : '' ); $reason_input_placeholder = ( ! empty( $reason['input_placeholder'] ) ? $reason['input_placeholder'] : '' ); $reason_list_item_html = <<< HTML
  • {$reason_internal_message}
  • HTML; $reasons_list_items_html .= $reason_list_item_html; } if ( $is_anonymous ) { $anonymous_feedback_checkbox_html = sprintf( '', fs_esc_html_inline( 'Anonymous feedback', 'anonymous-feedback', $slug ) ); } $snooze_periods = array( array( 'increment' => fs_text_inline( 'hour', $slug ), 'quantity' => number_format_i18n(1), 'value' => 6 * WP_FS__TIME_10_MIN_IN_SEC, ), array( 'increment' => fs_text_inline( 'hours', $slug ), 'quantity' => number_format_i18n(24), 'value' => WP_FS__TIME_24_HOURS_IN_SEC, ), array( 'increment' => fs_text_inline( 'days', $slug ), 'quantity' => number_format_i18n(7), 'value' => WP_FS__TIME_WEEK_IN_SEC, ), array( 'increment' => fs_text_inline( 'days', $slug ), 'quantity' => number_format_i18n(30), 'value' => 30 * WP_FS__TIME_24_HOURS_IN_SEC, ), ); $snooze_select_html = ''; } // Aliases. $deactivate_text = fs_text_inline( 'Deactivate', 'deactivate', $slug ); $theme_text = fs_text_inline( 'Theme', 'theme', $slug ); $activate_x_text = fs_text_inline( 'Activate %s', 'activate-x', $slug ); $submit_deactivate_text = sprintf( fs_text_inline( 'Submit & %s', 'deactivation-modal-button-submit', $slug ), $fs->is_plugin() ? $deactivate_text : sprintf( $activate_x_text, $theme_text ) ); fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); if ( ! empty( $subscription_cancellation_dialog_box_template_params ) ) { fs_require_template( 'forms/subscription-cancellation.php', $subscription_cancellation_dialog_box_template_params ); } ?> freemius/templates/forms/deactivation/contact.php000064400000001423146725417150016341 0ustar00get_slug(); echo fs_text_inline( 'Sorry for the inconvenience and we are here to help if you give us a chance.', 'contact-support-before-deactivation', $slug ) . sprintf(" %s", $fs->contact_url( 'technical_support' ), fs_text_inline( 'Contact Support', 'contact-support', $slug ) ); freemius/templates/forms/deactivation/retry-skip.php000064400000002222146725417150017015 0ustar00get_slug(); $skip_url = fs_nonce_url( $fs->_get_admin_page_url( '', array( 'fs_action' => $fs->get_unique_affix() . '_skip_activation' ) ), $fs->get_unique_affix() . '_skip_activation' ); $skip_text = strtolower( fs_text_x_inline( 'Skip', 'verb', 'skip', $slug ) ); $use_plugin_anonymously_text = fs_text_inline( 'Click here to use the plugin anonymously', 'click-here-to-use-plugin-anonymously', $slug ); echo sprintf( fs_text_inline( "You might have missed it, but you don't have to share any data and can just %s the opt-in.", 'dont-have-to-share-any-data', $slug ), "{$skip_text}" ) . " {$use_plugin_anonymously_text}";freemius/templates/forms/deactivation/index.php000064400000000127146725417150016015 0ustar00get_slug(); $plugin_data = $fs->get_plugin_data(); $plugin_name = $plugin_data['Name']; $plugin_basename = $fs->get_plugin_basename(); $license = $fs->_get_license(); if ( ! is_object( $license ) ) { $purchase_url = $fs->pricing_url(); } else { $subscription = $fs->_get_subscription( $license->id ); $purchase_url = $fs->checkout_url( is_object( $subscription ) ? ( 1 == $subscription->billing_cycle ? WP_FS__PERIOD_MONTHLY : WP_FS__PERIOD_ANNUALLY ) : WP_FS__PERIOD_LIFETIME, false, array( 'licenses' => $license->quota ) ); } $message = sprintf( fs_text_inline( 'There is a new version of %s available.', 'new-version-available-message', $slug ) . fs_text_inline( ' %s to access version %s security & feature updates, and support.', 'x-for-updates-and-support', $slug ), '', sprintf( '%s', is_object( $license ) ? fs_text_inline( 'Renew your license now', 'renew-license-now', $slug ) : fs_text_inline( 'Buy a license now', 'buy-license-now', $slug ) ), '' ); $modal_content_html = "

    {$message}

    "; $header_title = fs_text_inline( 'New Version Available', 'new-version-available', $slug ); $renew_license_button_text = is_object( $license ) ? fs_text_inline( 'Renew license', 'renew-license', $slug ) : fs_text_inline( 'Buy license', 'buy-license', $slug ); fs_enqueue_local_style( 'fs_dialog_boxes', '/admin/dialog-boxes.css' ); ?> freemius/templates/account/billing.php000064400000031757146725417150014177 0ustar00get_slug(); $edit_text = fs_text_x_inline( 'Edit', 'verb', 'edit', $slug ); $update_text = fs_text_x_inline( 'Update', 'verb', 'update', $slug ); $billing = $fs->_fetch_billing(); $has_billing = ( $billing instanceof FS_Billing ); if ( ! $has_billing ) { $billing = new FS_Billing(); } ?>

    > 'Afghanistan', 'AX' => 'Aland Islands', 'AL' => 'Albania', 'DZ' => 'Algeria', 'AS' => 'American Samoa', 'AD' => 'Andorra', 'AO' => 'Angola', 'AI' => 'Anguilla', 'AQ' => 'Antarctica', 'AG' => 'Antigua and Barbuda', 'AR' => 'Argentina', 'AM' => 'Armenia', 'AW' => 'Aruba', 'AU' => 'Australia', 'AT' => 'Austria', 'AZ' => 'Azerbaijan', 'BS' => 'Bahamas', 'BH' => 'Bahrain', 'BD' => 'Bangladesh', 'BB' => 'Barbados', 'BY' => 'Belarus', 'BE' => 'Belgium', 'BZ' => 'Belize', 'BJ' => 'Benin', 'BM' => 'Bermuda', 'BT' => 'Bhutan', 'BO' => 'Bolivia', 'BQ' => 'Bonaire, Saint Eustatius and Saba', 'BA' => 'Bosnia and Herzegovina', 'BW' => 'Botswana', 'BV' => 'Bouvet Island', 'BR' => 'Brazil', 'IO' => 'British Indian Ocean Territory', 'VG' => 'British Virgin Islands', 'BN' => 'Brunei', 'BG' => 'Bulgaria', 'BF' => 'Burkina Faso', 'BI' => 'Burundi', 'KH' => 'Cambodia', 'CM' => 'Cameroon', 'CA' => 'Canada', 'CV' => 'Cape Verde', 'KY' => 'Cayman Islands', 'CF' => 'Central African Republic', 'TD' => 'Chad', 'CL' => 'Chile', 'CN' => 'China', 'CX' => 'Christmas Island', 'CC' => 'Cocos Islands', 'CO' => 'Colombia', 'KM' => 'Comoros', 'CK' => 'Cook Islands', 'CR' => 'Costa Rica', 'HR' => 'Croatia', 'CU' => 'Cuba', 'CW' => 'Curacao', 'CY' => 'Cyprus', 'CZ' => 'Czech Republic', 'CD' => 'Democratic Republic of the Congo', 'DK' => 'Denmark', 'DJ' => 'Djibouti', 'DM' => 'Dominica', 'DO' => 'Dominican Republic', 'TL' => 'East Timor', 'EC' => 'Ecuador', 'EG' => 'Egypt', 'SV' => 'El Salvador', 'GQ' => 'Equatorial Guinea', 'ER' => 'Eritrea', 'EE' => 'Estonia', 'ET' => 'Ethiopia', 'FK' => 'Falkland Islands', 'FO' => 'Faroe Islands', 'FJ' => 'Fiji', 'FI' => 'Finland', 'FR' => 'France', 'GF' => 'French Guiana', 'PF' => 'French Polynesia', 'TF' => 'French Southern Territories', 'GA' => 'Gabon', 'GM' => 'Gambia', 'GE' => 'Georgia', 'DE' => 'Germany', 'GH' => 'Ghana', 'GI' => 'Gibraltar', 'GR' => 'Greece', 'GL' => 'Greenland', 'GD' => 'Grenada', 'GP' => 'Guadeloupe', 'GU' => 'Guam', 'GT' => 'Guatemala', 'GG' => 'Guernsey', 'GN' => 'Guinea', 'GW' => 'Guinea-Bissau', 'GY' => 'Guyana', 'HT' => 'Haiti', 'HM' => 'Heard Island and McDonald Islands', 'HN' => 'Honduras', 'HK' => 'Hong Kong', 'HU' => 'Hungary', 'IS' => 'Iceland', 'IN' => 'India', 'ID' => 'Indonesia', 'IR' => 'Iran', 'IQ' => 'Iraq', 'IE' => 'Ireland', 'IM' => 'Isle of Man', 'IL' => 'Israel', 'IT' => 'Italy', 'CI' => 'Ivory Coast', 'JM' => 'Jamaica', 'JP' => 'Japan', 'JE' => 'Jersey', 'JO' => 'Jordan', 'KZ' => 'Kazakhstan', 'KE' => 'Kenya', 'KI' => 'Kiribati', 'XK' => 'Kosovo', 'KW' => 'Kuwait', 'KG' => 'Kyrgyzstan', 'LA' => 'Laos', 'LV' => 'Latvia', 'LB' => 'Lebanon', 'LS' => 'Lesotho', 'LR' => 'Liberia', 'LY' => 'Libya', 'LI' => 'Liechtenstein', 'LT' => 'Lithuania', 'LU' => 'Luxembourg', 'MO' => 'Macao', 'MK' => 'Macedonia', 'MG' => 'Madagascar', 'MW' => 'Malawi', 'MY' => 'Malaysia', 'MV' => 'Maldives', 'ML' => 'Mali', 'MT' => 'Malta', 'MH' => 'Marshall Islands', 'MQ' => 'Martinique', 'MR' => 'Mauritania', 'MU' => 'Mauritius', 'YT' => 'Mayotte', 'MX' => 'Mexico', 'FM' => 'Micronesia', 'MD' => 'Moldova', 'MC' => 'Monaco', 'MN' => 'Mongolia', 'ME' => 'Montenegro', 'MS' => 'Montserrat', 'MA' => 'Morocco', 'MZ' => 'Mozambique', 'MM' => 'Myanmar', 'NA' => 'Namibia', 'NR' => 'Nauru', 'NP' => 'Nepal', 'NL' => 'Netherlands', 'NC' => 'New Caledonia', 'NZ' => 'New Zealand', 'NI' => 'Nicaragua', 'NE' => 'Niger', 'NG' => 'Nigeria', 'NU' => 'Niue', 'NF' => 'Norfolk Island', 'KP' => 'North Korea', 'MP' => 'Northern Mariana Islands', 'NO' => 'Norway', 'OM' => 'Oman', 'PK' => 'Pakistan', 'PW' => 'Palau', 'PS' => 'Palestinian Territory', 'PA' => 'Panama', 'PG' => 'Papua New Guinea', 'PY' => 'Paraguay', 'PE' => 'Peru', 'PH' => 'Philippines', 'PN' => 'Pitcairn', 'PL' => 'Poland', 'PT' => 'Portugal', 'PR' => 'Puerto Rico', 'QA' => 'Qatar', 'CG' => 'Republic of the Congo', 'RE' => 'Reunion', 'RO' => 'Romania', 'RU' => 'Russia', 'RW' => 'Rwanda', 'BL' => 'Saint Barthelemy', 'SH' => 'Saint Helena', 'KN' => 'Saint Kitts and Nevis', 'LC' => 'Saint Lucia', 'MF' => 'Saint Martin', 'PM' => 'Saint Pierre and Miquelon', 'VC' => 'Saint Vincent and the Grenadines', 'WS' => 'Samoa', 'SM' => 'San Marino', 'ST' => 'Sao Tome and Principe', 'SA' => 'Saudi Arabia', 'SN' => 'Senegal', 'RS' => 'Serbia', 'SC' => 'Seychelles', 'SL' => 'Sierra Leone', 'SG' => 'Singapore', 'SX' => 'Sint Maarten', 'SK' => 'Slovakia', 'SI' => 'Slovenia', 'SB' => 'Solomon Islands', 'SO' => 'Somalia', 'ZA' => 'South Africa', 'GS' => 'South Georgia and the South Sandwich Islands', 'KR' => 'South Korea', 'SS' => 'South Sudan', 'ES' => 'Spain', 'LK' => 'Sri Lanka', 'SD' => 'Sudan', 'SR' => 'Suriname', 'SJ' => 'Svalbard and Jan Mayen', 'SZ' => 'Swaziland', 'SE' => 'Sweden', 'CH' => 'Switzerland', 'SY' => 'Syria', 'TW' => 'Taiwan', 'TJ' => 'Tajikistan', 'TZ' => 'Tanzania', 'TH' => 'Thailand', 'TG' => 'Togo', 'TK' => 'Tokelau', 'TO' => 'Tonga', 'TT' => 'Trinidad and Tobago', 'TN' => 'Tunisia', 'TR' => 'Turkey', 'TM' => 'Turkmenistan', 'TC' => 'Turks and Caicos Islands', 'TV' => 'Tuvalu', 'VI' => 'U.S. Virgin Islands', 'UG' => 'Uganda', 'UA' => 'Ukraine', 'AE' => 'United Arab Emirates', 'GB' => 'United Kingdom', 'US' => 'United States', 'UM' => 'United States Minor Outlying Islands', 'UY' => 'Uruguay', 'UZ' => 'Uzbekistan', 'VU' => 'Vanuatu', 'VA' => 'Vatican', 'VE' => 'Venezuela', 'VN' => 'Vietnam', 'WF' => 'Wallis and Futuna', 'EH' => 'Western Sahara', 'YE' => 'Yemen', 'ZM' => 'Zambia', 'ZW' => 'Zimbabwe', ) ?>
    freemius/templates/account/index.php000064400000000127146725417150013651 0ustar00get_slug(); ?>

    >
    id ?> created ) ) ?> formatted_gross() ?> is_migrated() ) : ?>
    freemius/templates/account/partials/deactivate-license-button.php000064400000002507146725417150021427 0ustar00
    freemius/templates/account/partials/site.php000064400000050366146725417150015337 0ustar00get_slug(); $site = $VARS['site']; $main_license = $VARS['license']; $is_data_debug_mode = $fs->is_data_debug_mode(); $is_whitelabeled = $fs->is_whitelabeled(); $has_paid_plan = $fs->has_paid_plan(); $is_premium = $fs->is_premium(); $main_user = $VARS['user']; $blog_id = $site['blog_id']; $install = $VARS['install']; $is_registered = ! empty( $install ); $license = null; $trial_plan = $fs->get_trial_plan(); $free_text = fs_text_inline( 'Free', 'free', $slug ); if ( $is_whitelabeled && is_object( $install ) && $fs->is_delegated_connection( $blog_id ) ) { $is_whitelabeled = $fs->is_whitelabeled( true, $blog_id ); } ?> data-install-id="id ?>"> id ?>
    $fs, 'slug' => $slug, 'blog_id' => $blog_id, 'class' => 'button-small', ); $license = null; if ( $is_registered ) { $view_params['install_id'] = $install->id; $view_params['is_localhost'] = $install->is_localhost(); $has_license = FS_Plugin_License::is_valid_id( $install->license_id ); $license = $has_license ? $fs->_get_license_by_id( $install->license_id ) : null; } else { $view_params['is_localhost'] = FS_Site::is_localhost_by_address( $site['url'] ); } if ( ! $is_whitelabeled ) { if ( is_object( $license ) ) { $view_params['license'] = $license; // Show license deactivation button. fs_require_template( 'account/partials/deactivate-license-button.php', $view_params ); } else { if ( is_object( $main_license ) && $main_license->can_activate( $view_params['is_localhost'] ) ) { // Main license is available for activation. $available_license = $main_license; } else { // Try to find any available license for activation. $available_license = $fs->_get_available_premium_license( $view_params['is_localhost'] ); } if ( is_object( $available_license ) ) { $premium_plan = $fs->_get_plan_by_id( $available_license->plan_id ); $view_params['license'] = $available_license; $view_params['class'] .= ' button-primary'; $view_params['plan'] = $premium_plan; fs_require_template( 'account/partials/activate-license-button.php', $view_params ); } } } } ?> is_trial() ) { if ( is_object( $trial_plan ) && $trial_plan->id == $install->trial_plan_id ) { $plan_title = is_string( $trial_plan->name ) ? strtoupper( $trial_plan->title ) : fs_text_inline( 'Trial', 'trial', $slug ); } else { $plan_title = fs_text_inline( 'Trial', 'trial', $slug ); } } else { $plan = $fs->_get_plan_by_id( $install->plan_id ); $plan_title = strtoupper( is_string( $plan->title ) ? $plan->title : strtoupper( $free_text ) ); } } ?> > user_id != $main_user->id ) : ?> user_id ) ?> > > > > > > id != $license->id ) : ?> _get_subscription( $license->id ) ?> is_lifetime() && is_object( $subscription ) ) : ?> > is_active(); $renews_in_text = fs_text_inline( 'Auto renews in %s', 'renews-in', $slug ); /* translators: %s: Time period (e.g. Expires in "2 months") */ $expires_in_text = fs_text_inline( 'Expires in %s', 'expires-in', $slug ); ?>
    : license_id ) ) : ?> is_homepage_url_tracking_allowed( $blog_id ) ?>
    id}", ':' ) ) ?>
    : get_name() ) ?>
    : email ) ?>
    : id ?>
    : public_key ) ?>
    : secret_key ) ?>
    : get_html_escaped_masked_secret_key() ?>
    : id ?> - billing_cycle ? _fs_text_inline( 'Annual', 'annual', $slug ) : _fs_text_inline( 'Monthly', 'monthly', $slug ) ); ?> is_first_payment_pending() ) : ?> is_first_payment_pending() ) : ?> expiration ) ); $downgrade_confirmation_message = sprintf( $downgrade_x_confirm_text, ( $fs->is_only_premium() ? $cancelling_subscription_text : $downgrading_plan_text ), $plan->title, $human_readable_license_expiration ); $after_downgrade_message = ! $license->is_block_features ? sprintf( $after_downgrade_non_blocking_text, $plan->title, $fs->get_module_label( true ) ) : sprintf( $after_downgrade_blocking_text, $plan->title ); ?>
    freemius/templates/account/partials/addon.php000064400000053441146725417150015455 0ustar00get_slug(); $fs_blog_id = $VARS['fs_blog_id']; $active_plugins_directories_map = $VARS['active_plugins_directories_map']; $addon_info = $VARS['addon_info']; $is_addon_activated = $fs->is_addon_activated( $addon_id ); $is_addon_connected = $addon_info['is_connected']; $is_addon_installed = $VARS['is_addon_installed']; $fs_addon = ( $is_addon_connected && $is_addon_installed ) ? freemius( $addon_id ) : false; // Aliases. $download_latest_text = fs_text_x_inline( 'Download Latest', 'as download latest version', 'download-latest', $slug ); $downgrading_plan_text = fs_text_inline( 'Downgrading your plan', 'downgrading-plan', $slug ); $cancelling_subscription_text = fs_text_inline( 'Cancelling the subscription', 'cancelling-subscription', $slug ); /* translators: %1$s: Either 'Downgrading your plan' or 'Cancelling the subscription' */ $downgrade_x_confirm_text = fs_text_inline( '%1$s will immediately stop all future recurring payments and your %s plan license will expire in %s.', 'downgrade-x-confirm', $slug ); $prices_increase_text = fs_text_inline( 'Please note that we will not be able to grandfather outdated pricing for renewals/new subscriptions after a cancellation. If you choose to renew the subscription manually in the future, after a price increase, which typically occurs once a year, you will be charged the updated price.', 'pricing-increase-warning', $slug ); $cancel_trial_confirm_text = fs_text_inline( 'Cancelling the trial will immediately block access to all premium features. Are you sure?', 'cancel-trial-confirm', $slug ); $after_downgrade_non_blocking_text = fs_text_inline( 'You can still enjoy all %s features but you will not have access to %s security & feature updates, nor support.', 'after-downgrade-non-blocking', $slug ); $after_downgrade_blocking_text = fs_text_inline( 'Once your license expires you can still use the Free version but you will NOT have access to the %s features.', 'after-downgrade-blocking', $slug ); /* translators: %s: Plan title (e.g. "Professional") */ $activate_plan_text = fs_text_inline( 'Activate %s Plan', 'activate-x-plan', $slug ); $version_text = fs_text_x_inline( 'Version', 'product version', 'version', $slug ); /* translators: %s: Time period (e.g. Auto renews in "2 months") */ $renews_in_text = fs_text_inline( 'Auto renews in %s', 'renews-in', $slug ); /* translators: %s: Time period (e.g. Expires in "2 months") */ $expires_in_text = fs_text_inline( 'Expires in %s', 'expires-in', $slug ); $cancel_trial_text = fs_text_inline( 'Cancel Trial', 'cancel-trial', $slug ); $change_plan_text = fs_text_inline( 'Change Plan', 'change-plan', $slug ); $upgrade_text = fs_text_x_inline( 'Upgrade', 'verb', 'upgrade', $slug ); $addons_text = fs_text_inline( 'Add-Ons', 'add-ons', $slug ); $downgrade_text = fs_text_x_inline( 'Downgrade', 'verb', 'downgrade', $slug ); $trial_text = fs_text_x_inline( 'Trial', 'trial period', 'trial', $slug ); $free_text = fs_text_inline( 'Free', 'free', $slug ); $activate_text = fs_text_inline( 'Activate', 'activate', $slug ); $plan_text = fs_text_x_inline( 'Plan', 'as product pricing plan', 'plan', $slug ); // Defaults. $plan = null; $is_paid_trial = false; /** * @var FS_Plugin_License $license */ $license = null; $site = null; $is_active_subscription = false; $subscription = null; $is_paying = false; $show_upgrade = false; $is_whitelabeled = $VARS['is_whitelabeled']; if ( is_object( $fs_addon ) ) { $is_paying = $fs_addon->is_paying(); $user = $fs_addon->get_user(); $site = $fs_addon->get_site(); $license = $fs_addon->_get_license(); $subscription = ( is_object( $license ) ? $fs_addon->_get_subscription( $license->id ) : null ); $plan = $fs_addon->get_plan(); $plan_name = $plan->name; $plan_title = $plan->title; $is_paid_trial = $fs_addon->is_paid_trial(); $version = $fs_addon->get_plugin_version(); $is_whitelabeled = ( $fs_addon->is_whitelabeled( true ) && ! $fs_addon->get_parent_instance()->is_data_debug_mode() ); $show_upgrade = ( ! $is_whitelabeled && $fs_addon->has_paid_plan() && ! $is_paying && ! $is_paid_trial && ! $fs_addon->_has_premium_license() ); } else if ( $is_addon_connected ) { if ( empty( $addon_info ) || ! isset( $addon_info['site'] ) ) { $is_addon_connected = false; } else { /** * @var FS_Site $site */ $site = $addon_info['site']; $version = $addon_info['version']; $plan_name = isset( $addon_info['plan_name'] ) ? $addon_info['plan_name'] : ''; $plan_title = isset( $addon_info['plan_title'] ) ? $addon_info['plan_title'] : ''; if ( isset( $addon_info['license'] ) ) { $license = $addon_info['license']; } if ( isset( $addon_info['subscription'] ) ) { $subscription = $addon_info['subscription']; } $has_valid_and_active_license = ( is_object( $license ) && $license->is_active() && $license->is_valid() ); $is_paid_trial = ( $site->is_trial() && $has_valid_and_active_license && ( $site->trial_plan_id == $license->plan_id ) ); $is_whitelabeled = $addon_info['is_whitelabeled']; } } $has_feature_enabled_license = ( is_object( $license ) && $license->is_features_enabled() ); $is_active_subscription = ( is_object( $subscription ) && $subscription->is_active() ); $show_delete_install_button = ( ! $is_paying && WP_FS__DEV_MODE && ! $is_whitelabeled ); ?> > id ?> is_trial() || is_object( $license ) ) : ?> is_trial() ) { $tags[] = array( 'label' => $trial_text, 'type' => 'success' ); $tags[] = array( 'label' => sprintf( ( $is_paid_trial ? $renews_in_text : $expires_in_text ), human_time_diff( time(), strtotime( $site->trial_ends ) ) ), 'type' => ( $is_paid_trial ? 'success' : 'warn' ) ); } else { if ( is_object( $license ) ) { if ( $license->is_cancelled ) { $tags[] = array( 'label' => fs_text_inline( 'Cancelled', 'cancelled', $slug ), 'type' => 'error' ); } else if ( $license->is_expired() ) { $tags[] = array( 'label' => fs_text_inline( 'Expired', 'expired', $slug ), 'type' => 'error' ); } else if ( $license->is_lifetime() ) { $tags[] = array( 'label' => fs_text_inline( 'No expiration', 'no-expiration', $slug ), 'type' => 'success' ); } else if ( ! $is_active_subscription && ! $license->is_first_payment_pending() ) { $tags[] = array( 'label' => sprintf( $expires_in_text, human_time_diff( time(), strtotime( $license->expiration ) ) ), 'type' => 'warn' ); } else if ( $is_active_subscription && ! $subscription->is_first_payment_pending() ) { $tags[] = array( 'label' => sprintf( $renews_in_text, human_time_diff( time(), strtotime( $subscription->next_payment ) ) ), 'type' => 'success' ); } } } foreach ( $tags as $t ) { printf( '' . "\n", $t['type'], $t['label'] ); } ?> get_id(), 'account', 'deactivate_license', fs_text_inline( 'Deactivate License', 'deactivate-license', $slug ), '', array( 'plugin_id' => $addon_id ), false, true ); $human_readable_license_expiration = human_time_diff( time(), strtotime( $license->expiration ) ); $downgrade_confirmation_message = sprintf( $downgrade_x_confirm_text, ( $fs_addon->is_only_premium() ? $cancelling_subscription_text : $downgrading_plan_text ), $plan->title, $human_readable_license_expiration ); $after_downgrade_message = ! $license->is_block_features ? sprintf( $after_downgrade_non_blocking_text, $plan->title, $fs_addon->get_module_label( true ) ) : sprintf( $after_downgrade_blocking_text, $plan->title ); if ( ! $license->is_lifetime() && $is_active_subscription ) { $buttons[] = fs_ui_get_action_button( $fs->get_id(), 'account', 'downgrade_account', esc_html( $fs_addon->is_only_premium() ? fs_text_inline( 'Cancel Subscription', 'cancel-subscription', $slug ) : $downgrade_text ), '', array( 'plugin_id' => $addon_id ), false, false, false, ( $downgrade_confirmation_message . ' ' . $after_downgrade_message . ' ' . $prices_increase_text ), 'POST' ); } } else if ( $is_paid_trial ) { $buttons[] = fs_ui_get_action_button( $fs->get_id(), 'account', 'cancel_trial', esc_html( $cancel_trial_text ), '', array( 'plugin_id' => $addon_id ), false, false, 'dashicons dashicons-download', $cancel_trial_confirm_text, 'POST' ); } else if ( ! $has_feature_enabled_license ) { $premium_licenses = $fs_addon->get_available_premium_licenses(); if ( ! empty( $premium_licenses ) ) { $premium_license = $premium_licenses[0]; $has_multiple_premium_licenses = ( 1 < count( $premium_licenses ) ); if ( ! $has_multiple_premium_licenses ) { $premium_plan = $fs_addon->_get_plan_by_id( $premium_license->plan_id ); $site = $fs_addon->get_site(); $buttons[] = fs_ui_get_action_button( $fs->get_id(), 'account', 'activate_license', esc_html( sprintf( $activate_plan_text, $premium_plan->title, ( $site->is_localhost() && $premium_license->is_free_localhost ) ? '[localhost]' : ( 1 < $premium_license->left() ? $premium_license->left() . ' left' : '' ) ) ), ($has_multiple_premium_licenses ? 'activate-license-trigger ' . $fs_addon->get_unique_affix() : ''), array( 'plugin_id' => $addon_id, 'license_id' => $premium_license->id, ), true, true ); $is_license_activation_added = true; } } } } // if ( 0 == count( $buttons ) ) { if ( $fs_addon->is_premium() && ! $is_license_activation_added ) { $fs_addon->_add_license_activation_dialog_box(); $buttons[] = fs_ui_get_action_button( $fs->get_id(), 'account', 'activate_license', ( ! $has_feature_enabled_license ) ? fs_esc_html_inline( 'Activate License', 'activate-license', $slug ) : fs_esc_html_inline( 'Change License', 'change-license', $slug ), 'activate-license-trigger ' . $fs_addon->get_unique_affix(), array( 'plugin_id' => $addon_id, ), (! $has_feature_enabled_license), true ); $is_license_activation_added = true; } if ( $fs_addon->has_paid_plan() ) { // Add sync license only if non of the other CTAs are visible. $buttons[] = fs_ui_get_action_button( $fs->get_id(), 'account', $fs->get_unique_affix() . '_sync_license', fs_esc_html_x_inline( 'Sync', 'as synchronize', 'sync', $slug ), '', array( 'plugin_id' => $addon_id ), false, true ); } // } } else if ( ! $show_upgrade ) { if ( $fs->is_addon_installed( $addon_id ) ) { $addon_file = $fs->get_addon_basename( $addon_id ); if ( ! isset( $active_plugins_directories_map[ dirname( $addon_file ) ] ) ) { $buttons[] = sprintf( '%s', wp_nonce_url( 'plugins.php?action=activate&plugin=' . $addon_file, 'activate-plugin_' . $addon_file ), fs_esc_attr_inline( 'Activate this add-on', 'activate-this-addon', $slug ), $activate_text ); } } else { if ( $fs->is_allowed_to_install() ) { $buttons[] = sprintf( '%s', wp_nonce_url( self_admin_url( 'update.php?' . ( ( isset( $addon_info['has_paid_plan'] ) && $addon_info['has_paid_plan'] ) ? 'fs_allow_updater_and_dialog=true&' : '' ) . 'action=install-plugin&plugin=' . $addon_info['slug'] ), 'install-plugin_' . $addon_info['slug'] ), fs_text_inline( 'Install Now', 'install-now', $slug ) ); } else { $buttons[] = sprintf( '%s', $fs->_get_latest_download_local_url( $addon_id ), esc_html( $download_latest_text ) ); } } } if ( $show_upgrade ) { $buttons[] = sprintf( ' %s', esc_url( network_admin_url( 'plugin-install.php?fs_allow_updater_and_dialog=true' . ( ! empty( $fs_blog_id ) ? '&fs_blog_id=' . $fs_blog_id : '' ) . '&tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon_info['slug'] . '&TB_iframe=true&width=600&height=550' ) ), esc_attr( sprintf( fs_text_inline( 'More information about %s', 'more-information-about-x', $slug ), $addon_info['title'] ) ), esc_attr( $addon_info['title'] ), ( $fs_addon->has_free_plan() ? $upgrade_text : fs_text_x_inline( 'Purchase', 'verb', 'purchase', $slug ) ) ); } $buttons_count = count( $buttons ); ?> 1 ) : ?>
    1 ) : ?>
    is_addon_installed( $addon_id ); ?> get_addon_basename( $addon_id ) ?> is_allowed_to_install() ) : ?> get_id(), 'account', 'delete_account', fs_text_x_inline( 'Delete', 'verb', 'delete', $slug ), '', array( 'plugin_id' => $addon_id ), false, $show_upgrade ); } ?> freemius/templates/account/partials/index.php000064400000000127146725417150015470 0ustar00_get_subscription( $license->id ) : null; $has_active_subscription = ( is_object( $license_subscription ) && $license_subscription->is_active() ); $button_id = "fs_disconnect_button_{$fs->get_id()}"; $website_link = sprintf( '%s', fs_strip_url_protocol( untrailingslashit( Freemius::get_unfiltered_site_url() ) ) ); ?>
    esc_html_inline( 'Disconnect', 'disconnect' ) ?>
    freemius/templates/debug/scheduled-crons.php000064400000007736146725417150015273 0ustar00get_option( $module_type . 's' ), FS_Plugin::get_class_name() ); if ( is_array( $modules ) && count( $modules ) > 0 ) { foreach ( $modules as $slug => $data ) { if ( WP_FS__MODULE_TYPE_THEME === $module_type ) { $current_theme = wp_get_theme(); $is_active = ( $current_theme->stylesheet === $data->file ); } else { $is_active = is_plugin_active( $data->file ); } /** * @author Vova Feldman * * @since 1.2.1 Don't load data from inactive modules. */ if ( $is_active ) { $fs = freemius( $data->id ); $next_execution = $fs->next_sync_cron(); $last_execution = $fs->last_sync_cron(); if ( false !== $next_execution ) { $scheduled_crons[ $slug ][] = array( 'name' => $fs->get_plugin_name(), 'slug' => $slug, 'module_type' => $fs->get_module_type(), 'type' => 'sync_cron', 'last' => $last_execution, 'next' => $next_execution, ); } $next_install_execution = $fs->next_install_sync(); $last_install_execution = $fs->last_install_sync(); if (false !== $next_install_execution || false !== $last_install_execution ) { $scheduled_crons[ $slug ][] = array( 'name' => $fs->get_plugin_name(), 'slug' => $slug, 'module_type' => $fs->get_module_type(), 'type' => 'install_sync', 'last' => $last_install_execution, 'next' => $next_install_execution, ); } } } } } $sec_text = fs_text_x_inline( 'sec', 'seconds' ); ?>

    $crons ) : ?>
    freemius/templates/debug/logger.php000064400000004015146725417150013453 0ustar00

    >
    #
    . get_id() ?> %s', esc_html( substr( $log['msg'], 0, 32 ) ) . ( 32 < strlen( $log['msg'] ) ? '...' : '' ) ); ?>
    get_file() ) . ':' . $log['line']; } ?>
    freemius/templates/debug/plugins-themes-sync.php000064400000005300146725417150016110 0ustar00get_option( 'all_plugins' ); $all_themes = $fs_options->get_option( 'all_themes' ); /* translators: %s: time period (e.g. In "2 hours") */ $in_x_text = fs_text_inline( 'In %s', 'in-x' ); /* translators: %s: time period (e.g. "2 hours" ago) */ $x_ago_text = fs_text_inline( '%s ago', 'x-ago' ); $sec_text = fs_text_x_inline( 'sec', 'seconds' ); ?>

    plugins ) ?> timestamp ) && is_numeric( $all_plugins->timestamp ) ) { $diff = abs( WP_FS__SCRIPT_START_TIME - $all_plugins->timestamp ); $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? $diff . ' ' . $sec_text : human_time_diff( WP_FS__SCRIPT_START_TIME, $all_plugins->timestamp ); echo esc_html( sprintf( ( ( WP_FS__SCRIPT_START_TIME < $all_plugins->timestamp ) ? $in_x_text : $x_ago_text ), $human_diff ) ); } ?>
    themes ) ?> timestamp ) && is_numeric( $all_themes->timestamp ) ) { $diff = abs( WP_FS__SCRIPT_START_TIME - $all_themes->timestamp ); $human_diff = ( $diff < MINUTE_IN_SECONDS ) ? $diff . ' ' . $sec_text : human_time_diff( WP_FS__SCRIPT_START_TIME, $all_themes->timestamp ); echo esc_html( sprintf( ( ( WP_FS__SCRIPT_START_TIME < $all_themes->timestamp ) ? $in_x_text : $x_ago_text ), $human_diff ) ); } ?>
    freemius/templates/debug/index.php000064400000000127146725417150013303 0ustar00 0, 'POST' => 0, 'PUT' => 0, 'DELETE' => 0 ); $show_body = false; foreach ( $logger as $log ) { $counters[ $log['method'] ] ++; if ( ! is_null( $log['body'] ) ) { $show_body = true; } } $pretty_print = $show_body && defined( 'JSON_PRETTY_PRINT' ) && version_compare( phpversion(), '5.3', '>=' ); /** * This template is used for debugging, therefore, when possible * we'd like to prettify the output of a JSON encoded variable. * This will only be executed when $pretty_print is `true`, and * the var is `true` only for PHP 5.3 and higher. Due to the * limitations of the current Theme Check, it throws an error * that using the "options" parameter (the 2nd param) is not * supported in PHP 5.2 and lower. Thus, we added this alias * variable to work around that false-positive. * * @author Vova Feldman (@svovaf) * @since 1.2.2.7 */ $encode = 'json_encode'; $root_path_len = strlen( ABSPATH ); $ms_text = fs_text_x_inline( 'ms', 'milliseconds' ); ?>

    Total Time:

    Total Requests:

    $count ) : ?>

    :

    #
    . %s', $log['path'] ); ?> %s', substr( $body, 0, 32 ) . ( 32 < strlen( $body ) ? '...' : '' ) ); if ( $pretty_print ) { $body = $encode( json_decode( $log['body'] ), JSON_PRETTY_PRINT ); } ?>
    %s', substr( $result, 0, 32 ) . ( 32 < strlen( $result ) ? '...' : '' ) ); } if ( $is_not_empty_result && $pretty_print ) { $decoded = json_decode( $result ); if ( ! is_null( $decoded ) ) { $result = $encode( $decoded, JSON_PRETTY_PRINT ); } } else { $result = is_string( $result ) ? $result : json_encode( $result ); } ?> style="display: none">
    freemius/templates/email.php000064400000002007146725417150012174 0ustar00 $section ) { ?> $row ) { $col_count = count( $row ); ?>
    :
    freemius/templates/partials/network-activation.php000064400000011505146725417150016557 0ustar00get_slug(); $sites = $VARS['sites']; $require_license_key = $VARS['require_license_key']; $show_delegation_option = $fs->apply_filters( 'show_delegation_option', true ); $enable_per_site_activation = $fs->apply_filters( 'enable_per_site_activation', true ); ?> |' ?> freemius/templates/partials/index.php000064400000000032146725417150014027 0ustar00get_text_x_inline( 'Opt Out', 'verb', 'opt-out' ); $opt_in_text = $fs->get_text_x_inline( 'Opt In', 'verb', 'opt-in' ); if ( empty( $permission_group[ 'prompt' ] ) ) { $is_enabled = false; foreach ( $permission_group[ 'permissions' ] as $permission ) { if ( true === $permission[ 'default' ] ) { // Even if one of the permissions is on, treat as if the entire group is on. $is_enabled = true; break; } } } else { $is_enabled = ( isset( $permission_group['is_enabled'] ) && true === $permission_group['is_enabled'] ); } ?>

      render_permission( $permission ); } ?>
    freemius/templates/connect/permission.php000064400000003461146725417150014733 0ustar00
  • class="fs-tooltip-trigger">

  • freemius/templates/connect/index.php000064400000000127146725417150013646 0ustar00get_slug(); $timestamp = time(); $context_params = array( 'plugin_id' => $fs->get_id(), 'plugin_public_key' => $fs->get_public_key(), 'plugin_version' => $fs->get_plugin_version(), ); $bundle_id = $fs->get_bundle_id(); if ( ! is_null( $bundle_id ) ) { $context_params['bundle_id'] = $bundle_id; } // Get site context secure params. if ( $fs->is_registered() ) { $context_params = array_merge( $context_params, FS_Security::instance()->get_context_params( $fs->get_site(), $timestamp, 'upgrade' ) ); } else { $context_params['home_url'] = home_url(); } if ( $fs->is_payments_sandbox() ) // Append plugin secure token for sandbox mode authentication.) { $context_params['sandbox'] = FS_Security::instance()->get_secure_token( $fs->get_plugin(), $timestamp, 'checkout' ); } $query_params = array_merge( $context_params, $_GET, array( 'next' => $fs->_get_sync_license_url( false, false ), 'plugin_version' => $fs->get_plugin_version(), // Billing cycle. 'billing_cycle' => fs_request_get( 'billing_cycle', WP_FS__PERIOD_ANNUALLY ), 'is_network_admin' => fs_is_network_admin() ? 'true' : 'false', 'currency' => $fs->apply_filters( 'default_currency', 'usd' ), 'discounts_model' => $fs->apply_filters( 'pricing/discounts_model', 'absolute' ), ) ); $use_external_pricing = $fs->should_use_external_pricing(); if ( ! $use_external_pricing ) { $pricing_js_url = fs_asset_url( $fs->get_pricing_js_path() ); wp_enqueue_script( 'freemius-pricing', $pricing_js_url ); } else { if ( ! $fs->is_registered() ) { $template_data = array( 'id' => $fs->get_id(), ); fs_require_template( 'forms/trial-start.php', $template_data); } $view_params = array( 'id' => $VARS['id'], 'page' => strtolower( $fs->get_text_x_inline( 'Pricing', 'noun', 'pricing' ) ), ); fs_require_once_template('secure-https-header.php', $view_params); } $has_tabs = $fs->_add_tabs_before_content(); if ( $has_tabs ) { $query_params['tabs'] = 'true'; } ?>
    $fs->contact_url(), 'is_production' => ( defined( 'WP_FS__IS_PRODUCTION_MODE' ) ? WP_FS__IS_PRODUCTION_MODE : null ), 'menu_slug' => $fs->get_menu_slug(), 'mode' => 'dashboard', 'fs_wp_endpoint_url' => WP_FS__ADDRESS, 'request_handler_url' => admin_url( 'admin-ajax.php?' . http_build_query( array( 'module_id' => $fs->get_id(), 'action' => $fs->get_ajax_action( 'pricing_ajax_action' ), 'security' => $fs->get_ajax_security( 'pricing_ajax_action' ) ) ) ), 'selector' => '#fs_pricing_wrapper', 'unique_affix' => $fs->get_unique_affix(), 'show_annual_in_monthly' => $fs->apply_filters( 'pricing/show_annual_in_monthly', true ), ), $query_params ); wp_add_inline_script( 'freemius-pricing', 'Freemius.pricing.new( ' . json_encode( $pricing_config ) . ' )' ); ?>
    _add_tabs_after_content(); } $params = array( 'page' => 'pricing', 'module_id' => $fs->get_id(), 'module_type' => $fs->get_module_type(), 'module_slug' => $slug, 'module_version' => $fs->get_plugin_version(), ); fs_require_template( 'powered-by.php', $params ); freemius/templates/secure-https-header.php000064400000002022146725417150014756 0ustar00
    get_text_inline( 'Secure HTTPS %s page, running from an external domain', 'secure-x-page-header' ), $VARS['page'] ) ) . ' - ' . sprintf( '%s', 'https://www.mcafeesecure.com/verify?host=' . WP_FS__ROOT_DOMAIN_PRODUCTION, 'Freemius Inc. [US]' ); } ?>
    freemius/templates/add-trial-to-pricing.php000064400000001432146725417150015020 0ustar00 freemius/README.md000064400000026515146725417150007667 0ustar00Freemius WordPress SDK ====================== Welcome to the official repository for the Freemius SDK! Adding the SDK to your WordPress plugin, theme, or add-ons, enables all the benefits that come with using the [Freemius platform](https://freemius.com) such as: * [Software Licensing](https://freemius.com/wordpress/software-licensing/) * [Secure Checkout](https://freemius.com/wordpress/checkout/) * [Subscriptions](https://freemius.com/wordpress/recurring-payments-subscriptions/) * [Automatic Updates](https://freemius.com/wordpress/automatic-software-updates/) * [Seamless EU VAT](https://freemius.com/wordpress/collecting-eu-vat-europe/) * [Cart Abandonment Recovery](https://freemius.com/wordpress/cart-abandonment-recovery/) * [Affiliate Platform](https://freemius.com/wordpress/affiliate-platform/) * [Analytics & Usage Tracking](https://freemius.com/wordpress/insights/) * [User Dashboard](https://freemius.com/wordpress/user-dashboard/) * [Monetization](https://freemius.com/wordpress/) * [Analytics](https://freemius.com/wordpress/insights/) * [More...](https://freemius.com/wordpress/features-comparison/) Freemius truly empowers developers to create prosperous subscription-based businesses. If you're new to Freemius then we recommend taking a look at our [Getting Started](https://freemius.com/help/documentation/getting-started/) guide first. If you're a WordPress plugin or theme developer and are interested in monetizing with Freemius then you can [sign-up for a FREE account](https://dashboard.freemius.com/register/): https://dashboard.freemius.com/register/ Once you have your account setup and are familiar with how it all works you're ready to begin [integrating Freemius](https://freemius.com/help/documentation/wordpress-sdk/integrating-freemius-sdk/) into your WordPress product You can see some of the existing WordPress.org plugins & themes that are already utilizing the power of Freemius here: * https://profiles.wordpress.org/freemius/#content-plugins * https://includewp.com/freemius/#focus ## Code Documentation You can find the SDK's documentation here: https://freemius.com/help/documentation/wordpress-sdk/ ## Integrating & Initializing the SDK As part of the integration process, you'll need to [add the latest version](https://freemius.com/help/documentation/getting-started/#add_the_latest_wordpress_sdk_into_your_product) of the Freemius SDK into your WordPress project. Then, when you've completed the [SDK integration form](https://freemius.com/help/documentation/getting-started/#fill_out_the_sdk_integration_form) a snippet of code is generated which you'll need to copy and paste into the top of your main plugin's PHP file, right after the plugin's header comment. Note: For themes, this will be in the root `functions.php` file instead. A typical SDK snippet will look similar to the following (your particular snippet may differ slightly depending on your integration): ```php if ( ! function_exists( 'my_prefix_fs' ) ) { // Create a helper function for easy SDK access. function my_prefix_fs() { global $my_prefix_fs; if ( ! isset( $my_prefix_fs ) ) { // Include Freemius SDK. require_once dirname(__FILE__) . '/freemius/start.php'; $my_prefix_fs = fs_dynamic_init( array( 'id' => '1234', 'slug' => 'my-new-plugin', 'premium_slug' => 'my-new-plugin-premium', 'type' => 'plugin', 'public_key' => 'pk_bAEfta69seKymZzmf2xtqq8QXHz9y', 'is_premium' => true, // If your plugin is a serviceware, set this option to false. 'has_premium_version' => true, 'has_paid_plans' => true, 'is_org_compliant' => true, 'menu' => array( 'slug' => 'my-new-plugin', 'parent' => array( 'slug' => 'options-general.php', ), ), // Set the SDK to work in a sandbox mode (for development & testing). // IMPORTANT: MAKE SURE TO REMOVE SECRET KEY BEFORE DEPLOYMENT. 'secret_key' => 'sk_ubb4yN3mzqGR2x8#P7r5&@*xC$utE', ) ); } return $my_prefix_fs; } // Init Freemius. my_prefix_fs(); // Signal that SDK was initiated. do_action( 'my_prefix_fs_loaded' ); } ``` ## Usage example You can call anySDK methods by prefixing them with the shortcode function for your particular plugin/theme (specified when completing the SDK integration form in the Developer Dashboard): ```php get_upgrade_url(); ?> ``` Or when calling Freemius multiple times in a scope, it's recommended to use it with the global variable: ```php get_account_url(); ?> ``` There are many other SDK methods available that you can use to enhance the functionality of your WordPress product. Some of the more common use-cases are covered in the [Freemius SDK Gists](https://freemius.com/help/documentation/wordpress-sdk/gists/) documentation. ## Adding license based logic examples Add marketing content to encourage your users to upgrade for your paid version: ```php is_not_paying() ) { echo '

    ' . esc_html__('Awesome Premium Features', 'my-plugin-slug') . '

    '; echo '' . esc_html__('Upgrade Now!', 'my-plugin-slug') . ''; echo '
    '; } ?> ``` Add logic which will only be available in your premium plugin version: ```php is__premium_only() ) { // ... premium only logic ... } ?> ``` To add a function which will only be available in your premium plugin version, simply add __premium_only as the suffix of the function name. Just make sure that all lines that call that method directly or by hooks, are also wrapped in premium only logic: ```php is__premium_only() ) { // Init premium version. $this->admin_init__premium_only(); add_action( 'admin_init', array( &$this, 'admin_init_hook__premium_only' ); } ... } // This method will be only included in the premium version. function admin_init__premium_only() { ... } // This method will be only included in the premium version. function admin_init_hook__premium_only() { ... } } ?> ``` Add logic which will only be executed for customers in your 'professional' plan: ```php is_plan('professional', true) ) { // .. logic related to Professional plan only ... } ?> ``` Add logic which will only be executed for customers in your 'professional' plan or higher plans: ```php is_plan('professional') ) { // ... logic related to Professional plan and higher plans ... } ?> ``` Add logic which will only be available in your premium plugin version AND will only be executed for customers in your 'professional' plan (and higher plans): ```php is_plan__premium_only('professional') ) { // ... logic related to Professional plan and higher plans ... } ?> ``` Add logic only for users in trial: ```php is_trial() ) { // ... logic for users in trial ... } ?> ``` Add logic for specified paid plan: ```php is__premium_only() ) { if ( my_prefix_fs()->is_plan( 'professional', true ) ) { // ... logic related to Professional plan only ... } else if ( my_prefix_fs()->is_plan( 'business' ) ) { // ... logic related to Business plan and higher plans ... } } ?> ``` ## Excluding files and folders from the free plugin version There are [two ways](https://freemius.com/help/documentation/wordpress-sdk/software-licensing/#excluding_files_and_folders_from_the_free_plugin_version) to exclude files from your free version. 1. Add `__premium_only` just before the file extension. For example, functions__premium_only.php will be only included in the premium plugin version. This works for all types of files, not only PHP. 2. Add `@fs_premium_only` a special meta tag to the plugin's main PHP file header. Example: ```php ``` In the example plugin header above, the file `/lib/functions.php` and the directory `/premium-files/` will be removed from the free plugin version. # WordPress.org Compliance Based on [WordPress.org Guidelines](https://wordpress.org/plugins/about/guidelines/) you are not allowed to submit a plugin that has premium code in it: > All code hosted by WordPress.org servers must be free and fully-functional. If you want to sell advanced features for a plugin (such as a "pro" version), then you must sell and serve that code from your own site, we will not host it on our servers. Therefore, if you want to deploy your free plugin's version to WordPress.org, make sure you wrap all your premium code with `if ( my_prefix_fs()->{{ method }}__premium_only() )` or use [some of the other methods](https://freemius.com/help/documentation/wordpress-sdk/software-licensing/) provided by the SDK to exclude premium features & files from the free version. ## Deployment Zip your Freemius product’s root folder and [upload it in the Deployment section](https://freemius.com/help/documentation/selling-with-freemius/deployment/) in the *Freemius Developer's Dashboard*. The plugin/theme will automatically be scanned and processed by a custom-developed *PHP Processor* which will auto-generate two versions of your plugin: 1. **Premium version**: Identical to your uploaded version, including all code (except your `secret_key`). Will be enabled for download ONLY for your paying or in trial customers. 2. **Free version**: The code stripped from all your paid features (based on the logic added wrapped in `{ method }__premium_only()`). The free version is the one that you should give your users to download. Therefore, download the free generated version and upload to your site. Or, if your plugin was WordPress.org compliant and you made sure to exclude all your premium code with the different provided techniques, you can deploy the downloaded free version to the .org repo. ## License Copyright (c) Freemius®, Inc. Licensed under the GNU general public license (version 3). freemius/config.php000064400000034545146725417150010370 0ustar00 “Add new plugin†2. Search for "wow styler" in the WP Plugins Repository 3. Install and activate the WOW Styler 4. Enjoy some of the plugin’s features for free. == CF7 WOW Styler Free Features == WOW, Styler’s free version gives you an opportunity to create a basic design for your contact forms. It includes the following customization options: - Text style customization - Text color - Font size - 6 font family selection - Links color - Links hover color - Labels color - Labels font size - Font weight - Font style (Normal, Italic, Oblique, Inherit) - Form padding, margin, and border - Field input - Buttons with text, background, hover, hover background color, font size, button, and shadow styles customization - Style scheme preview - Split view - Second Column view (Live, Unstyled) - Duplicate form in the second column - Default style scheme for all forms - Implementing custom CSS for tech-savvy users The WOW Styler eases the user experience by using also the theme styles as a base. This helps users save time to get the theme style into the CF7 form style with the WOW styler. To make your experience smoother and more pleasant the plugin is always under improvement. In case of any issues, the users are welcome to get high-quality support from the Customer Satisfaction specialists. == Quick Used Cases of the Free Version == You can greatly benefit from some of the best features of the WOW Styler plugin absolutely for free. The users who have built their contact forms through the Contact Form 7 plugin can use the WOW Styler in multiple ways, such as: - Changing colors (including text, background, hover) of the default form scheme to keep your brand identity. - Changing only a background color or a hover color and saving the form with different schemes. - Use buttons with different style options to attract more attention to them. - Use the Input Fields options to style your custom inputs in a unique way. == How to Switch to the Pro version? == If you have an active WP2LEADS Pro version (Plugin connects WordPress with KlickTipp german email marketing) then you can use the WOW Styler with all its Premium features absolutely for free. Or else, you can enjoy all the settings of the plugin in a 14-day free trial period. Days before finishing the trial period, you will get an Email reminder that you will be auto upgraded to the Pro version you choose which is most suitable plans for your usage. Here's how to switch to the Pro version: 1. Find the CF7 Styler in the “Contact†submenu. 2. Move to the “Upgrade†section. 3. Choose your desired Pro package and make a purchase directly from there. 4. License will be activated automatically. 5. The logged-in user email is used to send a copy of your License key, premium download link, and invoice. == CF7 WOW Styler Pro Features == The CF7 WOW Styler Pro version offers additional features and customization options. It includes all the features available in the Free version, plus the following: - Buttons (radio buttons and checkboxes) and style boxes one per line (instead of one after the other without a new line) - Individual styles for forms - Multiple style schemes to switch and attach to Contact Form 7 forms - Background picture and gif, opacity - Loading styles in tag in case the theme or a page builder removes the “Custom CSS†function that adds the CF7 Style. == Brilliant Used Cases of the WOW Styler Pro == If you want to make your Contact form 7 form more unique, live, and engaging, then you can implement gifs to your form background. In case your page builder removes styles loaded in the header and your form remains unstyled, you can load style in the body to show your form’s attractive design.
    Please make sure you read the latest changes and benefits from our WP.org changelog to get the most out of the CF7 styling plugin.
    Start by using the New Handbook & Knowledge Base! == Frequently Asked Questions == Here are some frequently asked questions about the WOW Styler plugin: = Can I test the Pro features in a free trial period? = Yes, all the Pro features are available in the 14 days’ free trial period. During that time, you will get an Email notification reminding you to get auto-upgraded to the Premium version to continue using the WOW Styler Pro features. = How can I get the WOW Styler Pro for free? = If you have activated WP2LEADS Pro license, then you can use the WOW Styler Pro version for free. Referee paying users and pay your license fee with the 35% affiliation commission. (Referee 3 get yours free) = Can I propose a plugin customization? = We are very happy to receive individual customization proposals. Just create a screencast video, avoiding showing any personal data. Share the video link via the support chat in the support forum. You will get the solution to your issue mostly in just one day. = Do you have an Affiliate program? = Yes, we have an Affiliate program, so you can earn money with the CF7 WOW Styler. You will get a 35% lifetime commission through your affiliate link and even more by writing a blog post. In this case, you will also obtain 12 months pro version. You can find the program details by entering the “Affiliation†section available directly inside the plugin. Watch the video to get a lifetime income with the WOW Styler Affiliate program. = What if I cannot find the Affiliate program? = If you cannot find an affiliate program and you have a Pro license activated through WP2LEADS, then you should deactivate it, become an affiliate, then activate WP2LEADS once more. = What are the server requirements to use the WOW Styler? = The minimum PHP memory must be 64M. 128M will be better. The higher your PHP memory, the slower you will run to the white site. = What if I use Thrive Architect? = Here is a video tutorial on how to add the CF7 Wow Styler in Thrive Architect page builder. = How can I translate the plugin? = You can use the Loco Translate WordPress plugin by generating .po and .mo files. After that, you should share the generated files via this email address: support@saleswonder.biz. = How can I update the newly purchased Pro license? = You have two options to do this: - Enter your “Account†details inside the plugin and “Synchronize Licenseâ€. - Change the license directly in the activated plugin. == Installation == Let's get your forms styled * Step 1: Install/activate Contact Form 7 WOW style plugin * Step 2: Go to CF7 Styler which is in the "Contact" sub menu **Pst. If you like some example forms which are already connected to [Klick Tipp an German E-Mail and SMS Marketing Provider] (https://www.klick-tipp.com/15194) [Get WP2LEADS too](https://de.wordpress.org/plugins/wp2leads/). If you are using WP2LEADS with an active Pro Version the Contact Form 7 Styler Premium version is free for you. == Screenshots == 1. How to add style in contact form 7 to meet your sites CI and design? 2. Make radio button items one per line and checkbox items one per line 3. How to add Contact Form 7 background images 4. Lets style Contact Form 7 5. Before - unstyled contactform7 6. Please rate us - form with styler interface with Contact Form 7 style 7. Example how to add style in Contact Form 7 with Sunflower form backgrounds 8. GIF what is new with version == Upgrade Notice == = All upgrades are compatible when upgrade from any Contact Form 7 style plugin version = The latest version is checked during testing update on our site and will work. == Changelog == = 1.5.2 + 1.5.3 released 2023.06.15 = * Updated: Freemius SDK for better license, trial, opt-in handling Please all update = 1.5.0 + 1.5.1 released 2023.04.15 = * Fix: Avoid fatal error when activate the plugin twice When upgrade free to Pro free gets deactivated. * Fix: Freemius SDK update fixes one error * Added/updated: Languages total: IT (Italian), VI (Vietnamese) HI (Hindi) ES-MX Spanish (Mexico) UR (Urdu) RU (Russian) PT-BR Portuguese (Brazil), DE German PO Polish ES Spanish (Spain) FRFrench (France) JA Japanese VI Vietnamese Thank you for your trust and great support by buying the Pro version read more in the full changelog.txtadmin/class-cf7-customizer-admin-ajax.php000064400000047637146725417150014375 0ustar00 */ class Cf7_Customizer_Admin_Ajax { /** * The ID of this plugin. * * @since 1.0.0 * @access private * @var string $plugin_name The ID of this plugin. */ private $plugin_name; /** * The version of this plugin. * * @since 1.0.0 * @access private * @var string $version The current version of this plugin. */ private $version; /** * Initialize the class and set its properties. * * @since 1.0.0 * @param string $plugin_name The name of this plugin. * @param string $version The version of this plugin. */ public function __construct( $plugin_name, $version ) { $this->plugin_name = $plugin_name; $this->version = $version; } public function save_form_customizer_settings() { $plugin_version = Cf7_License::get_license_version(); $style_schemes = get_option('cf7cstmzr_style_schemes', array()); if (empty($style_schemes)) { $create_default = true; } $style_scheme_slug = !empty($_POST['styleSchemeSlug']) ? sanitize_text_field($_POST['styleSchemeSlug']) : 'default'; $style_scheme_title = !empty($_POST['styleSchemeTitle']) ? sanitize_text_field($_POST['styleSchemeTitle']) : __('Default Scheme', 'cf7-styler'); $form_data_array = array(); if (!empty($_POST['formData'])) { foreach ($_POST['formData'] as $form_data) { $name = str_replace('cf7cstmzr_', '', sanitize_text_field($form_data['name'])); $forbidden_names = array(); if ('free' === $plugin_version) { $forbidden_names = array( 'form_bg_img', 'form_bg_img-position', 'form_bg_img-opacity', 'form_bg_img-size', 'checkbox_full-width', 'radiobutton_full-width', ); } if (in_array($name, $forbidden_names)) { $value = ''; } elseif ('custom_css' === $name) { $value = sanitize_textarea_field($form_data['value']); } else { $value = sanitize_text_field($form_data['value']); } if (!empty($value)) { $name_array = explode('_', $name); if (!empty($name_array[4])) { $form_data_array[$name_array[0]][$name_array[1]][$name_array[2]][$name_array[3]][$name_array[4]] = $value; } elseif (!empty($name_array[3])) { $form_data_array[$name_array[0]][$name_array[1]][$name_array[2]][$name_array[3]] = $value; } elseif (!empty($name_array[2])) { $form_data_array[$name_array[0]][$name_array[1]][$name_array[2]] = $value; } elseif (!empty($name_array[1])) { $form_data_array[$name_array[0]][$name_array[1]] = $value; } } } } $style_scheme = array( 'title' => $style_scheme_title, 'scheme' => $form_data_array, ); $style_schemes[$style_scheme_slug] = $style_scheme; update_option('cf7cstmzr_style_schemes', $style_schemes); $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . __('Saved', 'cf7-styler')); if (!empty($create_default)) { $response['url'] = get_site_url() . '/wp-admin/admin.php?page=cf7cstmzr_page&tab=form-customize'; } echo json_encode($response); wp_die(); } public function new_form_customizer_settings() { $title = !empty(sanitize_text_field($_POST['title'])) ? sanitize_text_field($_POST['title']) : false; if (!$title) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('Please input style scheme title', 'cf7-styler')); echo json_encode($response); wp_die(); } if (!empty($_POST['copySettings']) && 'true' === $_POST['copySettings']) { $copySettings = true; } else { $copySettings = false; } $plugin_version = Cf7_License::get_license_version(); $style_schemes = get_option('cf7cstmzr_style_schemes', array()); $style_scheme_slug = 'cf7cstmzr_' . time(); $style_scheme_title = $title; $form_data_array = array(); if (!empty($_POST['formData'])) { foreach ($_POST['formData'] as $form_data) { $name = str_replace('cf7cstmzr_', '', sanitize_text_field($form_data['name'])); if ($copySettings) { $forbidden_names = array(); if ('free' === $plugin_version) { $forbidden_names = array( 'form_bg_img', 'form_bg_img-position', 'form_bg_img-opacity', 'form_bg_img-size', 'checkbox_full-width', 'radiobutton_full-width', ); } if (in_array($name, $forbidden_names)) { $value = ''; } elseif ('custom_css' === $name) { $value = sanitize_textarea_field($form_data['value']); } else { $value = sanitize_text_field($form_data['value']); } } else { $value = ''; } if (!empty($value)) { $name_array = explode('_', $name); if (!empty($name_array[4])) { $form_data_array[$name_array[0]][$name_array[1]][$name_array[2]][$name_array[3]][$name_array[4]] = $value; } elseif (!empty($name_array[3])) { $form_data_array[$name_array[0]][$name_array[1]][$name_array[2]][$name_array[3]] = $value; } elseif (!empty($name_array[2])) { $form_data_array[$name_array[0]][$name_array[1]][$name_array[2]] = $value; } elseif (!empty($name_array[1])) { $form_data_array[$name_array[0]][$name_array[1]] = $value; } } } } $style_scheme = array( 'title' => $style_scheme_title, 'scheme' => $form_data_array, ); $isFw = !empty($_POST['isFw']) && 'true' === $_POST['isFw'] ? '&fw=1' : ''; $style_schemes[$style_scheme_slug] = $style_scheme; update_option('cf7cstmzr_style_schemes', $style_schemes); $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . __('Settings saved as ', 'cf7-styler') . $title, 'url' => get_site_url() . '/wp-admin/admin.php?page=cf7cstmzr_page&tab=form-customize&style_scheme=' . $style_scheme_slug . $isFw); echo json_encode($response); wp_die(); } public function close_welcome() { update_option('cf7cstmzr_welcome_done', '1'); $response = array('success' => 1, 'error' => 0, 'url' => get_site_url() . '/wp-admin/admin.php?page=cf7cstmzr_page'); echo json_encode($response); wp_die(); } public function delete_form_customizer_settings() { $scheme = !empty(sanitize_text_field($_POST['scheme'])) ? sanitize_text_field($_POST['scheme']) : false; if (!$scheme) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('No style scheme selected', 'cf7-styler')); echo json_encode($response); wp_die(); } if ('default' === $scheme) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('You can not delete', 'cf7-styler') . ' ' . __('Default Scheme', 'cf7-styler')); echo json_encode($response); wp_die(); } $style_schemes = get_option('cf7cstmzr_style_schemes', array()); if (!empty($style_schemes[$scheme])) { $title = $style_schemes[$scheme]['title']; unset ($style_schemes[$scheme]); update_option('cf7cstmzr_style_schemes', $style_schemes); $enabled_globally = get_option('cf7cstmzr_enabled_globally', ''); if ($enabled_globally === $scheme) { delete_option('cf7cstmzr_enabled_globally'); } $cf7_scheme_args = array ( 'numberposts' => -1, 'orderby' => 'title', 'order' => 'ASC', 'post_type' => 'wpcf7_contact_form', 'post_status' => 'publish', 'suppress_filters' => false, // подавление работы фильтров Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ SQL запроÑа 'meta_query' => array( 'relation' => 'LIKE', array( 'key' => 'cf7cstmzr_style_scheme', 'value' => $scheme, ) ) ); $cf7_scheme_forms = get_posts($cf7_scheme_args); if (!empty($cf7_scheme_forms)) { foreach ($cf7_scheme_forms as $form) { delete_post_meta( $form->ID, 'cf7cstmzr_style_scheme' ); } } $isFw = !empty($_POST['isFw']) && 'true' === $_POST['isFw'] ? '&fw=1' : ''; $response = array( 'success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . $title . ' ' . __('deleted', 'cf7-styler'), 'url' => get_site_url() . '/wp-admin/admin.php?page=cf7cstmzr_page&tab=form-customize' . $isFw ); echo json_encode($response); wp_die(); } } public function load_body_tag() { if (empty($_POST['loadBody']) || 'true' === sanitize_text_field($_POST['loadBody']) ) { update_option('cf7cstmzr-load-body-tag', 1); $confirm = __('Style will be loaded in tag', 'cf7-styler'); } else { update_option('cf7cstmzr-load-body-tag', 0); $confirm = __('Style will be loaded in tag', 'cf7-styler'); } $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . $confirm ); echo json_encode($response); wp_die(); } public function preview_form_customizer_settings() { delete_option('cf7cstmzr_style_schemes_preview'); $style_schemes = array(); $style_scheme_slug = 'preview'; $style_scheme_title = 'preview'; $form_data_array = array(); if (empty($_POST['unstyle']) || 'true' === sanitize_text_field($_POST['unstyle']) ) { update_option('cf7cstmzr-preview-styled', 0); } else { update_option('cf7cstmzr-preview-styled', 1); } if (!empty($_POST['previewMode']) ) { update_option('cf7cstmzr-preview-mode', sanitize_text_field($_POST['previewMode'])); } if (!empty($_POST['splitModeValue']) ) { update_option('cf7cstmzr-split-mode', sanitize_text_field($_POST['splitModeValue'])); } if (!empty($_POST['formData'])) { foreach ($_POST['formData'] as $form_data) { $name = str_replace('cf7cstmzr_', '', sanitize_text_field($form_data['name'])); if ('custom_css' === $name) { $value = sanitize_textarea_field($form_data['value']); } else { $value = sanitize_text_field($form_data['value']); } if (!empty($value)) { $name_array = explode('_', $name); if (!empty($name_array[4])) { $form_data_array[$name_array[0]][$name_array[1]][$name_array[2]][$name_array[3]][$name_array[4]] = $value; } elseif (!empty($name_array[3])) { $form_data_array[$name_array[0]][$name_array[1]][$name_array[2]][$name_array[3]] = $value; } elseif (!empty($name_array[2])) { $form_data_array[$name_array[0]][$name_array[1]][$name_array[2]] = $value; } elseif (!empty($name_array[1])) { $form_data_array[$name_array[0]][$name_array[1]] = $value; } } } } $style_scheme = array( 'title' => $style_scheme_title, 'scheme' => $form_data_array, ); $style_schemes[$style_scheme_slug] = $style_scheme; update_option('cf7cstmzr_style_schemes_preview', $style_schemes); $response = array('success' => 1, 'error' => 0); echo json_encode($response); wp_die(); } public function enable_globally() { $scheme = !empty($_POST['scheme']) ? sanitize_text_field($_POST['scheme']) : false; if (!$scheme) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('Style scheme is not selected', 'cf7-styler')); echo json_encode($response); wp_die(); } $style_schemes = get_option('cf7cstmzr_style_schemes', array()); if (empty($style_schemes[$scheme])) { $response = array('success' => 0, 'error' => 1, 'message' => __('Success', 'cf7-styler') . ': ' . __('This scheme is not existed', 'cf7-styler')); echo json_encode($response); wp_die(); } update_option('cf7cstmzr_enabled_globally', $scheme); $title = $style_schemes[$scheme]['title']; $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . $title . ' ' . __('enabled for all forms', 'cf7-styler')); echo json_encode($response); wp_die(); } public function disable_globally() { delete_option('cf7cstmzr_enabled_globally'); $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . __('Style scheme disabled for all forms', 'cf7-styler')); echo json_encode($response); wp_die(); } public function cache_form() { $form = !empty($_POST['form']) ? sanitize_text_field($_POST['form']) : false; if (!$form) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('Form is not selected', 'cf7-styler')); echo json_encode($response); wp_die(); } update_option( 'cf7cstmzr_cache_form', $form); $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . __('Style scheme enabled for this form', 'cf7-styler')); echo json_encode($response); wp_die(); } public function enable_for_form() { $plugin_version = Cf7_License::get_license_version(); $scheme = !empty($_POST['scheme']) ? sanitize_text_field($_POST['scheme']) : false; if (!$scheme) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('Style scheme is not selected', 'cf7-styler')); echo json_encode($response); wp_die(); } $form = !empty($_POST['form']) ? sanitize_text_field($_POST['form']) : false; if (!$form) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('Form is not selected', 'cf7-styler')); echo json_encode($response); wp_die(); } if ('free' === $plugin_version) { global $wpdb; $sql = "DELETE FROM {$wpdb->postmeta} WHERE meta_key='cf7cstmzr_style_scheme';"; $wpdb->query($sql); } update_post_meta( $form, 'cf7cstmzr_style_scheme', $scheme ); $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . __('Style scheme enabled for this form', 'cf7-styler')); echo json_encode($response); wp_die(); } public function disable_for_form() { $form = !empty($_POST['form']) ? sanitize_text_field($_POST['form']) : false; if (!$form) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('Form is not selected', 'cf7-styler')); echo json_encode($response); wp_die(); } delete_post_meta( $form, 'cf7cstmzr_style_scheme' ); $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'cf7-styler') . ': ' . __('Style scheme disabled for this form', 'cf7-styler')); echo json_encode($response); wp_die(); } public function change_form_preview() { $form_id = !empty($_POST['formId']) ? sanitize_text_field($_POST['formId']) : false; if (!$form_id) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('CF7 Form is not selected', 'cf7-styler')); echo json_encode($response); wp_die(); } $form_preview = Cf7_Style_Scheme::get_form_preview($form_id); $content = wp_remote_get('http://cf7-customizer.loc/cf7cstmzr-form-customizer/' . $form_id); $fragments = array ( '#form-preview-container' => $form_preview, ); // $response = array('success' => 1, 'error' => 0, 'fragments' => $fragments); $response = array( 'success' => 1, 'error' => 0, 'src' => 'http://cf7-customizer.loc/cf7cstmzr-form-customizer/' . $form_id, 'content' => $content['body'], ); echo json_encode($response); wp_die(); } public function install_plugin() { $plugin = isset($_POST['plugin']) ? sanitize_text_field($_POST['plugin']) : ''; if (empty($plugin)) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'cf7-styler') . ': ' . __('No plugin selected to install', 'cf7-styler')); echo json_encode($response); wp_die(); } $required_plugins = Cf7_Required_Plugin::get_required_plugins(); if (empty($required_plugins[$plugin])) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'wp2leads-wtsr') . ': ' . __('Plugin you are trying to install is not in the required list', 'wp2leads-wtsr')); echo json_encode($response); wp_die(); } $result = Cf7_Required_Plugin::install_and_activate_plugin($plugin); if (!$result) { $response = array('success' => 0, 'error' => 1, 'message' => __('Error', 'wp2leads-wtsr') . ': ' . __('Plugin could not be installed manually', 'wp2leads-wtsr')); echo 'error'; echo '&&&&&'; echo json_encode($response); wp_die(); } $plugin_name = $required_plugins[$plugin]['label']; $response = array('success' => 1, 'error' => 0, 'message' => __('Success', 'wp2leads-wtsr') . ': ' . $plugin_name . __(' installed and activated', 'wp2leads-wtsr')); echo 'success'; echo '&&&&&'; echo json_encode($response); wp_die(); } } admin/img/icon-cf7.png000064400000416724146725417150010555 0ustar00‰PNG  IHDR\r¨fÑiCCPICC Profile(‘”ÏKaÇ¿³(A`f{ˆ¡CH¨LeD宿شmY”Äìì»»“³³ÓÌìš"^:fÑ=*úé*˜“––Í9R»,Ÿ•"t%1)f¨m-’¢ë’ë²%‹ÙÌ*±tìÌ©vO¥žv¥æS¹¼Aç¯ö°õ°\þù¬\ÞzN=¬/õßÀ¼ýEN1I pHYs  šœ IDATxœD¼K’K’®÷©ª=Ü#2ªn’®ˆ#Ž¹¹n‚ÛºÂ[u2#Üí¥Êeó€”±pSýŸ.ÿ×ÿó½ã¹`jÑ:C€£òr´>ŽÊôà¯ÿ…Ï…ÚI)B> Y•¬Êßï‹÷÷5Ï'ÁûûÅ\‹RÇÇkü!<‘êƒ?ÿú‹1áú_þI„Ñ^÷üƒg¨9p‚â)&mL|PH"'¡Ï |ÓpAž‹Z ßs²ls¥,âáoú¸pTU£ÔÊšƒÖ¢ðD JF’ÂPꪰ\øî0ãÍ™ƒ$Ö;ÏR‰Þßpüúàù<és±Þ)Áš À˜“¹g~P\P›à`¥àk±æ@äÐq&·(®l8½7R2rΈôÞQSRJDÍ1ŽUXqñW¿±€$Bë UåãóyV`MgNÅ´ÒôâîA]†>*ôkrß‘S&çL„#é"„÷êx[|œ…[þÝ°(œÇƒt÷ûE»ÉŒR "Â9­ s¿!=*ßïÅqjÐß7bNª‰ñ}ð=^,i””’Èå“»93wÄ¡ó,Ši!ↀٌµ&ïwg-ç×ï'åqPEèã‹9…R.“ÙË0D8š–”Ñ.ZS®kðûŸ‰Çó?øþs“’QÎH ¯µh¯›çÉr§¿.çýî´¶(Ey< fO"}¼ðåˆG­ 0ú ”“÷û›b…ǧaùƒˆÄŠÏ}‚¦-ð¯÷RõBsP x*ß×`¼:É„bÂÊ…9¬ ¥’÷µ ÔŒ´æ 7Q¾ÿ,zŸÔ3ñùY©b\½“$@ï“<¹Â áÐ.Pˆ "ð.””)¥0î ÷ÉZ²[¡ÖµE»¸b ¥îKºîμ,€%ûϵkܼ;„+fp”J ¥G"lí ojÈ0 ã»q˜òøøÄdÞ‹ yÍ•%‹ÁaM‰û5XKñ$´¹6sÒ,x–J«Ñ5Ð匫C€s1ÌÈ©°ÞN›A-ûŒ\÷Åh уòPÒ úPD kuæ\¤¤X2T•rÂÁÝ! †`g"Ê\Ú1&='lž0çx¼þÜüùë>ŠÜB]A:2ŒË¹ã¦%£> f™ïï c!テ³$ *¾yéy Üý*tSf2d,† J~`*ƒ¹ŽÙä[+§£¿a ^ÑÒ©d2cufrȾ0Å Žp pm ‡Þ&c RR’ ±«^ ¬ÿë<™Óøo_ÿÍ¢“Tö›˜¿Û„àù™È¹²¼‘S߻ĕË"N00w!Và>¹®›åÁãQ¨µ0Æ…"ŠÚ¤· Ö~Þ@ ʱ(gF$³¦qß“îÊÁÞœ÷|q…£&ºMRÊ<³òçu‘-‘`¡¢œª¬Ú|ó|$" ¹@7Æ*@cþùƒ«RJ!Bi·Ѹ›²GèË$Q|Ü\Ò O‹9j•Õ¦NÀ‹³FÐuP–pµ›y/VÆypØÁŒoÆšŒ >‚z8`¤’öfbp•‹{Ã@«"@ïÁˆLÍ GK³’\ÞëEëoxV¬¸;TÁŸ'¼oÂ0 ’ƒûµPÌ$àB‘ºf z5rWÖÌ1!”¨‰¦ÂýÕ {s•Zp)¸tæ¼/Îgáyž Êëï×»S˜'d)=7b D”£*µPxs_ UAEñ¬>8Žƒ\ ³9×}dNºt8å8+ËaE¢ž0m¡’ˆ0†,\Ç:> 0áµnLœu;Á…d…¸‘©äü`Yçýôqc)!ZXÖ©&œ©0]xs‘ÚE)@NàŽŠƒ L…åûâ>j2—/éüÒUå¾5 J\‰&gqȪ3§a, ‹J* ©BΔ9Á Eèï÷þ®Gc‘´`9Ùy¤Â» Î@9€Áê+Å°˜,žçoÂj{ø®1ðX´>±6)Õp‡˜…"ÊÐÅõ× ÷F©‰\”àׯ'"A}œ¨)Ag8àBHáGÚM9*ÎÚƒÇç/Þ3x_Æo¢Nw|*š…GÒŸœ( çS±,´WçÔôÁ´+m8)…ðÎuÝ<‚W¼¿¡eoàçA_{î9©)3ÖRÌ¥!N¿••ÐIö{€tÍÚÿ€ªî¼¯›[fõ±/"7­uÜ½Ô M¿¡wR8Z5Ã{Zšâs k2/EÌ0ZZ¼ßbÐèˆ*©7l¡˜k0ûDD$H­;ïë*Ôt2´!’P5B:#c~#ž0yì ã [ÐIØŧÝ7ò8Е)”œ(ªŒ5¹$àó÷“R£/æ± (Ä! kÿ%)ÈÝ1j­8pL„vM%Tic2‘{ð÷·3’Pr%¥lH ¤òn´{"–8>+ÚiŠ?_x¿‰¥,[TuŽz’WâŠÍ…c$þýúƒ¯AùmY©ÇA¼[c®…‰Ç¤_ ¬’ñ7s¹TÄŠEbÄ`y‡U‘ß™üÂën¼}!º5Ô*³ç3q¤Éh¡OAWGGCÅ`:àäzî ;w»s†~54;a…N¡ÍÆŠ¹™5ƒ>þ¦k`ùA®B»¯?ƒç¯× bUFsr*˜ßí¦©ðùÝÌŸ,%ƽp‡z4Mƒþ¾yùb¨PÜ}VDIŒ6×WCGO%[!z¢ G!Äxµ/<„|>H–©î6qmÇ“5±Eɉ¾^ ™ú8ho羃ú€úp2ʼ PA¥RX¤\i##È¿öà@÷¥™s²Æ$I@JÈJÔ\¸ÎÄüó"¹‘ÎLU#ä’0Òr^m0V§A%QÒF(kB„QÆlX¢Jä J&†A¸SIÎ÷«z3ïDÒŽÛ ’±<Ñe­c"Ȩ)ŠÓ;+„T ín ¿ð9Áœ ) ÁÀ­’0S韛šŽ½pfƒoóùpÊZ‹5ùƒd™î7«)®‹Ñ6Z-áÒhß‹š2–Œqíe›’!ò`¡8Nð)ÌþÂrE¨øš{HŽÞ ‚ì{{'‡ÐJÈ9'ð7"A%nÁYö3{ß‹ëk –Ñì¤|Ìæ¼ÿ~Q*¤ÏDo7>¡ÓÛ†Œ½MTÁ‡’Q>jáïsNR:™+qŠxf†æJN[!ÎC”Z·›c%£]T ©| 2!V#FÇr%41e’Ÿ‰LÆDQ¨ÿ:Ø{‹$­¡–8žDq7RK‰52¾Õ¤; Åj!òƒš2á7×øΡ¨ ^ FZÈ‘ š4ŽÇ;„¹œþçæò«ò“ è™YjÌ11 òó?>.Ú5ÉV9'ÓoæÑTüêh@Ê…£´»ã×E%’Ñ['e8ŸÏÀ×Ø,;j‰5³‰‡³ú ûb KÔ#î”gÆÃ`©9'Ê#kñý×ߤ”È“’¥$Þ¯ŽÍ‰T#²ƒw,)憉Cƒk\xdŽr2ò‹¾&ŸŸËo.SbÔã@5£Å!Va*•ùîœZÑ_ b´k1qÇ?6—mù½o„©ÉplKÝß$M´¸Q?ya$‘ŒJ˜ Ñ ”Λ÷W#—“ßÏDHÆU˜­3®ÆðŽ'ÐÈ$9x·éÉãÐÿ8mLrN¤ôàãSÉY¸ß“˜9ñx$"”1µ‰àû¯?œÏJ=Üïs]äCAklñš´)f¡·ÆK gEcý{ò8uSÕRÎx2¼N¢u”Š'e¹óº&óº™% Ú Í6è7ä˜e`„JÎ'­½y}][ìÊis´9˜¾UçŽø6_XLÒÇÞêÞš–8>é‰6×ø"Ë'É3sk4îWç8) g­ŽæIRL&ê/Œd'zkMrڢؚ“ðEŸ‹¶u f‚HÞÐ]·†é Aºl8Ìæ›U•N㚃¸ÈJzþ"S˜£3@d ƒ!äHäTÈ@ô -¨gåóù‰Î`­b‚Ǥ5¥œe!ªŒ7Ü}P0ŠM:Áº;ª²‡ÂZÞ%r,$e9ójyß0&ùù Õš® – k Úý&[bHÐ5ñz0tñ§ß|¦'Q £}#TRÊh…S”·8ïXäPÖꜩü8&ÂAôÑ!åħ=hEi½3zã<úÛéý‹ñq`º(’±j¬»WgžF}+(Ê£|Ò?­3ÚÍT!‰ XìçLêã$Ÿ•¬J*™ðN„ãíb´ÉiH õ ­àzC=9kN˜ÐÚh¨ÉŒwÈ"‰!ˈÖðbÛÅ!•½ë…ÞˆÑTÈùÉ¿®‰úä=:÷÷âã#QŠ’ê¦_c¢›â†(–¶žÖîFc2#л¡²@ÖÖ î/ðÅq| I™c–ñ9PU©òý~ásÒ™0þ%€#ùÀ zoh.ûž`È$ë¤ù ±Þ×\¤Ñc(磒J!"Pµ{KqO”쌹~`ì ²ø¾ÚÞôr-Úü7Äàó|¢"Dz_Äíäs[wkÞ,œ—CÒ'+³¿HÙð“C¡Ÿ |QE Ü:õQq5²fRYÂlƒë{oDI`!r¾ù»»16¥Š˜mu\ÈHZļ9<£åƒkvÆ÷$’³æ¶Ñb,ÊLÈ)äȈ+ïÜïoD æ6Ñ¿€Á¸2+n,u¦/ÚlLHðWø÷í2XîÐúÍëOçó¨äÊ{Ý,_”œIˈ%D.˜aðþóEš + íŠe£JA®‰$§ß7×ûÆÂ׫£}Qÿ¹ÐjŒ¾ø÷»Ñ§Õ°œÉkpµ‰h%—Ez ^÷ÀŽÓy dЕx_¢Jý|’T¹ä£ ZÈÎu20Ö8Á¶u{çûrþýºp ú E` ¡ß ©‰_GEܸ®3ÛC 'EÏ‹¢úÃ{ G:;m.üZ,¶(?p»Ô"3|pÿy£@ú| GÁß7ýZH‚AMÆq¤aÄJt™üýjØgà ®¯Ù^4³,AL| KÂçq’²pž…aH¢ûØšÏGå°…¥ÝÈú‰GC#p7ªd4 Ï7£ÁG=H^ó<ÈÇYˆ DÃaÞ°&Ñ+#:º`U%p|:¥ž<> ×$ÕJNƒ9”Tîss´ô~s]N)B’Œš"‚¨â±- XÈŽÏ`æ|ÿù¢”‚‹:9Y+ˆÈ˜î‰á‹zfêñ‹Ùð}™ëaüÏŸ¼¾Ùœ¬ ç<–3k…ˆ±ó5ñ|T„BºÞˆe@qwZ[ä ªl›±ž–>&– +Šµƒ‹®NM‰9¾¹Û¶RIDïxL…1燲|Ðul[i³j I™X[(J¦H$Àè÷ÍЀ¤H‡‘ë;Ö°·MÆöº¡]ƒ»w$Áq7Ü9=öT$¤½ úíä*xßß׶ʉÖBž‹£ CÒ'yÀõþb\ðñûŸÿxr_/î905T„CÓFýÍìÎñØÛK4ñx(9'–(×k’-ÈRH%Qx>Ñd¬voñ5b{¼á@¢„½óFHÅéØ\¤’Él3I’rÔ„Ó™G¦»r¿¬›v_ÔúM‚ˆs>3"Êre¶›yßÔZÑ#1¿/l9K ŸY sã,<á|<‰é̻ѳ±¤ÝX<­5Fvt9¥(uGáîÂ[_1¤fžzs¢Å!{ ¬MÍÜP«TSº;à«@Íi£§«3ÆÄ ²UDÏíF1u‹$™T mMôã‰Ê -ÃJÝ¢i‹ÕƒT O¦ù‘¨µ]¨ryŠñϳ€Ÿi;ÉEuæ˜UR2T¿ù~M~?³Ä»½œZö&èÚ·È—ü™yÈBlj‹Ò®Î% ìÍ0×õ"¼3Ó‰hBÄp·bŸ"¤Gf”›ÆÆL±Ó.klåßjf¾/"N:µ«ÇO^À©Õ1e¯HXN¤R1Y%ƒóû)†– ãë!ȉ²cjøã ‰ãL_ŒÑ”¢LÙOn $}ðq ­}s݉µ`êDsÐ×$€âN‘ å²éÉj„Å2½ßÌÕÐb|›“kvÆ1V”1m™¶ '¢Prftÿq\6·¶jÕ˜¤_ÂëèÌwðùLz@H)ãIùzmÁ0«2Æ¢;˜€Œ¹\V¤Šüÿ w浘å`'¶ú |¡9m;¨asÒçá e#'ãº/J©ÔZpOx,T„’3E‚ënüi7öH$ÏX rN7Îò¼¹¼OÆ0\̱¢ˆ)§GÍ?0Öioa®àýºñuC)[dSÛ¼)˜ T'ÆFw š‚19 9WÜñþb…£RSE“âRiÚ;ñ®?;Üsªâ±c«Ï´òÁûÕ0«œ‡m±k€ø¤<„#Ö`¼¿_x¥rɨâ ×ÀUvÈg:Ž+‚Õ%PRbÜ {ulž<ÏŽ´¸»¢ÏÖ²QÕq-ÄàN¿;íÞÃÞ½ñúZüã4>'ÓcÌÌ—RÚ6 _ zŠðx<°9¹c1›3îÅýØöZZJúÌÄpF8K÷¹ŸiÒôvÓ£QêorªŒ÷…K²à+H‡!&ÜMèm #Ù–x뾧B­BÙËÄ'³7paÍ gUf¤úøæž{`å‡q;´vacšöò# GÝn׈m§¢pµIÊçAªAo?þ}ˆ&,¯?ïŸoEĶÐd‰ÏÇÁàfvç‘pÏÎÌýê,wÞ³ƒu-–Âr¡EŠ çƒêŽæŸCràž¨äÍѧ²˜s1{ÃKFÇÄ}Ѥ|@Xp>*D°ZÃÜw ÉQMhÚL ² ãn̯Áb2|P,‘Qj>i>x}_¨Žã$"øþ~qðùûÄûÅõ÷‹ ̾p‚x/RI$„9‘ â|¿ƒ5½–Ø"£;ë,œ!d±Ä{l.¾ºbÙé,Œ…ÓÖ"5ÇÎÌòŽŽE~V4*ö¨XzÃ=ͨMÆrJΘ.ær¾×üþHYеyó^ opœ™gÍøÕyÍÅÐ;Ž€GMԨܭ1†ãm‘˜”ŒŠ­Šž†ØHUÀ¬àÓYsRŽU˜× ™~q?Ì)X1þþú¢¤ÍÇ¥¬Öa ðåD âìLOÌÞ°”_¼¿:ò(ÿÃÎ §ÝÓ É¹W'î‹7Çz‚g47ÈÊayÿÞè}òƒTwýñÿXÁÛ‹qLÄ&f¶í×T„Þ^üu墨JÀZ  Ÿüdv:«ñú3@zfæ줲ݫ剥 0AåüH‚OcÜÂ\œ…㨌!ûctB‘„§¶ÌñLŒë¢·N”B=*å31¼C(k zk¸gŽ‡‘ÏÄ\†ýoÿÇÿþ†W$”9/zïˆÆŽ'®¥œÏ')o bŒTÄ_ÛëwÓ->íuÑu¡bðR±~!KùüøJðjöžÄÚíÖ:kMž¿J*ˆ݃” Õ>À}b,Žó¤<žŒ× ™Ò‰5v—%#ô¾)q*©\ÌVˆUÁïÍáÏó÷¶gÇÀg@stÈ™*xÐ¥áþâúîû,êÚáqmG“SÒmmÿœüìQ¡>Oæèô÷ÅꃬŠŠî„iÇǃtÂÓ%¬m‹‘EI½ Ž¤€0»ýˆ_;Ö¯ºÈŘc0úw¥–߈vîþÞ¼ñü$@Sâñû“5÷ë…™avR4#³ózß¼}±,øX€N^Ó©öà¡â|ÿõ݉c#@–â};’v–!¥ŒÙþ DèWûñûaŽÎ£ƒ;mñ¯ÿNG82˜:Z2Q2óî”âÔÇIà|÷†&å™O 2ÇŽ--h*Ì~‘rÚÏœÄno¢¤qÑÛ…‡ ¤Ÿ…Ù`®í0>×{‘ó~+H9‘³3T3Æœ»ð%º©ÔÚÉÁ5ÆÎÀPIi—êÚ5IÈö‘Çõ&T*ªÀʾ+ÐúøáÓ'"çþ‡\É’wê-œw`5˜öæûOgÕBùµx½™‚{!åAžåÇ&ºöY‘dØšjØ™HGÂZ%Öâž<3çÉZ‚ϵ¿dQêQ·*…Çéˆ}’ÏñúX:ˆÌy«q¸"‡QÎ |·FønlÅ}mÕ¼d¦Á;n+‡kQâ`æź5ØgâÃ2ýzÓš³q \7¡ÞIJÙZí)8 Ô‡‘Ÿ'¿ŸÇÖN€CÉû|$‹à #º÷µ‡9£ež¿>w)æuàî¨NJ dîKª¶ë¿%/:™úø@b!)ÑÇ@n!²âˆa^Èö`\‹ˆNJ™#§ a¬¾S¢pn÷' ó¾yÿ}ÚPÉ)wúR|îÆäÀuÒ¸™)(Gp˜ð禔¸/ÿ©»6ÆhäœIö$Ì)‡Ó‡ñþzSPŽš‰(Œ«m U§¦óן7#œçç[ eÛ/'¶˜–¡Áëø ‚X e·+=œRtæ½ÐwGÏJ?ñv݃xÜÛ])Y‘#ïHïRzúÈ{àÔåhÓèÉQ.Ö?f覕kíòZ1a´ÁˆŒÇÝ÷ƒBxGLè½ýBNã8Ó¿n¾ú›R‚œä’Ycîçï'ÍÜ䣰Æ"<“êqjaÞ ³@-ã9„Öú IDATK¶ÀaôÎ0®xC7Ž|P¿@ áÛahã(™1…1‚rx°¢³úB%øü3v<8òÜZ»êî?PÒw IïvqKã3CøŠ¿øp%geIpÏÁõñSoÝð{¶‹? úŽqõOgÑûO-Ü× Õ d > ò†³áøù-44*ƒ2Ÿã'Ú5в-JÉ ´¢¡.º4ì€ÇYYbýWš¯1[羌ãÌUÜïmúʉ;¼q&FY™÷»±"(?ÎÕ“n‚çLRåŽFÑ‚„ó ¡ 's]ŒÖIIYY!‚R2ÁäÏŸÆyVŠÚpªÔSðùÍì Ãð?ÊEJߤòŸ»oò£ëíf,¤ºmÛt@Ú[^`£&ÆìDä Šr·Éû…!0u@ïÝ/œÐr <Ú›k-þõÿ¾hm¡‡LøN„ÃßdN$ŸÔs‘ÆÜm; Ý;ÝZhs.Ú»QŸFå ÇU~Þ[F°b1¾þF–ƒ)÷šè*ôw€8LÛ… ”tÐýÍbnÕºÿX‡Ñvi)üu¡%s®-®,,)Ñs^˜)õJ$Š/:N–F—-„ÕpfÀô„¦ŠåQ:c¼PM„'Ö áqnûS¨,_´ëÞµiÔø`Š‚8¢ñCk ª‰úÃ{í¬uñõ:м"8A=w6a\[4Í?Ùöz틸„;mÞ<äA‰ì—aôõM¾ù(”§ñn>óD˜ó¨B*Of»pßQZ£°Ò"HhÞé½ïÖ9–~`wY•é7­O*bÂñ0Ԕ￿6Ãö —'á­5¬()+>‚ç¯ ²û[, ZodM¬$¬2ùõë ³¿Ç#%<. <àîÈá°´ýŽˆSNP#¤@lKTXÃèwCÄ™»/M7'© ½íë‡ñ }×ÂjÁûj©™£TÊ‚Ñ!ì—Å܃%ÙIµÅ}í¸}ýy! 2Ij SÒs»i>8=ƒ$‘ÿÄÃqÏGÁ姲;üö_¿ö»6 _}§iµ’ê±aGˆÓWCP’ “”; ¶ oõ YéóÅxÿÅsí7¢ÜÃ9ääR§”ÆQ ÍCó ZBPünä*¤|1{óÜÁLßLŒ6 çz0îýó©Ô@lÎ(‹6ú¾ß³“(™yuÒ£ƒ~}é|—Ht)÷zm`Õ¨HÙðXû`–R [Ï&¢èóAÏNÌ?Äs9¹8™ŠtÈ…ÿ¨wÛ•äX²í†™ß"2Ww«!èo ½éUŸÒ{A»›»jeFøÅÜô`¹ÙoHɬÈps›sŽÉ3ŸÌõbÝáç–4ÁžhvZÚ¸'¼D% ²Ïã„|`.\k‘ ZºiǬ n”Ge§E¿ÑŽ‡â„O¨Þpß¼ßr<žœÏÓŸ)3®û£dЂL£$C³2ÊËÞÈìT…é°ÇB«#ò`ï‹Þß¼/ø™¿8ËIEH4òSÙ«c×»xÿþEÚ›”"BÛ_ÊŸ½³§ÐêIná€pSÖÖÐ,hŠ‡Ý‰ûì”Ø ç™X¶ãïÓ"Ý8%`-“êImÆ}uZ=II˜¹P©|_7U¡¶€ÊXZqÀmhdtnî;žvœÀÁê“ÕÇ'o°Ñ”¨ÇSª,ÖºÃÜE£²©MЀ!,û¤üŠªB*hšŸ4¬°ÉXuuÔÛ„[ì/¾Žƒãà››ÇãAkÊŸÿøÅÜKO°?F)¯•ßÝ8 êq†’ÒÃBÝŽX¦¦æ ÕC!Bȳ·1g%iLéÿúþïÛ@ »[6©)eg–„-óYZmØ’Ï"‰Ð?§2ºÑï‹¢•óFm£Òù…,û }[Ôg"RH3ÈböÈ?Ï{1gÆô ¯7¶ú'—pUQBŽY}!»’d³}sï_FË M‚Í;îU²1 56©ìÃ×Â5,D] _ÎÚ3°`R#„ŸãTO©°§²×æÈ•DåÞ‚Où¨™Š²lÄ+òIòB¥’’DqQæ\ŒÛ ‘`Mc2cÒ°Ar…š9¿Ù”a7닾ý½Y}`mrN!y+tþÓ¶2Кθ/Ú3㢼Þ÷˜ð±OMMP3܃…Qj†6:¶Œ¥‚ªP5¡µr$ª%…¢áka¶Øx,÷¦‰†/b-î÷õ±^Ç4´m³—A‚Ô*‚1®9”œ#Ÿ„ŸÇ‰íE¿_´ÇIÊÎꛜü±–±W§=2- s9NÁl¡Ä¢®cŒÍráým8‚$¡Ï_¨LRú‚*쥌·a{Eºò£~‰Çd¼ÍX}òüª§²ûÂ.g8ä½q•×U¨[ñ"ÈÊNÔ&ˆ w7~¿nÞvSrâtX+X÷¸é—!šÐœIiQŽÏ±ÍNJ_7ãm¬{³æÆ<æb]ÏbÎ|øW@È´Åÿ§b#˜­X ëF$³Æ"+BJw™«JäèWüË×ç‡.9?(¥Åf7;eJÉaèqA$’Pš2œ3a#퓾¼&IœrœŒ;\QªGÊ82/vQ*?Ð.875Uöq•¥Ðqî¹ñ±IGÅÒæýl›ú*…vTd ×ýæÈ‘ס¼ß†¯P˜@õƒæ®àÕaÛ`¶8ñ—uÔ7F’º?ß³*¶2ÿq¿&IÜŒÔ znÖû¦¿óë ±Š½_ôùÂSãÐÌëšäîœ|TŒ&èµ#ÓjAí`^póÔÌæŒ9ã;RVrÛ¨DzoØ€<ÃNZ2äÔbÒßGá8‚$¢]Ž.£ë˜à+Sꢊ\ „í¦Âv¸KPˆÜSÐtX¡ÿ×0Ää’)5c«ÆNI«/¶ Ck ä,èLU…zTÆëÍèƒR2åŸ ãà™-”O„ÎÞ‹®…|fì»ÃR¤Ä¤ r)!»ilèkÛqÊÛböA¡Qω˜p ÎçV ÁD•Þ;¢‘)ì^…çy‚Á?~}Sä$?â–ŽåGzráü.ƾ¬™âŠ Áƒ´Í3Ø'Õ9³QJcÚ $'µ5%[æÝ.fÞÐ F˜ÂÅžo¦ÇgQMqýØK‰Pßø§Ê¢Âöò™ \y0ø¾n˜AŽñòd«cºÐ M+Ãw_Ø -]5#2Èe± ª„ìþóïˆ„Û 3GQÒˆÓ²œ ™‰9.¦MÌ6wŸó@Ĩ5Ñ»ñ”Âù<è÷Âm’Ë [Y®”ÇZè¿OD!çÊ­›Ü7øÇߟ]™ãÙ0À{§ne¡d-ø¨ne†e¥ìMžÎ½ý{’‡r™¦‚}ö$!†6kÓ˜£3f¼LŽ”Ù£X2!¨Òð½¹æ739j¬…iiJœg ª’uø~ýõÅþz`jXI…zÙÈ%øþxð[Ây³}±ß›µ!åÄaj1MˆDG5L$0SìsX”R°c°?§È³ä0‘™¶?‹PÿÄ®ˆ¥îô×"U!¥B;Ÿè¾À•TDa/½P1l-ÖØhÖðÜN*†þpè•>&Þ/þøzò/ϳ/Z ãë6úpÈ°S‚k›z*ýZhuÅØa› Q w\_à _BŸ€7JÁ±>¨- £M'sÊ'ñŠÏZ±Aoš× %çxœ1[@"iæZqRî sm|Y8íôä}]üêoök`+FhÙ…­Š4¥Ñ”"ë=d;³'ƼA2$á¾&¾ã!Õwhd*cî…œKì4öæþýÂ×M{6„Bï ³ŽJÐTü²'ìîXÚqð|6jú˜Mv|šV3.‰~wÖÞô±Xó&•Ly6Ž?leÏø³Þkb+0r9(G#׿a*g©1}~ßÌ«‡«xY嬾kM¤’*“Éì7{NÄ6c~ܨ[X¶x÷‹D¢c­^+Ì ÒaC(å kÂp|:÷tÄ•R Û‚Ûk S›*çqÐ$;;ejJqh¬À×iŽ”)Gûëå±Ý¸ö⚆õNM…ã̬µ¹­“\ié`Ë;¾#=‚S½ÒO”ÍõëM_Á Üs³ö¦•LñŒîåËΚh­Ä£’ïxAJAJLÎ¥4¶ß˜ÂÑ*Nþþs1öšj+T_`™8»;÷îˆ PpD20?²âA-ðu¬e¼¿ (7¦ƒ” Ïòd°Éæ03—/²m´<Ù5NI<±ú›ûV\3å‰y…ŽžÏFÊ!UnÂèãSÈÙŸN4AN”V`mî»s[Gç“Ã…¬á¤e“õ@JLs†Ñ80"“M‘C/¬-t[ýÞÆZÎÑ]b7“ŒŽ„ïANÊÛïÑYS™C‘9ƒLœ2¯€|ôÌ·5.À8Žƒm•½&äÅf2§á߆¦MÒ“”é!ö]™ëª‰óñ$%gôÌ\/””Ę‹=”ÞCcœNΛßkÓ½³º!®Ê›ÊZ†›œœúxp–Lÿ§ž9SFØØ^äiŽ‰´ÎqfίÂÆ|½c«[ƒ¥?ÆÅÞ16–¼qúg#;ãN‘'{;‹H¨½‘¦4üäo½1Ú*gœð[Œ)±˜ÚºèªaÊ!ü ²c±Ç¦¥ŠÍÄŸ3ør´J5‡R¤Ì½{³ÒfÎɘA%I0Ÿ Ä&óî±èqç}E*òÖPØ s…‰e.ÐøçâDs¤D Û:W ‚çÍ&¦ ûúõfŠ#§ë¿ÐÜHi3fLÊf^!ÝäDØ" Ýj‚ÍŒj”R­Ÿ Lèäsªœ"‚›³]ö<è+Fýœ3µô½™IPÖ˜¬IÇÖ¾þýµfò‘˜²ñmäñe,w£ÛâËŒï‰Ü›\2×ïoÆÎgýДjuR²È°°©çšüÃl¬Ôv š¹¯‹Ä¢xañjLÃTyÑ9JoAß á,FïäÚ± á¦ÄÏ£2wf­‰`¬¹°/ƒ÷œœµ ¥p»ƒxhñ+Nù9:x|gã}qûàq(Y±øl_eƒÀëèL>ÒÖ0Mi˜seŽyu&ÆXµòSy¤Œšó^“åÇ­7µ|=Ý럷ZÀƒKØ} ïDù#q›óþîì¼ÉRH¹ÆD²öOSÑqpHaÏÁãøA.UI¹qævØåØï{!Û`)þ‚IïùT!ûbáßû7µ4j}0gœx¹Tz¼û›“@BïŒwð(‰†³Ö€#a²Ù#R‚$ pùç¤Î—²W^èÊ® À·o^ýBU#Ê+Э³³‡tÓ7ºœyĹÆÇå›±n4m´ÂÜü¾`ë|R«bccz®d@ RŒÈº…T+Râäpql;ºÒ”¬B–Œ¶Æöμ Ë`ýâ‘7úXNÇe‘´ YÂVê™ X_¬á¤ÒØŸè­;¸8rÉ…ëúMÒøƒWÝì$øܬ ίÆWªàq…›3É2v\ÿêÁNÆ\w\ïÚƒu*ïq±~…Ò|‡/þCëqoÌwg¦Î-Ny(-ÃÈ-,ÏŸï£[\¡ÄZÅÕãÄbÌßèŽñ˜%¡%£{Pº,¦ º$•ô±²ÚÜøVZÙhü.h†|dÖ½¸M4ÅKêg«H)ÌÞÁ­³7_Õe~¦•\NÖXhVÜÃwH"·MÉÇ™¸ç›×zÌÕœ>/ž8³/ÞwGZPzjZ¶W®½Ñá<ådêÄVu ­e¶ ò‚onêtžõ ×À´=ÏŸS…°˜ð´Œqo–EîáG+´ö×púu1W\[Í, eCà¼ùq6ÖÈxĘÆ÷û¦xGÓg™Ð'Û÷g$ÒøÁJPi·'PäˆaŠñØ=>$Å-1É4ª*G­ Ⱥ¯Aš¡¥nਉ¶‰Ä’EO7i$¶)w±•Þ•ãq2×ä†(Õ°äIÈvªmÖ2ªC`Í U‘d˜þHÈ&tã¼ÑÙ‘¬ …­‰\V7Ú"#a¹räJ=y”ñ¶ÑûoÌG‹ýÅ"!)N•9cܘ+ª;Ú{#ª´V9ÞCÙ•ûºX„š°«ãÅq_è;Ø÷Ó$¬ÊgÂÞötçñøÁœ“þº©4–+cuä£e •³4Ú*Âw@1hGá^`&¤£’s4*5?˜½3pö|‘¶ó$øv?_Oî÷%‰†ª¸Ô¿×`Ï»ƒVÙc*åùdÛÀ¦Ðž ³Îÿÿ$ ´óˆ½ ¼Âܬ!,OH‚¶‰{ R2DJk¨V|Ç‹/¥LÚ“}ƒ‰G),ËÜ#¢¶Å…%ßs)¥$ÈY¯\1—H%Þ™„©P¶óüJéG8â öØì)ôwÒÊ!Œkñš±Ô­§Ð´ (>'ÂRØ3&ÚZí]‘½1cý^ÌôŽ,‚¦04¥¤ s6\m…üž˜ÜH†rƲ®Hæo?Ÿ|¿œµ.tnÌÃÈ‘>.÷ •M>”íÎÓa냔·w$Ú±‘VH¹°Øp*ÍÃ1—ÝØeRÏÌ£dîµð5([YØiO‹þÚü8+7ÆêƒÖ¹¤ß ‰ê%R‡÷ä8+E”T}lœLòàÄ‘…¶…³dvÞŒ4H»ðT¡·%S³’¨pÄ\e³¤Rq`¨&ÐË(%ü Yor{`Ç“4ýŽÈ´¯NÙ0vŸd¢Ÿöž$œþGZÇ;NÙeϸ{GYDfŽ›*…V.we÷x•#£î¼Ø‰d…³=驳æ$ùF–p|xN°¯°Ðª†IfR üÛJ/¯wlÖüñ`]7s,4ýÀ·rsá å'¥s(c^$„CN&F_+Q´n¶)k&®ß‹”b3û0rКl úu3ÇÄ,)kEÀ´ÀÒ5`­IÎ5ºfÇw Ú{¬!˱í›ÿ÷7"‹”vLƒKhUIRYŸž‰Ç™¹ße…9­÷°Ðα)UùªqáÚÎû5ÉɨÇÆ¥‘}rw#iâx”ØÒ'ÁU™>âÐœ‹ ‰Xö™ vmlÖ;âÍâÁÈâüþGì[Tƒ½¹ÄX‡ñȉéàk!;¼¹V`³¯‹ï_ïg”ÂÌ…YŒEÎÊõ}³[âúy¢u’{ï¨BÍÆê\γ0Þ%NÄZCÒa«²¹(”ˆ¼R óïø!¤ŠT§•Ø°önŸ“h ÈLÜ»ãÅùªO–ÜL M¤¶ƒ&ß”â”亖­º2 é+ Bn•êU£e¥ ˜9ñã‹š{Lö£a·‚U<Â;-~Ôj ùsú;cÉM…,™“ëDZ3åÜì™ÐóCüÉ’Èg«ž$M´#ñ;)ß×EJMë÷À<¢®™„fûxµKÀFvŒs6¹JlšE.yp›ŠÙÍXQݲ¢ih"›T ’6þLUZI¨e´ÁëÚd N€‰Rs£ûæ¦v0w@Br.¤Z0wü³|º^ƒ·Þ´ÔÈIR3¤Q€¢\}ÑYˆ mWΪ,X¯­›çσó<"}Ixç<¯¤¬{ ‡b{% ƒSk­^†Ùg2»’6õQ÷f¯É×Ï-Q“$ ©klh…ZÙ“±6µü¤h­àz¿¸¯Íy¶¿®0* Í‹{éÌ£?ëTÙ¯WÆÇ&?*{+kLTázA®JmÃèu”ŠÉûõæ¾;ŸŽ5AS‰æ´í»þ•p3®k1ÕÈîHŠÚfõA:öµù7c-¼}®;–…¢ m y².Hÿëý?þí8*åëáNÒlw¡´?Ï“Òœ_o©šODáPHGôªƒ/ý…CfÎÝoŠ©½¹0œÑ(›bA8º‘,´”°þþH0‰âa*%)ŒËFËÉzD+9E¶“]IÉ©çóä|4|s#EGŸì…”‚õX¤Œì s²r‘¿Â%Iä~ËÊ“I «e âJaéŒû6µ HŠ=@VÁ=qõˆ©ú_£»|‚/(9qdð´É¹ãÛ‚ó 5¥SÒœã# {dž/åF{±ßnJß 9cÞßo< ´Œ‰£ÛÈEx÷Žî nÑTCEI9¡–÷$Uá(å/wI™ºñ[æ35r!@”-L]{{OÄÃ%™\ùÙ*¥†•W1r†?ÇQáÃ{H9‡ñ™vŒ0­9‘–(­Òˆ(7@Ú É±7ca«´}’¢á3ÉŸß v ï½—geHL{…]ûø`ÏÌ6Ï?NZ.”iÍ\œ[f\ýF¸BœOv>PÛôž@üS–÷Åëu3ú ¶Ê×ÙÀ6ãr,E Éæ`ÚÖÝ" !~ø)eJIwÖ3Y1ruȆ_ÿÀ“ r ¹.`QJá‘OÌ,äó]8[¢–ˆ· ?¾~¢âØtòq6ÁF0E&½3¿ÿåùdÈÉý i„Õ7^ úñ·¯1×Ùor«ÊX«üyøR¿#ì‘›0_D¿Üãàg;‘mŒëŠk>9ÊõÁbÛG#îÂWù¹DᜑZÌEHÏ‚_ƒ‚"iý?ØõdÞN¿nô¢ sý%3¸;º¿ïAkÊóëE•5_L&c­ òì ²é2R˘ôãÚBx¯‰¼ßa†zÉlô`ŒÅÆ6çÇÏ趛l¾X8ç̸gÀ2D&s:s ÍÃÖ¼÷¢´š2û¾9#õ8k…q¤µD Œ ÚÞýZøL!Åe¥Pù*?éÆ;P.ü=Éúd''œ98Ûés°sBJvÈ< ïñâiåþŽÂÒ©&ªÇHž|²$c}‘æ&IãñˆB×÷òàÞïM¿¢­9然ʹ:'›ùY×1ÈBJðÜ7f‹e¿ñ~„kD^^¾žH)ÿgߎÿ“Ò» #€8%‘Jãȼ£ê1šÏ£9zât´j;y¿ßÐ.’4Ê#Qx„zµ”¤'%Ç53—I·~¹Ð=Pu?šÓ©ÜKÙ©>Á3¹äÖg ÁÆ‹|ì MÉç÷Se;ow†:2o؉]—É!J)‹TZÊÜ~ñu½9T2Æ$Fn‚Jr ®ŽOÈY©ùÁ{NlÜüýzrTáaՆ؂[Ø(ë}3‡QÛ{¿˜¯5`¥ðÈhÑ°úë7Çó¤æÝy¯7Ç­b#óøÛÉÝüws0'·ÊÂÊ6èÒIfüëQÁËv´ ¹`C‘,h+<gŽ‹¼¦‹l„¼½'ã6R 8ÏÄY[7ºåÞF´0†"îäæ÷sfY„*îû‘Ÿ?θ»{˜>æÞ󜄒÷}qßqŸ,E²²4bÉldË;¿kfÝ#ü„áÇÝ(ÕP”±Þx¸Ÿ°¨¯zÀöý‘óNÚñ€eXÿ°3-ÅAêîŸd®’·+ hE±oeËŒMhË4­˜NÖô Ì {ƒH€œŠœÁn»¯W´î~="vøîÔV‚íÔÄ0߈gV篎³_¿B.4§›°òÄ;¤§P¿¹÷Tüø…ù§b™Åk½ }oò4RIØ58í5–°¶Òœ±`gå,BH)6¯¹Y”¢]‰=%Àvµ%Mtwîy·p‚¥Fn‰qfŸ<'éÑè¯×ÅÚZZ¢µÄ#GƒpùDbϳ„VE ï÷-ù,Å29;’V48¤RK@Lçµp-²LgK”¥VÆŦ\ß)ƒÇW‹ÿûæÒÉÏú 'åNŽÜ‰R*˃˜Ì°”ä•Ä¾ˆT”=&Ö _ª€ìå|w´VêvL…KŒí‘œn|òxìV×ÅÖEÝÙ;7‡VJ»°•ñíìálYh5öŽ?7ÛÊJÅÉ Î âÂT+Ó‚-ΔÙÙÙ©8ž„×=ù™¾¬“ö2ÇYùQ3#ü¯7»?ŸOÖ„ë÷; R—ÁYñ,L Ö£šM¾ï7s/4ô†9 ùþÇ ïŸ‹uû¸5ác¿#;"Nú‘Øvpõß´û <rÏNngã‘`RuŨ½6;Ýœå'­=H2Ñ$äâØrDJô•Û&YÔ8ÝÛДxÔÂ2adhg4™HRl¬¿œ}ÐÙÇÛVD$ÚZ ëÑAWSÅw”]øZ(‚3t3}Bþ¾5£]k„^v®ÑE@D2Å!ʽÞì{Rÿ8#MWÎû~q›£S)IÉáþ&:º3ž³/6 §wá<MxÇ ‰îvoäÜCe°Íù<ÈËJwÇZá,O$g¾ïßLûÇñáÁZ7ø¤µwEUxþhœéäû~sÝ“Ê›eáæÓä¤ÓDk͉Õ{o®û¦¶‚ŒƒË:ª Uç(B;cjÓ7<¼²?uØwSÒÉy~Qð;¼¾_l‹æ`K…S×fI>jH˜-|!JlîURô<Ήxü@/ RóÑ* ‡{Þ¤3r%ˆ#ÎÍŒSd2Gæ~O^v‘¤P,á4^ó…ŠSÎcƒ[´ù ‚Ú†kc‹ðóZ¼y¡=“]ÐËÞgNν};in4dwÆm¸â÷Á(uÖøfÛÀIÌ9°{à®<OJ‰ènU‰Ä®²qÅ¢”5˜¯ßÜ+¡zGâ΢շꩉ9Þ êñØ“½&¯t®ûãÀý‹]î¨jŠ}EËä,ô~±Ö¤5 Ä”þâЙ ÕÈYyÚL-Ø~ š6Œ$öŸd\EúdÚ›i“´Çð¾nꪸ2ûLÎrò(Ñ›øq`KÙëM•Ä£¸6l†:RŸq—Þ÷Ä×…³ñ{¢EIu‡Ç£(oIHÕ¹Þ ¿7—Nʆš =ž Qd[¼¼úæÍÄ5Fø,°¶ñ¯Åk¾(Ú¨©p¿ßì Gc‹à>9ä Õ?ø5.î÷öÍñ¥Ôã¦+H#ÐO4·Ýüùû7‚Fˆn^øçj„ÖŸ6 ¯¤9™KÉ8­6õɨÐß7e¬É¶LjŠhž~²}“òÉÿð¨¼FãÊ/4=¨MÉ(r6úŽƒ¶=*Ò…áoÔYÒÿþßþϳœ¹†³úâ8Z?xccK*üÕ“¾ÝØ–_ô›LÕ„äƒ%ƾRIë2lŠمRŸ ‰96nÕ…ZOJ«ˆlä³MRÉ k/z_ìÕÌ©žää¸wÜ GK<ËI¢’fñP4G9";ÆÇ ¢)Ò€Û`!làÂZD\Rˆÿ••‹pÔ`Û*DXÍ$ÄS>¿_‹¹”’RÈIÛC3Ø[UÞ¯Áës*×ÏqÞ›ZZ+zf}ƤÔ2±Ædvc¬…jåYHÁWØ’·%f ÞÝï0måÈ ”r°·D±H⹄lM`¬Î½.D*™Âq&ž­2m³D±½°ysßáFkÏŠò¹~ý,6S,b§¡[ضe¨JUÑ!R¦J‹ÄúÜ¿•ï±ï ±èЉѷIØ–E9Ô¢|ÿ¾±tS³0$1G\5Ü-rñEÑ%¤RùP@Iªì‹Ïi+ª±˜tÖ«ÇŸ¨&Æ{áx±¶ Ù*8ŠûB¬D×¥Ò|[b[Âq¦;5Y„·O†]´”Ûè#šŒÖœäšy¨b=þº¥Û ¬åÈô5¹ûÆõ£Ph ÿÿ¨¹´düq>8RПjQdÞó¦ïèHxÔh‡šÏG’H¯f§4ñ£~½;ćÂ\FŸJ$ÿ:%Ç]ºAkm|ož¥‘“1®7 2œBñ¶cnDÒ§ÚhÒÎX,¯ù@ReÏNÍNΛçÉ‘Næ œ7 ¨-,K¢Òé”Ì‘Ÿ8µŒ-‰’4Úb·s&Úbù&É;zÓ{üäR)§‚6ªej6D;õhlsJî!¯ENobK—4Ý™Ô:7g f>Ë +f†ÙdYœ :AkdÆ×rŽ£R[Ärû¼1.…â™VSáb†JH4)»dŽ£’Èl5œ È<Ï“š7¿_ƒ-BI·èí;Ï#x;E0f óu1ʼnþ‚ û¦Ÿ9á+ÿö'þ@5À žHÅ¥vÊr’(ÿzþ$gÏ€"#éŸ Êqñ(OúvÖÞØ6Xƒúã'5)E•}DÄUצo™ÌBÖ‹Çã¤þüAï¯+µÂ×3sE¿o ?ÒDsÂm²÷[•ŠµVŠ¿ï7kmú˜¡¶ì`.à"±*É…å—¨·û¶I{u~œo×{cŒºo§_†¦¤å„¸¢êüñãA%qýºqbA®)…Š‘”tVd9–…ó‘?þ“ÄôÅò°=ëYb/°}NÌoÄÏú ä†ýù¸}_¸8u \‹éÑ¥q? .á­ˆ`Þ7*,D»Ž™à´j m\C q X!‹ mÔ£NûžPN$ yG~»…T vTr{¡¾È Îgô¶û›ÝoÊó‹ê¡“¯™ãþkN®yä Çr²Ípµ€r¬Í°‰²ÉÝHÅÙ™8IK¦$%ýÙYnH¤fÒ£ÒhhRlo¤AÏ‹µ 92â‚ZD¦F}YPÛ=\¶ÙÃQ_x_ȳðxd¾¿nóÁZ›9.R+¤SÉ„ØÛÂlslú÷͘Æÿø_*£gÖïoô«"–I&¸dòôÚõîø™Pu<L‰b“´¢,#5ò5h9AÎ\×›útŽó‹÷ï›9nVma“j¥§úö]'v,|C¿ÇS)í àÑ*cGýXÞ…=å=Ùœµð=〰íh]$I©ðK/ú¯…ÞFj‰aÑÌÛT¢#[R>²jòëcÜIè¾Ñ¤üøÛ{l¡JH²ûF­3h:ÏÑe ÍpìýŸ€–I9Àš*Ò{¬ÈŠ ‚ë'ÎÎÆôÁáØ|þü¢ÖÄxÏøÎK4 ˜rqÝATî]hÏÍ£U’Uú'æ[sP°Sɨ Ö'}.Öê´ãÁYÏ°ø²ã‚>Iç”Êžï ©ðãøú º Oih rᓧébPOÒ 2ñëål,ot Ú"RžçüÍ ç ÔLÒÅ^#[ ÎZ@M¨Wîû7¾'ç¿üA–Ìýk²\I9c"”T¡ø¥ˆE2ýýâú=©Ga[ ¬šÂë~ó~ßÔ3sœÐ-âï;ñã!Ô¬øŒô“¦LQ%5h5±vÆLés’gâñUðVÉ)È­wºX{ñЊëaBrŠ0™ý€å¼ä…æ‚–Í„´ÃŠ›²#äîHîpº²ûµF0©DÅ^Êpð1ãÔö¨:ÏJO ·š ̹°YpÛ”T˜Cèï7×õfÊæç×AÖw¡=•ùZ¤RðeÜó&§O0kNæ\@ôÈ×úÿþþfÙEžÞ÷¢¶Ù‹MÉÑ&¼>ÅEE–+ÙáëȤ|Ò×$¥ûcHZ´ËÕ{;G[-ôû5#G02·uŽ|]×sFòóüúâ_ÿ¦ÞeI’cɶ[ªörÈ* Ï\~…Sþ—Bv7P•îöRå@ç3D Y•îfª{¯õ8xªð«´’(ÇÉ­ Tþº3×ÅÏvðGM¼çÆù`Áäž´V¨I‘RÖq2kE3Y+VãÏoí…ª¢G&M»ÇïÆœã‘Ñe¦ØnTôÖœô÷ Ôˆïf¥z¥”Mj'Z÷úÛæ83{Áûû›R7õ¬åaø †ãËã°ªÔœ£oÍõÉ{½€¹¹J8$KÊøÞŒ9(OÐë»5ƒÐŽÆX“©ÐƒôÐ÷LÒ÷û iRÏŠ VŽšm ­à¼ÉîÂÞaΩ5jœ÷’̵6ª°wƶP›Q«‘kAʶ(Í)»°5Úq55Ü 'ßž@aÏJÎ £ûˆNöHŒÓlpäwìù= Gݤ’0ñ©‘Ö"ä3“öd!qGíð^ƒdJ±ž•Í£ýàÝÿþëb|%(‹ÂÍÌ_ä*È ´D#L~ ÈÔ×ɧ“ ŸÌrÄw™T-œ¦3c惦J5XËyõ‚sº äõ±ø,t:«o–{“dŒÓOxÿf®Dy¶ R[¬×œ–Ë"·`Ö¯kED¢;$- 2Ú2(ôïEmGq?qT÷ÅìÁ´ÇÃ>4pè‹C´Ý7ùî`F-Âì~wŽç“Z ˆpõÁ%~Gkл°×&—ŠëÁBa}“ÜÑCÍL7þó^¤íT™¬,$WT Ï’ùÊÏÇII™n¡3+d¾_Œm‘êƒÏ0mÆÀ#Õ‚ÔosrÌnt.Jm¤5è}¢¦œg#{Jû “òâü:bK´trŒ‚›’Äñ•°¥Ü¿~q¥‹Gýñ9%tXB*35j.¸*ë2d個Бeè¼F\`Iûz‡óÛ¸ÖäÙ•»¨HïÂöÀ–‘ì¿~¿˜£Ó¼ñíÆè©Í¾‘¦ì9iVñ {ƒÀ4ìA{/T¼€4È9?q¿(ÅÙ{1gJ4eæk3§QÊÈ›BiOðÍý뛹;r"Õùþ=H ¨)9¬·k†Ëýq)ˆ¤¹0mðß×…ÏÁÖƒ<Û{wÒŸÊ×ì^ŒëÊÆË?é¯XËôýâºÁ½à«Ãºøkþ‰–?ã“­ò+_ܺ(éD‘á/NÕL"C™è€¯Ÿ!åüõr¤*po\”œÉŒ¹:]Œ¶±BÉ…f°†3tAÎ, 3rRGY”óD¼ó÷_$ e4 Ì>v=ópÓçÍóñ`•hŸa!qômŒTÖq §”ÂZÊuݨ*ÏŸGäÞƒûú…ê²RcˆeÛÀ/Ÿ•œ*èfŠ‡¨â¨4ÞW6Ìcý*Ò(5âÓ’S¤Ú.bx¥é‹ûÕãÆJ¿?˜ï¸ë–Ú`þë¯A®Óo¼ßÔã 3ùuî9¹wGæ2†X\G\ ê“­ÊH ë“ûýæzê´_9ä—k³,0â5mäN‰µ/†y ÉØ9c#¨Æ!pçõ÷¯@¦9T‘(ߘ°úÂm2®ÈÕ³òU*›(‚=’’sbûâíßßßÛÆ?ŸÔÖ¸¯7÷u“<£ªÒª•# ¯e¼W`J7T7Kßd­Ñ|L#Ør“S4PǽIØÞÌ ßf<¬Rtaצ<+µ>Xlu “’ >ƒ[8 % :•œjb ÅýßÑ´Ó —¶v0Æ+|{ÉØ#3Çd¯wÄ`›„Ñ›­õzs¤Ì£äZ1[¸½?Û„B{ä¯÷orª´tR,j¾Ò2Ù«+ó\É©[Qí¸Vl8× óÊÑsÆj­+%“ëîü·^<Î'?þÇcÀ£ )Œñ¢Ø"kc§ÍîßÌ} ŠO8’`óÞ }RsÃ4î‘ÃŒjÆ™kÈJf'Ë™²àšN)B+ƒrlÚ¨‘,Ö¸3&ËNþ:˜¯Îûõ¦HEäÊ<ÏLb2WÌ9®k€Û'àcätpÍÍšN;AÒfÝ#(Í]€w¼­-ó¾V0ïÎΉãÇA•³ŽØè#(Û‚¼ô8sT}ß›1Þí ÔÛoæûFÒA®…=ßÊéó™ùDM5!)‘ƒþi%êtµ”ЈKûâHí±ÆçÙvû² KüþU*“÷ï‹V í¬¼zç¶Åþˆ-Ü÷ë7ÕJŒÊ¦•‚—ØbIƒEï{ª¡û½SZãøÊ\ßo\nZvŠJk¸;6…{Dz®ÕB"N¨ã^ØY€Å´·«Lwð°AI’îý“k%µÂmÁ<È)#{óúûÿáÏÿøœ?ÿÅë¾ð®÷ñoñKnMN¿×{…£eD®…SAhÞœµryé«Å÷ùxÆïÈl’{!cPJED)…Ûɸ®ð²ÕB«‰ëVH`¶½bhŽveëÂP¾Ê[7·_è'+süæ~+¹œÿ&¹ÌIì ›PP¦_¾~Ô÷ÿ¦ûEj%“D©ÉIµð<*«@Hß몴3Sú5Ü…ß/ÏœRÑ9É’ùúú‘M¿6Üi…ý9R9Ó•×5`~&(k¼°ûÆT Ò*ÕcîsuHnd #®)™ “¸'Íbµ`…ó+Ç=>/Ž3j­!LjÇ6Gÿ­cwäl1}÷øËÜÈ#ó8¾Ð{}ÖX‘.Ü+6-’B3æ=T_žˆdâŒCMÍgÑïÍJ‹vVÜ )œ§c6¹®°Ö’ÙSC-¾`uýw°ÖXj‹ë›§ŒÝyAMù“Ûwj:94‘Ey¾I„ª¹cÉÑB¿;³÷@y•‰ó¾&¾7__'ª…Õ/Æž8 Kyß©ºåc4Ž,ÊžŠ~b½s.{­I7}u¶$Džäš™ħ|Ô—ôÎûêhJñï× CT#$7éã¦0cÜÞq3Ž#×èäçŸ?Ñ>¹>CÉóëÉ™=:åkÒûÀJ*›$Aø½VǶƒ'„lG— óˆr߃¬ñÐ+”¢Êêçàÿù¿Që÷/RZ¬™è¿þ —Ä¥M`› ‘É…¹A'>.Ë„ÖÊõ¾èk’káY3¾„yC£ŠDi«”Lï–³îLjB}؜̩Hê@LPjIÈ£12¸*J­JÆòÉÁÉf3| ‹˜Ü§Â†-CÒAòŽ‹^ }xÅSFÜqm™ÃKœ$ÆŒðFJ¸_|OgY‚o£>(0ïA‘Íùǃâ•_×o¬$žå‹9¿ÙW`´þßñ¾ƒéo¾&»|väÆøp˜°½ã£ƒ(¥ %5üVæ½XlÒ³b»ð²ÎžY™IxŠÀ\|¿)U 89Qväļ;kÅ}0§xèQªßÍ Jû"7A|¢R‘¶°ÛH©QÛÂïÉwô˜ë±ìtVÀR·:KV 0m"{áâ Ý”åd}óAJ½¦:çú\1NÏ'³àû/!iHIö¾¸^oŽ3"Ûª‰½o–™¦:9{zmH'­`æiJ$‰5&§ “ÉF=sûàÌ…£V®ßßüýý"[ϲZ[Ôª”ãã¾½SËA._ø^¬}±çb¯˜o$TcNÞ×äüzRr¯Áv‹lüŽu÷m7b ¯•, í°ÆM*T ¼/|zœˆ:cMÖ%$Iðã8hgáÚFS FÍ¡äA­vÂWIl×Ê©5t}WcoaË…!̼ Œ‚ž‰fœ<ÌL%Ó_oú}Sr¦l'eAš0?ð[h¬KÉí‘ù衦„~I·L9RtÖǤ‘}/%Ö –`1‘Y¾ñeX Ëðy|Ê8íQ)ÍéïI>”’¾ß/ø¾(GÜùî¹xáTíñనľÜÑå$'¸‚Àr0§l¾Jføxëtã÷þ‹±@‹£²bf‹e‹×0ÖŠò…ÀcåT˜iR‹Àœ¸/¬|\„c1=Ž¸; [ºc%&±¸³JOl¬>ìD?˜iwJ‰•a«•qÃ6ûÌYœëz£ê¨„U©qþ¨¬ÑArЀ†Å—+¥˜äÊMJÆèa})ÎSp9ÙÛ™S)ÃÑœ9%‘ÑX¶ÊOÄa˜c~ ¯œÌn F¬Åîkâ~PF4>z64¿Œ”qaBGAÑIœþŠp7×{ƹÀÜ ÉJµF×Ùœí7o[ì½i¥ù‰˜bß{1Ä¢¨ÊÂÉú­ƒ– ¥Æ9`¾ Õ3¼È‡økk!9Þ¾fá˜}òN±¿¯7cí9PýØ“ç_orþÂS¢ß3N)³Ö¢äÌxOæê”2pK¤ü i/«;6¯¤T'`7D(ITùþõ7–¯óH›wï`‚eg Å÷&·Æ‘ çSÈÅøþ4)ÔöƒÞ‡”ãð†•3ú¹ÖZRÎçÉþœ»}¼)¹°ò†ÈsÜtt5G·:bJ™T );×+,§åh¤2Q)PfÝ+G(­çšlÛTÍhÿ‡H®m›•ã„WÆrN¿¹Õè vr¦ÆÄP¹Ù9“lÌ€Ÿ?ø9Ùo6¹'«hZ¨Lñ]:éq"c2ÆwL‘›#ÓС1¡ODæ¼>¨G uù6¼:z.LªBþ#ƒtúK±$ìÉ }~‘›uáq$J*\ï7k^lqÎ3âš"0‡°väñSJÌõ{P‚Ör”r•þžŸiµ²WŽ2Êõ+$¡NpåÎó©pßÏÝöž¤ú qE/‘mRô¤4YqÆx3ú;ÂW©ÛAØk1îNÊ; :Ú( ¨ù½p98Ál³u14®C—iOªWæJÜò"iâá–,Ž– '¾û‹Ý =c3f§Hâ‘6¹d„Â}¿™¯%¡‡’S ›÷íŸòÄËhÆÐ ÖŠëk-\x½;{_Ô’>…´ZÞ×…¦ðaÈX•ù6ÊøÊÈÈÔÝÉébŒ°)åmÜýýoj‘ŠS>™ Õ3'%Ãî/ÁŽ0•¹h ÓÃóÇ2–tðHu >ƒg²~‘ž T pó|Æf-n… Þ,7ãˆUñ6R*|5d9eÖ¸ñR¨­aSq¿É¶*÷þ;†F&<[θWï Û•œºú'ÂÈÉÙ66î(,ìÉ)™²9¢³bAZ“õ %w;*¹ I³lögãú™PZÔV†‹SRFsæJúﶤÅÑ Þÿq ²?žö©ìÛS(îÔæà‘yv¢èSEG¢Pý *†['¥¾GsËŠ8XaEFÚátŽ‚Ü3"—çEÑMÊ…Q Ó©ŸkTü©uZ‹ÿæ^A/ÎC±”ðV`¯`Ü+@Pg{Ÿ$Ur~0ì…ùø8~<¯±¢`Õ3)5úH”i¹1¥)-ÄGaºóÝ­:­ÁuÃÞ“Ç—ƒù¸ÖŒæ Í~¿njmÔ”°~sÝONË­ʵµr­È‚}*ƒÄ IDATýËémÐ×ßÑU¨8×ØT‡êÆmç•x•G9?oÁµ°Ç —CMÈ*´rr$çu}“K u}¿ÿºP™“†y&M-ø‘jdw–ûçó‰.· $JIÜ{³ CÕrR³2¿ ®˜µãˆ;ÇGá]Zå({gœ†XµÖR ”^ˆN;¥FŽa8Ì~LásÝ4eÎÛbàrŠ{LV…9Iö„÷þ–oȹp¦Höõk2{Ìdti)·úiMجh#§$œ[á«9«CnÆ^ë£ùRD6"7ÅÆ–DRQ ©u¢+ð•x”€Þ7ëjé M ÷Au¯˜Ôø```‹9 ×Î…½¨æ<$¢¸æ1.^°vðÝ㎧$.7Œ°ìؽàH<'î•÷}cÛðº9ò .K^ iŽtçL ­)ö¾#¦ú{ ½;`´j$MÜ)Ó­S®*0¾|%¾ŽÖÛ3xÅ‘˜v»wÆjm³Ü›9nÜkúA‰áSÎœ¹àŠ#ÒØk°í&J«+Á18φ{Fäälƒ™Œ±Kâa›’S w¤OôÓúsß9?)ú¾9´tò=²¢˜uK€>6¹+]ƒ›ÈïŬÆj'ÅfÑb;,ÈÑYƒ•ÍY«3J¡–‚ŒÁã(üù<áÿ—¢»û7kIzRx¶’)Ǧ¸^ˆÆpLåà<ƒè$r~tìÂñõ'¢ÎëïoÖ=8ZEõ`ζŒWÿfÍM£> ¾JüîV®“RJÈG’ò¨å3¼¬¹¸µ"ZÙãMòJ-α·Pªs½nÜ2µýÃ=ÜäbÚr|¾c™ÞI'–¯û›òùÌÏþ ð茛_“ÝÙnûàÝ,þ¹¢úG’«ˆtª «<}°ïœ IJÖ ‡4r®ŸÆßàýëŘ“V3éSv0¡§û h"eP)Ø-´õÏ<,³¹FÏú{-Ƈž2ÇBƒÅx·T2[Í„”•z8c¾ùîŠ)a-ùZΣ~žâîp~}¾~ä•ãdq£ùÆýàQfš÷àî†ì‰•àõÛ(yQ›l O‰”j0ä]øg°¦ªŒe\ïNÊJWÁÆfš£)ºûi ¤+V¿Ý_ ÔVp׿0j·s~Ž®{búÉ°[ÄA5-ê/æ0î+î´Õ¢æ*ìW´”ö¾y¿/ÚŠÀL>4ˆÞ¹a+¹Õè/,@ãڱ͙õ«”ÊÙNÜ.ÞãB_a}jgCu ¯/0xÍþ÷"Õi"W}%E¬öºoŽ­¤bÔR)ù :9k öÚ¤¢Ô’I[ÉDjÆÌcÇW¸'K&"Âá™u(ýĦ÷ #±¿A…ç“÷¿Ø~²÷;6µ0oФÔ#~¾TO4•8ù•‚@®kRÒ0’ ÇQP·hpº±<ÃtD&þ‘ÉäV?!«]ûRÙ=ai#f`›÷ïWœ|k¡Veí3•û ¨»uJK™¯çAMz¿Y¯ ¡ 5G™¬¤8ͺQÎLÓÎ.?â4º'ºV¨ésCd1ïÁŽUèÅé×ßø}C tZFæ6À˜ï+Ö9ª"òZñ”~õÁmƒt&?kñû $îW(ÁâN›*Ôlj!Ÿ‰c…÷Œ¸â='”ƒ”B{%OCÛnŽ\F-ÑewqÜ¥8ìÉ«¿Ñô1äš‘kÂZãê14|äž2n›yÇ*Ü@Œu%nϯ“¡›57÷m$I´cÓoÃXñùf,E“ÑÊë´y3ÉJz*uí8Y øz<¹ï‹_ÿýï”+’<¼+ÖAÏg‹“ÌŽvHIõCÖp¼ßˆ ¶ˆ¬wZ¤)¼ÆÙÔõì±R£FHH©1/i‡0ÆÅk òÎœéàfb×âDi?VŸÌûfkcá)ŽæƒznúüŸ-!%ÌÉá¸@Žü$ýÞÃÍb¾;Cœò¨d2swD6µ=?ašh–Ž5pÙh‘J©?pŸà,‰áQgöá©ã)03cô‹vüD–2·áïEß!ÁHª¸¥D_dôkOr2Þ¯‹Þ'%7Îù“ZORòÏ<&hPžCÔpµîhÔõÅþþþäC”„20Æœ”kaý³‚'å¸<l_Œk‘ ?¡SŽÇÉïî¯'!ª<øòŽíQW÷I=7N¦÷›Tϡݳœ£–@m ªÎœ+KÈnÄ'º¶ÄCØà+ֵħïI®y£’yã$óà진¨áÉH¾ÈUizò•Hpÿ×/î—ñ||qžBG_ýë«Qƒ9'_ßQ°I™G‰=¯yPryP©$Ý̽Á7æßpäù+l¯Ÿ04s¾#¨T2{l6wÁÝÉIX}òÝgƒç—²WðõLj%¤S»­$UÊDX7ê-PÎn˜-V‰‡ÖÞ†‰ Tl§ð¨°”ð¸iÂ?1Óâƒë—3‰}²œíäñã`þžÌþ‹\?°=x}ª›™L³M_;Üï*ÌíÈ;äŠÓRbª0Ñ9Âd’LjuDŽh­7¾œçדG=Y{Ó«ó÷¸±{F³S[†íMŸ<ò_µ0—1]ÉK =V·Äß…9=ÝüüúÁóÙX}bztõ©'¹ý²P¬©|8ø›1^tƒBÂ’áª\ï›ËßTY|}ýk®Yx3û$×JMÄzcïo¾¿ XÈ@ECY^jãzÝÔr}ÒßBIB.'¹¤¸ZD“se|îñBs£”‚èÇœcñ"PqÆõ›=Ã0Uk£¶Âà×ݱ]ÇY{!"œ?jüœ/û\q…½Ç׃ñ¾‘*ÇÁäÍL×úŒã=ߤÜß ur>õ`8\ýP Â’.ï ó±öº¹ngµ8)ü 5QŠÆ hB=*Ç3ó{¸ˆko«d/‰”mm¼DDt]Ñ÷‹¿W'×ÂÏÇAòÌô¥mÚŠãoÖ?8Ÿ†¦€‚œÐ41›¤Ôø×σ,ð÷´÷kès2ûŒéiN¨Â‘+-7¾\¿oTsí86&pKxzÀžŸbă߿¿‘û"£˜/ö~¢¹‘]1í\÷@¾’>C½’ñ­ø>w¤Dôy¯„’9v¬ ¥žÐßÌ7¤#±<€)õëÁ‰2pær´o´)^¢¼âË6¶/Þ¿B…-Ù‘½±1‘⤧t(ó=Xý†!ì"½ /Æ Üw¹%J;Ù»ãûþ$¡VÃL¸.aÈ$§ÑD!cÓù5µÆÆC€Õ;wï$w²;e }.Æ4ñÁñµHDªñ°’xœ`³c;ŽÁ¾êBá+gr‰éu;R³sÂ÷Š¦a5ò­d…£)žüîûeàð; Öê¸FiSæ+³®Nd6õøAyVÆÛ°þ>Ñ0Sm[Ô¯“’ŸÜ×s»QÚ©BZƒu¿ÙšH%sœJ9kœ8!§¾ßèÞ<ÏB©5ª»¥QÄixІ?³ÝZë' eŸØ²|~°(ÙC¹÷f^=ÖØft4i¬µf¤eIZ©{’åž¼añsK¬ˆÄxÿ2¶uŽ\y:LzðëÒꊷÙx‘šq¤Šocö7õ$=Q‘(̵YèG¡e¡›ã*çggBâ÷uóûº?ÆÛÓÌ’É9d ß6Ykð3¥Žšƒ*ÇñĽ³ûBZ#Õ“2&¯Ë£‹½>,i‘Ïéa!Ú°æ¼ß…Äqìˆ^*´ã¤¯Šñ ®¨9dáçãÁf²çfçêÂC,2ùÚXñ”è÷ ßÿ‰jXi*ÎB–ÊVá×ß/昬áAá­™â)d¬žOâQã!íèf‰ðAVlT§V%•qgµ˜òâqÿTÙ”1Íâþ=N/¸u^Kbý&™aÂ,W·µ"œeÆnºÓ•ÿȤΑߒ¾Â‘yORÍXÙÓ_[£{‚°ÝI{Ãà …¸"‹@KÂ]3Éö§õU07r+$#m¿oR¤Ï™\Ÿ˜ ëê´üÄkáº^ˆ(b_“.oþïžø¸Áúæ…c‰õ­çGT`ü×X¬»£kSJ¥ÔBJ†-5ɉçÄ{dBy²GI7åÌ‹¹^äúÅ%b8ç×Ááƒ#2*¹aÍØïrѬ‰ä0÷`ÕMZ taÔ˜[VR, !à‘Ðò¦D§hƒSÙ}³® -Qhojk¬¤ô¹ØÃ$hMj¬~²Ågl+ÇZ®w¿i+)k.ÒpRKì´¨© j¼úæΛ¼¢j[Zã¼nÒêÐc C¯…É'»/© ÃY€Xãºߟ¹Y÷_¬û¦æŸ8ʺoƸÉô[P3ÖÕùÜ7Ý¡ìŒí6xKb…Z†à×ÚNÌ&íÞÀNÎByfŠdÔÒÇy¨ìÙ™f¨9摉è ÿàÝù«ßhÎüÐÌX‹{Â׳PÎÊú½˜R^ì c\Ô6ãü*œ’ k–¾'­FÁ)ìBa€Ây Ùü3‡=>Â>(:Qr)˜8º"áßÔ4Ù£6RÆëºX÷à^“CËß4ùƒö¨x3´|`Ǧ=¾ØTKâŽUááQ^"MÆ=cÒ~d#yâùüIW`Æ÷"ýïÿçÿñi+¾ ±˜Èº@U…„Ûñ‡r‹#›aÓpÇùEasuÁ¥†.ë~c rJøl;R>öÛˆ.ö˜¬õ!omåÚƒ#ZmqÓ¤£±œ3˜å¨ÔüÀ%q´“Z>o’ÕÙ>óâþö÷/ì1?žxu¾¿_ÌÙ¬b|jʲÉüët+G=Y Ë7:¾ y+YË&5…Ô‚¦”¢dq\$vgã,¹œ‰¬J’É6A™ƒí š©ÚØbxß$tïˆ ™b­ÅœÈqü,‹µ7®…µ&s¼+4Ô©>cÀ™'çó¤Êàuu® ©$lVRZ.Œ+|óc8ëš”š)-#©PS"§02§™Œ5 ¢¶˜#1H£¦ºæMñ 9!xסl{r¯É~_xþ¼éófvcΘ!´ö…ž Ûw¿0“PdãÈÂ}án´ZI®Ìê× ’®ؤQZ€i×ÜÁP°Ea.g¨-,ã+qÙfû¢æ“£†Ï¯|‡`t‰ú|ÄüæîŒû×ßH°9ãË+Zð±0ߟ¢Ô ïÀˆûú„À´£âÛ‰Z íq„mÿ ¼+ËÙÞÙ{áèÇA}(ký#šŸdáÀîw(ú8ú5 =—³r}˜iæN_+pQ{ÓòÇ©–Úó¤éb™0?ˆAÜm›†ðóQY&ô1ÄÒšZLÃ÷ÆÖÄÄ¢"BzûŠ¸§ É-IáˆßóŸ<}„s&‚w°bP4[d¾ýÕQÏlÖµ¾ðiÏõu³}¡^é.œdj®Ø„Ëc¼ñ-ÅcH ™Ì6¹(j-bÏ:)ÚX#Z^|†‘£w$ë-<xkSª’ò‰ÔG!íÅ÷ë‹RJEÆ|Š-na&c¯‹d™’=&ÿ5!sq߀%¼ hF™TË,w¦ê¬;€&,ÄžaUCWø掵˜s’ÖŽ‰qª¬ÖÙ z¥¶­ÒÎ_À‡Msöl…;ÕÂC ¿ÿ^\WGuã¾b%šó]’7Rͨ-Ömñ…qE¼SÝþ-{ᨌqÑqª*µæX¬{úü8Ñö0Í_a"Òâ!4A¾jÁ÷æ=;GÊa)ºœí/rÙ˜‡–,×JÊ™yOæºñ î±Ù6Ã…˜„µŒïÙy~H<×\¬ñÍމ탔§ Áƒ()&]fÆèw¸,W¥Ï;~ât¦º(DÄz²Èé4Ø/‹¤i+Žý½Ùk°ÊÆV£Ûç´3rtr lݸɶ)%ðjíë YaÜ77‹­ã…AiUÈ+o’+Uà;i<µ¯NÅD#:ùh¸Vöœ¸mžgcj‰£àkÑóæGkHIȽ9gUû+¤¡5óòÅô •FJ_”Ý{óŽn|Bi§ô#‘Zaúâb"ùÿ~q)ÈÚ N]…ªàj¼_“ûÞäšØ‡’ü€$lÝ [줓‘•ûšì`XD2ùp|û¯Jæ>â¡Ÿ“×ë¢õå_­ðk –)¹ µE²‘P·bþàùf/å^lBÎç“š+¾:½§@6ÜùýBKãY2s ®w\!F> v¿YÓ¢Øèüþý›òÉöÃø xøÄr%•ä—ະÃÙ=Ó$!©ÑŽ0C½®Î‹½3íHÔÓY91VÂܘïŽ-'?2]v'•5?±}s´ N8úæüØãJVFP‹ÓÓó‡PÛƒñ6Š.ž­Æï†pfЕ̣äÃY·Ã'E+HMïqʨr°öÅ¥=*¹ ¥5pxÿþAŠG,¡È#œ{G¤¼ÆË< Ð鶘Ç4xï|Ö²À·“ªá2_|€†¥’|!³ $l Ö¼pÎ*|µô,û,š#:€Íê›Þ×gŸŸ9匵†vêÙ°Õ¢†º5î©GFÒæýû浄´*" 9)J¶Ì™2H¡ÛÅÒAN…¼k°ÿžÂÜ!ÎxHÀF·8ƒßaDÚ÷  ¶x¯7~§+ºŒ{§ R2S!i´mƒ”#žÜŠ£¸ò>:~$rK¬•è}°ûÂC@òžH5SgeØ`úä©?¹ä›Þoªü„v盥D:‰îôþÆgåñõE>#ª×\#Rß³“ÍÉràÖ™x|éS‚D”óGã§(ÃÌΞJÎ…Ÿ?¯wç?ÿkð¯ý  ï‰GuÞ{±-6-; òÀ¶r¿;›zF†Àr¦|ÆÛK ïÌîh‹BÕžÆõrD "aRÆóŒ3içÁÎ ~¿£T•2:&¹*;E÷“Ø|´Ì¸?ù– {²DÝ÷ý¾¸Þ7)WŽÏiµ_7ÉÂcð«OÆ{"U)5#ká%Z±2™Âš %Ñx.ÄŒ¦Ñüï+ð[E9‹³×‹ïq“Tùz|E_ÆÛoÚœHk””‘Vê{ÎX3'£µB²Œ^Êf#{3ŠAÞ¤Ø9ã.°7³’ÿ¾¾h€}.®×›1&_T´L® Ù=±GG³£–¢åô™xÚXqß  6Í9´`þOÝ^sâ;³FAÒÀ·3E¸f§ÍF-'¶oîaXRXý³&:(¥PjÃV´“T•|| ¶Ò&bØVöpXܳÖÁÑŽ`¬©që²ÿ?¢ÞmW–#Ù²f~‹È\‹ÅÓýK H‚ 'ýJ®]šÜ{eFøÍL–,ÕS¡€Ú$“™îfsŽ­˜rÿ¤´ŸµŸ¢#Ö‘o •#+‚1̪0Þ8uÇÃíÆýÃóÏoÎÇɼ×gÛ `u£~43˜ƒ,'EÁšâ;SúÄŽ@άì5°Wgï€e6Q”J÷í‰Ô8Zæ$ãJ:;ylžåÉ]Œû}³~„þ<Уqì¸37Žxˆj"yŽ5lJè©h<›Xc µðýh4%ºÇþHà æÔ¸ãz´GM+’&k¿É;”Ë3½¿Y;³w³ÄµÊFb½3çè x00$ ¶bH8lálh•G«ìÛØ8©jøÝ©Z ?¿øyMžƒçWæ}ÿæ¾ü뿲جÙÑžH6é²ÑRq™üŒÍxÏZyâ©1ô³’Yw'ïÂ*¡_iœM9jå–‚Jshá}Ìó©3+{:ïµiÍã*á ë,bh4=©Å"> lwî߯˜zઠùŸÙ_”@æ nØ‚òÞI¨5shŠ§ìú´–Ù)Ãëabd„ã?A`Ïù~T}Þ\ï¢5:Þ;EF½(gçý3#~轇'½}îaÒ¢‹Ñ=žcâÔ¹±'\)våÔ­†<3\ö"¥B}rsí›ÊIm™~ÍpÌkd6ÒuRüA2Áog±â¨^2çy"%³ìF§b>ñd,‘,yÇ`?2å‘xäÆíƒËâm#Kè8s;GÚÔ3QGfÛ §OăèD”PZJT ÉÔÇÀý Iæ××U"7q4¶@§xB8PqR5DGjakêã“Ò«‘ºãÊ#ºùS¨å@T"6.Á ô1ñ+¢Ý³8–3ß%ÿ»Ê›¥ãgF%Š1”'š7e÷ð[01‹Q)Ÿëyât~ýõ›·OþóorÊ„åfô‰žå‰œ¥vØ™Úé1·³³ñüþ&§¢šûf®ˆJδó «0ŽJ›“”ôÓxrø“¯ÚPŒDÏ7rgZ“ÀˆÍßy-GlÌΊ%‡ó)ƒû£©LÖRÊqòÈ…å‰îÊ5×è<ŽJ¥’«s$Ç»s|‡a&'+2ÕåÔ`ȉ„Bzo|¯hà̹?`‹P‹Ó‰¦Wõ’»³åøÊÚ—-Æ1ËÀãmÛ ß!Dm§"Tú€.ãæ@‘?jL–зñ¶ [ M,Q7î2v|Ó¹>Ƥˆ¦bmµãS¢~Z7¬¢¤"g¥–„¦~ŽŒÁ Â>?ü`l¶®*Ôd{Ån;}V†×}óî£ÖP©IÁö;"®ÚH8Q~çÌ_׋ükãUp5Ú]i,·üüpv4–mÞÖ™:ñé$ÛolOŒsvl½É8KCÀ€•x1-sRÉä–Øc’S&çÄ‘•Y$<¶'f+BhI9jaÏÉ{_ì¿7³ðýÇ#Â2G¢”?"n›s,ã8ñÂôÂW{²Ê«ò[ˆl†Àóë¿P«ð¾~Qr#yC«FRvD׊!9Ú{þë‡û çÉ2ïûætðR˜}D ¼Oê)œG£ÛÀzèÍßQ9ýDþ•ìÛèc€C}žä£±æ®ˆ|Rxå3tèìw+ˆú§éVPߊÙ2Ÿ)eŠNÿјÚQëhö8y¶?¢8ô¾¸ß= Â"̵s•Öž”âÜw |[M ÙÑ,¨(Œè8”:¸_¯”!hFku4 *B†tÇ÷æ “7øD½À¾ñM«¢ÁGI‘P`|H?gkLÛ.æ(”£qí޶ꔒ(^½å ¶02Ž"ìAœ¤TšH4}p­²e¾¾¼öäî?´Z‘¯Ì¸;g©´£PåÁSâèùš0oíønÌUqgŒEÒÌù•z£V¨úäLÊ+Ý”½‘ûæ– ^0;Q_ØÜÜ3®&ò$Õϼ ÷0Š;g+,sú¯›d8#KP"XJf¶q°ÓƒŸ×â²7vÅ@YZ#o§m·-ÐjuŠ9ÎM¿‚k°w |÷eó ñËo‘ƒ—8ËÌuÅV«Â½$*µÄÌ ï¸bÞОSàþËؾáX¨ ÙM"ÓÁZξã´êŸÙ‰l yág– IDAT缓‰ÉJ²’ãábÎ$VŒ*‰n7÷^òd¡Œ÷`ýµÈσ­ûãYt0ÃXI/6§œ<Ë´?<¬@®×…Žûæý¾Y+0ww’;s_•gv$é‡\õ&‹fœEÿ¬ú´!jåü¸áBvÙ{ç8ç×óŸW*GXpÄYŸ·DÕˆ7,ëIEƒÞo´6rJŒëÂÝIùKä ËUH)ÇÐO:k¾YkS[@NÊ-Ê7ý¦ 9tÔ\ï¥4Ji‘PóºÏÂð~½PýŽ×Bª}m û/4úùÄtÓ íÖõää¤ÿøƒñÞì žŽ#Ê'÷=só(%(É9øY NÞ£sÙÆUíS—îË8$¢ÍûŽDb’ ×44Ev¿:ø,9©5l/þþý›×{>=¦¡ PÛY-Uð͸o¬lJYøþÆí‰Ë`Ë ¦ì#‹çWâÈ ä —;í½iTºNî$Œ9ßØy æÌýÃTð)Ä82ŽÇ磡sñÚ7· ì5#^»áv˜¹Ã-ÎwI´Ga\ÿ°ÍU¥”ƒ\«æÈ;y5jËc þºF=[àþë9Š¢MRN¬þÆýͽ§Ssåüó‹¼ý}“µ¢’)êì´H ¾Ÿ?ï›õ¾iþWdøgCvæ÷mH”’6ÁqNóÈ—`x.X†ûõ›••³Èø´ú˜XøYÑRÙ¿¯þ¦·A–'|=¢¡Ø2«î¤’È¥Sƒ‰˜…p5— 2¨zpóºy÷‹ çyäŽ çÇ0“S¤ƒD‚ãþó¹æµñ}Ó'­ æ1+<Á¸WDˆ£jGÅU„Ùÿq,s®{r´ƒ¯?+ýõæê†Ò€ERbí“6í0lgÌj íÆfÎŽ¼£ ú¹ËÛvrIà•Þ{Ê v#jô»3®õ¹'*Ç©¨>ØóÍX“£Å)¹²Îsq–Êò…Õ8n¾ï™…{Â[Œá“Ö2úOƒí¾‘’IéD0LR–-ö¿‘³-tdl,æºáùd‹2»P=1ˆ A­€+~Mâh’½ã×âŠÎ {_ÀÅè…rÚWeõLjÎdÆ(ˆ=ñ”ùk\1h"¡,òñ…uaÍ„%ú¡Éœ@a^o®eÉ$ßeAÊø6Läiw§«S½À®Œ#±ÓÄocMØ®\¯ l“’|ÔÛÎ-wä(–¢o£ähî>™=~ü‘ôˤ\@öˆ€X*ߘ\T”úüŠÈîìÁŽ4¥‰Í{û½HŒ>1ÊòE>¶óþu3·Pî+ 83mÆ2¾j¢¥?(ÕQPš~O¬².γђ ©¢)®Uº÷@˜Ûfxç½~PÏ´öï76:Õ´§ò~¼µŠ³ò“çQ)Ré-q ‰:×ÞHR4yp:[ Ã׿¾¨WgŒŽBW€qÏ08倳ˆ(éüßþ§ÿ¦ž_…ÐnäŸÌ³©hüàÇä8ί³wÌnt)yÇN~Ză³9%æZÌ·Eìq÷î Û°WeÜóQlhÚtëtƒl!˜(-1ÆàzwÄA=‘sðüöžôœM1uFŽr«0†¡¹ðø.±—“”[ +%H²¯“zÜÒöúNx1Äy b“½¬™‘”ýɵ˺£"1,]#bÇI”r>˜I¢H“aïèÌ÷aÌ1ch—?þQÚBÎBÊ ‘ŠÙìŽÈ‰yúô(â õózGäWf‰ÄA©|Â=%D!1WwçþùaÞÐÚ#’y¾8²bæ!ÝXaÖmµ¢íd 2µæx9ìÍΟ?ßã$ÇY`{À;"×=BúaNRÃ=HH9'TŸäCq˘}Ðâsc»¢I°}Ç=xm®y±%¶Ÿ#% ÏöEÉÌQD¶ÅÃp9ŸïÌâîl³¦9fNŸ›ñŠŽÄq4LÃÙDþò±f«¿i9S¤£k¢úü\þ„}ωédöŽ¯Ìyl$ «|áÅð"´R"äÆL3>Ï&¤*Ì;>+Û°?æ§q‡Æ­ ÇèWGUb)üù=ï½Iî‚Ö„ì¾¹Ö›l'kD-ôyT4'Öí1 Û %Eƒ/%ܾC–b}öÏ`ŠRñÿç̨‡þúÚlxI¤{Ѳ«±íýÉ {Ä„‹ÓŽ'šS¼©}Öh-©¡çyRĉ×ØKHÅúÛŽ³ ©âþ›Þ xˆë“å¡;›²"mH?˜÷ §ÆYNJÜs•3…‚ÏH†D‚íØîˆÂ{Zl’1]È÷B FŠ«…¬O#ßT”>.Ä/ôÌ|×'ZstÌ]˜{#÷À›aÉH*»f6Û‘Ô¬íÀm3FüoÇoîþÚ¸DÅwèb­‰ngFZÂv¥ßot7žß·‹>ÕLk‰ýAIÛ§ …ñW³Sj ªÓ{²Ë&Eq•‚ÙPŽŠ5c¿_Ìîä)Î&íŠõŒÌDÕUÁ¼6d#—ÖÏ]~Ïô‰UÌ@uEÛ>1oW\+ª‹5}²:{3Rd9ßåÄþã`î¦Å²„3Øä܈JÉÀfÎWS-¬å¬õÂz‰hz¿açñ =Ùa΋Œ_÷ îIgãÏöÅ)ʯŸ+¼LÖRyÛ†¡ŽvbZ¹WdgÌ*¿ço‹>.…R>pßØNlYø´ÇINJYc0ûàõë/ÎçI;ÖìÌ©äÛ ’àk‡ï!e2d² QªHú1Íj†”YóÂý±O47“[cî(ÚÌ’Ød¸`ÛîPפ3…î{î‰Î›¦¹TõÌØؼ>íÒ²#)ŽJÕ•ãû¤na_°ZÌAõTYXJüü„ëôAšéߊ*· sÓJâE°à“”ØZ6~W(±%“–bí+ÔV×CƒâÊëÿúæ"ý«2ó„ð$TPXrSf…¹ö{"ÓY"¡t=Üñ¢dÍTý„€Ž%%Ž"´¯†¹È%”ÜÒœÛfÔQw¢ƒvv¦&æÌN¢#Áµßi>5üJÐ`VÇìäÙN’ [ ÒaA²U¶¥”31¯ü•Z0ö0T‚‘¸æâІ«b‡QÞ7?×ÍŸ[h%ñ×{b{‘ƒ´cÊQø~üÉz¿÷þD–ž””N*Jù§‡_0kÁƸQýÍM ìТ—„æ„ma÷ÁL ‡ò˜›”#ñ(W95僥F±NцŽ…δ“ãÐX!s¯9'Û&%g²(¿hÙB®5öÌ)Åᆲ¢!YŽ*ûb­I*G|U©’ÿ.kƒ±75%T”ÑU3_çK›ë5ƒAU!åpÎ"˜*Å*+ÏZÈÚx_oFš”ìb˜âÄ‘g Ä¡ä„Ú枃i“"Ê.™¾7-gò½||Ÿ$Ž ø®Å97µ®>A•ÚcÜ1$ÙJwÁ½ Ó™ˆ¬\K|÷l0ÏtwnhulnléIÿÎhîqEZr ý¾³œxkX”©ô×d‹Á4X›¡ß…ìŸáêõ7×’xr;Ü÷b­Ø¶äRH9ˆþš3-)Ëœc/RJÜ?žoÚñÍ7¯wÔ^k#ðرеe\¬vq•Ju RñÔ™ÐV#ùæ‹=;X„töVÒÀvÅQü ]µE’Q1NràÖ—FýTœ¼2ÉA=SÜa†èx‚HÁÍÚj‘ÁÇ)mJkHj¸+Ç#Ýö‰¬³<˜{6€Áìʸcð¦fAžÊ ß›b šSPù4í¼¢å£zOŽž áz½Y¾©åQrjŒ¥ä¦=¶d‰ù^üØ ´Ê‰~]¤ShÇ3Z“sá;6Lð\ØÒ£ž]þ…[ø·øb\+¼î›Ûnž?ûç…™@r ÑZüÆRv¼ KT Ðï›5ã”ø3V}¶¹Þƒ<6÷}´æŽx%•/òõsÅ„ÙTNr6Æ,ÛêµM Æ­, Ú­þLjU¼dî¹Ð™(OwDè«/CÉÔš0'Ž5Û¶Þ\ë°Üé¬pwV…{-6ÎÓ‰uããA+6næ\Œ”ø#C= ã‚~_G€GïÏÎ8­ÀäzÇÑ8å!­9X„‘Æ%þ27&‹Q Û40×%1ǤfYtw¼/´~~\óï#O¶EÊÏbíx£°S¸ö¤}¸E†;Õ ¥ZH÷ú ½c}6ïÜH*ä³á²H9QEIG¡é¤ÆËAæ «†û[¹ÊÀŠm'y„X\ŠSÞÎ~ÝŒÚbÃ#Z⚶Wä<£Zigðð7Ž'ðµÑb×\Å-”zx¸×¾I¶o ‰T„O•5 5 ðƶ7ÐÊ}B§M»¥Ÿ.G‡’Ÿ’Y}3ïÉÞ9‚šÑÜ°`¡¢=nÆgÕ¬RÁ¡¿œÚ„ò1ÝãæÝ—&ø•¸¯w|vZ°gÆç‚1Ù8÷uóòE™9VŒE‘£:_…16rÏйÆù³_Ï¢ì”0 #Õ±•jröºÙºØÊúœS`Ý–Rœ„J{â{}s9aŠ²Ú*¢p¿œ÷{2g`às>ÁKr(Ž"ÞqOQ¸/‹¯ã¤­@hyõ€7J‚C8jA¤’^7[ÀÙìkîû¬,ƒž.Ö½PÝ$6îôaî" <\yjJ­™ÝÃì²e°ç`x¢Å´]‹›SX²ð¾ÛÐt«àö…ÛMÙÀBðYZôÃ÷gè|`£Ü)Ÿ-9qw#O‰~¥`³q3×d ´VYT6P‡!§³› a ¥V<òLœ~p¶†dcÝÎæüóIYÎØ…@³•&—™K¸'ô0ÄOÜê“íBM™z6ŠGa+«*ïÞÙkÒžæÊZ?¬Ý#ÓoJ9åɺ7ÆùõDÏ“½÷»cö ¶Jn |²§4óõ/(¥ýÛ6ôþûÓiŠ‡ú—`Df_aÑÉJ>2¸aoÇS !,âA¡ÿ .þ…ù妮 gçÃãêàÍèwáHÙ“5&ÚN’1¨dX¥j¼ý׎Öæ'ÁêŒhÞ¡ÿµÍ1YH†¾÷§e*È4ò1Éš™ÿù}‚ÿ÷»c;ñ´ÂûõbìA:ϸjÌÅ*®´ÕƒlQª(þhLý\±öƉ“o.ÎùÈÔR!97þU0›0„\ÀŠ„1©Fx*>›ôá5Àëõ‹ÜZ¥=ß¼îNÊr„ Ø?<Gk\ËPÙØïPyS¶7tC®‹’}Þì8ÎpùÝæ´T©gáº;šb›ræ(pÝ‹yÇÄ»ï„,E‹ÒêŽ#øZáèPROw/Ü?¿QŒZ •Áœ‹½~³VfÍ秢däüRÈO›/ªºËk)%P4Û^̾£Œ’z¼\éIP„‡ÑØ+€­ðúë— ÿñŸÒ{1Ó"· Ì,¨ Óbš»Z†+±®A>”{wò{ ¹µwKdÅ=Þfì°ÏœÉ’¢Ô$‹wÿ…wC›r´Èñ5Ó÷ [äAÐI¥¡93üÆ\[ïÀª[&ÕŠàä\ÿÿ!âp|wÜBCUZŽ{äÌ>y­¨§6…±2/ëQ.É%ÈÑ×åØMß %y¤éÞFÉ€Tl D6î•=‰öù÷Õ9Žh\Î.œGœRÝ Z÷ÏE²Å¿ÎŠ7Á†£»¡Ÿ‘L8j¬ÂÞôëbo£¶ÊñLØó›kõÆÝ]ñ9ѳ’4Ñ_l’s#çÄRȵ¡µÁœ,Ÿ“„ñL µ‘Ô°wDzò. “ìðJµ8‡-æˆÓ\?”£ñUO.YìmlU^×›­Â³JRîkÓ·G›Ö¡T£´9n´8)4+Ëqcìɼ ›Ðž™âymÜ3n…¹7{9«’ vRœ„[Üsü² 9:öf”ª,.°„v™4uJ•»ì÷~³ 4“ÙbŽE{TT?‘t‚o^¯+~ýñÀ4³e“SaŒ7Ö•F(¹­DQgnš(¨P³²© ƒ~óùÑØ_'EeǾÝýêÌ9CˆX‘“çñ ¸~ÞÌ6dLh§ÒΨ"‹œÔäˆOö§ÒüMdäAâh*JIŽ\KÎvÇ~ÞL”ô¨ä´¹]ìš©EIÞë⾃W°ÝxÛ¦wãõ+iYa•ƒ>ƒŸ`˹y³ö¢¬BåhÂk¿Ù ŠfF®qѬ´âç™5+ÿ½¿£rÌ ÏÎÐÚHô5™sË­f¶Çgç¢X|ã¾ÙYøn0<Í ŸF'1˜hë¤_ÎÜ¿¸§³f”Å_¥SlF²S{Ý¸Ê jtŸ£â,›™œµ>Vâoý7oô‰Ë û ‹[”_÷/rþfûbÕæø†ëIm¸ÿ¹¤\¯ÎúµÉ¹RÛ“gQ\àÕo®Ñ)çI«Aʪ°7ïÑ9ëâ«5~lò^w03ºà䈦Kæm7ki¸&R؉‘1é#f#­ìå±þôˆ@Ü.ÔEp.¿ ¯¿oÞW'¥¸¦V 0jŸBï'ÐŽ¿ ÝŒÕ'ÇYýøòfÈ ÜI%†­k¿Én±|]JúŸÿÿõ¿ÝÝÈ9ŽykL^¿÷îxê¶9}GÊÜÙ’É~">~áÃÉš"L÷I„irLódËÉ9²ö3‚lLWön”šØEy}†q Eç tñq f`¤´nÜsZ$újÃ$áþÆw&žÄZ±÷/Œ¶ZÇQÈ)}ñV—c"p ”„™0ædy¿=Ó–™÷b\ÍåžR8rf¼oº Z•ƒ„”Šñ7-Ö‘¦%ô %"*þãàqî÷§`" <‚W‘Öpd‡û°¸ÆÕDœiÿ`ŸAÍæ²–r{bîáÏ*vÝÊëÃãÀdâjÔ| ~–q½Ö'sÈ'±™°5÷»‘U"‰w÷ ÔåÈ”úÀ<±}±æ&?ãj³ÄÈ­‘É!ýœ Ma~>OAŠgþ=-)‘V$ï°ç Cl"PcŠ Ë<æ8Ì„9ÜP#€"6LÞ¯I/Ú±©Ç‡ÓOæìÌᨃ«pPˆ{ >¦‹±’ÿàÓ¨“>_ØŽ+Ñ= Ûó@—{RÏ#æ SWEvœj§ä/jüÊY}³—±ÖÍïß0’ZkD¬ Ì÷=©å ñDæÂÞwé:aÚµ:«hx;Wþ$±ò™mù«ffæ¸Oú-¤_8K[y-掗°p”~xoµì à ¦äÏ„7NÊ lrYˆÈZÜ÷çÄXXÔóŒ'Uºñ5×µ1'÷û P¨VJSDã~a+Î…¶ä,˜Ç—„{(J ¹¨~|ék(—u¸Ãh¶¹ÇEJÑêÃ&Fü(’R>àa”S¸vç%7þÈT‰·½d¡Ql!ž!œµ0–³òŠ[lMÑUƒ$c(Cz؈MI©QŠ0GBš„Šì=©ídf1’äCAŒ}Ø$·JBá½¹öo¬ðÑ'œdn—ÐQÅxF GÓ+î…ù¾yÍ¿âc ÌX2èý¦ÕB;¿Â£`‘k—S±û¦¿:)ÅÉjæzð,ÿ'-< 5U|vT$#á›'kØh¸¡µ‚«Dj‡„¤NàWœïV’â*¤NjGü Ü}pÙÃ>àAJ‰ãˆêî=&¥d2O|ÄK,ôž÷…ÖÂÜA8jeŒ/ /…"92ë5¹ý¦‰ã¨¬™pJlkv\?r†”V˜®‰”ÂO€{k~$Æ5¢TÇæ(À=™mà=Ü”f×mCÕøþBÁËÆ=Aߨ(—O6‰,B¢²Ü"­©°Ö@-ÁèXnè ’Š0€ï“åû6~~Þ¤¤´&¯!d 2'·/<Ï¢yÓZ) k'ŒŠS‘xè{lju’@ª•RžÌ;DnqÖ’iA¥šã{ñó«3Ö„m<¿+åHàJKýr–ÝT 9UL2Ãß½v¼[K)äfÛÁöÁ4aÏN/N jLzÝQ 6þÄH)“ŽÄ‘£<´†“ð¯\ª¶3$užÏªËœrižl¼÷æþé´³PJ¢•xô7x:ïãd Zc•3fLª=® ³ƒÖ’œyMf¿‘ã$ I¿ÔÆÑRØE˜?;lÀâÈíÀ@‰&)ê¶g*ŒG毿Û:Ï–pë³vË…ÏnPÛ$GŒ§}™ê }Ñ÷5åQv„Ó¡læ4dLŽg‰AÞVúˆ$Íÿú¦eåÞ1¡ßsGmÛ×ïõ;qž‚‰ ’ªÒßý½pQΣюD9 {~PtñÞ‘ØKU¨Tv›xÆ´BB{sŠ¡æ‘P´sÂÚ‹¥ƒB娎´ÄJŠ +iŠ>„Ma}fÈÁ|&Pèsaý⑜Ĉpé:qúõæz ¢‰VÛç÷WPÖrÞ»S5qŠ²‹±à3ôíø bÂI-‰T)O8QR#µDªÎýk #Ðô£g%÷»ÇÔT³ýI‘H%ûƒR'‰ µÅ>þœb¸ÌP{Y[ã ËsÆ>VfÇì;ÍzA›Íš™)Q> 6››»lè“5>î¹3ŽNlÎôDÎ '¼…3ÅtZ}ãÉb@ó1 ‹H »%¦ù,C·SK½EàñüF‹S·SüSÍõ~3¶D•v{ZK´I³‹.•"dG3q/!·ÂÚÂz½`9}m¤lªdp ¬xrp‘H^ö‰má~_ÔÚÈ­ás0'l·¸§h6^÷¢qEUàÎq›‹MŽûÂøEñ†ŸpíIÑXˆ]Wçñx°rFôŽ!Tˬ>ɹp<ŸÑñ¸&Ȥž'{×ð ª{§$håàï·!ûFI¬¼â­˜+ªÛa;Z²éiâ‡#ݘc ù³ú•1””…”aO£ß7*…}O4…„Ó%NyíH˜EÇ$r‘æ4sj­Ôò…ssý-HD©¢lUÜu;âñ#rŒT2©U*ÂX›_×EîPNÁÓIÙ†,g4AEP+'I&i.Èãáœ$†" ¹-Ò¶ÞÑOÂõQƒ`<ø †`¥0Gä0JÉ$-¼³ÑèáKøÆå‚j£Tah'o'É ²Á'¶¿· "ØÜü|0op%´ýŒŒ )5j½X+q´ÄqfJ+Ìl²Cªü—£°wøÔ ýÆŽ+¾q¥lÂh›$ïNj™\䑘×o®÷ –ƒâß=`ƒÚŒÙïèü縟¿/§%ç8ž”ãÄ·á?7TÇ4îù&ʽ µÆQ&Ö K.FuØh©|µ„{Ã%‘ëÅž-J-w'ãë_öÉTç’‘éB<Ðà¢áy÷î¸K4âŠÂ,žI‰µœDçQh.Q*PjE³2ÒÂoãÇnÈÄO$ðâêøŽP‰£äG‰õ–îqµI¼ù IDATÈ6£âøª£ElU%¡ga\7~]¸6–næ¾™¶'&áG¦«1º“[Š$]uþúýâëíÄ7ø&•BÊaúA&¡K7 ÞªÈ{+– 㺱õ9bfáõŠ“X)‘r+팴ýȳcN°‘Øɹí;6ßß'¯#„/I<3/¡œ‚æƒÖ„1œ½¯×M-áuXk ÌеÍÞ-#RÈgÌŠÆý7ø¢ùÔñúšôËøz~QÎÂãžtSŽ|RæúÌ@žÇ6g^¶CöD–Qþ¨ˆÃɸJ4½nî¿®‚>jÌmDS)ËÙ>qa°ûæëh±îãæ½&>”"‰|܈ª‡» œa¡ž×YÈT0'}Ä×Ï›µ•³UÒéؽ kdU!5Áíàû;ŽµUŽ8ámŽ^‹’?ɾ½HEé–ÙÇæäNµÈß›|`¡Éy¿~coçñõ$•¬Jf"»3©HŽ#®ùG¸øqØK®±eð@.é4j^áÌ›¬Âïëï·ÔO|N¦/ŠÞTy û A23kÜl…ò€zœœšðZb¸²7ˆ‚-ý\!>¦ ¡¤Y™‡å€ÚO†¼(GA¦0Þ“R=??&söµ#û …âçìQªñ3þ:'måtc³ÿúó+À&s’Uq š‘E¹zü™ÇTäM%‹ð}, Ý×î7[C®¢ËÈ%ÑÑ/†_èíÜWï˜&¾kF´³M"³0gÌ â×Îœa¢Q-QyMŸÿ„¦z­Æ&c%6+}mjÙ³’ì íOu8¤ñ–5ø×£±¶ñª“ä· ¯ß“Ô\*hý{Œ”ß'Çqq]óc ê³{¡N«Êñ¨¤ZxÖÌûu³æ —EiDZ\³<ÖÇÉ/Öpvê n=Ò|ïM{8õØäR9‹0ÜY*ì¾Ð œQW—-˜mTð*+6š+ÈÑ­¢ çéWœÞ±%¨Fæ0æèþ áÍ´sx!‡ŠzÎ^ÍÙz·Îí˜ô Dôz[<ð–¦ÂHþ/%±•3;N\=BÖ4EL…]£cœ¦{Ú÷,PS¡ lY¹îWVTªd ÷Š1EE™Óc©9FÊÃ?è .{!a··<Ýü7QS_]ëæÔår¹+ýÖÜïšk9Î_¸ónIu[µÙBƒß_ç4L¢ÙC÷šóEf†àbëòìH ‘8ažM…Kˆ$l:K—WÅ…RÐàÀ•ÕU¿ß ¾1RuÁ×ÿ3}3ðá6½é©¡ÓÆš®®û]þKl×Zu@`sø$\o¨Rqåh »HÒ–¬-ÝÅIµD.f&¨2mzÛÑ0r ìªH­ØôkRïÛÍWw1f„Aˆ÷Êq:¢Æœxø'lä=aj^µ7Ì…ëjHZ¤Xç¤ÏÁ–2)Fz«w@oö¬ zm~µ€t¡[çxêdK¤íBL‰:+ bÜ}ÍF'Úâ•í®¨G'1D6 äíJ(5”qÜ0QVp—›eS'ŸÞZ©‹Û7O½k ÉŠ]6t,Vë<eþ÷:ꉪ áB¯щjatíB‚"­ù.8?\··Ìs :¹™ !²çÄ8*·ÖXÃׇ¥ æ³Dr÷°·y~;xxYѸQÏgV¬ˆ¼ ” !+« s~Xú©,Õ€Ù|ÂÚÕëšæ`-!? (ƼƒN ¤Ìh§6¶Xý`Y'ÄD”A3ñíÍš'„æ W!怅ˆÅ„Γöäxõ˜¢÷~jƒ.Ö<8{ ê^h¹'eT e_¬YXæ8QÝ@|ý´1—ÒZc¿\ÑÜṓV$lÞV«Õõ}Áxâ„zrÌÉc“È«üÀùÔy];KŒs‡,¶˜Iɘâ/¯Ý‘í¬hN"j°æ"%÷ŒáP‰ÁFvvIÚÉ¥10GuŽ"Þ\å®ÏxC¬O"vòî/á¼kzŠ¬wfo˜*º'Ò¦ÓNT/ˆ$zõ×Fqô´FÚ­ÓÚ)o¤œY2€E?'¶:×-ª@¯ ëh ¢+Äãìœm0¯»—<ª²¢0V yfŠ¼=°Ç¢þaNqIâÞeÐ&qBLÚ#‚0ڇ´2hu0ú"¦LÞ2ÌûGg©ž‹@݈Òû¢ÍºHEH9R›÷;° ®A'² )°0ÍĘÃ|² Ilƒºé‡¨ããC‚ãÖ\}·d!vojƒ6*–$1`j$FˆÒYópÄûéÔìMygO”8îm0%ïwjÓ4ÆPÄìoè>fÞ{/+ùn~9 W$!êµ^K•mscÍæo‚o±*Ì‘œ~,B¿ubŠîœ‚Ò[G¶í] ^‹.úŠ@'h&ÄÌ\ëŠÄxO’ºÏ¤ZãùÖ™-²åàÂåœè1‰1rÊdŽJ ß5»wjq1—Á¨‹³u?ÌVäƒãm'¯ŽÔˆU7§mÑA1}ì©p¹> Ñ£ä*÷"5ü5˜Ä‡”¸ÆGžÛ`c2Ú@sòõ}Í1'v6P!–@²ÀS}Q&~ÏÍ÷x§yVz¬ÎÏ)à+ˆ\6Bgå\Õ‹´cº¨j´%ä`„Síi“21àé:ÌEïA`.úÙ[`LÅŽêñ^ññ|>Y¨F•”ÝŸ0•×+9gÞ¾ùÅScLÄû5pá‚!Üæ‚[aÅIØ‹ÛwÕi?³vzït­D Ž±+‘ Jízç4ø]y,c'¶Ä;Ä8Ç"ÍŽØ@@ð ˆJy¼ó);}øeS(↾:Ç[¯£c»vò~á8«_k’Ÿ¬ANƒœ ¯_Ô†#×K Fáx2ƨŒÐ%$È Ì9y=;—pøN!jfŒ‰®@~ÜQF{òƒ¸ DZ $.ɨG#.u¹¿x»DfOèèØZ´9‘>‘h¬^™Ëx¸ì à ¾æ'Ë9É”ú\‘°x|ñÀšÆQ]éW äxå¹VΧ'4 ö±ñêºóàímÞèå& "±ø>¼×ÊÔÌÃÃ…sní›D|T}Â,2N@’óÙ"èZ,y¢'"ò9Ÿ›'ºÔH1’uãœø& :—®ä€ÉFÓ…Åy‡7@Þ2[SB2·¿®ÄW./3ktz;™ÝCGË&‚RØün¼ ]ÙvxòbÓÑ*˜·à®µ¨µ2‡3îú0.°h gЧÌè‘9oHO̶yo@2zˆNÑI,Ó"ë8‘ ×è lNJ¨bc o±‰p¿"™3¶ÍïÓ¢ŒùŒ41¦²Ž7äXt@9‡?h‹±–/„<¸¤D3¯©JiÃô^'/˜È)aº21Š÷OÌÁ–ýÐHØËF_ëžÑŸ #2‡GÉ‹ éâT¬<|Ýé²4Ù \_l¨Nêí`Ùò-”1&Ê%Ó«âcâ%¹€TcÙ ÇBƒÚ:bwžaÌ1Ø¢WÅÿä_ýügkwÚ¤Á9*ŠËs;ˆ¯}d1%Î~ð¼ÜOœ—ù •q{á ,…[»ÝñÔ ÍŠ^:µu.ûŸxï‘f‘³ >ô#ÌÚ‘9G£÷44{û-'KÙ5Œýf9G#E!_„-edebÊ\ 1o Y¾bØå+8 «ù»:¨¯A/›çõ{÷ “©Ìsѵ“V‚ÖOt*" ™Ã=õfÞ/Ñ'•#f;rÇ”«n„ஶ1:!‡_bîcH‘´9ÙÆÏäŽLF˜<·ê!›>Ý×9\.9‘r&©2æâ©žD1¶=r´Ù0 ÔÜÖ}ÙwRXÌPHå´+ÓžÑ4ð6àB‹æ¾ŽéW5ðÚ²­ÒecNeXg•r·tl9&{ÍÎE]] ò¤O,D•=×sÌSq1Ƥ²¼»âú\جa4É̅ž¨kðöí³†¤vR¾zyÌSå¼uVž$‹Žp—EÓH¿‡Œta&ç#è\ÜÎÃk·rôÀÝ£Û+£ê‚Ú&1GTœBcDɤä€Ü#ºÀÆ‚¹È/.˜ÀSkhŠ„¨h»U\½˜»»=2®â«è˜ þŒ6;˜.û J)Ôê›™µ„9±d¶k$†²ÈÛ…x:%·ø?ÓV.Šì›(‚Q’ð¦7âÄ°xº$qd™ÒoÏŒY±í®¾ÏûM.ùUAƒ; Ù­žɘ¼·B“ç8©·§$Rð—Ì~Òuƒ ÁšÛÁèFë) C¸­Áíè¤0±Þ¹õÆì 6#DÈ!1Cà<+˽OöíJŠ‰¡õ7¨î°¿‹ÅäÚ*œ·zGo%Æ #4Ä‚_çÂI;o ´\´}Ì™¹ŒC ”ˆLÚ9}3“.ÌiÜžn…¤ùñÏý­;3,±ò`¨³8oµ£â&¶¼ï¼x¸dpko¹ÈFÔ žD„KNÌј}ÒÏÆI#ÇD3cž :³~z÷øNò&YKB#`lº±¢r¨!UiCH«!ºƒ0jãý§±AޤšŠdEg†ØœÒ‹3ØC\Äé§Í—Ììꊿ c@o cÐWcñ/ñ¬Ä ^*âyhkôÙ‰’î«>ÿßgŸ¤mÑæµ fèš^ã5…}BÙ½ŒF‘dŠq 'ÅÆ,§·h÷FÝî<ûFÙ ×-ùjjàü¹á`ÁÀ‚QTÝÐÓ/´ªŒÃõ Ò:]˜d„J‰^nŒÕŸ™DWtÑpBpë,&ÿzjŒÙf\^>@JŒ:xÿƒƒo¼ÿW<Ÿðyâ#ï¾ä£Ÿø±Oµ3¬ã}Þ>-h‹ðÎ{¼¼Þcá}1ðNƒÐ'ã0F´yB[ätE‚¶»uñèt=Ù% ²1ÛÉ.†Ž)Gò–X£A0RIþŒÎ@φ´‰nX¾0-"³AóC_7¡ÓègE,{¿Â‰+ê³svóšûÓ¡‚m'j™Äb¿nlæ%¯ÏOOä”Øò žŸoŒó ^½À²O7‡aééî'iðëb,‹&cŽóÆõra‹‰:'Ú;%4lNöóëT)Ì‘8nߤž½8…ÑqW¥et,Þ¾=C›NX6c®Ó5§•imRß<÷‡Ì~gù}˜Ö{=•§á‚(‘¡ Õk¦Ù ¦ lù‰Ù:—=’¶ÄZ'ËyßQÝcpÓAsq.(Åûch\.ƒe…y1†-â!yÈÂÇûÌì•Ñ*ª³èëJUÀfnÿìVQØ¡œ)b2IøWµŽÉl‹ósuJqξ!Œ³Ñ×d%d<“§§g"™õy0²±’rJÊ\"ñ¹²æ¢oJ £OˆQ£«NÖÙÉ%Ðò…KØ õŽ¨Zü-•Hcðþ‚(e§÷áëÖ8Ј+pÔéŠɹùØRòߨv¶ô@Þõ¸Ç@“‚°‡È³b‹mfÇBãÅš£M"“A¢uá¬7RyÁ_¾>ùÍ_ý]þøwÿ€›¾m{Ë«O<òé¿ûã|ËG_ñüÕ¯ñg_ýsÞ~óüÕ7Œ0:—¿àúø‚òò;øîïþ8ßúíï¸mù퉵Ãû ®¬:Ùc`.?æëL‰~½³Ž¶å|?MˆTº žo•5¹l\·Â*‘zTJƒ #@‰1_y>m,új\®\ÊÎÛþc UàÄwâGGŠ8b¶9Bls²Ñè…½<°]"k4žÛÉ2o'V:&€ø5L£;7[……†‹O­Ò3&Î(Uþ"!œŒ9àœŒ¨ 7lAL=_½%™A)‰e“[;Y2ÙöŒæÉÓÓÀd#ÆÎŒƒ”Þ=%xº…^£bã÷eGÝ¡MÎGs@¸ä³(š ©qbv€edßÐ2X:½"™{‚IÝ›­sR–A¿1:Õ¾»Û.ˆzv½wbtƒQï“<ƒŽx0¦™¡cz ÑôR‡ÞÃÒ©u`RH\¶„d!ä Á ÎÁ1Ÿ)Ú=mw‚™¸E¶æ1TŒó¹q­øˆ=2N 2|Œ=›ø‹Üýà2—°Ð‘j>Òæ„Äæ‘Zsø u­å5Þw¢ˆúï2§Ó]ðk…7Ú8I—‚öH­S%¤ ®ØxBV§Á.úf0ú\«dæªÜêk¦f.–‰&½)f……m'©ð§_ø¿öÿþ_ÿý‹•ÏPÆ3ŸÿúïñÆõ·ÿ>þî+ôõkþès/.¼÷ùëçÌG¿øEòeçË|žùûßË?üoÿï}ò‚^Ý9X’‘ö #TºLæQéo„¹GÞ€g"î˜4cىآl™1GwãËeaÑ"–„‡-£+RéÄKaŒÆÙ&ÖNfê¹pÊrš± –• ¼¥XvÖÚãÀ¬B÷=‚WÓ?Õî°Qrš ‡O9£wî Y´±m‚¦Áµ<ðö~õØrFÓĦ¡1#êtçã0Çé¥È`M‘5s Z]¨.BRÜݦnËŸ•*H„¼ZØCfÛo†HFÕ|ÒD¹W’’ÇxâìBÈ‹º"EØc ']²?ø# aùbˆAVå²_©ˆ$–U‘ Ù¡™€˜çÛ‹@Ž÷‘¾7Î{¦ÜSï¾óO0l8Ç ø*Ê$Ëù`bøÛñ=„AFXBÚ“HÖ“¡Ê¨ “™õâ¡P®»'® oï•A‰Ñ›~–Ùf`+“5ºUyUrZИ[†d4¤÷圈$’ ¦ YÎÜ'LfƒÞŒF%®EЋ; ÕwÏívî°[=aý@ötw«Ak ³yK[íŒÞ©Ë¸Ù_Q§’íNƒ“¦Î´Ë!YwDûbX‡¥”THA‘½ ‡ò…¯ýÿáßýù¹ßÀÆ ¾ó­”ç¿à’vÆÓÏýùûäW…—ŸþN.ŸàeùKôúqBÿSÉ«RùÒoÿ&¿t>óÓÿø‡ùöïz×?0½Su¸žœ3ÒB¿#àç]£È÷°ÙôiʤíJª'*žBÕ»71í’3ÇëÊÐÆ)Ñ+ëR"l™ãy!mÑîØù ‘hnóåt–Ÿ¦Âš”ï!´ä~ƒX"šãæÄc•ÅÊFÒìÝ R)®Â ÷̾ô„XbäÊìÆ9ýʦ€~¶´Ó,N–GHÙ7:õ<¨¦ÄKtî`÷–¹?Sº[¥—Ñš_EU¨£Ñ?¸Š!á è$ÇÝÉÍwQ°Öå¶a!c6Ha'Å JÏ‹` $Aí¡ÊUKtöFL‚6Çx[œ! òlHò»Ô“—])Z0&OOo ½_Ã×¾ÂXð0”´%'½¶ê¶ÉŒ;žjãfu%öxzÂL(åÊ–n¨ráçõó Ý Á„ÀªF'oJL,¨aCb–Hîl¡÷‘ )‚óø«fŠæI†M2Ìé 0­ŠJ ^3²¼™×îù”I‚mó­Š-¬¥»Ó8ŸOF7JQBq€Éê“ûþ’3½VrN~˜ˆJ"ä ñ69ÇɹŒ21%’úhèRâu'FeT£.!²±çPü‹¢¶Ø/ožðo~?ùÜñî{ïñ±ïýQ~êG¾‹¼æÏ~ïsüÎïßû’ðívÒ€×­óÕ§7°W8Nx:xx7Hüùþ.ÿqÏ<\ŒOæ#ô7ƒV'G\ä©\òŽ¾#ý$/hsÀ˜èåâS¥(ØÄŽƒÒQ½· mjGN!Ôyòö¹B(\òGÈ–Ýô²uúÈŒ*ÔÍ`Ëì@µêâg‰Œs2êºÒ…ëå©C:C…¼9˜ôØ/™ˆS©.!³lÐmCæM}M»UŠ“ÌȱÁÐ5LÒ Å_È~<»¸˜#ÚN×ä.™v6/:éþâ§$ÔêUs"‹R "BIÊÃÃΛ#2ƒ åxžÜ²@|D—ÑŒªÈ£znA܈ޙž7‚*mNnßì#ÃÈÓÖP"Ú([0BÊØ Ów ¡F”E± È èJ³†«Wº&ëð4”©Ê=ÌÙïãÞñÖ˜J9š0"ä:Úô¡cJyÛ‰yÒjeL§Ù*;¥÷Ès]ì1IžC:=ç¤ëÆž”·ç¢¶EŠ‹-_è]i­“ŠAHžŸjÂA' DÙЋ‹£½-¦(,8ÏNZþ»i2.w7W_•=îLSÕy£õ…ÝÃ,¢Aè«Òƒœ"(Ä»Ýæ$l ÕÀv,NêÓ /./ï_£Íèua½ÐºûÜ»OaU0iØÑE¿ßù½/ñ;¿ý»|¹í|ú?ûc/ø‰ÿ^>v=™?ùüáý%¿øï>ǯüûß Îßú=ŸæϾð—<ÿõä“ß÷ ô»xÿk¿ËÓ±hC¨Gà ¿ñ+äÇ—üã—?«‡Ís4æ\¤íÞƒ(F{¾yM=@ H¾Ð¦Pi\b&ÌAº· 9‡£·ç䨯ÙJ¡ØNmB07Pֻ̻dzesí/ØF,†pVÃt¡»’Wq>D2b”ŒeÊ’ŒF¿ïA¼äe¶Æ½z¹ãÊ0ŽÀX‰A'™Û“EF‚Ö½ÈwrbU«¸Á–."°íŸÕNˆžgX+Cå<;cPÈÅ‘yu³5,lO´ó‰ççNÉ»ÃC;Ð}“ƒgÍŒØdaèt1¦q ÌWxi )ÂbæâUÞXfÜZ%.9Äq¥”H_k^—Ä}ŸÍr{Œž,ìm8æZ %ƒ„Ë“c9v,Ø FQñ\Vr¡OwŽ¾î‚yÞ\"•³â M†ÆG„Áó7æKáÅ|ôj‹`†m mÍ)ÄGCTJ„x´’F—„H!®N]By( ‚Š!9rž#˜vãd»$tEÞ¼=HÛ†ÆÈ9` ¾!(Q)\y6G”‡‚ª»*? T„y6VôJ´"c-Fm(JÆfD}`ÓÌTã¹Ì;IDèÝã % ªÆy:"ì2ÅC{⯾üM~û?þ1oeƒ~ããø‘Ï>õpã±WÒ{…Oüл|êÓ?ÁÿÀGx"ßõƒ|õËJ·É·~æ“<ÆÆï}ñGøOÿöOø¿~ù_ólWŸà7ñy÷Õ•¿ÿ3?Ê–ñ”À&Ç7¿Ë¢˜L†t¦>ÄɹÌÉì'­ûä™_Þyÿ}°ÎÊyº8m)=²]v‡¼¶“|þ cæGÎJ»5æYHÛNçdœ„ËNN‘u4GÒÓU(ŘÓxþ{©AÊ 1sž'çqB`öI°’bI„èþœËÿ~ Žu"$°âÑò¼‘ï7îÉO̯H"/–χ[°Kñ¢ÜR„íR0à¼ôÖ 1PëÉ´Ž´…ÙAŒ™ࢄCH±’Ò$>ß1î¤\9;ÞêrIÈÖS#çEŒ„M=–è@`â–é­Bmt[¾ª ælþ±Þ@nηӀ([ÁV¡™’J@–µqˆõ IDATyOY¯U¢&¬nµæd×D0eùeÜ¿9»³é¬wÄ3‘XO†·§i„Õ "©S]Ö”@‘…œƒêöÙ6¸^¯ˆì÷.º#r ¨çÞÑÁèÉm”šQ›4ëÞ4]È :©ì0Zž´ÑÐîxî>ŒÛò𕃨¦'ÇT]¨YÂœ9šá÷x§ò.æØp6<@ØÒ=«ˆ;4"Ö£ºqDØ°1¶k¾Ã"æïî¸6þúË7þͯüïñ·xU*ßùÐù‰ŸúG|Ç»ïò0+­>s}3YÀß}Wù;ÿà»y“6>’|û§è)cl¼ûòã|ÿ'®\ö7üïÿç/ñþ7±)ÿ÷/þ>ßòÉOð}ßÿqV€”qÞ¼~‹™p½\HÛÆ°À¨>#/¯NMî÷~ÔX˜kÑ–ÂFÙ`Fáaƒ°àÙ\!°aw±+³V¥'Ö#f˜M¸l™g&ò|ÂycmRÜÚlDRœ2à ©Ïô4‘´AW”,sÔš8¾ tÒÑ0ü®‘Ñ&"IBhJ4cœ†‰xÍwô&(_×Oc±fƒÉøóäìS\¾¶03fö|¿Ã[»'{spŠAH ‘|ÉÜÞvæà$üô?û™ÏÆXÈ×ìÂбš‰æ¬dàrÉÝœ2[§V7Ш.î×nçIÙ#!Öò/©­‚ª×9›¾`+ˆ”=0×ày˜¢E–tF¿ï÷Ä%¬Ù!Û59³­v™~øô‰XõÊ®÷`ƒ¨’7Vp‚ÌîäayàGÍÑ\NNÚðt•#$scœ¨€i1æÌ¿¢˜UÑËTSa!¶ˆÚYípþíàíóûÌuï…çs弬µÐ €zcùö€·-Ax^7¯àZw' ê½!Gí³ç%Äjk%RÚÑ)ä(ÂïýÎòë¿ô+¼ÿUøzüÂ?ÿqþå?û¼ûjçAž(Á_?3GS¦²s¾ÿufë<2¸ÎF:n\ÇIÉ˧?Âg>õqêÆ|îÏ‘ð@¶·|ãoyõÞÇøè»ï˜Ì©˜uJ­dBL~…üàFÒDŠíœT»»Í872)ë‘Ž‰`M‘£úá¹í^[gÞw0ge.oœŽQI»²fup*AÅX-„={sôÍ¥†)Sâ"HFggÊd%ï‹ÃŒ}Ë„iµz–Z#*Qï L,ƽÕFDîÞy?56„̨ɳÝÓÈ\対§Œb‰¤`¤èõL› ‡ä”(×BLó6iÕÁ )rÉ÷ Žòø‘a.Â6±0Éq£\l‘EÒ@ºŠf¢LJH”05RòvÕ1ªÓyÖdÛ")e_ ™ã­íž9Ù(ûFлB¼Ü²™ŠR ”T2Ü}%ñp½ ng'$cË›¯Ag½7ãÄûËŸ@óç£/¯œ­²¬’wØ/W·‚­Åq RQ”Å9<¡)sºŠm°=d¨Òží^;£/DaØ0بBï“$BÙ#iÏî¶ìN–P˜³Qû¸ç326}áµÛÇÁë›ïä“4'¶¨lªý¥N!"!R[¥ÞNêít ºI²]PYÇáî¿™Óî»/#O OÿàE¥Õ{qÇ–¹Þ'ƒ…O©èB0ΛÃCØì=„k z«—³¦”îÐr›qòµìšƒðÏÿןÿìvˆ6l®9QÄUò”“{ÎÍk«FëÄœxxØœÛ>«7ÅLc|dÍI=›3ÍÄWM)ezÌÑ°ÕX}b¢Ì ³u>²ñ°g¦y‹*k4bPJráq$AËýÅlÎ;Û¶Œ-Wò÷ÇmÛÈÑG¢Å#¸,rX§+ÇÑ›UJ! ´ºhç áp.οï}P¶ìŽ©1&f ™ÈRχ!E¯jî§Òê«ß-Ò“9‹–Ë*Áÿ¬¡ã$%eß/lá¼3Í«‚L$?»Ÿ\!ß "î)9~%Hd­'G“¥ A:c6fØ`Ƈãꔲñg_ú2ÿúÿø-þðó°åÅGÆàç~ú¿ägþ»ïãÕ‹@ç™X&ìI Û#Ød­”k˜è¨„ý‘ s ´èlQùØ{/yñ±w¸l“¯ñk¤ <½ÔˆùÊõ!sÇî •lɃ;W9²Z#\¯JŽ¤˜HÛ"JoAU|D㎤ÿp{%÷¿¦D'2£÷ÜiѳßQoêqƒTˆ±Ðfe.eÄ@“³/Öý‰ÉéÆŽÊn­³–Ó•q[Ža Š5õŒCt\]NB=Gz‡ )9lÆYþÊT#Y.TÎ%͹«/æX<^ ÂÎXNÚ®µ³ÝÙ£uZo¬µÈûF,‰Ù†QJa»J)„IªXm~mÿþ·Ÿÿ,xxåÅã•¡Únx_ Ÿ·§µVö‡+9rÖm÷Ú¯åH¤e\JF’òæõ[fu0h;+ÇñÌ”…hvûéêLõÚbUèõ¤u/ ^»ñÆž9¼ÿ½Ž·Ï”ËÅñÝs40ïZÏ:Öâx~vÖÀRŽÛ£5˜êäî`ähOoŽÎ­VzëN•-ÊšUááá‘T G?Yý`ÖIkÃKqÚŒ Ÿž@iÇ&1(µãVÔÕYÓ™z˜'ÄÞ>ÌÞ±]°¹;Áu“eÄ “ATãåþˆ¦Àüþ8sM ‹²Æjkx_A¸@ëœó ?g”TxùøÈïÀ¯þêçùêç~‡O¼§üW{ÅÿÐ÷ðÃÿôÇùïx‡k}Ëe ‹¤‰>¢ÏÑîQÖ͇v ió©D…ÑNÂ2]/ß¹ð½ßóiÊãK¾òçï³Ö»üÕxàk_ù2ßþ^âÕ'Þe¬Å¬‹Y#c)!ßЩL§XQJrpj¸o„ª2zEÚ­ƒÂv}@%Òúáö×åž Y‹²-òÕÓ¥£ÜrÔYÕ' ÍQvW¶©câic0i½QD(Ù},£5zë÷lŦýMžSòÕ›–u©óÿÖÑèÝ3+[Ž^ÁÄóþÍñ^„§§OmøÙ~ÀQST™Þ°ËåR"D€äSOÔ„NN1u>æˆ°à›¤Ù;[ô\K'áŸþ¿üìš ›ÙEŠ’9æò"Œ;ûM€Ö†M/%…À–š}ÌŠl10§‘ñö e~Ó°HW§½ªÝÿ;là §Ywn;|œ&xjŒ@(®¦Ö‰5—!8Cîíó~t&™áœZK…Þ&ÇÛÆA$çH ˆ´i<z3D¼g0…ˆ­‰Fçíj‹Y':ÔGauË’W4Bpïz«“±nØ}?½_½áÖîM8+0šGr먴=sŽÑZg4a.¡ŸÝ‡&¾ ˜'«)%&íé-½ªï•Wc CQJRe©pƒÚŒ&Q–ã½5C”ùàiòÇô§|é¾HX_ã»>ù‰ÿú‡ùÑÿþÇøþïý0Ü¡È}H]£¡ÑGïµ!4æ;?`r¹{ M õFcûä+>õíßÊóóäOÿó/“¶÷ÿä7±Zyøä÷òâ¡x-™,:oé§!’Ÿ–“ß‹çdLBcJ¤âí°á(çRl-Ò}w¿×ÎÆ› èŒú Ë”e_^æ0}×/s9l¥í¹‘Š?ësLÆp7¨ˆ¡@ˆ;ÇíÆš'3,âߘ~„ ±ÅWõrμÁ½S` XçÍK_Tˆ ÎÞ {s.²wjPLˆÑúp#›ziŠšbëɵƒa„-’ÊÆnµ—~‚%Î)Ôq²¬~öþŸubd8ÏgdMRNþÜèÄ“t9³DÈ)°§Ä@H®å„Û2L•mß@•ãV]å}¸²åÈÛV¹FÄPÁ÷øCˆ¡°ºøúM½¼bŽˆ‰1l"ÓÅ¿[Ì9()’Ë1Ú4ú8ˆÉhÜyx›¢˜ÍëÌË–(A†Ä¶;Ã/%öíB¾DBPÂT¢eÆšŒ9¹–Ìãe'ŠŸècy¤s¿^<”2*­ý­Sk­áŠfôÚIR€+­9É”RÔsº;0%º‰h}(ñßý‘j“Æ “5ŒL¿k){Îœk!³‘‚¸n“z ¨QÊŽaèb[‘Û_ûÆ3ÿá×~‹/þÁç±7_à½W™ïøÌ·òƒÿÍðCßÿi¾m½f[ åÃ*8|›ýþL T]QÇÌ7=âT#DhÏ`æÈ0áW—ßòI¾ü•/ýá¯óðéïæó_ú_ùúà¡\yõÎ#ױ是mË^L›#sN¿âléÞôäÕØk.òæ‰Ó5s¹ú§óRÞ˜ËC>„ê@KœRQœøDÜÉÛF¸¿ðsLŸ̨g¥Áž‚3ï„fo/!pƒçç—ëN.cNf3Bo„j‹Õ1¹Ždœe9Ge¬J7#‹c`Åìº×ž±X} ¸¾•’ËF=Žã •Lˆ‹ÙîÏ3ƒ)ÂY==B – âÑèå'1d¶ýJø¹ÿåú,ÜM f÷Ê ›žk¿Ï­NÕdz&í\L[w{e¢ÿoËè·ÊqôZYk1¢²fôæé 06 ¢rkãh  K”Z…Öœ¬#†ͨk£°¥B·EÈ–6–¸ P×ì¢)Ûuwz3ÚÑX÷f•…òàè©Õ_Âs ÝHêYh8rèãþ%édwì™°êbZcÛ6Ê–9žOÚ¡“ º1æ@U¸¶NßÌåE)lÆ9ÊÀp¬{.æ= Dö-ó¢lÔo|•_ÿÿ~Ïý§_ãý¯3åïýà÷ñ“?ýƒü£ïÿ(ßv]ûp´54db¹€-BÚI6âhÖìw ·±æ›Ìzx¬9mhÌ$®1òæ)™Ï|æ;¹¼zÅ_ÿÅ[¾ò•×üñ|ž?ÿë“ww>õñ+¡NœsöÞkÍùuo^¼óDVå¹aÄáì½Ïúºç}žçg'|ˆ‘ãÅÂX;)ÏÐê….Áòæ|U¤Ø3€Þ7$ºC†X‘CŠô¾PN)Gc¿kGY@ö“-xŸ˜ÒÉ'Nµ°¬çU„LuŠÔ­ë͇@+n%2\cROöW9å&Ÿûägùâ¿Î¼;ðàî:ï|÷½üÌûáýï9ãm³§-«õÔow›kÛ€*>ïÐq÷³[·'ª›_=à|ÄǼ¹H£­¤õ’Äʼù:gù½¬Ï>ÍË/Þ´¿ÆÓÏ?Åÿý¾Êúê[x÷Oýsæ0qð‘þ(ïûï~œIÈùøî’¶qLß®–¯oFÛUûß¿ç—Ä$FÂt ×Å’ŽÚ©§ ã!zo—¨O\û{¹~í.nÞⲿÄw^:ñ¯>O©{n<ÈC÷_gÈÊñtA0Íu´nBš‘^+½Z£ˆO‚øÁ  :ˆ2á}"Î0‚ kÅ{A]6Í"˜Žsy~Ä{3˜-Ë Ý¦§riÍJÁã³áÍGköð>ƒë¢d²@Zt8cØçÔˆ˜á,¯Z«Œ±’&ƒÑôq"«‡ÖXƉºb<áÑq¥rÒjF·a Y›Ýª z§‰Ð½§öJsàR¤ÖN?Uª33T=Ù!$j),K³æ¢¶Úh¬B{tó8·5àC"¤Î²4B¥1†õÉ”QœÚÑ(;jÝë•ÊqíLQˆnp,ƒÜ´õü_’¦ÀÚm—c]”"˸¤”NJ;zƒWÛÊao”•ÓiÅûLñvµ›‡àÇ€œç¨8\8ß‘+àê-Pv4ú)2ÂÀûŠª#¸IÍæ;m¡e«õÆ6»^;2ÃeJSF»d¨·$žËÓ%¢ñ;tœ2ˆiOt™Ö‹[!¬¤ ø8³VÏ©ŸÐã e3-§“Ù\Ó<½ÞÆÉ 4,ímæ]—q>±Î»‹SøFö¶ ü føî …?ÿÌ7øÊŸ}‰~ý:´•ú®ëüÒO¿ý¡wðà}žEΠhE߸¦Åã– p‚æÙh;î.°ò ß !ïM#zyÛn $58)jÂ®Û ï;xó1öñ/•ªOr¼ãøÿûgõÜó‹àÆ=×éû“¹Çï·êôµš C]W’$BÖN•ÅFpêµ[ú4†€Ä`ˆôE·…iÔ&ç&`%ç 1‹ ¥7‡ŸJÁÑñ9pè¬Úñ92ê Õ[¨FRfÌ©Õ|1 1"k¡W ‰5åTq6ÖWoåedaT‹âkW¢Œ 5¤bFƒ+¡¦M¬÷¯ÂÀziÿÒ÷nNˆÓ¢©ÿ:h«¡Æ|œÌwл¥ÓŽ0íˆc%ÕÛĉ7½éWöï‚“çâ»ÏòêùÊ«—ߥ½ú*×î½Á½ÜK/J_¹,(-]9Ç@ôB©+½)õH+ I"Êd—’n›ÅhŽÞ:>9ûw{Æ„°l웦‰Ž5JiµÀN×Ò;1§­0⓽¡G³ÛœCÌ{àt»Q Â0 ¼K‘1­,&N/ѧ‰¸m4†’œ'2‘s&L¦LóDޮ΋l&P|!»DN™„c?OD)dRôD׈ÉÄûu4hƒä„ä…ÿÁßþÈc:@‚uË9™ŒöÛAGÂm–·Q®Û ¥4iæ'œ†«È°«Ù죉41ÛÉ^W´+sÜ1í‚QU1 ‚Gïƒ)G\È4o¦ˆ±ÙsF²3ÜÔ.x‡d¸£n»µKק”3±Bw¦Œ×‰¡•V;-èÖs zÇ%BFØsÙ„á†jÇUC.¬eÕŒ< Õz–ŽÃÞ‘×x.ïàF!¦È<ó‚çØÍÉk]£§Hœf$DÆðx±1_œ&sv Ÿ¨*^"7o»›‘`›n4ÊXaxÚ±EBH\ž _üìßð·Ÿþ S0ñî§~äüúoÿ?ú®G˜œÉB%êøÇKÿõ_6°¶Ý@ŒEðúáo꿃—ˆ·âSç,Ñ(>0êúÚó dûžY¬Æz—=.'®^½‡ïÛ=¼šnðù¯|‘‹‹•çŸ~ž;·_àÚ•÷>ð Ñ­4N¦7‰0°N†êÝ­Œz²È˜OÍÛØÁœxj=R^»2õÍ$æ@kY@;ë² Î#!0–JPašc(­5Z·q^Hɼ÷¥±ÖA¦÷87^k×*͈ʠԺ¬8©¤Ù› z,L¼ ËéÄEx]¹¸}äÕ%2M&¸>È»LèfKƒ“DˆykÆJÃd_[0È®{öH˜èµ¼]¿ëYÿóýðc¥ZË,ê‘`Å^!Öjf /ÃrñÛ?7§DUròÐëaœð¡ÂT‘èÑAý 'ëíÃüÝNì4é]¶¯ÈÞKѶ_&Øy!¸.LÉ~ÈÇnŸ7|¸Uñê˜óÁ¦—Ý\ät¼´’÷ˆœè[1ÇBivj¸it‰Ö¡ÐAœRuPO Í7¢›É=1| ¯žL`ʉ¶(½ú¦Íĵ™j^£Ë¿tŒ“u-û˜qbÈ4H0 ¦¯F±­U£BLž¢•ÓE¡;¥|ÛôlŸ†Ú`ÎóžËcåKŸûkÿÓÿÄeÛsyë~â‡ßÉG>ö+üü?¹‡³úýt‹}JäðúynoëŒÙFŽNxÝó@ä5 îöií”Õí&(1Ù"W¥­GîÆÉ}6a¬/G%L‚ øËÛ\‰çì:ãMWö\©ðwO¿@ {ž|òI^yµñð#q㊧”W !3\¤©ÒÖÓ‰Ñ âg[”r­Ô‡…Ž@i£ ¦WËÙhŒ úV¿6§”6(Ί5œ8†‹”BòÞÊZ·ªmÓÀ}'ÀHäÃÀ'Í1Ô±,GÊjæŒa”zAÔ…äárÜ>žvâ8Ï=ñ<ãxÁ•®ÆÀUÓÚ,vsµN3ûéZim3ãpÄmuô0»h¡#W7Ï,õ£ü/þîGk^6ÎhÃùDwƒÚ!'Òœ_£ˆ3?|[‰­v[L@qÂ%S˜1Éð$ÁÚJòŒ÷•Ñ/AûÖcô!/ƒ!F J6;çˆ÷3§º²ºi«æB­2úµ$ ëPÃYi£,&ºE³2‹Vbèĺá¿Û²ŒkÖë¶M|S”f—Í啶ô;Þ+cÛÌj«Bšò†©^Ñ!ÔÚ(ÅQWs¡õá`†'ß¼n¸©ka]«+sÎèÌ­ãÅØ}Ë©²ž*A¼}¿Îá‚°¬Žz\™wœn]ð™ÿëSüñ'¾Àñä‰õÄ÷æ7ÿ‡ßæWþ鄲ƒpmgýž{¿Ú)î=£‚‹õ„;¿iÔ—qç¯bó£»­=öûîÒ…}Ì8,¼5šåô7µ}=á³%ÙF[ée!hljãè"-³–Ε)P—Æç¿ðþìþ÷jç”&~ê‡ÞÆG~ÿ_ñáŸ|3Ç † IDATîâ&)%Ü÷,`[ÄΙ«oŒëzÃõ!Âîcàʲéî NA»òŠ7 ×…¾qÎÈKÎßmw¶Ñ+ª¸Ñàòä=a>#.8HáÞ{„7¿ç­<úæä,{¾{ó›|óo/yñåy¹íyËC÷rÏÙlÌÞq9ãÈÀVÛÆj|“ç )?/^1íHSB‚#D}‹ÑÞ…¢8–R­²l]¡{vû™ÞWÖÓ²lá¢nÝ)šyl]+cÞ«]ûÕ]1FÒè"¬—w¼ âQ§ìÏ2“Î{äl·gÚâ½»«?M”ÚQi„Óš-&ï>¤mQ-–šŒfÄ«Þ¹€ê ”¶•½WDöì;än9ËFáÍsfšmj+ ]°,μzý‡+;¦½\Âm±Ý‚a—BÀÉÀ©â½Pª¼’wÎz’-UÏÙrêÉÔꔼŸA)å6«‚`?ÏÁÀùŽÂµIèmðןü ÿöÿxœãˆ¸óxÛ¿—ÿíúÿâ‡ßL?®vÉY™¼aŽ¿ y>N†Ó¾«Ü=Ýc†²ØÛ?dÛ(ĸõh€l#¾Í&ì³ýÞ5‰›hb¦¨òj øˆÚ¬ëÿµ?Yp½CRòÕkñ¼p§qÿÃ×8ܸ:…¶¢ Z¯ˆÛ›©7†R#ÝÍê 0‘p´jdç¬p¥/8Dñ´1ˆi"ÅÈi)”fOÝö´)ÈÆt8²ÏVêÚ ¨#¥ ïSvt¼‰½“gÚ'\𤘙½Ùíís×A<óœI^h H>0¨´ááÁG£Ze¨¥r©æ ·Je±IДÁYỺȨÑìò> ’q­ ü¯þ›ß~LD#1Ôá|£‡£â±öç,~(ÞÓ« )ÄJtÀ©AœLFµÖñ–¦™è" ¥uE»õ£‡Ÿ@=½zÄ;Jo´LDŒö¶&¡ä“„<óî@õŽ:ÔžE`¬tÖÖp]ñæ0ÆWo-­Né]¨Ë‰v,hï ¯\^V‹ÿlìˆsh ŠY¡V¤ m4ЊïžÚ:= ü4™S°oø³ÑáñÒ¯8é-Öut8Z[‘à°[p±‚‡atãà• ×$’qÚÍšü6ÅŒîX8’…}Îô;¯ò©¿ø{>ñ‰Ïq\mäùÿëÿò»üüO<ÊýÜä²ököá϶éo%¨¾vº¿þËÞúN¼%í¶½ÅùˆÉn[ÿõaj…\mÁ8'ø4òD­£œw6.®ç¨d®=²çÚî!ŽÃñÌñžú«gyáÎ-¾ç W®Ÿ‘¦h|D½ÀÇe AÒŽ®ŠÖn˜q¥Î*Æ’¯I Òûk¾c_ñðzSÚj5x1$†«´åÜ"õ!ãýÄ涻¼\­áx{j÷”ËB««~âÄqiFqơݱ–JéTèÃà.F«ýn‘*u¬§KÖR -·¢žäQŸh ܹ,œŸ.¡w‚4„zZm(ÿsûÅÇvÊÅ éÕ:aŸHÁ:ïœÏ›·{ û;º4(u5Óê°hDSé†UuÙ]Ì#ApmЛ#ÏÖïˆñtg§a-' u€BÊqf :]žÓ–B ÙF8J§Ÿ†xv‚¸ÀªÖ Á;röL8´{ЕîMè0À¨*;È!0rF{åT¬ßïìpIɲù1š{«$DöSÆWkY±~Äy+²ñ”ePë ®‘æ‰t˜£ÁPBP‹ûd ]·ÏVûÔË7¬­Që` Ž˜9%’xé©—ùwø8ŸüäWI)sëÕgyÛ;îá÷>ú[¼ÿÇež”ó6*7¦Jœw&œžÎÙe³~óG¼èèk—q‡ñŒjDõ¶=¤ï±é6™­æló0ýtŽÕ‰S%·J ÛÈ뱑Å%nCŠ-!3÷Kr+¤yæ‘·¼‰«¾½s“gŸú ž{¾ùÜ‘yR®ß¸bûX¿ò.âX©­26šôhö†é@¥u›L.!b¥E›¥êB4Ž@YVÊX¬'Pc˜fçÉžy«3ÏÊPD­me¸ÎƒµbÌÌsF†7Á‘b¢À¥žláªkÇp¤™&»ƒŒàQ/¨ŠËJ[ !FÒn&y£ùf‚¢T¥•žFÐÀ4Íxc˜­Áêxlø_ûý>惰ˆUZÏ9$†ÝÝv–0¶¸©ÅNóNÇ“‰{Ί>6J9ªvú÷®„8áö¡ŠëžÖ+£Uk·¡±´A§“BÁ‹Ø¨"9BðÔ1(ë…¥w3CÌŒ›ž!R¶Úì4QµÎ6/ä³3¦i¦:eÜðÃã‚uäÉyªŽ}tæýw9ïpNéu’cŠõ‘(V¹düµÄt˜’†áÕì°Sb´*kÊrZ¬6KÀ¸ë»P|ˆ„hµnÓ€Ž›€ŒjÙòÃ~Ǥ™ç^¸ä³ÿïŸñ™?þ0 §çO¼ÿ]{>ö?Ç>ð$+ Ý <£ç"ßÃמøøçžá?<þù&ß|âO|÷’q¼$Îèñ»õ‚³qb¨ÒšQŠ£Ž×Ú†RoçX}dÏJŽ„ÀC÷=HÞ=Èsßø[^¼€Wžø6·^z’|v•ûn<ÈäK;1¤ÒêÊX ~ š*:£4–²=ÈEbTR¶jò›™ÈgTUQÈB !‰Áx™óìHóÌ ÑE‰j§¾]¢Úfr´jQïó6ù°Ô2ªuÄðzŽOÌJöÖ•¦„Cí ƒ#fE½Z÷ 8r> Ú¨ue·ßÂZmtnIÀ€w†?ÓUÿáýáÇæèÉ1Xö˜#®Ù¦í$w^´2|‡Ñ0‚eröÒÄ>Nx(+º †zÚhÉÌq¢J«!¨ª9ÅÚjüvM¶ë"ö~dmD‹w´ÖÌ“€Õ‹‹‡‹ó•ÚV‚7ã⼞ ;ß9®…WS¸³ïtµÓ3È™u5Y7wóý{ëoæ·ÍÇ_û9k™"„ izÍìT— è•Ö+çUyêùÆ~ü«ü»?ý¯œø'ï{˜«‡Èä:» |ñ ±,œÝ{/‡ûn°Ÿ¡šø)>wWpªÖftX³ô£Ee¯LS`–û·¾—x÷{8ñ’¯>û,ë‰/ýÍ79]¼Àý\áþ‡ïe–u)hPBÈàlL˜œœWžÖ:}X:°5¶„…•ŽLŽÃΓ\\œ(kg7GBqBÖtÖPñ›·³lOj"/¢¤9Xب):âp!нC´ÞA}kY Û)îã°ÿ:iDœzœ¯€EùU1Ë~©,Ç­wòˆSBµRŠµPÇÉƳþ7ÿÇßz ”ãX¨Z‰’8Äâ±±ˆmtô• Šh"ÆÀC+9$ÝuÞè1*‚ºJgÐu ÛÜ¢“­UÊZéÒp’8W–ÓJÎÞHÎÌ@«Z ïº4ŽÕ*—ë`];}]«…Œº¬¨z¼FÂœˆ>P ˆ“÷¸ƒŠ‹‰<\T3Gи¼{…-æ$D' çXg›W« _2ASêØå„ônÁ¨èmÝԭʬÚ惙’òœ­É·^Ø¢zú+b„/žæ:i øœyîé[üÕgçËþqÖóÀt6SOGî}ë÷ñ®}£¬<þ¹¿ço¿ú¯¼x éywW÷f{.]9K¦¾goí4otÿºíô½½öÎgŒ-¨u×(´Õlß}2„HŠ¯3 ïš|F9ÙÌy="ñŒo¿²ðù/?Éßm<üÐû¾ÂKÏžxæù•+W„³äxòå…ÆÂ=×Ïxh?8HÙ¾ ‡ëK¿/DИ™$ÚÊeœ w(…^+÷\q\{ä~úþ:K½àö ß!´™—Ÿš/y—¹:O¤}Fr´qîX¨«"bÏÀ±B–RlÍ1ÍV^#âñaPË‘i®O{œDzSòÔÙíê]3£Øí°.Êz\¾á“0Å™¡ÂZWzˆ›¬®¬@'N–a‚±ÚŠsg{Ó/G Œ¥9"9o·³BÌÙµjbã]VÄr<b ÏrÎ쉭ÑënxÎϺñúý_}¬k%8»žŒ¾ÍýÕÑû‘^:„õÔPi2U7À%²$ºu=RÛBõJm ËRq.ØØEÅæäC©«6ZTŠ6–¾RÛ%½­Ð1dÊP.‹e¦ H³w¦"œŽ¦T.éZñ>’Ç…Œwhœ†ñÞ”@Ð(8iæ ]}UH º€vg¦8Ã&ü ȸº™V Þ|'¨P‡Ò[a?evy³Ï£7b4và ½é}a5阔=”“«´èmPµâ\âòfçÛ_ý;ÿÄ_ðŸ>÷U–—/‘iGOoæÆ£oåpý*Ç‹•/þÍ3üõ—oòͧŽ|ñ;¯nÙ_ß“nì9x¸žQºM8þÞü:ÚvÂí`O€8ŸÙfÖÛöDxý÷†¼³™þù+hHÌôVðib,—¤zÄŸ=Ì7Î÷|ñÙ#»ÐÚyö©K¾óÂùÉqí ä ^xžzö»ƒòð›npßH,+Î'Y[Áo›ŒŽÓÎí4áÚJ ‰32*¢ «\;»Î#¾î<Ïçÿáëì¯ÜËw^v|ûëßâÕóK}çCÜwãÀj]–ÁÏ}¶ç ª Þ"»í[¶”`kFjÞÍ3>̬KCLû ø7q„Htà#Á'¢FD…µV./WÆP¢7ì¸÷‚öAÌ&ZÔ± C~"ÄH«Gk4šônÌM«‘bY—Rºdü„“a©Ó‘ÉS"M6=P£6k êvëluÅÿìoüÒcÚ•CÞ1T9o…)LÆ°¿(à½`ú˜Mèk'vi&ˆÇƒÁ+XО­Â€Þ¬*ÚÍ\mC‘èˆjÏ„ºtÑÈD÷‚k}C¡9œ$|ܼÐ{CeaÚíð!Ó;ìW˜c¢9¥·e+[TŽ¥±ô}Ô×ê Í‚6C…œ&´Ú•+FÁ‰³0´N©íG\R\˜i]é«Íî«|ó¤l°&›ÈÒ‹õä·ÎºZckšüÖÓ )XO\«t ˆ:v¸}³ó¹Ï~™ÇÿýŸð·?K‡ø€GKoæÚ½Wð¡ñÔ·Vn_ï|KâÆ•À+7=_¿sâûß>óŽ·ÜàY8„JWyÃòýÇ›€{MÑ›Åû͹çÄÓÛú†)À¶iÜÝ0Dp!"q²:9'ÖW"Ýyž¼ ùµW^¸õ*|å‹GîHx×Ûç·”—^±‘váÅóÛÜ9/ܳ¿ÎþêLÝgŽ1#½3Õ•˜gd z]8æ-D¦Z-¬æpHôêxÓ½3¼õAD"/á9n²àZãë_ùC7œöVõ=Î5ðDé5’cfž„µ `¥ZÐΞÃCXÖNY:­­ô6i¢/‘ã­N«yOv)ç×8uËÁ ŽiÊxo!¥}N¨8ÊzcÚ»UÅ¥4¢Øa9ôJ/«}¯n¥zVL¬^pÍ"ɽÃéhÈqtl^`97˜®¼–9ñú؇ )ÑÄ£![¤U<Þ9Ö­S¼â”Ù¥ÈI;‹´ ~Þsm œ7Ç2Btžœ2¢Y!ë°‰p†qØÜp$Ÿ‘!8¦¼ÇyG•ÕüÏ^pÛkJÝ°·Qð8M¨$ M™E"§a G¹„ãÚinœ1ÛŽC‰ìHS¤÷mÌ¢‘ÓrdY 1ÉæßWkQõž®ƒ±šÇ7OL)³^\RêÀOP!+êXO ½*Ò=®Ž¥˜Ü'kv4¡R(oH÷™aËV1*§ÓjNIqVè: ‡@VVê”e¡ù >ᆙÔæçÊé4€ˆDgˆ²QHi&&XG%î"Þœk=^Éjã$P$¡!‡¼§ºN;-´Ú,§ ‡M’bT;e5_Jjž™)ãå_ô1·yŒëºƒ5ü®¥£òn²VœÑˆ!ïÏyÖ.U¼Å™ûié&jxu¨73cP–ÅMÍž”-Šê5»ôÖÉ9Ù|gØìi}PeE†cÊJ¥béD­ÐýÀuÏùzqDXWX{§œÌ–,CI~‚(ËB”Lœ¡5»Ê¯KW-˜â•AÁáìëJÈ°›Éicåâ´°,ƒR;ÞAL3y¨(Öã,KŒž&œó¬«aÑ&ïCéË°‹3Ç—ïðùÿðYþý§>Ç5wAH3ýxWßE¼ñ}öÜsÃq:Â˯@JGÎpº„Ý ·üô=»ßù»v‹ÙU4ϯ=üõò–…{Òôº÷îÉÞÛVù^·óZNvÿú÷lîn† Wû½Ý ^Ö&œ÷ÌK/Üá3?Ã7Ÿ½àëžwÿÀUT•[·L9?¿9NéÅsÏ•FHp¸~ÆÕyc`N‘Yû6³V^n3I“.ÜÎ;nc¹EŠV5Œ¾r:]põÊ5Þüoå¡·>È+ßy–oñÌßå•&öÅ IDATŸçžtéÊ5\_éý¿Þ¡û=­w–caŒ•>:Þ›†'øB0èf)mC¹GBˆ¤<?“rÄJ.XÛ9)À~·'x« K ƒDk«—cb?Eº³n@/‘èwLÓŽÞs ¤ä(­“RdÄÉ®øâËJ?]’C&c8Æ”ðgÃaÇÕ«; £9 œFÒ.m¹ o¦¾Ÿÿè¯?v¬+ëeå¤Åªj1@eH”µX$w“[­hõhUæâ]ÌÎÙ:Éû­?¾³›2, §Ób‰Ý!Áš¨w†[¨K5èˆjÅùÁnºJ™ª¾T·@P‡>°˜(Ê`¬6:¡8Ô5J7Íú×ÎEæ)½3¼(´JÁM‘ÓzIrÂ#ëq¥×Á¼Ë&Î- ¥¬öƒ Š–Ʋ\8qø³™ý•"ÐVEDɳµ¯´¢„,æɳÁØò!GØ`;Ÿ>ñüw/øÒŸ~šO~üSÔ™®ÜKoPÓ[èûG¹qU¸÷>åxGˆ}80:Ì{ˆÑñÄ3w¿õÀûâûù¯„½ç³¤çyÞù{â:œ8™$Ĥ@*¹,»JV VöÚ´Ö[»–?ì?‚¿ekw­ZÉk’’,Š”!Aä4“0éäsºû OÚw@JÜÚ®šÌAŸsæôôs?w¸îßõ±¹g§í©›JjJ¡ál¦¿]#»ÕÉj\AÝŠê¯äu¿C­ÓÑè+c(‹Ãõú¯0m5¡”ø¡sTyð}§¹zøú‹û\¾ÔqaDz±UÑ ‘ýû‘噢%¦llZŒÍ0(š©â$ loµll>†O>Ÿ‘‹BS[£H¸(¡ÐÍÄkŽÕËzB×)¬õô1¡‡}êz‹s?Ì…ó5z8áp±d¾»ÉØ÷\¹|ƒûÇ#ç6³Éy¬žR¬¡ï;ÁÞi«ùº•’¶~Û:x¬QäœQZ#d "Æ$Æ!˜L*eŪ\A.¶Ö“Ör KbE #%r—Ð^Fï(Ce=Ú0 ZyÂ8ÃVŒn¤(Ó¨Ú€X­¯i¼ØÕ•$™ÒЋH©”ÈгÞKH˜¯üOøÔjì1ºPWµÈ T®ÂXÅòt‰Išªšbj'"©[q´uÚ ‰ñN3óµ ±£1ŠTY[| ®¢3CŸ0>ã½E  I;|(ÔÕ„l %& v-ˆñ†SŠ<L–”FçŒ0õ µ×èÉq@ÞkêV`›š"ÿ¯€ª, Y©ôΊü8{lUa¬Odë0g‹+²œ3` Ö{!Û …¸—1`ÖS¥$ÍJ¹Kt´¾méû“'§Üüà}~ð÷ÿ¿ûîuÔ| 7íEÊüó4“ÞÀb™EP5¤…s皢”ì X­Ù?ùÏíð{¿õ‹|f{É<Ü%û‚,jÀª™ —'2Ú55vr¨«‰Œ#Qk ˆŒ(íz³/ +Ôšðà ?xŽR eôJa9j:cÑõ„û·:Þ>¼ÏFe8ØèVïÓÌf…¶5œ»8¥ïGªF¡UæÖÍöN"Ûó9?<ã,fôi\Ƨĸ8 +ÏI™ÑgG—¦œ”M–¡eÔ›œ1VÕUŽ+¦uâÉǶøä“_`:{”ëïÜà¸Ûc*>¸v‡;wo±æ|ìü6õ¬!E ¾Æ:CJ=)YrÌt˨ÑÊÒ È¶"¨0áI@Ä?S+…VãD+“’'Dr¢d$¬­£¤DJýj¤$ÑBSJºå±­&"M»œFú8 HLô©²ìŒc@…M•ìZƒ nЫUuŠ’÷_Odù—ÿó?•Š8§8kéÂHR¥½ì"(8üÄIý†AcPª¬3BGc ^ËNtfÍCvLœ¯(Jö’­jä@—¯¨céÆQ¢®j©4èÉ噃 €DÛT8c0YDF)±û¶oE=¥m™‚Rk4“Ú •¡è î;rZa³½ƒQ¸ZSMœ"â.¤q¾•¿C5ŠQå: ÙÚSJ"õ+ñ*Psa"µt^ä¡)$ÂБs QûW– ^yïßùú_ðÆ['TS‡Ãí&v²CPsfÓŒ³°èC!²“ †‘Õ"sr¬° ŽRáw~í!~ûs[´~I_¶ øª‚Å%L;c)Ý™ôÚ¬ùÏ{ˆ ùƒF¡þôùa#°ZàÖh–Ænd6r;žãͧ\¾ösení)†šJVìÂ8bL‘ÆU—Y~ðæØÝ}˜ÍÚÓºŽÊ ½©ô‘Ã<…yÃÓ ï\Oü䵫¼}ý„nYxíýSî, ›ç6˜µ»ˆÉ°±½Écœ¶…Û×os鮢#pï¨p÷Ýw9Ú¿LGÍlkÂÖNKÑ…±¡Œ CGY+øJCШ0@m&ä4’UÂ{Ñüç,Ž¿‚¢‹ÄP´Íä(Ûµ”@¿vÏòJ˜Y šÏYÙ7r–y~×­7*-Õ̦¢Z%)‚)äU"õ ÝNQ*“†®‘Lµ[ŽŒ!"èyó8ó/ÿÇßʬM C 1¡µS‰1“SGÊàôÚ'ˆ·a”“׆†µöa )Rˆ•YÆ¥Èq•X*WZáL¡:ù^¦@3Hã&+Ì胤—FiÔ8’:±fr•¥­Tž“X™kaŸ›"6bÅ)Z?Å™Š4d²Z{æ©BÆ1­*0™ Î{¼wëN|¦²†b,‹qW+”ÑØq!¥m¨œÁkj“(Y Ð UdΫTB#¢ Ñd†®`²¦q5Œ ï_¿Áw¾õCÞzþ³íí6ˆz‡Ð~ m'2/."¾Ëå£þýz@ßCwöF>õøŒ?ýã/ò¹‡z&eŸÝéûbŸE½™Õzè„AÿsEÐf 倭&kÁP™¸¯×þ€’ ±ë¤0bta¢zBÖ™7O—\º|ÈÞÂΖasÇg°\Vœ.`sb„+·Ä¯sj /^ÝÔȣ¦lì »Ð¥ÄÊNY抳EæÙ7÷øógÞáÛÏ¿Ë›—nó“·.ñÊëoñÆ­CˆžÓÁчŸ3¹D6ê%}üO<ù‹ll=Êê,PÞ¼ ÃW®òòÕ{Ø1²QÔ³-ꦕ°>á¬"Ä‘;P‰vZ‘†E.$Œô¿¬Ý¿Öš¾K¤Ðã­Èy€:AÊSkTÆV² 6#)¥õ¾ˆ4ecŠøªÂ;KÉâhL-$¥ÆlAn{[ÕäTV[H£”³Æ@’){«È)Ñ÷ Ìþû¯>e "˜Ñ­­¯ikC. rÁÙ[˜"Äû`ÛZQ"´uEÈšåjEÈ‘˜‡R#+–!”i€@,°î¬G;ƒ.5I—¯ÑJ>?‘pÖËrM·~ÙÔÓzGY´º®)V` Y#"Ÿ,ÜýDfÈbRV24)FÒ0ÎáufG˜d,t–Œ”39 Œ]2–¤ ceѧxBé‡Lè)—¥!g… –ÄP"¡WäX8=YðÊkoðÝo}“»¯_ÂM4jö8ƒÿ8¾™1©3Ým³¹\´§c‚‡’H-Š®dþÕ?„õ[¿Ä´ l†{ÔÖPÖÖWøb²u¬mqþéÁ×kgß×pP·Ö§µˆI–HÖ»¿k¨‚·#%•ñ5=Ž^m°ß{¾ÿÚ}nßîøØょ;=WÝù\{[CU(šaçÏÁdª8Ü3ÜÜ?¤Ú5<ºuGmœc˜:ÍùÞ þî[×¹¸¥Ã;ï/9Ü;eïÀqóî=^º|—·_9`ÿà”Ó¦f£ÝäÂÄqþÑGø¥'â‹WTlr»ïéÔ®á7Þcïík„U‡Í©ç[íˆqAÈ+yÏ!š‘® "V ë=Ɔ^ȽdM0…z"[©‚÷PëÌRÉj9Q˜*¥à¼0/JUhJ²d¥kªÜ‡Þ®’Éj äDFJ4híeŸ!” hÈI‘£Å¹BÓVT•“ŒÝ‚FJ6ó'ÿéß=•S&ÍÐGÔ ñÆ£´ìEç‰Z£+%0Xe(@D"Zȉ1&ÒÄþ¸Ý ¤(&‘¦ÆhRÍZÛ¥a€´[£¸1I™s9­ «a`™uëp^n§>¬RTΉ 1ÊUY€ aȤ”鳌1tË}è Ý@ÊšÚy0‰>,H¡G£I} äÒH‰…”ž˜*ÆÜ:ÁŠ¢ë`,†`4¦ˆŒx2ÚŽí %NX- WÞ}ç¾þŸùÛo¾Î^×ÐÌ=y Õ>F.P»B]Ãéf­x‹.W0­ÁšuÐ×r†»ÑeèÄÂjþè>Á—?VñÈxzNÊe­lþ•¾‘  ß•rn-ùE뵑‡h´AS–”8~XïËCÉŸ‡ní•gׄá‚1Ž1DNò”+{#Ïýø[n$•ÂýýÌ8*Æ$?—Öpñ!Ådb9= Œ£¦maµ„Å 8×dl«úš¶2ìÎÅBÝë–ϼz匯q®Vܺ«HÅSUstý£ÌÛ—¯u¼zçŒ{G94T[,KfîùåÇ–ì~ê3¼sÐðî; &ægkn'ÞøþOèVw™m^d21«5F9–K9ðÏ1Ð m"ÆãÚ;Àb¬¡nkБ¾ŒXePIÊ‚’r XçEâžýª#ÅLÓŠµžRˆ @è m[ øÄÀ8ö²9Š#‹ö-ªDžê™©SGL8U›¤³S݃«Ic·Fw»uIPA "ìòµ-Í]BÿáNÃÏô~^& *q΄N‘.·¼x½ã­·.¡L¡ëGÇ™º‘¾ÆÝcÐ(T.ܽqJ#çšàœåÚû#ûûpnKñøÀ³:ÎüøíãjÁÎÅÚí‹Ì'…ºmH}âûÏ°P¢âðT‚ËO?b.œ¿8§×ÜÙK¼õÖÈÓ?ú?zýÇ(½«/0ÆÂd¾ÉlkÎÑÁ–·©Kö»,níq{ÿ€œ*Zå˜L=hEã TS†ʈ͊œ3ceïdKe5yŒ¤(ÀݱëI1 Ȩ̀WiÁŽkMc-Š€²—=”ÄFº®`œ§ö5&[É*MT™´ ”XÈi$0¢­œÑ2ÃjEH™±JJ„eÀ|íûÚS©Œä’©j‡-š¢¡n ÊEbHè2⚌¯!ÿšDå ßrD{'svg±Öâ•è¬õú_!5ŒDm0FÜR¸„3XÛc(M,‘LÄiE;†¡Ç&GSMðÎ3æ­,Ziô˜Ñe„Ú0o6qÎÉ)â½ÀµSl4-³i‹ñ2–³k1œQ U Jü£n+aå¡0Þ f©IRNøõ%+ÌZqs•Ö˜Qlaò—®Þçµï¿È3ÿð#^ø«ïa£g6w”ñ”<ù$fó잃±Ot£¢ñ/¡ÀÖNÖ<£%TN&!²‡)4 \»;-|í·ŸàËŸ{œ™:an:Š¯ÁŒ³8•Ä1&L›¬~j7ÀU(mqUK‰ƒœñœÐª¬{Î~ÁúFþb?µ;ða  Æ·B±‘¡jÅ©šrùfÇñÉsËbýJú†XÖjON8SUšóO¹·ãÚÕÀg>Ýpî¢XÀŸžŒìŒ+͵“{'+š¬˜NÎÑÎf̶,7ON¹ùAO J|ÿQ(€w… F)&­Â¬F¦P_@©DÎ`UÂXGÔd»Å4:ìc7wˆ!ñÚ3¯ñâÕ›¸“}ÔdƒÍs´vBÁ²"Æ« ÎÊÒXŽ@g5•U²àå­…˜"…¯¬ ¿+±” k3†¥,ÓYHyíXÅ|2ÅÃX'%XZÎY2•L§r¦O=TïÖF¥¥œÆ|í?ýéSYCk[±ÎP´¢žN0Zd½Ú5Ôm…³ ÊÈî{îÈ*b×›mÆj Ö(…¬;¤IE‚JTÖã´FYE2 oìµ ¶6ë†~ÕˈÒ$BL¸‰Ç:CȊ謳j¡k«‰¹udj=Fy¼–RÃèÆÕ†ÚÔÔVjƒ³åÊhªZ\YsTä$$«j´­Ä¶¼w¼õÆ þþ[Ë _šýû†éÎ&F÷¤êQâäIÌä‚LBfi=ÞS¬ ÅloJí¿ì¤þïÅAjÝ,‚éL±·Ì|ö Ç¿ýÃ'yò±ò2¡)‘…šWs3p¦átŸªnѾùÙÕÞuè )s6ˆ¬xYÍ8 -šBcÖ¸¯5à’"j¶œ( ?RA5gÌ8Ž~r›_>¢u–~€º‘Ÿ³dE¿¼ç/(|«ÅÈÑQÏI¯˜Um wît,r Ú lL4Ï¿qÌÞ¥}šóS}Øò±Ì2&^xå.lZ:g¸s\~&(%¯iÊkesÓl¢ë fhÅþ‘€]¶ÏoÒLûm¼ÝQolâ÷yýêeîvTÕ„vâ˜nMÕj!» Q^å Ö÷¨j½– ¹xºBÔ…’…g!b!iÞ }jYo*¦Ã(åíÒt¶ U±G& "Ä,VNB"Ä@tŠ2Îyêõ®Êc~ÿ?þÑS¡—ƒ«}Å#fEô`Ææu1”¬IÆU¡ôq…‰Jp[yDGë=)eV§KÆaXC ,QGœ1Xe y$éL¥eùè‡VJA\^"h7AW¹y6ë¬Sl k‹ žR2É@)Žµ~{̉¬Å†,Ç¥ ÞÔbØ€fâ„ X´Å*GFC‚a5¢²8Å¢åä~ „Hc¬ÚeqÙ¿ò/<÷}¾þ­è¯~€Ÿ§ª"ÊÔü„æc\¸8ÇêB7úQz,çv`!¬%Ϋ¦IóOÎäÀ?øõàMÜŠ¾ËL'…?ü/ðÏõÌšúˆS…1hRQ Aa'–Ñzf œ[D®N¥(6v½H“ŲÏyº ïg._YpŽ]CŸ ÁlÓWžå˜°g§ÒMVú§²òÑâЃ@á*î¯/¿zƒwÞZ2fs©ù‡®Þ)œvrS= ½L\ÎÎ4F)î% ç ÜñÐ|cm[°°\ºYævØcb+Šß!šžããSœÕœ”Ë€ï-k„®þQf“Ö«µëF¦ü(¤,Ä$]"©x²™™QÂJÇö®Ã$Çí·ïsqŸý½›h?e{kJÒå¡@•$; UA­áªŽ”¤‘×xGc5KQAQ™°ŒÒ”ÖW ÆyB0‚Ð7…’µªn¹Ä’å… b&k”ÆÃpÊòl ·2>ϋ ¦ö4uMR óÕÿ?<5ƪßzE!÷8‡vŽ )fJÑ„aX;ŸZÐBÊÕ4mpÞ :臞!Æ”ˆJ*xmpk@¦RŠ> î§ÄZ.VbŒ}O?€vž¦®ÐC dZœR…qæÈÊ£\%¼öRˆ£§”c ¦’ <£™ÇÄÐeúaDV={ `ÚF±&Ó9c­¡è,hèä0¦ˆ5—.Øä©Ø!äÂõwxîÙ÷xá›ßâùïX»hÅ|.ðŠ¶†s°8£# NknÝè¹úîw£æ“Ÿý,¿ô©m^ŸWßX2óæCîñú\ÿòG¬ƒT ñP×e_CP,ÇÂùÍÄ控ݘ³;9¥ïzÎ:xèc ý2ðÞ ×¸vûüŒÝsÛlO'(4¡$²+˜Ê¡‹Á邱Šœ-Þ)¢…¹éÅJ ò˜ÐZÌl b?¦¬#ŒÈîK;»\ÀY‹ÊÚF”¨mƒY“!#cL;Z¡òz䫼Høÿà?ü›§Le‰«Ž@ÂUMTÖ`l›¤ˆ)¬~áù+¼«±á6®&20„Žb3“I‹5žUXgðNøïc?’TD™"õÿ‡ÛeSfìqˆ%…i½bb+"#A¨¡0.VDåЄL][úe¦Öãì‡"–q(ƒÂX‡Š‘<”Î8,ÁÈÎ~V¶²x-^ÚÊô@iÄÊI×ç8¸vÌwŸ{—§¿÷,/=ýû·hv¥jÚ$ìÆ”é'h9¿ÆŽE˯$[¦8îälmËÌÿtóVÒäåJjÿ-¨<œ®ÀE7Ôó¿~å×ùå' “ñ »ñU×ì§9ÙT,Ê׺)o^¹Á÷_ÛçÚ=GÅYð›5}ÝPÇ¥ 7ÃÃ<ÿÆÿõ»oñíßä‡ï.¹º¸ÿ”gpÄ^=æÞÁ7ï`‚ç‘Oî21#pXæxËza[J£e:F5ÛÜ?‚¯Ü¥ß'–º‰¹>H3³²0F9øÛ¢ÜÝ”C¸w›séÙÃÁv·$PŽÑpçÌòÆޒǶŸzä¦Þñì›×1Ñ^/Ëó“uó´ðQP9ØÞ’¬dŒ’iL&°w ç7áâyQ[žžfÚ‰cçÂÙŸc±Šdû(¹ “8¾uÊ•ïûS\µÉ¼iP^“ŒCG¨tE3­‰&µ¢™m0–H(½”%¹PikLÑ8¥¨]ƒ2Š’ké? Å‘}!Å)c"Æ‚Ó…fbpµ'9UÓ0O˜M*Œ•sZד…b­)˜ßÿ·ÿú©¢ŠXMÇ‘¬‚4ÀTfì—k¡W"Œ’ UU­Õa“33Œ}¤ _ÕTÇ™†@D[éõ¸(0â¥v5èS[Û±‡µæ½¬v‡A IDATV4m‹Ò–ÍÚ“tbÈ5,Y’³>1%˜có [¯W‘U¡ä¡„h ŠÑxëqJTt†’0Þ2Äž¾ëÑ£A;À;¼®X,2ïüðm¾óoóô7^àèÆ)Ó©¦š6(ç±³ ”ÙçÀoËÔ"G¦Sˆ îÈ›ïÁ½sþXd¼7ö’Èâ‘ètr‘Fà8Ât*·ÓjË“Èoÿî'ùê¿ø8Ì5JX¹ó,ó„£[¤¯ Ö)RtĘÑ%c\&ç@?öŒeE*ƒ‚Ñ`þàßýÉS…ªdù…°µÈÕª#Í‚,,Ð`l+ŒÀl0EAIh–à Ô®&1óaDŠ–ô ¶Ú«µ*‹¢‹+Ô¨¤>Í…°QÎa¦Žbœ¶x婬BcPÙ‘¢øe ‡ª*A1ÕÕºjPºa\ }ÇUT0FƒÕ˜Rdµ¹Ä2`ÌZÇf´6Ú€©)(ÒÍÛÜxÿO¿x“oÿås\zýGÔ;sÚ¹%RÈÕ9ôöÁo£tÅ[óLÛ(ŽO¤TÖJÆ}¬kÑÙL°XÝ V# ñ£ÑÕ•®ú$ÿé\1ô…ÍsŽ¯}å—øÕ_(èÕ>£=‡ÙÝå Lyáò>ùôežÿỼøÊ=®ÜHŒ«ÂýÃÛ{gÜï{ô1v[ÙÞæ…Kÿ×7~À鈦X ,ý1É͹µ="€‹èSàî2°=Ûe¶»KL‘FÂÔŠ˜-{+Eè÷ˆÉ0è NËéÁ1~’:Íå[‘y#&›Û[0ôr·™,Ïä6Žù#sáÙDäɺg\8/%Ôjg«Qsùúc<#eÍÕ«'X'!¤ÝË|.Kl‹å£P¹pR–ìkcC •ƒÃS8àÜ–à“¥"eaeØpSŸ§TPñ„4øÍ &Ó ÷î°ÿþ;œž³g{cBS{ÆU‡Žq½Ù!$R—˜8…ǡɨbĆÃ…Ÿ‰ÒëiÕ’¬#Vyl­±®ˆÊoRÑzDü†ÆGÉ‘U7 ”`톜X-òÁ!€«41¬ª{\5#µcZ)ª(X®à¤H[¬j£(6Ð'ïP–l39UèQœF}­)9³\®ˆ£òÌR|íq,ÆHÈò€êV|3G)RZI!½†U*äµ;ÎéPh‰ØJá› º $Â8PR!2â*OAD1,qÆ1±S¬ŒÖ£b¦T‘l×6fªF»¡T\¤›+6Í&ÇÇ/½ú}Þzæe.ÝŠì/F89`²ó˜Š€CU-zë3`ªµÓKÄÅÙRvã·6!89–ú}µÞ†;>’Ù~)r«9#:€­u`¸¿/·ãC;дp¸_ˆ>òÿõùÌ'·)G×æÅnpÿØñÌ;ð­g®ñÊK7‰èlxâ¢Ü¸qÔ#Ý*R”âŒ*^¿z‰ïüø” ïØ=¯™N4wïG®ßƒG¶a¾«.srXжðÙÏžãèäÿçÙ—x|ç8w~—»ËÌîd Tm?0·{aάžÐ¨c,~R±¸Ó1 âß°¿»»¬kÝuàX‘;ˆÝ-‘<ß½/gaêåùZ˯MèáC|þÓ§ÿðìmfÎ3x¬J®Npt ˳Äö,…å{dfJIVpûl̤k”üÛœ ± ­¤q»Z*Ζ…ò„!ÕOÂé‹Äå j2egæ»È ó7ß{ð{¿Îg~éKlN' !ÚŽumÍt­MqÅÓ#ß4ÅBÁ1›Nä5Jï2ymTU¨• ÀŸ°Ù¢=ŽÓ Ì@#ÎG´Ëä2âTac¢LMLEí°e/>´aì,yL 9° Ù¦ÓšIÑUUœE0¤È„ oÖœ#6[TÑdt²B©}…igL¼!¦ÌXµ©ÈÍ€Síá%ë¦7!åH—z‘õò`³ð›ëHzlÊŒl­ˆ£¢& áA³ÌúHZ§Q¸ÂØTÙ‚ª ýe@-k›%À8â§3š©çpïŒï½ü2ï¼ô¯¾ü#860ii+ MŒ‹kØí/av¾€ÔJvì×÷¶R’ÚŸß’[êä  ûk¦Æ ~‘Ò˜*Ðz˜ÏD°ì`ÕK–0ŠˆÅ Ü=P|ù³ ¿ò ›l´+¢Ùep»¼¿ßóý—.ñíï¾Á+ïÛ6ÌQÆPØØ”sï~ssÆùŠM?ðöÕž7_»*³ãþž”Aô?Yìí(ªˆ;š[×÷™ÕšëgKþÏïµüÙãbSs Õ"r”-s㈺}†ÛæpL\½uH]7<ôXátèzÍþ¾jc$øM&RâlnÉB¯kôM¸w(é{·‚;‡0«ä *‹Qnç3ÍÔpqÃòÁÝk ω¿ÂÙ™¼Þ«Âjú›Ÿþí×øÎwßåòÕĹ™fc§p|*Æñ 4\¸¨øÅÏ_àKŸ<Çr°|ýÙŸðÒ[·ÙYJ‚û (#ëŒADGºˆ °ï3waZ¬S,N"?¾|ÂÆö&Ÿû”¦ñŠåR¡µ¡Öa8aæFy—ï¾yÄ_÷F1 »¢8^¶Žád!íèä£4ÿê-ɈÚJêt¥ Gv¬‘ÆéîLºzÝ ‰®·Lô1&žr6™O »çeÊäׯux€2PišÔzÛr{sýw:ý(H¬égl­ƒi7€5?=›Ñd·KiFW”îÊ ›3U,¬úÌõׯpûÆÛ”£3š­–ù|JÛÌ(¹0¤%EE úº±ƒ,¸q­V#cWd„˜ó(^z@Èd˜žK"¢©Ý”º®¡(i‡qR”í]c GÈ#væ 9ŒILêÂþý=žýÁU^~é*Mw•¢"ŸýÕ_ç—ãË<ññ‡i§}( P"Áiˆk2.Wdda¨® ^m`s!¦@¯ ‰JTq W`TDÅLÖF)rVF\ˆäq¤÷Žy­ñÊ XÄL¨ Z·8Ýs:äQA†QJ¬ÆdŒŒ“°æŒ6Äî­`P#ºxš¶fê>Ø?âÒ›—¸ôì˼øö»/ê8ÇL#L¶HÕ.Ê)œU$ÿY7rãxëÿüǃQžRRÓ^Ü‘ßþá? kçl`ÝŒªÖ J–—/szæ¹wÜñîÍÀ޼γ?¸ÌÍ둦ïxke¡èt²6•|Ý[÷àËsÇc¶Ì̯½}Ä3/Üåä 6E3)L:)UÜ–ÞJ7þö½Â¿0a:I,–.hîYöïF¾ùWÏÒê'øÓßü$çë^–¥ŠÂÕ;Ì›'] ?í¨ÜÀd³eyæØh{º¾È϶]k›Sùó8Àý#9è(–W+É¢y&38=‘Q`U)ÚÚp/rt ))&mÄom1ô[ßN ½”PM “©l®–’eôƒ¤ÔîÊzÃÙ˜ŸmØ>‡ò1gäóÌO}ž5g3½žcv¿@>»!ç$ïaÛÛ;çè—=óãë\ºõ6ŸzìS<ù_âSŸ¼ÈlgFɘ3>:ÊþÌж0i=Z p1F\‰Æ~ « ç*Òhð6êÇeÓYÃ8@NÐÊQtF©ˆr™JiÌç¿ü™§îÞºÅâì{×îñò3Ïóôw^$œöô£g¹t¼ûÞ!¼þ=NSÍîFËd*î*‘µÅ¡V†é¤Â7ÆÐaM¤mktmÉŒ2·ÔŠ” bÚÐhEôÊZ&¦ÁÛDI„uaf”¦(EŽ§ôÃ)‘Œ*¥+’p+нù¥³ «žTFŠñ” ­ÕXW‡ŒÌêe*ò'û¯¼ößú»—xúËÛ¯П. ÝÆ9 “ÇP[ŸGϧø-²ÝaÌFš5?Oÿ?#˜]œ|%ý1~ô&ƒ:ÒÞI'zkKêPŠ¸4ŸÅÄÝ®pi¿ç;ϽÃsÿp‡Ó^3« •“õáq!Q]Ë!º°›ŠƒãÀW¿tž¯üæg˜Í ÿðÆUþòÙ#±bÕIȨ̂°³ 9H?bZCÛdûÄ&Î)Þ»,^ ÃX˜µš«×"G‹Ïz‹Ç¶,éä:©xVn—Ö$ŽüÃ+·ùîxô¡ »ÆöCTÔnß—À·½-Ù†÷29î%(øJ2’éDí½û°¹)¯Y¡2÷÷$h-Wrs«$QwÖš#©{ŠòÚÌ6¥äX,¤Æt朧£“õáV¢x06|´5ÒTÌbîK*0m¤'qz–ѦB·aªeÆ>cõˆ­*gY­^ûá~øú-vÌÀ¤àë–b=µ­)rÉX§©ë ç9꺦¶…ÕÑÖж5u5Å–ˆUçUUAJkŸÅˆÍ ïÖôŽ2 s‹6ôD æÙWöžzûõk¼úÒ[üÝwžç½wO¨¨©ª„"â½¥© wN*n\~»:aX,IãˆsÔÚ‡L4ÐV%EÆÜ3Ä)eÆ0ˆh]‘Jˆ®ØžÎQvF•<Îj¬–Ñ*Lð~Žß¨iŠ"£ÈN1ÄD š2DR„RepJã+%“P„Ò¡ô:ÅŽkZW(¹Çò¬ö;®½õ6ßyöõ_þ‚^z‡ä·i¦™j¾ßþE¨¶Q³'Põ6 ÞJ)lÎ KL¥Öià‡vÛòçŸôZŠzºX³7þÑ“”’C8máÜyù²ËA u»Akn\[°X楶Š¸¶qŸ´òÜÖ¥C/ã4£ ³‹žßûÍÏð›Ÿnø`™øú÷îòÞ;ÇL½þ‘‘V¢9(Hr3›Ád¢Ù¿¿¢[ Ì'š£c™ß_¼“ÆðÎ;=iŸÏ|z—Ùî„e™RÜ”ÃEäéïßåÿþ¯×9ΊÜöîwBqòšz­vœ¯•Gpp"‡ßûnå›÷¤0 pã¶èÚ)Ü¿g 鬖5é”^‹•Ì­¹Æãåú÷S¹Ás’ï³¹%Ú­— +/™Ö¤Ûj]ºÉb©Œg”/ã ¯EŸ$có˲Þll¦èjŽŠ'”á„8æµ/aCs~‡¦r¼øÞMn¾úc†“g£Aq'^&β¶ÆÄÐ'ZcI}äàƒ3™=ýÞ)«e"žÁááŠåÁ1C§O#ãj wŠ19¼-L}Ö¼FkEZìfÊ°€eŒìzÝØ¢KO±V3¤«ÂîF‹Už¿þÁxî Ÿý˜â“¿üÏøÂçž`~þãL«(6ØN–IÒhÐ%¡uMÝ´”ì9Ø?#/Ž •Ã$8Û?cïú=TÛ²£ë|õÓé”f¶b54¨4°±»‰¶TÖ‘]Á:ØY{¯±Ù³ÒšQi”n0©ˆ»o-`¾xö–†+¯½Ç•ç_æÇ/¾Îá>(×QÏ@³³IÙü4ªÙEç(éŇ .´•MÂå¥ÌQ¶¢¤‘Ò¢êm¹1¢° ­ù§Aà§Oÿ_#Àn)Ú©Ô)%ãT^“¤œÅ¬äÝ R¿×VâîíÄ—~w‹Ç>ö}P<ÿâ»üõ÷÷àÿeìÍy-ÝÒ<¯ßßqOgˆˆwÎ̪¬ÊªVS º Ô€ÔbÀÂ@ÂÀƒOPßñ p „A7ÝdeV÷æb:ãÞû׈±öͬj5a0âœ}Þx׳žáÿüþIæEÒ§U™»ÿ®” Ÿ¿*/üo¾—ÁàJç~ÓÁ´°KUe67†ÿþžøüó_ñÿá¿‚ŒYÁ?þ§'þ›ÿö—|ë_^+\ȼüÙÕxë9 fëp]~ßa,ç4Aʤºdx•4Uæ4fôeUø‡?O^9_Ê.QÄFï‹Øªº@¤‚°&ø䦌!7—Òã=¬éuLåV¿½-æá ]YþÃ…R†üd·mÙ©R"dAç«4“×ÒrŒ$Ó`\±°[] ŽÛZþø…æ7ß*~ùßýoðâüéóg?{ß\Áz$Ä¢ÎÍ®ºÈè%çoéjønµÌ¿CÈ:óvYˆaàнš²J¿¿ÞѾ:pÕ7ìZÃîÊ`ë-²ÙSÉñ¯ÿ;?ÍàÉÉ“ÒÛË㔋gÜ4Ä°p÷o-¶·Diyúà`œø{¹åÏÿá?â/þâgl7ò"ÿ 䔉Z2>ÏÈñ‰ûç‘_ýö|ÿ * †jÏøí{þ÷Ÿÿ?l¯Zä²ò< °½æjsË‹Vðdnø8ž8|ö9‡O÷\ݼâÓ+Á”7›?̼y|*¥®'Ê…¸ÖúÄ4‘!q8Ü2ΞÓðÈß|ïùÿ§ÿ¾þö{ZáñË©@.ÓŠ>üjó¨êoÝü©ÜðB‘—ü2"ÇoPý+0#i|‹ì?!ÊŽÍÕ FGž…ëöÿ÷¸¼X‡ ܾ,B™7J-ü·û1ÁaW^ܺ.'üó z+˜Œ.óå—-ÿá¿ù%ÎüÿË/ù¿¿vƒ¿þÒØìà×P^j£áí3¼Ú•æ—Tå–ûøÓ†it|ý»À' ž&Á49þÝ/k^ÿèsV¹ðÿúÿóÿ˜øÉŸ^ ¢hêÿøš¯5òýÝLc$×7eö?Íe¿,¥÷ /#¶†O>–(ß~“¸?—­/‚¿¤á!á+%Ô›'x±)5ÿýcæ¼@gÄßiüí·—©Ët‘b_¦m_}V¶˴âtÊX+>sž×û£‰Aà}f<>Y¬Zxzÿ„F¥3iúj•T;S\—Çj,ÝÞÏøJRm:Ü"§‰ÕƒôgΧ‰þ¶ ôOo›R›i¨àFˆÅqkiÒJ6‚¸íÙhÉy^ð—S$»3ÇýOø¼:ó'µl÷?¥ùèÁ=â?þÏþ2K¥ñ~`] UEáöç Ó8áü™ºÚ±,’ïßùî»·ÙÑ&Ãl:žÎŸÜ.üÅ¿ýïógú9í®%œ'ÒóoŸÏüòçßqúú|u÷kÎw·åjR¾ä·\óâEE’ ±8fqyBÆÙ¿àv;0Õ=g×@ž`ÿ)ÿàKÍu­ËÊ÷ï~Îïf õÙ…{ºÍg|ÚŸyß‘¤bß¾bÏ|ÿüOy>~ ª¢«‹Ç`ð¶6¸e%-O2–Bn~ŒÞ¼BTe%4/wäõHžÞÃrW~\‰ó–î•$Ô5»—¯±mϳ»)kµù2ïª|ýƒø_09HM@ß—”÷<ýÝR!gØmËÁ<‹ÈÿWˆ©¤×BÀ»‡8h ¦.ÕT¶å~è;´Mùž>•ÛS*xû/·eýxàþ?þ^½nxû­ãí]à°)ìçç™á4•æÃÿ?ú78l¯2rs[ìbÈô›ŠáÈD‚h[¦Ã7×e¬üôŽåy|ñªÀ‹s,Aïñ±”J)•ÏZë"( —´ÿj_2™·ðÑUæ“OÞ'ŽÃŠ’‚‡¡dOŸßÂí­âë¯"÷c¦R’¦Vì6 ï3ÏgB²Ž÷hm¹Þz\°,‹gÕ mMð‰q’ÔÖqüðç&Úô‰Â“’‚5!Ä=Ñiê¤YjMP„9ÒLæŠ'_Ã|bÛ$lÄ6sŽP™Š6„E¢Ì# Ir†)4DQ¬È5™.R#ÁÏ$Û¡´¦ŒÅ3!Ê";Èw Ï P¿>CüGÿé¿šÛ®çt8WÚ¦ ¿r2 ¶:ŒiÙì:–9rÿÀÓÓÄ÷¿3(]‘­æéë;ÀóÙ¿öüøË Êœ¿~Ë÷ß½ç»ÐB®©ÝÌ*¦QÝáA$¨[’dG<à”*ú¼CÔšÜ÷d*z;q?JvbâÍ ;¥šOD «µ’iæ„<4byt`36/lkÀH¢7ˆ°;Òqd\¼{Âê„A›ˆÚþ˜ 6äé-Â=‘e{±7+‡×T¢Ø4 B7W–ç·ÈÃO©¶/ÈqE´¡5¤ñ©þüa7 jÈ—Aÿ?wk»øÃB̃Oòé'ðp#4ê2%ød³‡O^–¿¿ùPn@„ ²ý°+Ê»ã /v°¿‚7oÊ´bÓ”¾ÂÛgøò£Òœ{ÿ®¦íîï#RH–E°é/©ûY¢fÛLhy8÷L!ðrwiT7p}P˜ÊðöC©ˆ6\<à7¿ƒm 7·x¢MÉ‚B,ý”`»‡ãS LߔϘ3´}…>|(Ï£ßÀ¯¾×יϾ¨˜Ç̼8†SÑhت³>ýDñæ-œW‰+ÓÃ×löWÔ]ÇÓÛï În~ÒâV² †'Ö|…W=]]¨½[áþ—4&ïnË^D˜ñçÎ'Á¶vÔÉv_±Ý”éTHE§AL„T!¥cÓV§˜½àÓv®·¼¹;ñáí)zžÎ Ê ¬iGã •˜ =q̼ØŽƒfÍ-‡Ci$BâûlQ½%æ 7/¬YpÛÄòŸÿ[ÙhÅÃÃ3ó8²Ùn ïGúmC ‚yhÛ-RÔ§Äosäùû;ÞßgÔ¦¥okæoG&cØl‰¶! ‰†䂱 HضŽí®¡ÛÖÈì¢U#U¤±"X¦øžñ™&ÇùùÌñì¹óW\™‚µVF”™æì1F°¬‘y>SëDh÷Ä(ðwl†ÊšÎÞ"‰–7d½E¬b­?¢Ïg>¬< UD‡GP}aão¡Ú¢»×Ø®!…€O`ZTÕR`9>‚Tuy…0@¾`²š×( iüžÜ|îawÈ«?¥h>ÿî~~‰Úé÷½€˜Jã«nŠzð‡üxiÆÉðއ߿M´…ÒÅ´þ!˜üð}7}Q$ÆTTxÖ–&åm $˜ÆáËìaÛ–üùg>®œÏ¶„PÄ~—1•D*Á<ÄËŒ¬ºÕÁÕ^ð“¿÷1÷ßy¸?qóªçô<3M‘Ç{ÁÍmE¾ùŸ½.û÷p.èº-åÉ~¯_—}ƒ®UîÆ  Òm˜Ë4EÈ¢«×J0ŒåwÖ:3L%#ëãïH!Bäã_Õê¨á—%®¯!'R˜I~ÙBš‘¦Å´-º®"!–3ÞwH“iÅÈ´Àóã“oøôKKßµ(Ý UBIÁ®·<.Dr^Ѻf¿1h©8.3·Ûžº6¼{”ÌKé;|þQæÕçM-x÷Íãà8‚yÉÄTÆdJ—þÄó3ܾÔl6†]·ð«‡²ò\7‚Çû3‡å‹?þ˜èϑþd ?<‡ýUÉ>¾_| ƊߧûÚÀÃ}âéR&Òøw#Me8º›ÉÙ³ß#DBÕ×(ÓÖ'¢¬ÑÙaT;Càûׄ|‘?z¨¯^Pé'š¦¦íLã€~bõ†%q¥qæQM´j&Žá<05Wti¦ÛDn>¹åöFÐo4Zg–9ãÅŠ2™®µÄyx:"…%¦ˆÑMÑ;¤È²®,óLUYº¶£¯NqdE"ýÌÕv‹‹ð|>bu¢²œ*„\c@DIÌ©gœ ,)RÕ‚ºª 9È9½È‚ºˆÿê¿þò‹Í†_¾±Üç³Cǽºçß½AŠŠmÝÐÃè´Ùb¼ÇÈ@ð&„­,§“ç›_¿å·ÿäk>úÉ þôïÿÆJbÒØZ±z÷C¿”¦·Ü|ôš—;îïÎÏŠô¥àÓ5ûÃï5!Nô½‚Üpz(]ãÃÀ2&ªÚr8\S·_|Üðøð’Óë42ÏRfܪPf U3q·çÆß“ÁšLzæé¼AÉ–{¼›I¿Æî?†œPÊ`}F¤Àñ¼°.ÏÐ4ô›+ê,xZÐ5uÞ ä„ KIËF 8Ÿ™³*0yõ„iYÃ:‡oXoÄ÷ók~öÓ–ŒäñéÌ'ÃêªJ¼¼©é÷=1ƒTGæ)ã¼@êÄÇŒÉO¬‹ç¸VlÅ÷˜Y³@pœyûUæ“?ú rŒS9ù)•F£­J·ßÅôø÷ð-^™r~—3µð()h|`U-> ‚;FIµ_yñRSU×´‡ d˜ÆŠn£K¿hÊ[LnRÊh­¹½~ DRö4uWÌpâ‚u“±UËáH5R¶¬ÓLða-ºÚâ|¤±mU+pn ¸šÍnϦ¤, Ná\"º©l¿¦ŒV3U³)"¥§ä m[£t‹w3Çu¡ªæB0ÌË€”–®5TF²úD"Ðlú ǧø˜‹˜)0šy-ýc oÉ©²Ø'$úé»3k³¢e… .¬l»ŽWWW,Ás|FMÛv¤Tóƒ/|–#‚]P‚5 f|˜ô•yyµEËãq¡ï-ÚHÒìH)#¥â°ßÑÚšq/P 7uY‚0?xh¤£$ÇEqö¦Ž«ØuÅ"3IyêN¡TéØJi1ªEJ҇{¾úõ‘…Ù–[!Æ©l£É–ÊÖ¹Þ°Z3º•ëCÅõ¾æé캠ª$ÎO„àX—– ! ê*‘bd]ÖE¢m¢ß¶TmÍ«,kÏÓ±§®,Z &WÓw²¨ãR ïžÏ° +ëøkfYã_þˆ“›Ó3׃Ð#/o#±j ïi^¶¼ª_晇·'‚©hjIZ-m·`7 ÓÒ HZÖ!^†mFWDòL~…ÿ†¯ãŸ!šWÌ«àé´•Ü^—ÿÇßþâÈ8EbÊ„˜qA!Æ·¿ ® ê,WRÓL?£JGÜfÉâ¿û'ŒC¤ÖE½³DXM™xARXP¬ÄéL†ªÚ`ú]Y’™XgÎã]­|ô“ ¯^^³ß ¤–´@Š¦È°ÊК«5ƒ[!〉ÎÇéBšh´¬yÆ;0ªáæªÆûâi tDŠžj\H)P5!ëbzƒG‹‹ž”d ¾"!ˆØªfæeÁ‰Õ’Óiâ¶jyuý n=¡”a×í‘Rñì§É1¯!.X%‹3wmñnćHe4çÓ‘º.2à¶ÛâÖ£Zª¾&¬+u«YYɳa¿¹¢®{îŸðËíë‚¢‰„2 Æ\1au…[3Þ'¬-`ÂeN,.cMÆVš„@iE¿©ñ±ÂV5×»]ey:‘â„R[Ü*ÉYÐö’¾ßÐ×-çyâ<ŽlúÍeÅx$g˜Ö@ꊶ©¹{üšwÑ£l@#ˆ%®®Ø©•ãôm ËA£dxx˜ùæ]¢Ý¼âöúÈÏþä××=Ã0…Hˆœ~Aˆšy<³J] ’"` øU«0~ÁX—™”ÎC¤í i4>DžVv[AƒD+AfD)Å•¬0¦ACë'‚ (S¤™u§éûŽà3»CáñkÇéTøŠëb~Á…'š6ss]Q×¼K,ó€­AëšØê ßþjaé4¶zÄ-ãœPéD#,ÉD’Qöh+9“…mQÉÓm÷ßþ u÷5vÿ¾»GÉ€UE<ððí_CÙÜl!DÒ¼’s`Ç%{„äyaÅŽ½í`õ#!Z¬Šìº‰Óì¹5˜ÄÆBºX‡•r¡øFd4ªÚ!¤À&XŸÉ¾bU s\ùèãš—/?áåm…nŠ‰ip™yˆØz¥®[¼‰ËDЊ¦)˜7c²ÚàCájÛâCäöjƒ–šÁ øUR¦­,^%NÇ'¼óÔ­ÇTÅ„Ä­‰¦•…ª%Šá‡T’à=§ã#m+¨›¡,)Y¬äÜ¢+…m"):B8ÓvRŠŒÞÝ ç'º®%¥@+lÕJ—‘ø%’˜Pö–ÕïLY÷l·;†áăÐh£:²Ì‚DÛo TK eYЕ¤© ¢ÓyÄ­‚ªn/Þ‰+1ÇßcôÊ&§âýÃw(e±u‹['Â: l‹±5ë2PKm,6ŒÎSb)L(%pAÐe°¦c6e:æÒÜöA ¨¨kx¼ŸXæ[K„hÑZµ4Wc%~Ï3BxrÎ,.’sÆÁ3ÍÖšºpÞ­ôuS ¡Ir{}ÍÓøŽñìpb–D¿âü ·J´\É¢ÇyÁa¿åÐmñÁsœ§¢¥Ûî‘)ј‚ä6J3MÒ™Mo2âÖóôLH‚¹òLË#o?¢¸ݽ;r÷Á×ÈQ®n7ÌÁq:ßc¬¢²ÝæŠÓ<3œN„üD×ÐB1{I¥¯VàCyiûAp3óª8ÏÔ*^z' ÖÔT­eY2ã鉪J˜¤‘Â!â†Ê44›¡5§³&g‡’ªÖ—QŽ%Çžóñ„”+u ]סf]΄à1¶”OJI†s!VufžbŠø°P[ÅëÏz^K”šir,s¤ßT#‹T;Œ’áw'ÒãDN Y2Q0•e‰0ldFtIR6,ç…VDê¾#¤Ìñ9PÛ@3OÎRMUñÓëžO>Þ€¨)lü«ƒ&¥º”~ºfY_rÿ~aNts@„H Ee¦‹ö_²ÝÕ4ý–ý¡¦­ i;Ú^c´C0©%Æ…,Ö²Ö{‘R§œ±zAÉ•ÙAF’sÏãÝ ¥ ²‘ì'¬Þp÷xÏ2;Ü2• [“R±Mkû ÞG楢k'„hX\B)ÁÍaÇäf”®©lfrQHíÑX>~µãi<=Ï[RŽ¡ª,×W[ZÛðp<‘Ò€V™i̸PRP ]W³»jÈI3Ok© M…±–™­[N§gÜóP±„…®~¦6=b¸ñ=“ß ×glSRÉÑÛÖ0xOóxÇ1(¶õ™¦êPMÍG7#Êtl{no¶ô½*f/a%¦Œ’Ö Öu`™Wº~ËõÏö ÇkÎÃÀì<9 šFPÛ9+r.–Z hÚ†'Öe@È-^*ö[ƒ1ç'¤  ¶ÒH†‘ `±ºÀC´’¼¸mW‡–†ÿ´»\zm·ÃÍ8 eÉ--$ÝÍo,~ (¥y>ÍÌsäÅKAN-F7ÛÒ4’a”(Y‘‰Ä˜BâC"åˆT )·Dw$ÆÈf»cGBL()ñ!’ÓBJ’”*\p4mO]5Dï %H7„t"åD‘ãó™®9Ñn®i›¤)WLµ!§HðRÎ4­&'Ø´×èà#ËâÇ%g”~Áa¿cr¬¾x•k]#Tõh*Û£”D6 rKm:bòLî-khPÊR7šº®îLJšÕG¨µÔhUÓt5Ó$9ŸVêf¦©49Ô«©$aô¡i!ºVRçŽy,˜æ,,!Dr.öQß½yà÷X©9'îîϨˆ*±yÙñÙg;žÓÑãýJÓm°UÍ8%R:±N [Uh¿eZ'´Z¢e\N¤©hÍ— bè¶ ã¹<ô›«–›Ã žÏgΣ§ë!$Ƴ£²–xqØMÉò ‘7œçˆ»îP‘t†ìpË@2ÐÒVsbFi Òb+Y"±„”8>/8¹~Q#…D¥T¬ÚT*VÕr‹ŠÈˆ±‰ª)ijŠ'„ÎäXÜ”O'mË—?Rtf¿ûs²s<>±[þ|cHñ–Ó´”ígl Öà§L]U$)0ösR ô½¡2;Rrh]¡eâÃû3Uyõê†a(°Ëº¶¤\ãÃ3"¯Ä ɶ;KóÉ2‚¬1Ò’E"&O ‚q1ÖÐö‰®—ÄUpÿxF*GS)\¤(ÈI³FGHc6 +¼w¤4¢C`ßí©›Àì"™,¯XÖ›Þ"´ÀyÈAãÝŒ– ¥:¤.öÜ}ß³é•ÑÌ“¤ª[®¶uŸJO·Ù ¥gšOÈe¥oª²áejRJ¬Kdš-œž<¦ø8ŽÕÅŒ³¤æ ñyB,Ðm$u-HA#Q:!»Àûç'RøÕ£T Ù0ž=«©ë†ûyFmšâ˧jRNŒç…ežé¶-]§€@k+r®yžï±vƒªzb\fâtLÄ0r³ïémC¾“ì·[‚ƒf7Ò4êÆ’“æ#±B.%EˆBDÜ,/”èÂkPÂp}}ÅâFÖ .1ïp^Ñ4 9 ¼ŸPjEÊ+®÷7×-Çç'–¹€crH%Ðu,‚®u!©c%•­Y‚GjÐZ“£'MÓ„ž‘±Ù uât>²®!4Z¶TµBIOðg¬LÓ„‚®nËûj#}s@EÁÛ‡{”Úp»?ð|zO®{¤Üó<ž‘Ù ’éPBÐn,«“( m[xÓ¨A·‚ÅeÄ ÏOÏÜ|þ›îÀÛ‡{æåž®« ©»@G$J„ÐTu‡ÖÅãqYŒîœÇÍwˆœhì R9†Ó²m·´/ÔváíÓRš©ªOÇ#,BT$Úf5ÊZŽÓŠúûÿà§UW Û®'åŒ[#Z d…T·LH-hºžWÜ:w 2Á/˜ª¤g‹PÒ4ö2³Ì39k–9áBÀÚȺ.%UÍ’eœAfš¦a] »í-#19úö c,ÏÇ#Ó:Q[‹2’œHY¡ä„Ò•­8쮸޿ éV®owô}Ǧ¿¢ï4Ó|æû¯ïŽ U[q÷õ3Ó|âå§R”(¥©9 ”-VU1²º"ÉY`j…6’°ŒäÙí´n8>/µà|À»„,ΰKbÏäìI æ)•Ÿ!nòLîÈèÖ‹à¥xÁçñÎáýJL¡Œ–²eŽdvû¥ޯŻQ7ŸF¾þí¾úí#§ç…vÓÒ4ª2áY\`=9ø‚N—eœTP VÕhï‰"3»XXqUÂTàÜÊxÈ9Ò49IŒÍä¨QªFJCŽeZY¦•®¯¸¹ÙÓŠe-ëº"³F™ÒðªÔ¶ I[uh¹e +Á/X­ŠDZêâcWIú^‚¼Œ‰uEÌ S%¼,s*{ ÓHÓÔ|üâ#š^s÷tD¤LmË®EÎ-J®1¶4¦ç%Ú6ÄnDHEUטJÐÚž®Þ0­g¤¶ÄPB"µfžFÖÅ‘EÂ9‡R†”kð,kAÓ) Ã8 PHZY´íJ§~]©êMS‘¢ûým.Dá+Jm±Ê`µ"¤ÀùtBiEU·ômCeº¦aÓV]±ë{mG •ÔºÁEW21a¨Û–ëÝ+ºÆ0Í#ÓPþ/ÿ诌rhUÜGcÐxð!B.iˆl·»‚°J+FKR6ŒÃ‘i|z%q~$„H ò⯕#g‡­²L畦ktÌ‹Ç\¬¿Œ–H ‡~GŒžÙOlû+ŒR,a §X ÑctŶ۠t"FÁÏô]T0cAWáÉYC&EIU7k¨« ­ >©ËˆnD©úÒ0”캞u"Sâç¿|âáÛo‘uÃ?~ɦSe¼”5«OSQ5¦|Ïu"®¥$UµA(X’'‹rø­Uì÷[´Q™gW¼î¼ \²±”`Y¼ «hº2]×uõ!#„¸°Î²”UËë Ú*Öub8Ÿñ9YPR] ¥«ë{)¡rú¡'ð~F*ˆ¡,…¤î~˜†ÈëÏ:nn¯yøðá„E§ ŒE²r±šwÞá¼g»Ù³k7ÌÞ±.3Î;ÖX–‰uYÂÈyZðÞ—@&( Ðy&ÅSgÞ3Ñ;PX+™Ý™i hÕ °´­aZWNÓP›ÄÌ8”¶¤‹£•Õ–”2wóxd·»" Íi™Ö•ÁÇãù‰÷÷ß3;MSÕŒã@HMwƒÒ5óú DÚzsŽ§ã#19ÔOöê¯Æiäíû3Jfê¦&OHBx*“IÞ—_0ÌÓ@ÌšÏ%3`KÓnËâ…óxçy¥í7ÔMžu ´}Wl¶râÅÍ B+CS®·{´Ù3»"o4Ú²¬+ÇóˆP’]¿¡±õ:á¦*–JJÃDÆS5Ï gÁ÷ßùðèXóç‡3ã³#:A°™ç5óêå–/~|`Óo‰1ñ›ö-ïïÞ=ÂóÛÀñ¸ðp7’’(ý#9ŽèÏEËÐ]¼ço~ñ žï~u&ÈŒR%V”ô¤è±µ¦®$"{R —=@Šl7;êz$¤®R`ê£-»î–Ïn_ÑÁýð„uU1`©kËy,ÖÑÛý­AV-·/znn }'I©ÆØ­4Æ”ªX— yEÛ ¥-BrÖheèzͦW4U„œ‘Bb¬`õ·jrœðñT€ªÓôH*kŠìwðdçŠY˜Ð5P6¢uV’D¸ì̸uAJC¼ôªª¡©zb.¶ã)•Kȃ©èÞĉ>!Eàææ%Ûv‡ Ê&lÚ!³Æ……ãð„¤ãz &Ïãã)†K 0¥¬#°,#Ãä ÁÝDmÓ1R×E§TÙ{XWwÉjêzCe"9 bÒÅLWZ6½F Ë0;¼‹HukÉye]f¦”4­b8?#¥åÅÕ-BœwD7’Éd©ç‘ûûmtÙ~t+1”±õqœ‡™Ó4— noî¾g˜'öýJ†åDŽ–y}f˜ž.S‰ú—þòË¿rÎ⃣n2mWãÝL&Ñ55RiVçD mZ”ż0kš¦æöê«ózÆÅå⾫Ë"…›©ë 1–1—6kL¡².n0ZcÆùÈãù¥$ZWE«-«ÏˆäQRâ¼#„‰¬l]¸ ïZÕ6êºâ|>ó«¿y ‰µ$ ÉÝì¹Ùd~ò£+ö׺>ƒ@« Óˆ¼ H]Ù£¢£Ù+ÚÆP›e«K –©ì¥ O§Ä:ÏTZ°9ô¼º­‘Z2O31&–%Üùb¦RJe)d„ª©ê¾d :¢¤(ÎF”çŸ}$Ä‘ÅÏh!IiŇHJWb ÌD¨jè˦/ J! …÷…1ÓÊ8N(¥°•A™ª4»æ‰ RIºÎŠu^‘”®Rrè;º®&RÖV¥Ìd ‚+Ƙbt}E]÷H¡@d™~MÄQ•DjIW·Hepn…ìÉ9Ð4=û®¨üæu‚œÊ¦^tEÜ%~ /–Œ §„w¦ÛtH­8¤ dñÿòôË– šÞç*tuE Q…=Õ=j5f4£qÁà’[¾ ®hF3ÚÌ°Kt$ȼê¨.¹ð;ý)næ9î¿øþ’ñâ‰)ÒvÞ¯ Z›,Œ%°Ö²Ø…à-›¦aÓÞ0Ì+IXR„M·£k;Æq&8‡s;ƒ”"{ébŠlúžº®¹Œ#ÆH´*°«§®rÉkõ3Fóúg—”…¡ª ʲf×ï¦$¥@ð<ÞN´UOa*¬[v¤m ŒÊ׊ºnóéÆ¿nêüoQ IDAToRÕ-BjÖ5âý‚T‚eXíJDÓ× eU’ÏWÈ÷ÿøi¥©%R¶fH–¢(©ê–Õfüõ¦Ïþ£Rù ål6[nvBŒ ÓÄ8YœÍá†à`Z!HŠBÒ–5E‘m±HºMÓ’­§Xýˆs'DÊv‰O W¤ô¿2N3AÍ(] dE ŽÕæ¥[mjªÊ ¤`š"_Ï|þøÄü²R¤¤,ušév¾ùÝ[¾ý°§«+¦e¤í ö·=}W1.‘$FLùrÓf8fS±Ýo²*œµØ5o¸ Øî:Þ¿ï¨Ûˆw9NêcMJ9àìÿX|É[ïR5Te)J†ae™f¤JÌóÊ8_ñaæñüÄu^©ŒÈ#¦¢¨ /5¯KÀ-äÿøJìSb”\/Õ-h¥¢Äº‰ iK¬³¸U°¬3!F”¬^‡1vMHUP–šÕY–ÕQ–%Rx¯iºœ•wnARäh™×£ÛvCÛ)„„®Ï—à)o…‰˜Âä ´Èæ»Ý-uYe€¬·¬vÂÚ@Lš®®)‹tnÎ…@^q–SdµÝ:‹‹–¶Ü°©î‰rພY…V-H ‘MÝòææ7¯FÄèDY(”©±k~I#Ùnniê“Pd‡fšÁ5uS eIJ>ׇm@hŦßÒŠy9£dÀy’‘·7_aª†óõ g=ûí ÚL¥rˆKJÚ²b\FÎ× Z ÚºÇz‡Hž4e çF«×J³@¤€1’¦mHa%&÷Ža8¢bÓï(ÊürwÎã½ãn .kæe‡õÇüö;) i+¤„=¦( A d‰’à"‰I|-ÑÌÓ ¥EÙpº,OLa¸;ÜS—5§i¤SŒ,¹,W}OJ–Óé ZÊåM »H¼·˜²¦ív(¥HÁ¼ç:Í,«C«Hdص7e°ë€³!+R\¯#Ÿ¾œùë_~á—Ï+Ã\båÂÛ¯ßpóUÏê=×És÷Õ¯¾Þqwè©Š‚¨ÊHŒÖh­Ùöon J9ªMCß”tD(™-=4‚‚y‘ÚqÿfËnÛ±ÙAÓ bp-eÙ0‚ó(µ¡(Ò(R,0zOÛæÉòi¸²,'šú–¯î¿%Æ…Ë°P˜Ž¾ß’’ÀyMˆShv] ][s³¡l ò¼¡§,5J ¢0%R%¬ÏmǦiØ6•.˜—ÜTJ¡”#F ÇcO„8âÝÊb!(–Õ"’D EJ’ÛÝm4Ãu¡©;ÞßßÒµ« ”JSW%˼PU ­k"FELQàSçX»¢”D(Ãê–œH‚y¶(m(+ƒ³Še]pnÁ(‰]"Þ_¨*ƒ65eAÌ´Ý–]û†BG¼O “¥,kœõV» ¥©X½¥k¤’„¸Ùî $¦iB(Ï~sÏÍö=J ®ÓDJ’¦ÍŽSŒ.?m øS49ÝjW\ô]C© Ö^³MY¿Á9Áéôkçü93»NŒãŒ÷1¿ÎHm eÕPã2`¤fÛíHR’¤Æ%ëêÑR4â ›(Š2נוqø•M÷–úÝ 4’—Ë@Š­#)yª¢"$Áé´¢#E¡Ada§¨Z|ÈÁ ½D\H„¨˜hÛ’áz~ÂÛĺ8Ü3_>9–a ¿éÑbÂÚÈãÉcî oÎUÜîÞãý̯Ÿáx|Îyqé0¯÷«²H©‘R±†Äº”jY— ‘j¤QØÕ²Xϲ.,6¡U‰w‘ÕŽüúyàãÏ/„9 Ò µ°ÜÞ}}Ï»÷-_¸cbˆ¬ëÀ/K4ˆŠ”2PD)ÇþЂ!DÍ&̘BP DÉê,ZE¤Hµ¤ßv­Iqú¬”W )o¸\×óßÿó‘øwüvÛbL®S±Ìc¬Èœ­OÊáÓʶß2{—sKäx^ ÎÓ4!4g'Xý‚–YÍÆà¦ï „Ü!D¤í5ºˆ—óù.:ªŒÑ¸è‘"¿¥ƒwìÚ–¶ÔœF—7ªÜoªÌ­§aÅY]f”V„("ç0;RÖдQFœ ØU¢*ͼÌ8?¾öG4ë ~FÈDÞy´ëÄbÏ•Ø–mFÌA’%Ö^Xl)™màz~¢,7¹àæ¡@` Q eÀs:Ÿˆ!àüÀå¼Ê%¥”uÁÇÇŸÁðæfƒK´´ÔT¥!6Ãùò ÓxBh‰ÒïWÊZã–™‡‡+m+PZ’¢B(Xg‹ÐŽiYy[|MßÕœ§‰ÙFÎÓ#n]©È#«eES6Ôºà,gÎç3ótåöæ–R®ëL­]»§¯jÆéŠ #3Eå¸÷ ãÕ᪬ÄÙJ7tÝ!J¬¬ëˆw‘®ÕD!ˆ€TšNè-‰±ÂyAßè¤øñtæx¼¼VXuÛò§?5h•[qUµ§l4§Ó‰Ÿ?~" ‰%?ýë/\¯ñŸ,‡ú††È8gO¤¨$P–=ÞM¬> ¤¡®:úªb^3‘¶ˆ<ý2óéêhÛ‘½è¨w-O/_~úÂyv¼}“¸­JLß~{ƒ&òÃ÷r@ª JyRô}M×Æq%¥’_>_9?¾`ª= …QûûŠÊ[|X€…¶ÑtÛ"쪰οrræ:XI°W|ô}K Žy^jÅGϸxæé‰ÏOw) Çp©ä Í®£mJ„–4]ƒÑŠŸ>~b³Ý°isƒR )~âéù·´ía‡f‹V‰_ŸâáÑa”¡®û\Ð* ª€‰ÕŽhÝÒw¹d2O‚Yx|¼b<ÃXV«ôm˶íY¼Ã˜™uZp6#ÏuEÑr¾x†ëJÝæ¶ÛóËŠR‚ª– ×ç¯TuÍpŸF Ÿ~|hsCŽDŒ>_O‚ÄKJ k%R®ÔÕmî›,%Vʪ ®«üÐS„Á¹†ÕÎt]æè•Öxgç ÉKRéÚÌŽ:_.\¯'Œiyx‘X?S¨&ë-I¾>øWVçðþDÛm_çË+*SòËåB]6|ýfÇ8¿ðü\’RBh‹R’—ñ‰È– B\¸\ŸH1 ¤k{š¦C …–šƒ.䊳R†¢¨`]y:¾`” ®*«˜ç+¯-0DZ(ë-Râ²` Aa %GˆùÐnnhš†çëÏçh™°Ap9Ol6 ÑeØŒ B}óíÛ- Oß4—øÛßùá‡ÓkA%òrœékÍîS|‹] 1 ©¸¾\™cBÈ@p+uÝÖt1 e±E+‘›ËEÅaÓÓT5>,” ˜—‰Ë8àƒe^,?N<þta¾Ì¼g¦éÌuˆ<{”ât¼P–uSàôuCðŠ@.Õ\.Žª9dDqÞ³Ì)%åkzN÷Zü1l¶ÚHŒÑ( ËrÂ9OŒšgR’aÐ""ÉÞ~#ë<¡ ÔM™¯ÊFPŠÂ´ÒtýS¬½ ¯‚.™§)…ѬëÌËùÄ0œÐ…A›¬Á”Z£U.¸ ‘+ÒÃ8°º ï""IʤªpË̼¾öHŒÌ“÷BàCÂC[—8{æ|=â£Êí×q±}áóOO Bì)¢g[9d]“bbNüò)c…Œ)9]"——ü5’±”:¢‚§j%ý¶Êåà8>Xw¢«;Ž×'ªº§+6<ŸŽye³= Q|ùåW¾|ˆ^¢\âäÓe`½Dœ¹¡ Š8½à‹ÄÛ·;Yeî[Éá¾AÖ ‡CÁnk(èûç2g».kΗ _N3^¾%¨-"æÇ'n߸½ëˆ!ëÃðÄñÅ£âþæ@ÛlXÖi¾R izvíë®\¦‘eV”:__~ûᎦ1üüëvIú†m% h>?ÏœŸF¢LH£¸\Wf†ëš³êúÌêg°óº0®YÑæ¾ÿø…Õ9öû …–hSdy)0¯+Û®§ëv óÄõò8š®FÅx]ÑZp³¿ÃÅ•Õ:Ü(+Ãáæ-ÖFëQRƒ#‘AŸ)%îw;¼_Æ'LQäb”sx7’Rb¼ZŒN4uh ”lQJ°ë7´U•ó RS™’eÐBÑ5[\th(JƒuSþ{*xss‡¬X­d±3… ¹(GRŠ(¥±.ÃœÅ<)ꊮk0…ÉIÅPp¸eÛ6øò$ˆ\¯Sî6´‘ÂëøhÊ×=™‡…iv4í!ÞO˜¢~uR4¦¨ QÑ5=}}Ãê.DŸ3 e©H1é©°va^.8´N©™¦ âÊ8 ï6Lv$FGSo(Ê%ÀZÏp…uqLƒÅûm Rª"‘RIL)À»+!Fêv‡·3Î/l¶*£I1?$«Ú þÿýûÎEÉËø+UÙ£æÇŸ^xxQH¯éõY%êÝž¦«Ç?ž¹|>á—•ãˉçãˆ[Ý6±=4ô]…’‘»w ïÞ÷´ÝŽËõÊOŸY—€Öšy•,Ö£µf&\´vw¼Ýý$Éeº‚ЬӅi©µF7L‚Yð0œ¨š‰B‰)#u]½Âõ\¾ßÇSnEKW7ĸ0N3J•Ý0Ÿ^f“=øQaaÿ¦çî¶%¦Ä<{ˆ]¬´ý–at|ùõÈõê_[| ï-›¶¥(*ÖeÊ{JPŠÃ.‡•¦%QH…ˆã¥DyhvPê†ãË„ Žé|åü)Ó\꾦nÎÍœÏ×, 9ÇéôÀ0ž0EEiL!p~ņ™” ´É%¤”Tþ•`ZæWà¥âz¶ù gÞÜì˜Ö ÓtÊ©E;³Ý¸Ùo°ÞãVûÚi˜(Ë€ŠyŠ„¨`ÌËÃÊ4¸%àœ`\ 0+U“Ù_ÖBµƒ¤¨ê m ÆñÂlóÂí8/6·!q¯@Àº2´U.è„0ñáÝÙoÞó|>2­žexz™!,tmEU× „(1Úc$…€R¹Ð5¹xöôò„s3‡íŽÕ;lðh©i@&IUw9z« u]£•fZ<Τ–)©›‚¦.¹œ–Õå“ÆPªD™Èåü‚u#MÕRWQ$”6x·Ð” ]Ý‘„hØö5û~‡ è¦ì-‰Ç—¦„  œ¥œS8°‹%¸HÕTå-6:b (áhê¥+–eF™‚®j¹Ù¨ë–yÎñü›m÷*ªÎ¨ÿåú‡ï~|þ•<ƒ·¥›mK»1Þ5lozûȶÕ45(Q1Z˜ìÂrŒŒÇf‡7;¾ù°áp(ÙïÛ}ƒ.¼Éõ·>–\Á—‡Ë)rfÆÉCØU²ú /Ï_HÉp÷¦¢m5>ÎD³ã~³g³-ÙÜ(>¼»£« Ë8QwonL³çû¾ðã¿ uG°¹ŒQ7·ÝðrZøë__øñÏgñ%ï¿~Ãí¡çå剧ã‘iMÌS@ÈHÝTìw%Q&ÆѱéZnî+‚1Ô$ësF½œÙÝTì·=É:fQ@ÈJw]U­‰)¡L‰1ÎYtÑRÆñˆ’¯ß|@ÈŒëªjMY*6ÝÑŽ!P¢ã|õ¼£´b¿}ËõúŸ~b™æ5#K«B¢ô!JD²8¿ e~©8—ðÑ 4´eÅ0Nœ/º¶fÓöLó„ -k\Ìó’#àRç/º)(Áz‡w‘¶k‘‚›‘"„duÕ²=ÔxX— Z—H¡ña&’û 1Š\ ‰Åb T¥¡«2Íw±3)vý¶Uƒ“‰}ƒH¥©¹#Ëš7/I Úhº®Ç¹lßßÝP–Ë:¡¤"EQ`Š‘uu@IÍux"¤H‰,ÖÔÇÓüÝ4Mì7F—$!(JÉn³eÓKê&‚ÄÛeÁiÞ”ÍÓu&ÚÊ J†a@ÅY¤)iª=ÂÖ<¿ üôyâxn£âr |~aZ9¥)Ù¶%Ÿ_þúçGÎÇ¥2ë¼îkŠ²$xÇž©Û;ÉïÞÿžvg¨6¿ýfÃ~Ûòðxæ/ÿý_ÑKKˆ5vˆLãŸ?^øË_9~a¶U§(kèjÏû¯#]Wah#óÛ«HU°.‘/¿ŽDJ’©¹>þÄ<Ìܼ»! xyq|þ21Ãyâáaáéú–kæYжȧï?qýôÌóË•qžyy¾ËiȧŒ¦ t­ÁûÄ<_Pjd²žãef±GˆžºêQ1ÎDt„¸ u†qdNEÍ8Ÿxz9a¤' …šÝÞÑ5{|XQÒ2M!"Rš²äíÛ{ÞßïQIðëÃ#ójé7ʲÁ(u+.&æeD °Ú„‘]Û¡¥Ê'и e•õ•°"E¶½ËÒPUS¹Ú¬›ªáÍá-R8®ã…u]P2s$œµ —•ë8¢d`ÛvÌvev+ÎHYóÍýïùj§¨Š-F÷®´MAr†aºbtCJ‚$­üüã…é<°Ý´x-øéÇ#~ P5\–Äò|¢¿¹aw³e³)ië;ä O_>óñsd²!#…wT¥B×Æ µ–l›-½òñ¯ÉK®O'\œÎ‘ÓÕùräã‹ã‡¿¼DbsÈd›¾m8l[Æuà:<|š ¢6)‘JI*4u·‡–—Ëßÿò™iº‚J´]àþ®¢j – $Šn£h» 1‚w#ëšxzóóOW¦óÊp>s::ÆVï8Üj©[E p|™¹ \N 7GäzåûyAšÈvw‹Ô†€G™ša„q´JÓw5ºh‰ÑP˜ˆ9(¥µeQÜ`ZfŠBÓ4†mŸ¿x$“—…´Î:ŠÝထb~ÜìKâáòLYÚ¶%¸‰y1`­Ãû€H.ûÛ »®£. \ð¯ÅÉ8¯orP"Rü\‚iŽüôñ™B[ÞÞ…Šçó/Sâ½Ä¹€’ŽyÌ"qÓVl7·²¬CÖ´!ºH½é(;O¼®¼¬Ç)O‹»’Òä܈÷ )®˜JS–v Lnf¶#vñ5ìû ÁãËSþýxo‰Á¡U>åØÅ’‚B›ª¡î 5 ç/ÀHEU;fãäøükdvî˜ü‰/nf™¥V˜ÍŽ…ì)·‡öw‡}Gô‘Å> Û€¬#EZ(§‘ÉŽL›’ÙððRà êÂKìÃÈíMDŠ•!Ô„GÏrý•B(šÚ¼ ö‚Ë´`ý@W´Ä4s™2YÞÝÝñümàéËýMÁáÐÁëën¸¹Ý3NÓy¦ª4u)°‹e½BÕ45Ö^Y§•Óe%AY(n5þ¯¿rIž»ßv›7B› ã½cò î2óß_um誣5UÙpŒ^éº}["¡H…’š¶4› óð…úf{×Q7‚$nPÒS%J•hsež,Ÿÿõî¶ÁÚ7>òt0¼½oPR4<¾|æËSàrvìº!¾'IzEú„Ÿ)J>|¸a¸*>>-¸:òþÃó—°$Báp‹âûaÃÓ ~ù2róXðþë-_ýQR½(ÄâØ7‰u]9ŽŸ‘th]‘Ràxt<>Žè W¤)ªâ-JKN—gˆwwTÊEŸh$ÞÁ#SƒŒ37»=)z¦y`Y²àDbu°ÛØÅ#h!YýÊâÎ<=Þq>ÂÃé#…)qÁs>Í”ú~ûjçHe .[”›Ý…M]²Ä@£7h8Hç §ãϔՆ¦ª.ðp:b]xÔU‹†ÙÌ늎²ÎŸBJ‚¢Ý1¯–J8~ýò?}ŠØe ªEÓãæÈé|%x‰)ÖÜφzÛ#¥@D‹U5Pàì„]'\()en·:/ó‚)W´ÊŸõºïñ–èQeBmî7ß½{wàÍ~ƒžóu`]œó|üqáoý•ÙZ¨·x#(Ó@ßWœNœwL«"†ˆ1É'êràp×Òõ»NïJÓìúæ«ßÜòïÿáO¼ùzËí!pÿUÍîvK !Z&¯± 5g(<Ða´V¼Û’îÙï š:eÚ¬Ès}¥î0µ¡ÙÔìö’7÷-»mOY”4¡¨Øï[š:Ÿ” (­éëžMß’ÅÙLqÆ…$[º¾@—ŠÝ®ãë^òþ7nî[ ²ßI6ÛšeIÔ5ëÂù¸r–Œ–Vž$¯’3¥Q”…%2‡@—h2r{¨¹»cY<—«¥éjÚ¶DHÁ2y>­+ .1_f„\iJÉí›=7·[ªºÂ.‚/®Ç‘¶†õ‹ãÝ7·t-ŒåþFòÕoßàbÏ¿~Zøñø„²ï¾:ðþ«Ì ør˜ùt±áèK¤Ñ\O+û~eèØl[¶;‰_Ïç oÞøãþÄþë­1ZŽ3ùÛÃyÀ®+?þ¼ Dàíû}s›ù’)R Úh¬ˆTà“çéôD°í÷¤`¦•iN™µ/Ëœåëk¿e×mÒ DCW5Ìë…çÓ‰ôjO–U’ŽRåùî$$EQ£C ˜Ö•ã債‚„ÂÅëõHˆ¹Ñ4 FK–e"†Q®ê–~ÓRV´â쌎ªÐtmÅ´\€‚¾ï2 džYÖ‰ºj1JqFBÄñÞf®¤®Ðª EIˆŽyÊ9–›Ý· ¦ñ‰®ïiÚ.—¢’Äè‚ͶÁhÍj=.&B (ª<+æ”uÒÎ9RZØô[Ôø/ß~×ÔÊ‚¾ë©tĹ+!Œ‚íÆÐ5pè4»jáþºm甕"IÇ8žaÀ^¿0‰š››Ž®ÍS.Ë*©ê’MW`}†(Þîo¨Ú@Y¶Û’›Ã†Ý®G–}—g¦ª®¡PšË¤‰1cÁÙuTÚsw£ÑeAYvX»dˆb”\gŸVµ@Jw& ‚ÃÙ™ÕZœ·xó<ÂD[inv7TUEŠ0Î ÞC m"ß|uGÛv¤(èú’m·¡nk’Z$Þ¾íÐ*ðÓ½0»m$2ìùHQ×9§_c¯Îf«çµ2JÒ Ó²fÞÿ¼hNÏ—¼»ø2Q– d‘)8W•¼ jz‚,§‰·¶ÜÞ·TuŽÞÚ%Ð4e]ÒmZ·ˆ•»û[¶û }øwܽÝìÀßša}d[Ì GÉí»oßV(eè·ŠÃÝ–ûw;n‰M=ñáÆ·_¿c²žóq@¥Èå<ñùGÏ7ø–o¾>`ÝÈÏ?>‚ãÍþÀm_…E¤D=ŸO¼û°ãë·ïY¬çŸÿùg¾ÿñ‘e°sfêµmÁÛ›¯©ª —ñ„µ+RæŽBnÌkb 8Qª¡¬*‚óxoѦ¡*;–åÈ8¬¬ócjªªA Çj‡|6Å¿©êÎy¬cáV0¦ h%I”H!ðáL+!D”)‘¢‚m—3ùÖ& ¢¨94eÞŠ¢Â­ùîoʆ²–ìÚŠqRÌó3ZW¬Sć‰a®xxôjB/¾<_Ø´†¢,9ì ý¦ÇÚ€wþD›oÞÜÜHQr>Ž$™Qg1èr¤V÷[©÷z IDAT4}ÉÓù‡$R¶ox9üòÃϸxO·©xøaàí×`ÔÈÓc ¤Ä~·§*:N×+óÕ!Õ U“©HZï矿d•v{þõã#Çã'æçgìšè6{ ›w5ª=ððñ…›û†»7¢8çÑ:á‡3™øžÄŸþóÈ7¿»e4ýëå8L:å)´ª$¤Äx½¢µÊ˜×ÌSà×ÓÊöû?ýúLbåp×s9•x¿0SöʃDJGšŸ¹ k»ƒ`Ûíé›[b4üòå'Ú~‡)J¦qè(*ò„&N×’u ×3uë¨Ê]´”‚ÌMpùä@*ó‰)©ë ŠiÊ)5MQq]gÚ¶EˆÓ|~Í¿Žç/Ø!Õ¬ëȦÕtÝ7 Ó•y‰bX(Ê 1FBXØm¶5×é-Kœ‹Ünn¨‹’OLJ@ —,—aE JšÖR7=ÉãñÌé´R*KRŠ»ƒÉ’TmÅ2yˆ†^ƒê-­0lâ»Wjj¤ª68¿ãBˆ5Ί´Ðª÷o¸Ù|æéñžÀD©#]µ`G‡‹%ýVqsWòæ«’®ƒª |m¶È$©?¿ð8ÌóLÕß³ÛŠBR5-)½Á!&–—@ð m{‹‰e UI¸U-M#QR`fñR‡)Ú×;ºg`#ª˜™§€6e&æ’KRv¹2])*>üñ@ #íÖPUÓhY¦#u[Ñ7;šª™XÖ+B"–þE™’ó 6Í‚”7<è ¹9Ðïjʪ¦DI…[!ÍH)©+AÓ´˜R2 óeáÍÛ mW2­·yKDö»ŽeLËË÷ÿ7ÿüßž)nßÒ÷šù4± úwl6-Þ»¼øC¢.%!Ô¸U ”Ãú¤ï÷ÈoÞ2ŸF.—†›B±žž®†*xÊÆí¾ÇKOЂ›Û÷l=MW’¯µj…¨zT½PÏ1ÿ\ © “½0­#^QÞ‘~Óòæ¦'ZÇ8_òð†?QÅ.#Ó×ȲŒX·bÁ˜@Ó—\Ž0G¤DE ãkŽ¿ í¡i ´6ÔUÃËif]FºNc× B, ^Œ©$%X×!$Mû¥B¬TeOˆuʺGò–é’r¥nj¤*:±ë;´”œ‡3ë:å=Qট&Š2 ñ¹ùçù·Æf]õ(­¦kf' »4ÐjÅ{‰Rä¤*y a;æÇá|f ·wUß U•Gp”…@%UQÒ6ŠÙL㌔%ÁG®cîC³f.@õÀ4 TãèJGU- «¢ë[öûŠ¾kQ"  Áýþ·©øòò™ç/ §/Gž®„$)Š@ÝhUäõ[X—À<&LØøôó…—§+ó8à‚Ä”5!Îx§èú Úh.ËósdžòRŽ–qZÑFQUgnõ¦,Ð…Ä.ŽM[±í·H£ØÖ1X\°lº=J ¾<ýÂóóZË×%àˆV°®#v])LÞ­W*¢ Ô$úH †º.) òÑ5e¨L†u]£iš’Kœ D† [2ìU)‘IVK×oÙvÜì þðû¯ùæßÿnºüÐK22Okg ûÎÖXç°KÈh+a2hBL•Ð&¤bZÞ~Øðû?¾e»1$ºÌ³`m[‘¢'†!¦Å¡Dàæ¦ãþmÏþ°cS“¼Ç¹•$ò_ŠH°R@âXB`™-Ú”l7;ÞÞH–yÉW­¢á°Ýr¿{Ë~{ r¦*J 3BH¾zs϶k¦1[‚.§›®Ê¤"—¹úRÌ¡™'G ù3)U`Þ‚Òk³ æì‚š¢ÐÔMOŒ‚yž©ÛŠ²¬) X¹^m»×…5Zµ(åPENYÊ´¢”F ‘yŒÓ@p°˜Ê ”AËĦé Á³íjª²Æ(ͺ^²–bg†Á³,‚¦‚²Ø`—%CBœGêH·©Ù÷[Ôïÿñþ»yLXoAál…1S€’¢i© ¨²æ÷÷|ø¦£é4¥©¹\_f¾üzdl>&I@8žŸ?ã—©%!ó(„6Ä乌™glä´Âf7ñÕ‡-o¿ÚrûnËáÐQ7¹•·in FŒÑ¬.ñçù™?ÿè‘Áâí‚]<뜨û‚®€ÆÚëóäµHŠÓ9ñ÷Ÿùù—Æqe|‰¦æþfÇFÖœ®#.Œ€d¼¾=áì@J3óýNÊ×Ml»ä·ÿöí%"õK‡/½Ž|šzdgIÒSI¬[åë7RH¬iÄGKÞJ·к´ÓŒã m:*-•¥”@›ÊmöMa*¹ O§ïÐF°…B)ªØéÃäŽø(5"å!.”ê)©yîp}Š}¤èCÉŠå¾"u¦s!R£Ü†š6¦ñ@7tm­%1&*Öí¶aÖU‚ßÙnwª”„½Y¡l×£e¥–ÔNy=¢µfœ1{bÚhFÅŒÀ’BÀYxzèœaÛïø5QKÓR•ÜêÞU&JÉ(‘É%Ò Ê¶5£´úË:ÖؾQ•“'ÄÄæ#J::k°6£D%fE­Z7ÞÞßRr<ÛI+óòÆÞeɺL_±V7ɲ&æõŠTt8øîù783â%RfÆîÈ0 „¼"„b_~õHµS‹$…&±ÕÒ¢U»EH1`uá¶\1nD«Ê¶íø$±Æá:Û 15áúk9µ9ÒçËwôýöxo³–éÌÓáŒÖ™Šl(¸è‘R°ÇDÉ·Ûk%ÏÇ_ d¡°¶Cˆv¨†‡Ñ±ìwÖíŠ5F|ÚQûßýt<ô|÷ü=JjÞ¯3_ÿô3¿ýß±ù&Ô6s¾8¤°aùöó;ÿö‡Jö;*J†©bóB?¦©Q±F!e‘éºÞ 9“³ÀÊÂç_tüêÇÏ|þt ï×û†ß J …m.(ÝNt!5UfrÖ¥@Ãê=1E¤Vüê¯>ñüÔ}J5FŠšß¾Íüñ-8Ù±CȃµbM‰Z2®ë‘¢ãõ–øöM³|»±•üBX†ƒÀZÃé|FICJžè#%oHa™Ž'r¤xã4]ÇBÓ2ï¬ ƒ]1¥Â¾ßøöò·k¥ëF&rÙ9?Ç 9JÖeg>4)•} Äx£$‰T¥ í«DaŒÅ¨6P3Ƶ|;•œ¶sŒSO®í)ÄB,­L‹=Ka'F…u®³ aê;”’„ ȹ•_*™R<9ºAáìØÖµx¤’h#2¶?ßQº²¯Z |z~âùôFj^ï@ÃçËG.ÇÏ”´±®ï(Ó 9)î@ßôeųìÍ{´j踂x\ñ 9'æÅ“kâûÏØOøòÆçË_óùòk‚\¡HªL •àïˆ:ðñé31¾1¯+1*ÖåÝGÆ~`‡6¯ØÞ¨Y“ËŒ²­zb\ !r¢”=x6_PÚ ¥À‡¶I)£EÔˆ±šR2Æt óžâbT¶ýNgÛ -“èúDi®†çFÉŠT‚Ãad° ûvŸ–Ås{£VG, ·{k YºÖÔ&8u#ê¿ýÍ?ýðÝ ýzûÂÿûoÿÉËÏ¿'fK=_¿] !Ð9Áº¾|Ùyy¹R¢',¿Á4ÿwÿðO¿¤”o(ÝCm›OwvÿUcœãpè8JŽüþw3ÿõÛ/ÌóÎtè–}üû¿åýÍ“dß7R h•Ðºð›ÿö™ŸNÌž?|xvlkâíºp›#)IŒRø\x¹Þîˆ"_$‘7ÄÔs>)J¬ØNq<ŽM„²Ü8ï~y`+¶ïP]Õ¾?KâõíŽdGª„‰®saTQñ~ÇûD¡3d”Tt½â8œY¶ïsaì%Ú€ÔÓa"ÏõeN{OÊ0tŠ\ •JߨråíÚ ™B*´hÝZcF+”nLþ}ßÉ¥à:ƒ©…Eæd!'µ HZK¡¦Gw!’Š÷©>?ÿ kÍk)4’v+È’à=ÚU´êʡŘÈhíøp9q>|$ç÷ÛW¤TXÛž½é©ÕòåíhÝc­d=R´ L­£ÊcûÑ=A%Ú‰Z²DÊqê ¡0ßo‘û‘m»2/¯€Æ˜Ô2þ5“BF@nóëûŠxÔt‘•±ëÑÆq}¿üŒ,¥’é`ÂÓNð ½^«ak Ô̺$R¦1sã *U‘º£äÐÒˆŒ,ô]‡†¾»óÆž<>*‚÷„¸Q’Á0®Õ–¥Ìôã!%>®ÄÒ©µ²ñ%ÍÚ<y¾|öö3°c» Ã9,¼û/Ì÷Àǧ#úóm…ëÒ®4çIA­Mrðí…·ëF'FÒš8Nžq’œ?}æ8øø‚®=Z:„¨äà°]æÓù#F¸n3Uh¥y{½ó¿û#oÿù…ÿþ/¿æãó™T ¯¯/ø[a[·÷+B-|úîÂ/~90ô‚i8Œ‚\VÖ9òúšùÝ<~ýŠ‹|þaäïÿùž†ÛuáËú‚•i$&ÝXâŠP…_ ’¡? ë"1, £á~3¡êGÜGGN;÷Û%¯¸î#ß=ÿ ÄÂ>{„V(ݴеR „X;‹'^®o¤T0V#…&Ç룊|Aëžóå3EüÜNøX9KÏœ=¶äd¹]#ã 8žmŠ/$)z‘éð Ág¦^#„e’ZçÆ žšš¹VDpNœ†sCO• µRòŽ”ŠmÛéí‘©·Ì¾E‰agrÅN%k# !q®yS^ÉeCʈ=¹4¨…RMu9Ëêÿùó ÄdŒ="%ìÉs]_P(†Îa´ eÑ8ù2bÜ„Éšuøe¥³Š®±:°‡‚³¦Ñ¦¤¦”ÈÛÛWJ®Š÷ëÏ\¯o䪇ÏëP¹!´¥ê"2ß߈©Cš&Ô§çz¶/·7b\pÄ2ºÝl±„XûÏÔ*°nl?c©°¢Í«”H—)¥'‡ÑksEqÆÑTo*SUÁ§„Q Þ‰¥´Ì@'¦ o·•5ͤ¬)Þ“rBK;&:éú‰÷û B*ŽÇ ZiÞçWFÓ1 µBgÏô}a 7”(5£þù~þ)×ʲ,8­éú#§Ë@×[ŽãÀåh¡f”†óÓÝYöÕSD¡?hŽçžï~yfè$±xŒ6tÆ!EFÐNÇÉžøñ×0æÈË×WÖý…‚&‹“‚ÃÑpúpât¶ˆ"¸Ý"?ßGÔбGƒÿ¶0 ãÁ!€Óá{„,Ìë½[n[ ,olÞ‚·ãyþ|b{ö]ÒYÁqÌÑI!ƒ§{vüõß>ñt9ô[X¹/_ѪÃõì¤õ(a¤ªh}dè$¡xJ¥ ´„àt:!”ažW(­s]e;MsÚ@ÀiV¿à—…q:"µ&Ä -[;•Ðh±¹â¤¤÷ûÁI”T Riö¹® Jdöݳï¾!¹åÚ¨BB"ŒåãÓ'äýÖQµ…9$0ö=/ïÝ'Œ> äJÌ3) %+Î ¤N¤$°ª>æIÉ; rGÛ6¼m3R8%˜×oÌËÊx°žÂ„Pk!†}kÕ-¶oÏŸËMÛâ1]á0žùpžØüʲ½ót¼`¬æíº¶é¼Ú±zÀèJÌ;ó\é´dÛ7äЄ$ë=¡lÓŽK“ì‰O—gæío¯_°úÌØ÷=úö†Ò…®Ø×;Z;.‡+/%±ÌߧÇè |˜Ù78$½3ØîÀ–“í8»3ÜæJ dXç&ÙÖ•\vŒ‹(Ù?#í ,*ãý",ÎŽGKIGæ% ´¦ë%…Bô‘°·@˜”‚ÎHd²,!ÊLç:BŒLƒâج¡ÉoD‰¬!Ri‡ÐœQ:£ÆXKô‘eË'öæ†ÚÏKf¹·›Y,‘Rî,ú€@£$WÐÆŒ¼ßÿÈŸ^¾Ñw=Ng”T|»¾¥Û•¬fŒ”ä"š~Zœv=!G®ï3×ë!$Ö*ºNP«Å¹†Ù^sH.‚mÛÛ*, ÛCµÅ@o$Ÿ?ŽLÇ‘m7z>ç˜N¹@\à4]Ò0Ú®}c;‹ˆ‘ÃIó«óÀÓ§‰R R†ÃÄ”²3º Ÿ›¿îù|"‹_~ž±vÂhE­m2;ô™Rw–Uàú×W¤(P#aèC`:Y´<óòXmu#ûþFª=]¯ ÛÛ 5Og1¶kvÝ”¨4Dxð3‹Ö8m(9Ò9‰6Žm]ùùë„„°eœ=µ„cÔmp¤;†®G[Ëõv#çm„œX½GÔJß9R1”Z黑˜Û4º–€#N[ÂÐÓEÝúJR; xüºJ+èl[ÀjÍaYö@© !Z·ÍF©ð§÷+ó=`L&–ífX×…~ptý„ÏWªh·­&+‚h̼΢m·ꉧÃ3Ñ9b.hSPQaÍ@-Æš˜…T Jˆæ"| ڌќÏÏøàI>¶\E¤¸‘“¡ÃqÒX{æõþ3Õöœ¹mïDŸÈ¥y*s •>öU‘SA˜€_#ÊJ†á@ç<»÷ÔJc2ªöu½Æ‰÷k†v[ȉaäÜlÎRYžNqýζ/m{"+a¿´n…©™†#&E*•ûýJ6‰óó¼ßPª ˜¥Ô(•)U T!lMˆ*),„=Â(²…³î!¡þþŸ>üô§oïÄT‡#c§ÙÃÎîwŒ.tFHCŒ™”ÎXë0:"E¤ïF|ä$ÈeÃZËáp@H‹–ÞÙ‡ßÞã·•Z+!Ej-Œ½C(ÃÚdp½QtCåÇ>ðÝÇŽÏ\³ÜêBª=F¦áHΩ¥ÃŒ¤:~ñÝ…|æ|éTºÁ¡1Ô¾ïPÊ1ö#êšáÆ)b4¤¢(Ä&FÍ]C~ëôØÏ7u%Q…$Ǧ“šÆq仧ï($Þo39e´’ä(¥bt“„Hmò‡B7œèºž’ëòNç:´íþr}»¯ÑoÇ#;’K$Æü¨­î[Ó£ [$Ö,œŸð10¯¯*‡ã™¾·ì~ã~¿âC¤ï'RìHyGªQ$J5NàmÞ›aW+ª-äpÖbMOÊPòŒ3øÍ÷UðŸ_~ßâÞF!hYRbEkÍÓñ£H% „%–’ŒhÑcM³ï€y²º‡]X²m K¸CSàÝvϾfŒÉ;’«Æï )Æ©QVOP%qÙD°RöhW†&×À)ë‰>S¤”ˆ–¦!Á†×M¢[ ‰†TëlÏæ7æåʺvïÉ|*8©Z&]f”îÚ*7lX-‘Â!„'§Œ±–~ÐRã\Ƙ6ã(Å>²c }/Qßÿõá§WÆáÀ49^Þß¹^¯Ä, jjÎìÛÞ(ªDŒ1ä,Hi#J·’JíT2clëz§B*‚Û7Ú¼& sûvÚØ¡%Ì‚$øŠÖ‰œÚšÊªªÄZG‘ £zjÌëFJ^¹¯ï—ó‘_|¸p9H ÷%p:¡îAM)šmÔ-R`Þ_©Y<È/kjqKS1¶k»~ïÏ@ª†¦î­r Æ)RÜÙ÷H­üø>)#kne$Æt Btís)BHä\ÐÚ •$%ϺmĸrO|ÿáoèÌ@-3ûF\o0FB!ĵ ”dGaf‰5 IDAT°û+)ÏH2!%Nã3§áˆÒIuð8Û£ucöçTš2Ì&:Óóùxbö;{؉1àãµ6´ÍYè{‡žm›Žç©ñ÷ˆ5†¾ë‘ô 3—Ó‰iÙýÎv”ª¸_¯ä´='ºSŠ'UAŠ…˜KZdøv{Åo3BŽM/V•Êûuçþ¶Ñ;8¿£ X÷”v¬‘8;|"ìï䬈¹9÷„è8_F¬qÌwOHkt&åeCé©í¸1ÎrhmHRÈ(#©$‚ÿBJ3ýpär:°ÌQ ãÐs_î-ðäÀ‡Ú ¥ ‹¶Ó01ØŽë¶ð~}%§HgÖXöȵ0öMÎâB ‘bîõø‚í:dmƒviÚÃCŸ§Ú<@È–z´®GKÊ…ÃqÂÚ'ÔßýÓ/êúï?=SræÛë !ë4C®´Õ“h{Ý©s*)7Á`­cZ¹Ç ÄãNL±5¿T¡ä\§ã…ótn$Ø°‘âŠéšwý>_ÉÕ“k`Ù"±h";9nŸA‰¿[RJìñŒê¡‚…Í{¶ˆiAÊBÉ•ŠÃ: Ö4SÅƾ.h]1º`ìÔ"·¹½à„²h­ðÞS¥áéòLo,1ïܯ7‰nè™—ÆŧVJÍh%R3OÄÔxÖº¿ ·DÍĸ eEGHíŸÙu=çq¢sg'œYöw²(,ëJØÞ9œPËüFÎ cRX*‰×Û;µÊvÓÑcÆÆ£ïŽ<¾§ÔL¥ÝP¤r›PrGÖŽ”"_owîë̲ÜXCfF´²¤”‰ùÏ|ýfÇ-¢lJŽœO-9KJVíê\#RUŽÓДª8 #“(ÓôcÆ|ð8§Ü¢E¡×u'¦™ëürñÏgŒmz°øp<Þ® c[üuöWæõʺ$Öuær80¸‰÷ùJÉ!1¢ÏäLëêá$,U!•Æu®³˜Çwìºn„mFJÉépÂjM £ Ëê)¹)²””ÔbZ"¥iznB†¡gßÑ'JÜïW¬Î8g)Ùù!l3g›QWˆö¶ßã•-·ÛGô+R’]KîEO ;RèGEÍžœÚ©5M#ƒ™·•Ý¯tÎ6`õäê±Ú‘s&„­¹u V!R)”¨Í ™šø¥s¦IP¸®Ñ‰½7a8LŠëíFŒPK!¥d¢â‰¡°nÁ§ ½¥"1"u ¿ä”˜º¾1XpQ VKÆa¹žR4Ëì[;NT¨‚iìè'Cˆ’vP:1uËÔŠþQ~iÿ.µˆÇZ,7êqµAid¹Í•Q¶§"emRW=!…ä6æåNÉ•a”HÙ¡¤%åJŒMЙJ{éÕ 1.)b Ô*Û •Œ”m@…›fÜèö™ãüØ*9´qXeJ±n©aëUǶ-Äqýˆ1–=>‚‘†’[—$†BŠe,R( %g‚hÙ–Ô+¢ þùÿá'ë:–eAˆ„6Ž} ¶ëZü4¤°¦%ÜÖ½2õšm[Y—Óå€5ÍñžR«ç²C‡mµå: ¢²ì鷺£Ôˆ³MbImÆö’q 1ï:݉,$ó¼5Àヹ¾í‰}SíØBÆ™VPñ>C#¿”ÇÞZPØÖ¹¡¾¨LƒÅvSû…¢1Ü÷½É s©X­¨µp_fªl«-«QJµÝqNô£Aë??¨ŠÃ4bd¡J”)íäìI)5ÒŒ1©ÐÆÐ9‡€=Çö?4¬H©f!ˆÑ¶k°„š ‡ã)`Y"Ý0â\kåñigêh"_ßþ‹T2ZµdJ‚Ñ9öð˜$+‡sã*ÎöP û¶P…ät83öŽy^ضÄt< &§œ[\)¥àÌ‘®7Ô Ud¤´ ^BîëŠ6†*ÛvC+ Ra´FIÉ¥æ‡#Òµ•ªq)©E´mN)Ö¦ƒå8Žô¶çrø„³íEì:‹¥©d‚ŸÉ%RKÛVÕjpnäx¡X|¸CD‰žéÐsOˆšÙ}"ePdÆ8 "a”ÁÚœ,RU¬‹ žƒhÀZ©ech©Ùömäƒ`Ú œ"5vDi‹¶†ÞZÎãgt#+ƒ”êñÂr”ZÙ}"Ä@?8N‡Áoì{DÊJÎ+1Ý°Z!­¦ŠÝoPÈ%±n­%¥ ”ÈP#ê_þßüTKBŠÈaº0tR ž'NÓY ¹fNÓk©Ìô}Çóñ{R‰ £âr¼SbYnøýŽip}*’óႵŽëýŽT¢å ¶)kCCçÊÛýûòBÊ !$µFœ1Œ®ã8~Gg:z7!T»†º‡SmÝ^ßçGiâ™Î<ã„ÔÞò]ß?8õ°-7BLHQÛ\IrøÍã÷•=ÚŽÔ,J æ9°î‘ZÛnXÊ€ÓôÄq<âÃTZpeYV–û Q3ÃصO¡²?Rx•ãt AH+çÃ…¿:?£´fKC¦õßáãB¥Ò™ŽÑ5€DJ‰ež‘²0ŽŽ”2×;¸®"ñhÓs> ”ZØöú6úQʹ5"¥BHI +º‹<Ÿ~$¥È2Ï-Rj ¥F’HQñ~%øpº ¤Áç gÖ=vÓ©`¬bß·¦êVí¥/„b¹Ï(Yè{‡1)Z,9¤LJQ3>d”ÒôÆàSD¨ÁžÑrdÛ^(5‘"äT‘b…jš½XTºA6U[)<Ÿ¿ÇK®þñ9Ú39‡Qú¡ÙRJ{!¤„ÒÍI™sÄÇÖÏJãÜÔôò*•* X—+éÑ7Q¢½ Jíy:u(SH±q%´Êa)T!UŽã %%(A- êÑ°^àwÑ~¢ TCQÒ5 G°úBð)vR (-y>_øpù‘É©e'«ËøÔ†¨H¬s¸¾P²gt>œ?Q)ì~{ ÃyÄÉ%J‚ú?ÿõŸ~Š9!Aš€V‚cB«ööÚ÷;}?áœ%ŠJ"çÊØÙYƒu¬Þs¿ÏX«Ó#ÍUH¤VŒ]ÇyüÌ¡F+Ùvš´Ó(ÆB)šaèØ׆P¾Oí {¾‘k¡¤Äî_)HzÛ“ÒÊ4 n ½U\çWbNhiº—ÃØÞ¤%"a:2Œ¬A#h7S@·P8ZU¢ÿ³lC‘bÀ‡ˆÑmzNÓ™R+ë6Si«°èˆ¡ ›,÷jÙÑá¿ÿòGjÖ¼.7þñó÷ Ý3kôÜ—oM1- úúïÄé§ ÝãúvßV¼÷t½å|8#¥ÆÇ’bÓYõGFk¹Ïï ]oZv¤°2/¡ 1¬ [O|^–GHH6ý³„wRÜð^ Mâ|øUp_¿€4\¿À¨Jª jDˆÜ~Ñ\Áv°‡ D*™5lD?S§_>ª+OçOd"×û ¯ï_¹ÝÖÇkko}Y)Rñg[Š6Þ j‰(™0VÓõ#ZjÚZ¿Ôvˆ‚³¢õ¾µ| à ðr{ÇÚŽËáôØ$´’ÆëùòòNJ¾û —ãG$ #• _wÏg„NˆÚáÓJ ­,¥D2‚ÌÞŠ=æÀÓ©{œ1tA[Íí=r»Gº¡%ÈRnA¥ù¶b•åÃåsΕ@g:bØÉ"0/ a_È¥âú‰ƒëBàkÆê?þê<=¾}}gÙ_II°í‘ó4"¥à¶\É©éÊ•ÉLãDJ4ݹh#ÑÚ2gŽÃ„¡JZö½©Ë´–¤ÒRqmp%%0‡ÆeÜÂL®êˆ6’n€’+9J>^Nhk y£T(q‡qO…JâýöÂêá0©U‘Ù·ÆÜÿôô Bp¿ÍL£â0)%±¯ ·÷$çØnâÃ¥g]ß^¿Ðu=[ŒÜ¯%'¤®h=¡µ$î3B€uÃdÝâRÇ~¤–¦—B`måÃù#‡á3÷åiÚ†gßgb¬n7rÉhU™ºFž—Hª™\7Þ¯ßøö:H÷ÈËýÎËÛÊÛuc Ç ËÛ²“Š$æ̾E¶9B!úŒÒ‚‚@_ÃòVI´zBK‹O‰=Ï(]èí,|ü®ƒkǺ)¦K *emÇmÛˆqgèÊtH)©%QsBÛ- ¹&¾¼þ5ö¸`» [¸ãƼÜÑ"±,ŠÀiØÖãøÌix&Ä}Z¸çB•­îz‡ñÒ⟺gº|à¾~Åv¡Í ¢h—œÐB°—B®¥5Ô´ …¦É¢LC/çÚ¡ÔF­¤EÈÁ†í„˜Ù÷ ÄJ”+ÆÆvrk‡ˆZ2Æ4Z1Å3ô©ÏŒÓR|¹ÿŽÞöˆêø·/_™\ÅvÛVØæW¦CÏwÏŸÛŠr[)Ѐ¢yçòû¯ÿ‹§Ï||ú+¤¼¼¿òåí?pÆq¿ePã~¹r8™¦ !,(¡P¦#U()±m7¤î˜¦‘}ßxÙ0¦ãxâÃJ©[+ðì­? µB›Äipnâm¹rìz¬kÑ[wV¿qè,óš›wpÛÐQs¯Í_9_WDÉeÙæwB–¤Rˆ«ÅÚŠ¨+÷¹’µ!Þwüž8•o^q¨‘q<°—i_y ^Vp9÷•N½±òW76ÑaÙ&¡¿ú„µÖð…=]ÝBJö(URl{$„Œë5‚6™m™cAë,'Ûñz¿³m+~_ˆ!s¸ŒÄ2³í™˜*µºndêªíûB £81ØŽ}™)¥çÃÓGDI¼Ü¾sÁ醷’Ê õ"SÄÎׯ¯|8 |Û®üéý•T¹?ÂN® ÒV®÷|¬š,2Bðwjm$¥@›(ÄyfÛÚ÷¡2–ÁX¤”,é­5)(JjŸÛý†íFŠÐÔܘN ”IH i -¨È}^°òŒmtË®‡À¾ÏLã±ëYCh's­H©ˆÁÓƒÍñ¾ÝÚ/žÔR 6DU›’–%!deè Û¼ãcd8J¢»¡uKGÖZñ±’åL-†œ") œÉø97š±r–ÎõŒî>}eèz§¸Þ~‚Z‘ôø­°Üï”R¹½ ¤®B ¸Íx<+ïH©(%7ˆærgÛï@V¤Êʺ„Ϭ±0{Áæ gY^~¦ 9Qú•Ã¤Øcó-Ì/3¿uWöý†ÿ±Çu_I!ñ‡/ßZÑIrªØJ.h;áCÁ¿¿‘c¢fÉñ¢)Yâl¦¤Êím!l‚R ~óhÕá÷ÂzŸ¹.Ç“ÆhÐöµÀÞTâÉ'ÇÂ: þë?^ú¨Ä¥)½¬r\×Ä}Ÿ1¾b²âž× èJÁ¨Â-@Œ…É7²eÇWg¡¹¶Z³9v…Ú.›ewG¤Ì t8u`ÿðÌ[Õ*™Ž­*6a¬”–çÐJ‚ç>ÅÉ}»s¿¾"£s§¶ë‡nävó™¨uG‰½+fVÊXQbgp’uóH‘°úD-'œ{c]^Pjb´_®¤¤16“Ë„ £žÎ¼Þ_1fÄHË3E&ëpz¤ÖÂpúžœ=JZœüBÊž½ŽÓ5ìÜn/lþÎñxƹçv¤8 T#f%ñ1£¥hÖW¡Jî÷•RƵàHeÇŠ3FUr(§#Äw¤äWÖå äãFDaûw¾Ì_É>ŽO(cعCißÁszkéÊ$9tJ)È;)ÝÑ£ÄÒ 4(´:²……J å™&„ÒHUY½üÿ™z“ÞX¶5=ïùV™$wwÏ­Æ%Yp31dÀ6`<`À€á‰çþ3úŸPª*UÕ¹çìŽÌ̈XíçÁâ-yl‚ddf¬øš÷}^L#ïü9kÞÕ•Oö/Žo?ot]¸>MñÒ¸Töû ú®•ïäGåŒßÿÌÒ?±—Œ%ge}…Ö&êÃã쌜Á œ1‚uBÎÊ@é]øí®,Ë3WWÀàû[ãþVùãåf-·ûàË…®ä[E‡ò´‚?á^ G°ì¯駫!¿dW~œƒü0ü“¾óWáûï;ÿá?ü##\o¨_Ù‹â lœˆOŒü@zEÅ’«²mo`¦Ý(­s¿ œý ïLEc_Y¬pÔÎÙef!:ᬠ]Ѧ4?¾þÈ=i‹üöÛî…§Ôy;áåú¼}ã÷£±n_¸Œf »>ñâ~£Û„Á­TÒ_‡«ð§_!}ú/_ãù ð]2\ž“ð‡ñ•ß²…å ôFª?y¾îÕQ3¸ß~ü3å,\èX¹Õ;%?¦ÁFÞW×bxÏ¿ÓtÞØÖ[îo;ßïÓ!— 2-¹æÏ 'Ó{níӻߎÚ:¨ãbŸ¹×LÖy ä\9ÎÁ?ýéWRÚHAhÙóVï†>ÿq§íW6”œÿð5ãLfK‰K¼lâl/l)`ì•Û áÆÜßø‡ã?ñÕtT…ÇyGòAðÞwÎ}g4¸>!$¡µ“·ûøhðþ…%6Æþ•¦–OÜoØ(.Sx!ï_ùÛo{™šÿR@Æ š û;¹ØÚé»%¦Îã¦ôæç´Y:cû=óóçÊàþóoüǪ´1“†kVŽsL‡ *ÛO×9º0ºâÎ~: i™Ã[, ùBÓ¡âKà‘g ¡â0$SËëQhGæãÇ€ŒÎ·W™ÃÝt§ÊÏ\ÚÉýíw~ýÍññcÂF¾^w ö ¾Ã~7@c/¢åãóà׳ÃmÌ–.†ÀnùçÇ/ÕñO¯8 a!üäâ÷æøÃÓ»†í¤ÜùíçÁ±¿St °ÏÄÏ–«¼ñõ÷Îb 5FÚ_~ÉüýŸÜû÷vVûØ(ï_Gà…z5Ð#yXÇˉé'÷£Anìùï؃ãâÀÇ«£w¨œ1¬u¡­V œ‘3ÏÆÓŒ1õ¤vwõzüüì¤aøY…×{áþía$kéò‘·]Ùû[þtžžø›ôŒÄý&löäÍDjÙ¹ˆg‰†ëç•u{áû÷n|ÇÄë|̀žñv>sÜÛ³ð7^XŸÉ:î9Ãù@— ¬§ˆrJø†•D ËÊåã1Δâ%}âjoTžáÄŽƒ|@7Oôò' ³É.Äí‰-t¬íxç¸í‚µèA‡ ÿöÿ4ôÎRNÞÒ‚·†ëe¬Æ˜‰¹í¼¾Ý)ÃpìJ»ß¸~º ä·WúȱȘy¥~œÚ://_pV¹¿½ÒuŠž¢Åå‘ýµL+ðsbÓ†«–V|;8Á·7áã‹a‰³¤ÔÑhIÑß¿+_®‚I–ž+,¨ÊñóD}ÂyÃï¿ß Zþø7à²EÆýη¯ÕÎ5Áï7¥Ue Â£æ ŒÙÜ9Ç8›cX¥ÁÓË'œ ôýEÒmÿŽs Ã%~¾þ¤*\ü,ÑÆ^•£>'Ç>oÎÖ&Å ¨z¶ܸ˳§ñ,ÜåmÀº|däŽ8ǼO´ýkâ—xãQ„û£o\xb\.ìwþ®ÛnæÑÝé9óreü™Ð¨”¨3:íf²ç4‘ƒáåÙã­OÅz%\>ð²nž×ÄÒ~Ío|x2Ô2x}-¼\…?~~áº|¡I@Ç|Êží+[¼ðô|Å8èuð¸U./ F 9CI¼„k„×î WáÓóÆ,}tZ›Ö[k…>¨¼«@…æ…†`öÌ={J[)í%ÿÆn´>ñàËòz3¼þþŒ˜¹¬Y—Ï<Îß~ýgŽ·¶Ÿ_þ­îüüíÖÈ]?òaÙù¸|´|y~æíPî¿'Æç9ñÇ0 ʆû­RŽ‚ÑÆåC䟯,î¿xjBë5“ÛxG®Jkˆœ±Œ1@ ù†Û^H½‘ó 醬†ÅM±”iär`¥ÕÍùJkH™ˆò´&6¿"¸º-ƒÅÃÛÍðòaøêÌm5øÅkáç×ú^&ÿ¿çÚ(ü׿|ÆúÂ|Ë0žøåÉó%ܹÁß+ëq î+Ý}à¼w8Þft½WÃ_|rD¿ýcæ×!<¥DÛ+ûâù¼Úiøùµ²¼,ؽpÏ¿sùü…gó‰¼ÿ ûX¸ÅÓô÷B0ß)Ÿþ†¿Ð¿Ü¨Ï÷¿SÜþC}¿’+ÜnÛº±XÇ×Û ¸1þ½´ûóõç÷ë_•OÖñ­ÿ|ÿ¾ƒ<1\ÿòºá·sçí|ãC~!þëÀ“dö²ÓijÊe‚OMç%~>v$üóŒ'?$ŒÒJÂIaëƒ#ŒùlXßÙ¶…yþÈÈ¿Róƒ?◆ȠõÎåù¯ø'{oïc†¡,žÏ~ãi+¸— ›¨9sÿ9ƒM—§/lOŠ ‘RNŽ‡`Me[<Ï^Ø |x¾RJåvTþòãÊÐÎ×Ǯϣìuº× Šô‰›×.ô>PäÖY·gœ-Ôcz Ôz¬š¡¬Û…e‹ ˆ¿s<K|f]ûQÙ™Hd IDATÏa°$òDŽ£°ï#ƒœO:†ä C¡uÅ:ázÙ8š¥ì7zîÄÍc˜Øí³pÜïXë~…Úùq*gü’*a}Â…„3“†”´ïGc‰–Ú÷=Oü˜]¦}½íÔ#c½áú´Ð´2PérázýŒì?ùÓëŽ÷–è;ƒÊ;ñ)ç9éÓÞ-~+ô¼ʺmÄ5àÇâ8Þ7]à ‚d8¢œgcxϧíäqK<Ø“ß~ÿé³Zþ›/ÏXÛùñŽ•øø—†&O8ñh¾3†g½lüòò»v>}{ÓyŠWþúcâ– ýûWõo¹l†ýÑ1æ™-TùO_>ÿ©9¾ÿþ“,¯¹Ý¿óáeåùò¯¿å¸'nŸy¼}£seó‘ýò_ѶÃãœúí-yJSî¹Mûgϸ°p]”ᙯ{¥šÆþÇÆq,„4£ÇKÔ3³\×åDø‘ãñ–é:øåË3›‹¼Õ>Í-ªˆÔG¼4®î#¯ý Æf@´PzåÅ¿ ^`âÙ{ç™ÏŸ!—Î×£€*Oº¡¾°÷F²†Ò,¦7~êN@+'µ¼Q®Ÿ÷ñ?ÄHþññàsˆ|üð Ýýîå¥$>]>ýòãDÆ OV¹Õ÷üJ~…G_øãGø¼F|f‰žQvê}e¸íyãÃÕòzïÜoó)Ñ£ulJ\Ü åè¿ÖZ.Ñá4Á÷÷§ú 9!xá<-9+VóE)û®lJm 1óFTHŸø¸\©£òãíćÉÕ;»Ö^çI^ÎÂÀÐJ%°6Ñ»â­`Œ‡1HÒb‰Þ`iÔëBÙÞTT•Ë Þ²'Ö»ùD Ï)`Æζ]§Ö…“è-C™nUí8fÈRÆC¦Î©ßMn"‚ÃÐÚcbãÄbäGmÍøañê0íÐ Ž ¡R˜Õpx¡¼íØ.0t“¼e³Y„{½ãO5Y ÚûãDþ×ÿé¿U}&„+. º%þpM¼,ÆÀëkcÛ×OŽRJ1Øò'Fo<ÌG6?f`…Æx uÁnžƒÝ’,Ä˳xÄxÖðŒw…·ý1! æÊp+‹9ˆò ˜~þœùgþ‰Ûã+] «¿0ô'Ç¡`„_R€å…½5ö³ðùi¡÷ÊÛ>³ñj´1xrm ü,Ž—hȽð}ßñvÃ[e?áõmg» Rx¢ E9©û¤}úü‚rß ·óŸa£•¯Ç'?Ó^‡‹3»þdKôÏ”z'矬ñ‚q ½6^|çÑ„*~CŽ‚5fÂ5k§ A¥Ðî·xypÜivåúqåºD‚¿ò%¼P|æÇãŽ7†—Ðá™=WîÇɇÅñùó¬dŽýAi–œO‚i´¦üÌg©,/¨¢©ï¬¾BÉ…&ƽ׊¸€(ä|P%’Òc1»r©'Þ{œkg篭“Öwknn F™~vkѳ`¼'ˆã1ÊìÀtЂ:bš£Töó'Ú,j bÁK ` q £!,ŠK7¦RµX¡…Ú…-y¶e¹ëÞ¸õA03~,·Æ‡FS~ÿö6ÉW>ÀPÂbQë¦@kè„yºyð:‡ê„ž+>Eœ±Ðáèƒ~6:3úìzY éý`‰qBaÏ9óòÖa] ýUÎ\1½2¬Á/3¡ÙuæO^Ìl‰î¸Fr+äGÁ-–zéœûƒa.8b˜&¬V£vÜ¿ûwÿášðnÅŽ“®VVÎbˆôVg g<Î û±Óï3´à­(›dBRü²RÎÁ8N²tÌ5p}^ˆZèú ¤/\Ö•¦¯ì>mí…vÿ;âö ± gwä²ò³(uüd}ÄmHô¿ØhE9Z¡—Ž‘•žKŠ`÷ãàyq<Ç+§XRèŒ`ÙÌ^;e¥— {´ñ «eñ_¨?7özâ¼ jƒ-Xb4¨qÐ ÎNQÌyÎzë *o׈±ùÒ~r ‹˜g;ïiýÆ83¼|\émB4§|ø±¦S^¿N€Šôrö†[¯4>¡ôÞ¡ ‚ÕÙcš¹­0(çÑkYBšLˆ¶“Œa5å °¦²gÅôŠéÔ$NµX*öÝ…bcéçÁèJ2Ž:íÌgª/– "Bg§¦m¥ AŠAÂ4êxgñ«3ÐÖh=àœÐ½ÁxÁgCéÓ2¥ª³±Œ¬Ôš'dF#û>ü”)9î`G¦äÌ÷­;ÒÁ¯+—¸à»!ÛÊQ2åÙãJðç gnïŠ×A鲂 P;U Ë$.¡×R¨† \`X «ÂèƒÚ *ÐÛB²“Ó.E }J¨Åeš¥šëŒz¢Æ°¬qÞød¤Ïav§³ŽÈÇm£uCÓÁþŠû›¿þ­dz+˜èfk+o:™ñ ÕBô‰-,ˆÀC"Ê“¯Ý@&àQë !zÃóêèÆÒG4ƒm¢¯hV’TÄT‚ĀьŒ†·+Z…C ]3:A,&ô9!=ÀhÅ¡;ƒ—_©Ô3£¦c|ÀŒ†ˆƒ!¹éÿgdJî ïÑúJé•l.üá9qy^yÜ+ÿüÛ+gÏ–*\£ÁÚF—v%æ¾glÚ¸¦Áýˆ`#Î4² u˜^` ‚÷øÕsìc'·üø‰¾‹¢Wj‹äs'Ÿ1Ž%öG¦`H)Ò»a‰‰b¨f!­–1¦9Åôk®X=À˜‰p·o&ºèÀϺ ƨ?“lípؤ8flUm =.-lëJ0†?¾ÓZ#¹Æ£Ñðfº$ÏŽOW†uô|Ü‚Ü;ÎBòg#ûy2ˆ hmP:ÝZ¬‡!ýýà !xV¿d0¤cÔÀ€q:|´x÷Lï'™Jõ–`,µ FÔÀ½Ï›:¨P(™Þgh¬ê`ï'£a1•1àч½2a-£Òe¡i§”6£ÎìÔ[˜èX\šÚ®Äk`ÔF-‘6N:fñèy`û”éÒ1Xz³äb©”£šÃF‡AÈ¡ö®ÅÓ14#x3¡2Úµwjúnæ¡-ƒýõÁz½ ÁÏJB XàË0(ÊÞ*¦ ½)‹KØÿûÿøÿ}­ =wð ªK'¦ +†®¼»’QÃdµKÀ ;s¶çÙ* Oo–Oœbð¸Y–Äê"[Œˆ™qÏn(£grëÓÁe`ßOÒây¾Fè³Êh}rÌ/ׄöY²„ 1p‰ [š6W¥Áhˆ©$o±:d2`ókZ0N(µáL'š<Û•1ÍtœÖ01[Î&–5MÜ·ŒÆc––(Álrs§s­ Îì|OÐ ôÁ0Š7ŠµÓfÜjE´’–€÷vF ©ÒJ‡ãƒà´“žwϲ9¬Ïh°xoÐQgÏë§'ßæÿ%ò8ï¦9K§5Uûtƒ‰s$“HÉbrq‘%L †$Ïv‰xcQ£4é[¥©]‚`Ñb1cVnƒI®1²O²ÇÕ<§•h-Xo‰!Ídõµ>7/V-Ñû÷hw@ë{”ÙíÜ1jðb0>Ìü@3ÖZ‚·\¨­à­{ç.8¤6TëöDJµ‚t¦ß‚Žäb >²:‹µ†îÀ©NMF/¼=&#!¦HS;‡tÑ1PŽû€Œh¦1¬ê$q8 ÉúD‚E,Ô‘yŒÅ…Ùæl~ÅXOïc2ýuÐÊ\-çzbt±Ð¥+Ú:ˆ’\ÀªÁ1Ó£z«HŸVþ¸,DçÈ%Srá,^*‹ó¸³;¼7 ­ˆÞqbHq›@ÊQXâŠÃñ&°÷Æy>ðvj/‚[Y̆óu`XºqÄå¶ÀðB2ÿŽÌîmàU(=ÓÚ\-‰G Äc»¡YÅ8C<­ÓÏÌa3&D¼3Ôy”ñ¼[ëféT*m@pfzã£0Š¢Î°Ä•¶ï „¸z Â=W~ü镧5ðéù#¿|üÄm¿cTX·•o¯_ùö¸³]6D gU{t´OMA­•ÎTg9#  xƒ—€Á2LEd%çÁºzzhÿB€±ÆÒµ²ˆ0\¤™¹/ÏŽ2P1”ªŒ>ðf`p˜>ižú ˆs„ä1v0tzÅZKrž:UÁyÅ;8Pm³¯ –` xpΖ`Á8ŠœŸå¸É`"ê¡æ† %Š"N¦"ÎËæéeka'Í‚cäFцŠ¢5£ Òj±êÈ­“sC}ÃeK©2q¨µ”Þ¹ÄéŸ×1V;M¢¨èð x  ç°ÉœCªÅ 0P2Ôqõ¸.˜îQ+˜ }uXëÑ猠dò¨³}pž6:ûý]fd{× ÁŠß ƒáò²áˆü8ønDžâ¤Œ3Ð{'ºHtsKxïÂí#0S™‡ºê<àºbšá²MXn¯u µŒÁ©™×æµ”Ç1¦Á íÄ=ùNN±œ¹3tà× µêð2(}⬼™{b§B¶‘ýÆýîP3Ã1>¤Ïˆ…Ö¨î(Cr¿zŒyÞÔõ™WlkÀ¥”F•ç¾5å8ç„%Ðώ˃[ýÉQë:Yóû~0†Nô¶ëàQÞ²Áu~LlÒPTœµTÝ´Ö-÷|€˜wn¿bMçãË Þ,¨ƒrLÜv×ÁèÆœ§¸pM‰f:µ*µÎî('†m ŒÇñ>äóðÈ}ÏH°<_¯,.ð¨ŠANÎëJïÓ^+Da`è¹–Dr\+9ïf4ÌôsÊHE?ÁÖe#S¸Ÿ™. Ôã‡!±–ˆE•w"­‚·ŒóĘ÷t!kÐ0(GGýäÑ›!x t>Ú©7S.»,é%~—@ísëò('«øeÍZŒVTÞ5ð¶g¼3¬É#¹NØlt“Û8E]ÊY:Þ{â°¨V?Ûªà"Áö=£VY¢#ø€h¡‰°ˆr2Ì|H ç=›nÜÊAÖÁâ<Ûuao¹ñ,=|B\Y—±Ðµ³ÌÃf~™3)@7à†íg²öÛ9+ª¥dt(Ea xí ëˆ>bSÀ‡@Îm°u@°„pâi£räLJô‘ËóÓá…³fŒ8Rš@^¼ãQœ±•öž‚*µ6î¹³8ŲŸ3rø)¬¬ËŠãì´\'5¥œ›p-\†fªTD§lÄÈ£¸â‰.ÖˆÁq+Kš¹ƒ·Ÿ7„€K‰vkSšê†tº¼ ?Sd]…š+íèl)²yO këjHÞá°œR f†1Œ>×>Î[ÎVP/„ðýŇLHŽè"zçç÷7V¿â¶ÈYKZøò%r=èRX‚§ö†5“VBð$³¢Ú¹÷k…ÖæZjr‘fŠë^Nn÷.ÆÉ€k¬Á/«ƒZ+f ââ9 µ\\¢ÖŠbÞS}Î*•®•œ£6lðxo¨çIJò>(«Ø1)bq±$“ð‹‡!Ó R<â —˜.󵬕f 1F.ÛïçSnYÆ9ö1H6ÎÒ_¸™`LUŒŸ×Úí`‰ )ZQú˜¯ýº.,Ë$ÈÒ”¦s>1THÆaÂX™1ÿÎÞ;EÆÂXaÔ3Ú`tX¶9Ïùq{!-:¨§}Gƒ›ÙfÚ! Â0ƒ‘•ãq0jgñ¥ÀžOƒó` zíd8c'©) ž7¦Í¡qöé‚ ‚ ŽÚÞ¦‰`{½ÍÖĬœ¼õxëpÆ1ÜÀK3 ñB šuF¥ôJŒžàý´w·yO¨aÎ8œ¥7¥ha? Žµ2ýÿRq8¬·úâ¥I梌ÏÏ$ç-“a~®ì Õq~Ò·þÜ Uò;ãñ±OÊ£ZɈœÁL¶¹u¬³xQt jixµîµQZ'ׄ‘w æ˜û×\ -ŸøuN¼edrùsÞ[F˜É-–YbYfÊ«È`˜rBHkäýX‡ ŽB.<ÉÆìu[§eè¥QÔ ~¶Ì·§„Ìè2g\ú7”¸ÍŽÞçà/+G)Œ.,kDQ¬Î|òû÷/—IJFLˆ•Q]„ýVÀu$ÐÁ¨'çãÄ‹_£föûNÜÒ¬¢œPj'¨#9ÏÙ26Z¢DŠm¬–¢ðãöÕŽ[­4¼XZ.´½‚’OÈb(­ã›%Ó¸Ç:yƒµ7¥tºõÄÕÏÌÁVy´Ê˜°fèeð8vŒ“ù=Ú±£Ó-ÃÑß•sÎPC+qù0Ÿº£O)ðÓç²äŒ(l1`¼P…Z”çF [Ń BÏÛ˜ðŒk°8ãßwøŽ.o,‹K8稵0ú ÷Š×†(Ä5Ñûàí|°Ä@8NXÅzøð¼ÒŠRϯ?vêuð²-k”K0Ü…C ÏË…§ucT¡VåêenJƒ\) ¶œñjÐmåjtÒ…9±’]X¼¢G§™Œ¢Ô^Q q[¸„éƒG/D°qÎ(H {9ÐkL8<:µVÄ8BWˆfö¦2 0ˆÎPšRΊŽÁ8Ù,Ëývë-½Tœ3ħmòÈëÜMoˆCPbDˆë …V h!Å•:ßwrî$oX{"Æ„:‡†à:*ç~rèêçÈ N@kCÚ`A&EU;ÈDDý8v–eÃ,–<2Áö†UhÌa[)m Bœ~tÀaÑNŽž£(ù,Jx¿c¦dë,|ÀŠp¯™rï¬~6‚ý¬œa aGõ„bw¢sØ.<òŠAs´'“SïãèÛqb\ÃÃ8e0õÈ´äxœÓ~œ‹,«A;”‘ÑcÒ†Ój-ñöع׎XÆQo;¥ÁL $Cè+Ý€w–¼W¢ñÈ2·$ 5“Tµm±`Ž=R§ïVHií$XT"ªA)bf¼mˆ™Ošþ.·ŒëûA°[BÇàx»‚'†š‰Æû™¸Zé­™`¦µ¶Å coÌAH8ë1Á0ƒ“2*i(.lJŸQXKv`æï4ÆžÿNÂÍ…&†`Ü\Õ0{^TM¥!qGêŒÁ£SúÀ½ …’ó8#œ­ó¸?h§`l$&GLŽ^NÔÍŠfûäœe]g®oo,Ë\må\'¼T,]t&/#Ð Ò)^ˆëÊ>2¶ \Št;}…R¦0çùÙ¢nÆI‹ ‹ñÀÍÐÎrdÜè8ãP xË9úü€ „äHÑ‘$qM¯7:Ö fX¢Ä‚kD1dÕƒ‘N4Ìérîõ=-‘ôa¥·ÁYC¬A­¥öÆ>ºêÙqç^¨·`„Å{J—Ž—€'¢’±1sñÉ'2mcâŬŸï_ž‰U­w4WÄZža2”¬ NÁ‹]¦Á1&ÿA½¼‹y,"¥6Úñø—ÃÖYú,”£pûvŸOu;ÑëÐrÒ™Dá¼î-s] ìçA«í=ê[°>±ßö·;×í—àµÌjÌcg4üyÇ%G¸FtÀhSJ½„ˆo†Vçuùfñk˜"¯:·?çYÈyr¡iêà‚Aìœ}ä’9Ï‚ï†"gŠðdчåèÔ2J£pâý¤ÞŠ2{V+4@™‡€êÀŠÁšÈëPj«„àùxMŒ`Ð<{Ž¸`I6¢Ö#†KzBFcïç k\&ƒ¯fŒ1øhYèY0i>µ+”Fγ¯)t¬:È™‡¥”LÓëZÄmœÊ©0lTÎ9ºÑ÷Ú@ >xðî=ÙÆ]ÙÄPµs–†×B`–Ô&X’[Y|/<õØñaN£e +–SOrí¤E‘.HŸT%ÆÀ¦™ÆóØz)ĸá‡Z°b¨ª”šI6 ÖÑÄÍL<Ê9ãœã)xn¹!Þ`ã”CÜÔ¬÷AñÂ0JLŽR:F+1E.—É3T¢»Á5¬”Ò¡BŒ´Ï@S£4 FÉ'¼œ£"ïZ|Ó — ùž9ÊAžàÑÙXšö)I&ñÔÖP3“xõ½àñÆrY‚ñå`ŒN°tLt7‚‹ _bⱟˆ¸3^è51úImÛ=ÃÔ¤tÄ;¢í´³"xì"¨ŽF3lÖ¨Ôkq +ÄKdÔ +I!1â`LÝý1hF©Ò±­ržƒtõDõ8,̶È^¦ñÌ­C›ÂžQCÚ<â„|kÔ^0¥#˜ItòJ´£†qÎ{ ?æk) F‡Ì m¥ Lmä0 ŒT¾ßNڞѮì£2¸kðüÜoœG⻆G]'÷¹§3óé\S†c%SŽÆ²­3&úùeáéz¥Ô÷¡ŒŸšíǘý±q隣™‚c&åõÚ1Ö°¾óäêñ Òð1bU0 t¨µhSr¤à Þö<…4õÀ;Ïö|…Ú(÷:‡y:Þ…)qêÖ©t`K‘Õ*]•b,JÇÄÈóó‚í*•Ÿ·ŸÇÁ²­xp¶±l,ýTFçS,¬Ò8]dï•Šáâ=kZi½“dfÀ“•Ñ:â ~÷ã$^Wbt´½#mFIUkQÓñï™™ôÒðce.¢½3´sjÖK®ÁÑúÀ ,«'«¨U’úùôzo+Lm©RÂÉ  Í`´“|Ä›@7ƒ§cO ŽYͤ°`Ï9sècÐPžã‚ÚÎY*t¥ŽFЕËYªrŒ]ÃlQP"G™öçÔaõD]5Ÿ˜npÛB4 ÌùÓÑ)¶”hfØJ>iç` K4è-:æÛŒÁGEJ£˜IT²AºÿD;ø5ƒÅ¨{Ï­,˜.\·+ûyGEqÉS¥rîýì<ˆV¶ëÆó§'Œ18uS‹cÕeFŸ)„±°úë,g­Dõˆ8übõF¹ß`Ìp™è§üY¬à‚0š0 Ôœi:¨®q± VRgEoœP¥hŸª X<’r”FÙˤ;Pñ´|²Ä© £¬QÖq!™aˆj 7ÌPœ ¨tðÖàãt á³$>sÁ<ô]ÙÖ¨@‹³–”’8Zî¦"f@³˜h­e‡4&zÜ ]ç©mzqt¯h’YéLí…ä#‘ÀY*â>LyåâW´wr«ôÖp!$1úA~ý[V®KÂ"ÄèieÐÎÁyϹcD‡A¼ƒú¾Jr3iͨ Gå­ŸXcˆKbŒ€+Êb-Å8Ëóvõàƒ(†JÇš¹7W<؉ÎRÍ õRØLtx#œåDýŒhóÆÎ?7òõ–à Z*û­áRD“b»lÂDËÞ´)«÷¬!QÚ`È J&ŒˆÁϙГ–+e4ñÿãéíVdÉ–-½Ïlþ¹{DæªÚ§ô­.t©F  „ZHêFÐô#í·mgW­•îó×taQûºªVåŠtiÓÆßðŸ'ú†-¦Ê" l²qròu>‘èßuYã[«ï)g>6ï}[ìˆ6th Ñxýô—þˆ…ß>>()º­tºyç9*¡zs1³RÒFÞ ÏëE›Ø”˜Ÿ{¤µÊ÷UÙÓ†%÷TXŸÈ¬Ì¢üØ?Y@{ ÂX†&%ŽEUAKD¯ ­ 1;Bà~$¶}êv5²Ù»opóDÀyvhô{ ÄÈlë ãÀ÷7I\™hƒ1·Ûvp=õU1[dQf÷«V6ß',Œ^OºL’FÏ$ˆx€©A54»uùl.ƒÝ2Ó:)l®­A•Æ$ªSšWw ”rÏtkŒ×D§» Ÿk*[Éô9óZÄh„u6°E “÷ÕÊ÷éªQØ2»,^Ö9-Ãu²Tù(™-&ç÷ü*#jZ;ŠrË™9Œ‹Æq?@^ˆÇ~£H¢ÏÎzº§¡‰8„G¿È9“5veþÕî[ åæ2g­ƒ«_ðr¬DÜã4‚úµûyVì-±.…Í„ŒÛ¶s?vFÔç n‘:+³NnrDz³ Û÷¤•‰Na?6®m¢½þÓüŸþn¶˜µ“ŽQ¯Î“6*­Vï~œƒ:¼agiÄl0êðeÅ2¯“f×-s¢ä„©Ð—a ¼Nºu^çf!Ñæäëu–QBr‰Gü¾jkÅ»ô†‚ýe¯…] ñz 1s”ÍuXI¨ã|q;vò–8_'cNRHŽ<c¬ESxÔÆužØæ˜ôÇ ðãó7¯]ªÕ‰Gæ˾°†V‡“i¶ävdM\Ý3*Ðzç¬OdMP¡®Á*©Sè}’£'¸ÖuqÆýþI‘ÌùxÒ‡súÄœžJ"½žíª ¤ày3_¶ne'ä@“ÙœpõŽ†è¥§OC1yf ]ƒ:âõ.]­NcÒm ÀEX K© 7ha™˜QDH9s+‘¹&9GT£S¡s¦ÄÍË^Å­ÒmT¯ [ƒ[ÎlÙëºÛ¹8¯Óý!°‡0+ãôœ½Š›`Ðŵ:==i‹ˆÔ &O=Îj´5=.m‹¹¼g;Š_ ‚£ÆG±VGw­éUOÓ\ÂZsÔëÚšQR ïÏûÓóˆì Kg]ðú"o‰Y²—V!’»“c¥WÝ8‚o\W÷“ëì¬SïsÛs†Í— G‚õyÁвû)D##HT,ÖŒïï_þàÆ@ïƯŸ/zíÞ%§ÞÛ—Bàì•Œ& {0â¹ë(.ç´Y13nû#mv‰mrf‰bÍ(é:(²è³Sŧu¨1Ê ¯@Òä×—z!¦¼t¡ÙèÒ©³q_ôå˜é}½QR˹DæƪsVæw§Ž‹ë:ٶ͊FGLÍ{Ú ôœhUi¯‹¯ïŸÞ‚T;¼lUÃã´‚¼OÔÉÀXÓÛ”{4¬6zŸÈQ@‡Çz“h£BŽlšYÝ@sLï§ð¬OÖš|èÆä1^Ðm&¬.ÖUÙr‚Úùj“¸(Á fsùlöV5"HyW_ V½Ãa¬.a“ b"Z¦¾Ôùbl瀥ŠžÇîZá»MvMD[,œ´f#$eÉrnß0°Åi•Å28¯†]x/˜,šþÅÙ K­Þ:HC[ ó®`]‘9;ݪW䩱kd #¨42»Ñk¥]r&Û‚eô«QÛ‹Q ÷ÓÉOŒÅXâ“NR„´)õ9Ü0$ôÏ%ç;@’ŽB Ûžè ^ß#A uÿÒp°m™¤â^x”9Ã`Ìþnš\__ ÆQ6/J´…E´uq‰Ç°DÙSbšgõ›-L ‚RÌ7ÇkȨF—'‡qÛ“åæïëIZ 9A_„œè«ûÏ»âò HLŒl1áØ òÛ磿«¨½6þ|~9²iËXÆ[Jiu°ÅH<¼°³Ê$®å_:[f_™ð|¬}a«»‡ E$B—f¢‹ë»c1PB¢·:ÙS!™×$«Òl²Ô ÚDEHeÃÆäÈ÷nô]@‘…ÆÀ–#s)zúXˆ1µ j½H%3m"ÁX Ïu2ë`Õ+­Çd™ñ±°•³^¬ù"‘a¹t;Ç¢Ê0'4™(SA] Å: År&„ˆF¥Y¥^~ вsÚ _Û¶Ìë²0ˆsòõgç,/6™„ÃkÊhÆÊ“ºõìH÷|JŠ6õ5ˆ9rÑ‘¦£K­ö-qŽÊŸ_/4%Šq@\´6¸Æ —Ä”“Ú&‚0d9¿oBÜü༞ííÌUrÚ({!…µX¯ÁV\ãÿùë 22)CƒL& ¼.¿nÆiÐÌÖ¢”ûFD‰°Ú$ÿ¸¡AXõtÄ2LåÝ•'0;½©GDƒ³œRŠœg§· ›‹ÑüĘ&üz¾È{Dl‚bŠìêcá9m)%¢9Å%ÇÂ’@’Ûqct!oiçG\"œÝœÀ¢ËĺÑÇrÌéöûýMÑGíË[z‘Èd¢ M`ù‰'A ùq]bâØ £5þÛ÷“?~|Þ¹ïwúÕ¹†K^’]{­r~½ØnÝñp ¢ãœÂ$™Lõª¯UœªcR1’.z7Fí"—ˆ:žr›Ê?á푨óíÜÜv¢ óE º6ë䬕,‘bJ'¸Ä#£7¤/r ÀÆœ®e‰|¿*¿®1@9bwÙMc¤Oc¢&Ì”°PÈ4lØ´·º©yôy4¡ÄŒu§Õ(KaôÎñq£Äøæ \`иûâz^ž©8æû®oAÞŒ¼é±í’9¢+<¢â Ì—Ž´±ÅÈ_$±‰“‰ò–°qÑVàhZ+_TÒØȪoz0Ä¡Á÷ð®äàv÷þ¼ç…éNrÎôê²#) [D]$½cödÛ#² íUH"§²¢O!©ED×’päd(!E–ºÃ3ß3ƒÅù:ýИÆ~¿Sî½:ôIEèc¡6ØrdWã› ËB‘›¢â¬ø§›þ꬟æÓOs–™Âkx¦Šú]¡lsNêùB‚’TÈŸ!Å®‰bŒý4žcSæâ?O1E,2ñÿ~,°wAhM‰0ÃMªÞìÓÇd­·Õ×1F¦ ㇶ¿²Ñ1p E3éæåÆ*ƒ° œp¾.f€©wdz½×–3*†®ÈoGá{¼8ÏJZ‹Þu úìì5rBJ¢uœœxý¸‰±§·ž7úÕ½"{?Í † ªuzÜgbK^‰!bÑ·ôÒu5íÏ“4ÿú{æ¶ý`XCúE.ŸL¬ÕÞ_|Bb‘58ÁÔ[ŸÌ˜ÉOÔ¼6‚)£/hÚO†¾Ë5CbÚ|»ú2­žW#õIZ™ãVHæ4ÏÊãËX2‰AI‰D®Ùh}ð±%D3¯ÙÝ/ƽdBš<Ÿg&HÀþQ÷íýrÇâa²K«w’#eßd¾ŸO ,𨰄¨ÊjF˜cäœh6Hq’ò-Eêë"½B f!è/_`›Klmuº nŸ¿‘ƒÇ»÷´SswVuÇÞ|èpÜb̨F®Qßj‰Q’ó"z‡’2™ÄTe×JªJ¥3t²‡‚©¡! ÑKkFó¸o9 «]ô«úAšÇ®ä[¦j ·ë]Šé¢·ÀeFx·\ý'á?ýÇÿñï¾XðÑ ÷á=ñÈÛÎl38n;÷²£A™s¦!ËAˆ ØKâÇ~C–q]•ý¶£*$ÕÌ0eÎá]î²8rF³P碒’W1 …z¾x½*%*Á„kNÎ9™­‘ÄÐœ‘ÝGÚipH9bI}ùU›F$Eâ‘øØîoÃÀš ¯ãªÓÈÕ}±5Yôþöz—ä=ófè®H0Ƴѯæ™øÝ3x¯\ÀO£7Öšôiôå ãÆ­ÔÞAÜUv9e,CGa-¡âgµè˯ÍMGã¬|U7OÍ5 •¢¬ h!¦cnu~?n£SÛÅ Jxc¦ã-±…ÌÎ gãYnAòQ´·“«7¦ ^½ÑÇ`ËÅ—¹Ýw!cLˆ‚uáUOúÌ1É%qßÎáqÔÛ–øøïþ{rP®?"K8[Å$¸×àüFt½“qÊ ‹ý88òÁÍfD%é '%äcЯŠèB‚`([~Gp Æê,Y¤ÍƒK)À ~í]»Ëô©eEº,$+:« 1𺞃MZ–NRÌ”âx¼ÙÀÛ§9¸$DB,„0`Lj7Z½X}ÒÚB-yÉ’¹EA–—xv&ûžÙöÍ¿pk£Õ æ$iARDì¥p¼9û½ÐÎÆX‹ÉDW@²rJ?›·pk'爨pž/ÂùÏÿËßGïŒÖÞqÒÌZŽ>rÀÆâ(;Û^Þš±\Îa™,êÑÄ nÇMÁ‘Ikb³ŽSž¶Ø·ÇŽw IT…5¼ÿݯ×åÓâ¿Ì±&åHÉ3ö›Ò¯Ê¬ÍGC›l!20Î×I0wú-™Ù;³6šMÎç‰L7Æ[ô^é¶@§(‘ˆ9¤cBk½6’OšõëÝØb¦1h£¡ªÐï2 1uAHŒé'þ †¾»ßŸÍ+Ÿ£$r¸¹+m)­M^£Btÿ¿Nèþ—b OmÉe«‹_»ˆ¢¾&Ö–oñ[c5±Ç=ïÞч¡+8`¢OÚhÄ”8òNO•Ë ÌîÅgÙù—¿ÝÙoX`ô§É'«wˆ‘-DtA[ƒïçƒ[Éüøq‡™çÅü« e Öì¨,$GBP)ʞض€-}rö‹ ƒ£dN®«R_“©JŒÆJÎ{è¯AÎÞ v"V+Z”R’YBdÅ–s E‚ÒVcLWRŠDc.b‘}Ïؾ!âå÷´eÎ×É Â^ Ƥö††@82EvZí¼Ú@ÌH˘crª‘JàG<¨¯ÊÊo ­5T…jfBÚåðf¥^ëé/ ‘ãÓ›u‚e…Õ‰c‘·;¥l ð¦MÇ –uM®ó"ßv×¶× Yd<ú Š§a5%¤9øãõdv_z&–`×$îN b QÕüáÈG¡É@ºajX^l–ØK¦èNí•þú…ˆP4¢o+²c™Û~ë0€#xh'‡ÈV”¢ÃÂâ'2=­wÙb®É=oÔ^¹F%í s«MBreYJ­0ÇÀÞ…£c ‚¼5öä~Žö¨T½Ð½0Õˆ¥B¤Ûò±3 ³Z¿?Ð1¼Z—uîÇAÙ2£n´>©vÒ«RjŠ„.Hs0æìä¦ï°^BFÂdEA§q-ã£ì0OÖ¨Îÿ;a‹ŒX‘¦ùFÙ d·Bç1™G¢¯>»¦?¿‘Åy-ÂK¨}1Yü¸m¤T°ó‰²ˆá¸Dü´þ „'ÌñZuÆÒí¸âî;™)ž2¬öÞ#AЋEà2%‰ùþ$ï(ÐGeŽIH‘”Ÿæ´S¶À¼:ææ=w<ëÕÆŠP$2cD7e¿eš5ž­0ÆõâU¶63);2Î4Q[à ŠläJ̜ϧ71åB¾ebÎJÈQ~3®[¾s³VbÊÔ^Ù,’bâìéƒÛ¦,¦C$ ‚ ‚‚ÏN7¯M..ÉôœÝ9X£OhóÍøVïTbî8Œ%(:+Õ u…±0bˆhŒ<ë‹e>^u&cq»}ðû¿ÜhæEžbF2åcÿä™›unɾ»1Ê~#šr‰Ã*7MÌ>8Že¾½¾V%X:8ŽBŠÙéÁQ)7ÚÓT¿ÿíNJÊìžGÿ¶“¹%ˆûݹ°ß?˜Òy]•Q;£_Œc¶”¸•@N‰\Òœ-/8ôÆíöÁ°Ig—rÆNÐÈ.‡[*SeŽ…N_nIˆûF‰y ߀Äw´z‘6?9z› ñaÉþÐo%!q¾—Âo ø³cóéÝœ˜:Ñ¢B½&2ûçÁ¶Ý™ãâ:sRvÉL±N ™²E ƒê„úh £ÒêƲAcñ±}S¢×'Í„íþÖ‹i‹`°.ÂSáUOlvrä’)[BmÐχ+!­ÑUÉûÙ.Fm,õ/özvRJ„à=k=Ymq]žØÄõ¨¾ð.ò¾V ó9)AÉѭĶ}¸yª× 'l÷ÛöÊìÙõü"^bæ(¹™Ñáæ;›âX¹Iâ ÀU/êë$ÆÈ6»/%Óke‰Qùx”÷g xCÑd¬NÞ {؈:&¤Èj[ŒŒãƒe0ÛIŒ™¢J›¦ Ö˜<¯ŠµwÏ„_¯“vÁç–™Q}³8W›„¸9S}VB² ×Rd ¾j -ŠH1´/ε8›#¨S).—Å­ˆ)õõ¢·“$S·zŠªG'Üî7x½<…•#CÖû~n 5Ò ô¯F]¶Àû'[ Lˆ\û•ãUyŽÙdß6'Ô {¢i$:ÖŸµŒ×ó……Éý÷DZotŒ|<,oë9+’ݯStnW¤$º¸ñ#`,q‹©&a¬I[þ;赑RâÇçzvú÷/òÇÎnÅMCaIl Ë\UØ÷ƒ˜"*•X§,ž³ò‘o”è¯åwWbâ°øî þv#¨ðx<¹NgÝ·ÛÛ©æÆš†›ˆŽ’ÙSÁ^'£7Ú«’ŒîŸýL‰ëª”؉ ÿöáˆ9G®sчBÞ1Ïö#¤#ҵߴ£GL­ž8þÂ]¼Î†íp”ƒî;(ÉÈ®ö`ªQÞ¡¢WWÖ¯“PŒ-mŒs1»1BB§±m wÌ:Bç@5ê¹hõÁZ ©Ä÷aËìÈÆÀèöDfcidÆÄ=·=¢ØhUÈY±ahù+«é™Å¢öî”àÙés"ÖiDP¡µ8+{aÿ¸Q1+Ë‚çnRdöŠjcÎNgAV€î;¿Ø-x;†ÂA.ƒï×7!&Š&Rr£ÀU_¼ªŸ {ÞýEœ³É|û–{=©²˜!°åBçûuñù™()R§Ò æ‚=¡IéÏÁº%Zí\õòqÊ|TŽÛÆíó`T‰J†×׃뺵7ÊæÖ5YЯÁϯŸ^.þ÷vv7C쑹gïŒzP$ KzD‚FÖ„³5Гme¯w‹æ²WDËŒKýnù6MµÑ™,RJôwYƘ“󬟙üÛŸŒ«4q” Êu]~­¨ƒ:;m,îGæÇÇÆ0¾ž_\Oo_^šùÌ;’U&ï'u:©ø=‹kæ6‰æ¡•þê B¢×ÏþÅólœW‡:™›WÂçRØï‰ç£Òe±¢q‹»£áÛ–£´Böò˜sT—­ÚtIñí%Q® ­uÊå%-ñv 9óx*ky~>ÔÆl~4²,»¨ÓKd÷8¶LMˆ/Z¯z1µ£ñ Xç|TÒvx¥º$r> a#–#¯‡Óo]X³÷bÓ¨ ,ïäær`4á:_¬9ØŠW¡]ç"Ý|AMä°½QGw”}_ØhÔi¿eö|P¯Æ’áh¯®XÞœ)hÎÃ\ïƒ •ˆèâY_\}°Ä7Bjë4.”ˆtaŽÅlƒS1å÷Ò]Ù‰Ô솳¨„™Íâ[Á34@;¡ Ãr%…Å^Ó"uML.âï7žýdÄE¢H‚²f÷¢ ,Qº¯ÅJ ÑõZ»WȌů¯òÃí­»íŒ1¨¯€®ˆ¨íÉúº¸4xX¤+}MZäèáÇ\ Ëlt{ñ<¿éßͳßfŒGp䀵†Y#ÇÀè†Æ‰Ü6亸®JO‹cÔàÅ’" *îIøÇ@²8‘¥ùDž”ät˜Þ=uç0$ãºÎ÷½1¤¢r䯯ÅÿøS&Ja ÏlûönÀÙˆøid,á:6:#z÷¤ã‘#}øq©ãÁ~¿ÝMøùøfµFÜ2)F×…¢l×:!åØ=ðÔ_\³a9¢Ó›I¢À5N®ï“=nä=±V ÷A³‹ÅO§i„ù¸}¦Sdtd eÛ¼£\ä=±m‘9"É& SõÈ¡$T„-îŒf Æ.ÆJI2szw®Ÿb„"Õf{75ãÛí!$í„-’—ùÄ‚cæGO”c#m‘6:Kª«1–8%ÄB¯ËE ¥ñ³6¸¶^œ×`#¾X1bÝ°bƒÇ2G¸ îL\ƒ³ TÝ`ÖÚ¢­êŸµ£@z‡¥0¯e£]–±ª1mrš/Øe¾cšy»3ՙȑgy¶\¸m;¯¯_¼Øo>iÏf<Ï â9Kæ¥äbȱ¬³®I|Ö‹Wí\¯'Lã#fÒ{+¬AiCÑ(·èýkup=.ØE¶H:F*A9>o[ÀD—³‡dj=½ýTÌ_ºGÇVãö±Á·£½SPˆóÎí¸A†?¾ÿÁu¾¥LñßͶlÛþ6VuBRf0æ5ɘ݌m4öä]Fˆê¦¦ç¨ÔG‡³¡[àÇÇÀëëbêÀò;J,îi×ôÚîMkCO|^¨• ‘ 7†A×I¼ll„˜¨¯ÊÔ‰Ñâ ý _M#SëEÄ“œ²„óÑüš'‚Û™Ü3bâ±òvM`°ÖÎy¾è+â–ïn¨¯'ªä(„¢P7bN¬©”Þ|éù~1ç2ZŸÜR&¦ì/wLžÇoÃó&÷ĬOþüsPçd“@o{#hzOl •U3Gbò¦ô¾¸zźó/oa#m‰j•ï_>…ï Ú²‘–’²RÒF ðU<Ÿß´ëâh;œVásd–º ûª€[öJºÚ'!öÝÁ¹Ïë$>þ¬ ­ˆ$x(h ŸH t{b× › Y¹fm”ä'¼I l‘?þüEÚ3ÿú·¡>*Ù¨µçn"é'kN¶ã@~+Øj”-SOomÙ5r&–Á¨½;Ñw;PóÿïÇíÌ|s?/ÇQº'¢EúhnÇÕÂÕOºM¢¶¨Ä9b¡Ö «í¸³ß"õ¹¸Åt ¤ì‹ºX3seÚ¯… Ar SYºH¥°úäë|¢r£lQ½‹pIBÖäõÕÈ º Ïï)(« Žöðc/Lõäí–!À<'½-d+ÞI+™j•yº ïs;œl³Ðú#oH <çÉcŒw¡yQiN…õ¨o­ÐWß?v¹¢†í‘¼EGê×Ò¨îü 99*m ¢d‚%^—Ës²ß7~ü~#¦“5„N`ŽË»ïFÇÚôˆ·,Òl ¶°“Òz§2ÜìØÁêBLéjŒÙÙÔV¬L¼æE`ú W3r*lN7Zæ!2Y Õ†ùñã7Úyr¾*ÆžM‰-¸*ÖkC5`+Qç ÙE}ªs÷“$TŒR –ݯyãU5æ9ŸØy¡·CWÃzçbbmp;n{&.åñ8¡³UúT/¢6H·Ì‘!‰.·O&‹Š†}Sd:°UK„ï²û—×|Ñlòï円ßhmò\ðŸÿ¯ÿð÷’¹Üˆê©¼”9+m lTFkD>´“ç÷1gÍKhJ´q¹vA[I •Eë!l.DðôZ „è°͉\rK93kåç÷Oö¸óãó“œ 6ÖÛ-è¹ùÖO–-'Ù$åÂ`ðz>° HÔëEïnرÕÙBæ8šL®VÙâÛc0*¼• æ9‡1Œ ^‚QûäÙ.r yCUèæ†êh$Y”Ûæ­2}±íî^›8áöõ|Ðk%•Âï¿}ºö+Ê¿þ»¿ñqÛ£c IMÍQ•úêÌsÁœœÏ­{MÖí¾½w3aS¶[æy̆€z#—ÈçÇ…äþrÿ>WM¿ŸwEÂpu´^ùþ>é,Ž¼±•âÁ 1! K×ì$%Þ˜m5Žœ [¦­EÿöSd*182| h­¹;Q#Rþrå(³º“´­˜¢ÍOä#SŒÞEÆðÞ'0DÝ­Rö·ž_ÝÌ–!D°DŠå͘´z:ªdf7Z}bŽÛNŒÐëd.ï1a¸Ò 4¾¿Ì9ë6ü®½åÈÕWóFªÚ/Fïh4–FÄ„',õÏQ£M®Ùœ[¡ ge–c'¥Àš†n Ueöéø³sRgGK"¦D̉cÛØK|O(;²„V/âùü¼¹yÏœ”qâË“¶1ñÎ4&A"A¯çɳñoì÷ÄŸ¿¾xÕ‹[8ˆ(!ºÁeÕ΄óœ, ü¸ú_$Ò×å›Ñ©=ïkéIDATrp]y>)i'7T$!ãmRܵ6+ï„%e?XIxõ'ýEÚ?üÏ6I)3®º:[ÜÉ (ómdBMæB4¡Mºœ{Ü>`ÁÿߟØØöBf¢*gõ‰ä·ætýÔŽEΞ†”*\W'àÑͳuÂ&n•&ù’ç^îüùxÒëâ:'Kû]Ys-Ñeð|6r®Ñ©“㸓pÂÎóû¤7÷õËêìe£¤ìûr(×ô†Û³Uæ€{ÚX _½S¶2rØÏÇ“ûî{9~/¡Ãh“fdÁîifÊ‘Ñ©Ú<½”cÂR—×@ dSr¶mçëë›~6ºÖ¨d{$c[DÄXIYÁ¼îe5x®'[ˆ”c£7¥_Ýþ9ð|ür4Ü–Xç ¡ TE# ãU…«OrX"9î‘ÞðE«*JÅê†à¦d|ŸÖëâB(‚nóÃ。ÒŹ%ã'rúT Ë£à)bâ›ûvu'ºpép,×F{È^·WÄ'`Þ9ùÝžè/#Eǹ÷Ñiý…ÊDphê9½Ób‰–Š¥wõÜ7ƒëˆœhŒ·-gF…ýG 3i V] “´)áÿüßþÃßÛ5˜aÒÆÅhÞ.Z«Ü÷ƒ¼#ÁÜá¦ï*¯}CSví5˜÷Ø” 'L‚ßGwæz„ºïžzzžØœP2²Ø¢äÄ`!&||~°ßË[ò«ØÙ™Á`ú}ÑMòÎÍ?b!…:¼àÑTHÝ‘×"â÷ýŸÉ",aÓÌ}÷åd_ãŸ-6Óüï1ÏAÍÖê÷µ¾s8¦Y£!C¨LRŒÞY#9Gf_Ô¯Ž­7y¿~}#c°m!y1øúõÅÏç“5Næ_5_ï1Hàqufo®D˜òñyçÇï?Hê.Å>'µw^ßêÕÈÇFÚý¬€ÒÈ5×:1ž×…šr„%Ë‘^VPu/Å_i³7Ròjª²;@äñ¼H){·BÊ„%ôv±¤RÆ–°¦¾† !Í»ôbÜ‹h|wª‘‹»LE…½ìÈ‚xxËMšÑû ¶À2¯Þ±Þ¹… ‘ T l1 š”>½ eSŸhç„óz±ÞÎLF'¨×°Ý~ô)<¾O¦ a™~ ÏE£ ­Ñ—­*Þ–”òF ›[â³·•rãvl„!Ð.n{&cJŒˆ:mHE©£a¼»$ß+kø§l™¨‘Ç«ñóõ Ÿ’<Czƒm×›œm”²1Ç õ –ñ:/ÇÌ‹ÀœôîÓUȉ56ýÝž}: æÿþßÿ‡¿Kï@›ŠÉBSô±ctÎ׋rlüþãwx[;ƒÀê‹9*st† ËüÃÏQÑïÑ(Ø"¨wE´užçÅÒŘގ¢ïÓZDihˆ,&EG¾1lbVœ/—£‚zÁ¤ÆÀZUyßœ'¸&ÔÃøÁ»âYYÞ°rÿ¸±mÎ ² )GŒdS úåSQ¡¾ž\ÏJ{³íêëd‰³ðJ Ä•(êÞø7¬Ö““Îêôe-öcãH‘^]–‹DÎëÅ«V¿C¦²“ƒpõÁ«V.©ITJ*¥`C9çÅ«_<ž•^;½7'0eïÜëm2¦ƒGDþâ: A@ÄÇAMB¥·ÎlN×¹}&w¸Á«6‡yÄÄFa+^ iÓˆ)‚/|Zø8nÌeœ¯‡Ã<ð{wÌÉÿÝ÷ø59Vë“Ø5³ß=Æ;šñ||ÀÇ[ i NV1Ò®„`Dñ{yŽØ–ä›x£‘·ÀÆ¿ýú鳩ðL‚†äÔàuÑ[GKæ^2ÉjÞí0qåFõ –Dd{»QèT\¯•˜"9%ÆtýÚ€ ÆlÚç?“‰Ãëæ<7]ì[¡¿£·åxñ•„ÎbÔ¦ÀV6Æ[ÿÜoä¨<Ç Xà~Ü×˽Ǒ`FX‘É$m‘}¿û^B'[Jäp1rʬÖÞ]lþmº¥âZëlnãÌÞòSŽDŒÑé1,d¾FË©8ë$‘€Kyo\om÷Vn¬ „àÞåä¥èh+aíâç÷O®ø"ïÉûî»Ñ{uÙÍ"Ÿûáëìˆ ×õâº:j‹nö¬þéÿßÓ¹kI’#WÐÇ+"²ª{f¹‡ßA‘2)çPãíÿ.gwº+3"ðrPðœQ[«ªÎà~¯Y4Avà=cUÜH h²úóë‹>&¼³ìx¯ÜíÉÙ;‘…¤ÀZÂÏû1xJLüö|qþS©— ×þõ¯¿Rœp¿.îzãKB¦ƒ` óÁ$.k“æ&¡CpJ×_“I°,{6ÆÀRRLo3¼=1ºÉ˜QhCisá×ÂÏeñh…öúB¦øš ò±³&<Ò¢÷›{ ¶(Ìhª¶Éšƒ°¶\x”zÙ¼+ˆC¢™¡__/d=l•M ^M9¼¢Úˆ"§ÜKÙòA—Æu]œ£›©JY3ó(‹‡ì”=ñ¼’E ½ô³q+47`Þ,5fAÑÄÔAÊœÐΓP,DåîE+ÞUõ•­¦~¿:9j»9ëIÎ…\¬¢,Ë£nÐG ßƒ¦>NÖZ_„ì 0Ę1vW¦€ó‘Ù'>Œ2ø`ß×Îã–ã>›!¼²é¿¦N2I'}Mº…î863šê¬ïôœÁGÖéçµìºêÄzÙbÞ6}-Ò/ƸpCèøqY$8–B[GJ¬ÍïÏËðQÛ#Ñ›²ú$g#ý̵Ð!×hmr×ÊçÊøØl•9=Q r)+ 4ÄñUâ«WÚXL”$8…ö¼©õ$¦ÈyßOk5 ¶=ã‚!# 2”ë>©ÃöéS]'ºÑO‹W%½'íþ†’’Þ§zã¬7~A)“n2ÓåÈÓžÞd9úHÛr\•6‡ýò&1qžüþÝX¬ ››*ý6•#{¼Ž#‚(óVÊž/hŸôÿ›Œ«¡ÞsÛLz´Œ­ãAò‰ÚNTÞ,IØsîÕ+$ÏñëÎóëäúºIGÂo_(l>òtÎæ>‘B°z¸³gؘž,ënÔ׋î슿o»}ày±¢'Ædp—a·´¥JN0‹>á$òº/<ƒEF£ÇBoŽåáøØÿþûÛœFݲÒÝ-Ã~{Gï•5”»^ä”ù<œíF§¥Œ¢x6± c,QÇbr×AÊV"â¬2éœ×þ€~;Ú\œçE]“ÖÌj*býÿv_DçYKqN™ œÙ€À±=Üìü|žô9Ùr ‘KÁE>b6ºð²•‘ˆ‘‰£·kõì“1•ïÞ‰­CÅjœ½—@]À4߶[Mb»ÝÊÃú êUI) !ÐÛ¢¼‹Mõ¼iõæëi9Á·P­§½œ½zYŽÖlz—Ã-E0pÊ}Þ¼^á=ðKŒ>|_m•äGyR`z X¼OåǶóø¾›P¤Ãj·`Ûvöý Æ„‹ÖR›Nìwºo8gµßÇãA«W­¤ccÏ…±,g‘¼õ=ü¶%UÚìû¿„ëºpº!!žçÍó$ x—,mˆ’R!Ä‚öõ.£Uk”ŸâmƒŸ?^ü¸ÁCü&)O^ÝÊT›$¶TèmðãçOÔ;¶h·¾Ù,™zÝÓVd7ñJ¿&9‹íNC–«N[CîÉRN¨:ˆK8öƒ®“³7Pjø6 †`ÿº*}TbŠ|ûv°GSÝË°sçó´b‰Dg`qžÕ÷¨#Ò•«Ýœ³[aîÝ( oÙïh "ï ˆQ?Žœ3·V>öBgÚ"§ËÞì{¦ýl\× D´VžË(¹Y*uXÆ8mAÍïæ–#ö  «'–wþXU‘œéS9Ÿ<)ÚMaÍÎ}VT—uô¹X÷ħÄ~»ßB¶Ö›íæÕ*Ç·Oöh«¨{,ÚZ¬ÑÙ‡Ð^JìÏ벂‡$Ë—ŒÎi–×f7’¿þú+8Ç8Õz,j­ä¼±ÂmÆ+h¦öîÝ¢¿¿|ßñAþä Æ’ˆ#r6û2 9r|îP¿»‹WÈ5Yañ'J´Êï«>iS©u>#’2Ѭs÷3Ú$ô6QÀ­&Ñðx~¯>fÓ¸õfŸáb@¶ ­Ó¯FzÜc'½ª½û%㧠ѓBäÔ/pŽ=ï6ðZ6 e “z[¬»¹…_KW”5¸{åÕoF€oß Ç¿Xžßá8Ÿ•«ÝÜçIÈBíƒóïÇ9[ó>¶Ã†\£¿]ë]Ït”vv¼ëà+Eˆ[æ~^¤(É‚$Ú'>yªz‹}ÛùÜ>¬ÉÚmõ»ãÇo?¸´â4P’w _¥T@=_W#®ÁîDìù¨ý¤Æ‘ö¼£NyËú.Xø5Qi¨_²YüyÙÏ9zãÖI82}švžµÑúD†Ábd9Òc³ÔdW¦¯Üõâno^èÁóã¾m ‘DôFG>OCÏïDhs¯¦|¹›ODŸ ¼{Oª+º ô‘7Úæ‚Ÿ0ZEÊfïíQÉé` …QotŠŽújœç“­Š¸‰ÅñÕ*kØ·ê\ÎVeNp Jæò|Ë9e#ô¸{ó;‹ä7‚,|È<ÿùÅŽÕÅCŸW¼5ÛÄ{ÑSï tñý/;aæ„:+£™haÛv¶ÏbûÓW%Dcý©Bô&QEÖ$²ð õuÓƒò¹?Hâ9õ„ªÌ4Q¯¸‚½Ç÷ÉRCÆé踢Þò a˜íh8t9‚8RÆPJrD÷™lõ¨Nž×…“ÀòŽGŠ†Ìª7²”¹÷T>óα®^wµuÐPd8¦·MZÂy]ô^y|ÏÔ¥ô·Ë¾ÎÆ×׋‰Üý¶=uˆ¤à‘àhÕÌ8o‰ B¿/Îlú·]‰Š[vvböĘîâùúIBý`ÌÅÝ&%²ž É)žÖ•û<™s¢ªf¬Î» Üt!¦[Ê‘3­yj¯0ñÑþN¹R¢Ý:û£ Íq]÷æÈ©ORˆø¡¸Ùp%#1áÔnŒ½V¼ólûŽ„c"Óã‹Ã«Cë¢S¾ølí¼ÑÄ1Ô˜š–Ÿ€ßþñDtq«âÇ`‹™¿~$ÎË’¬A"³Þ4‰ˆ³­NŽŸ=·Ãsôj7’¸_„dZ?ùˆÄâ‰Õó|užÚÙEX äÿëßÿ6œPÇ ¶N­ýñA –«_ÞÑ/†ÈR„®Ë²ñ] ·åÞMªx^˜.âÄ„—c²ìéƒ:9¿|0Õ±Ö»s }¤/z«Ì>(>A–* !Ø‚àpïÚp¤¾y|%ZI‰¡ï ²c“Ìt Ãðæ­UbÃ/Ë{E2aé€u2²$˜3.ÀœJN;)%ÃËÛnPMg¥§é,ÕÙTYâx|nüòía3uÜ÷Dgej7»UŽ¨:´ ³WMåØ„œ=,êâ?@×¢õnÑálCAž¯ó¦½;æž|”åÔöâqc²Ö …DIï@½3äÝPB©ð¹?èXoGb lA[cN% ¤Ð`Y†2^=ã®<ïÕŽ,eAþç?ÿíoS'k`pwô9Þ£YGï‹^»©µ½½ñ%#¡´bÔš…P[göÉôŽ5=aF¼Š‘dÜ l‘àÀ­…”LD¨õâúžÊOF† ŸÃÞ£¡âðoæ](¶T¿£Ê*FÂ)àTÐ9XCI[$§D}Vb0ÁÉ}ßd±ÈððŠ¬†ÈâÕ'£ BÉöþ~²Ôòü¤…$Á'Oôj+M G3ÕŒ11F¶Ïͬ.·â“9þFŸ¤º€Ø’ÃÇDÄÞûà¹æ ‹ Ø(âmÝ;•s<ž°%e¶#qä· ƒwäÂì!ªuáý@½£õA‘ÏoÞ T…¸¼ó<¾âƒc“3"™v7|p|ßØËNyDRÌ¥ä뉤(b-Ëœ2ªÊ×ï_Ì9íÄõ‘»7T ¥`+·à(aqõñ§/Çšj°Ù“ EìB‰%áT¸ïÊOq –gzg™ú-ƒ#2è(çì,?M­uW+?E½ržAøø8ŒEùº˜ÝŠhÞ{RÚà ·~-ʾ%âK›Š…æðìvêûe•ñŒ ´êB\'‹ÁDQe/¶nnÀÔ9tLî1Í«„ [9¬„%‘´UZ\`ŽA_Jzÿ{ ‘àšlæDb[¯3×h´Za J ‘òQ?¾NÄ9ŽÏ|\ïüüýDÛ@R$ç`ƒ.‰ì Q‡õ<íuâ±t e¶›~5\ÒZlÅRãn$/¨O J >’Ü:H{!)¬f°Ž¨ïÙ¶«M›Ö©Ò=Oq+ÄmdzxÈ¢úH­j0Pgÿ‰¶”í ´.®‰Ñe½Ø•oËè{¯ª8‚zBŠ;Ûž,ìR!Dº¯hSC,³øí:ÙË¥2ûMUáˆ™í£°œ#!…„úaä$?逸RÖ»ýàtB»«íæ×ÅÞ'µWÂnSð¦‹ûjø¤Tñ„~óËûVÓ»Mëï¯Ó¢¼ïÞBqËtjhgÍeù—ùøåAÌ‚;÷zq¶‹þ#r8Sºµy½é[÷…oYGµ2SÜ·w•[ø˯´[¬z-e©ãñíÁõeÎzïÅ k²à íÁbø%ø­Ø—ÆPŽA­üI¬x³Ö‹äÃW¢ *w®Á 8"ÑÙFg1x½N£ …@@ Ù³œgçl ñÂëÙùq}ÑÎÓ>ŽýÁzÏZ\ðÄû#Ðjä~]ö¥ïlŽ4±²ÓZöå&ÑìÂc5Š”@‘ ¿ Aé\_—1/r¦¶›žiy‚7’o­/öƒãc'ŠÐª9ÿÔÞO“©fì0NG@–7gA)„Ö¨½SÝÍpVÌÊÛÆ=Læúÿ„teI‹MûIEND®B`‚admin/vendors/codemirror.js000064400001405524146725417150012046 0ustar00// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/LICENSE // This is CodeMirror (https://codemirror.net), a code editor // implemented in JavaScript on top of the browser's DOM. // // You can find some technical background for some of the code below // at http://marijnhaverbeke.nl/blog/#cm-internals . (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.CodeMirror = factory()); }(this, (function () { 'use strict'; // Kludges for bugs and behavior differences that can't be feature // detected are enabled based on userAgent etc sniffing. var userAgent = navigator.userAgent; var platform = navigator.platform; var gecko = /gecko\/\d/i.test(userAgent); var ie_upto10 = /MSIE \d/.test(userAgent); var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); var edge = /Edge\/(\d+)/.exec(userAgent); var ie = ie_upto10 || ie_11up || edge; var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]); var webkit = !edge && /WebKit\//.test(userAgent); var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); var chrome = !edge && /Chrome\//.test(userAgent); var presto = /Opera\//.test(userAgent); var safari = /Apple Computer/.test(navigator.vendor); var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); var phantom = /PhantomJS/.test(userAgent); var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent); var android = /Android/.test(userAgent); // This is woefully incomplete. Suggestions for alternative methods welcome. var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); var mac = ios || /Mac/.test(platform); var chromeOS = /\bCrOS\b/.test(userAgent); var windows = /win/i.test(platform); var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); if (presto_version) { presto_version = Number(presto_version[1]); } if (presto_version && presto_version >= 15) { presto = false; webkit = true; } // Some browsers use the wrong event properties to signal cmd/ctrl on OS X var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); var captureRightClick = gecko || (ie && ie_version >= 9); function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } var rmClass = function(node, cls) { var current = node.className; var match = classTest(cls).exec(current); if (match) { var after = current.slice(match.index + match[0].length); node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); } }; function removeChildren(e) { for (var count = e.childNodes.length; count > 0; --count) { e.removeChild(e.firstChild); } return e } function removeChildrenAndAdd(parent, e) { return removeChildren(parent).appendChild(e) } function elt(tag, content, className, style) { var e = document.createElement(tag); if (className) { e.className = className; } if (style) { e.style.cssText = style; } if (typeof content == "string") { e.appendChild(document.createTextNode(content)); } else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } } return e } // wrapper for elt, which removes the elt from the accessibility tree function eltP(tag, content, className, style) { var e = elt(tag, content, className, style); e.setAttribute("role", "presentation"); return e } var range; if (document.createRange) { range = function(node, start, end, endNode) { var r = document.createRange(); r.setEnd(endNode || node, end); r.setStart(node, start); return r }; } else { range = function(node, start, end) { var r = document.body.createTextRange(); try { r.moveToElementText(node.parentNode); } catch(e) { return r } r.collapse(true); r.moveEnd("character", end); r.moveStart("character", start); return r }; } function contains(parent, child) { if (child.nodeType == 3) // Android browser always returns false when child is a textnode { child = child.parentNode; } if (parent.contains) { return parent.contains(child) } do { if (child.nodeType == 11) { child = child.host; } if (child == parent) { return true } } while (child = child.parentNode) } function activeElt() { // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. // IE < 10 will throw when accessed while the page is loading or in an iframe. // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. var activeElement; try { activeElement = document.activeElement; } catch(e) { activeElement = document.body || null; } while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) { activeElement = activeElement.shadowRoot.activeElement; } return activeElement } function addClass(node, cls) { var current = node.className; if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; } } function joinClasses(a, b) { var as = a.split(" "); for (var i = 0; i < as.length; i++) { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } } return b } var selectInput = function(node) { node.select(); }; if (ios) // Mobile Safari apparently has a bug where select() is broken. { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; } else if (ie) // Suppress mysterious IE10 errors { selectInput = function(node) { try { node.select(); } catch(_e) {} }; } function bind(f) { var args = Array.prototype.slice.call(arguments, 1); return function(){return f.apply(null, args)} } function copyObj(obj, target, overwrite) { if (!target) { target = {}; } for (var prop in obj) { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) { target[prop] = obj[prop]; } } return target } // Counts the column offset in a string, taking tabs into account. // Used mostly to find indentation. function countColumn(string, end, tabSize, startIndex, startValue) { if (end == null) { end = string.search(/[^\s\u00a0]/); if (end == -1) { end = string.length; } } for (var i = startIndex || 0, n = startValue || 0;;) { var nextTab = string.indexOf("\t", i); if (nextTab < 0 || nextTab >= end) { return n + (end - i) } n += nextTab - i; n += tabSize - (n % tabSize); i = nextTab + 1; } } var Delayed = function() { this.id = null; this.f = null; this.time = 0; this.handler = bind(this.onTimeout, this); }; Delayed.prototype.onTimeout = function (self) { self.id = 0; if (self.time <= +new Date) { self.f(); } else { setTimeout(self.handler, self.time - +new Date); } }; Delayed.prototype.set = function (ms, f) { this.f = f; var time = +new Date + ms; if (!this.id || time < this.time) { clearTimeout(this.id); this.id = setTimeout(this.handler, ms); this.time = time; } }; function indexOf(array, elt) { for (var i = 0; i < array.length; ++i) { if (array[i] == elt) { return i } } return -1 } // Number of pixels added to scroller and sizer to hide scrollbar var scrollerGap = 30; // Returned or thrown by various protocols to signal 'I'm not // handling this'. var Pass = {toString: function(){return "CodeMirror.Pass"}}; // Reused option objects for setSelection & friends var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; // The inverse of countColumn -- find the offset that corresponds to // a particular column. function findColumn(string, goal, tabSize) { for (var pos = 0, col = 0;;) { var nextTab = string.indexOf("\t", pos); if (nextTab == -1) { nextTab = string.length; } var skipped = nextTab - pos; if (nextTab == string.length || col + skipped >= goal) { return pos + Math.min(skipped, goal - col) } col += nextTab - pos; col += tabSize - (col % tabSize); pos = nextTab + 1; if (col >= goal) { return pos } } } var spaceStrs = [""]; function spaceStr(n) { while (spaceStrs.length <= n) { spaceStrs.push(lst(spaceStrs) + " "); } return spaceStrs[n] } function lst(arr) { return arr[arr.length-1] } function map(array, f) { var out = []; for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); } return out } function insertSorted(array, value, score) { var pos = 0, priority = score(value); while (pos < array.length && score(array[pos]) <= priority) { pos++; } array.splice(pos, 0, value); } function nothing() {} function createObj(base, props) { var inst; if (Object.create) { inst = Object.create(base); } else { nothing.prototype = base; inst = new nothing(); } if (props) { copyObj(props, inst); } return inst } var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; function isWordCharBasic(ch) { return /\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)) } function isWordChar(ch, helper) { if (!helper) { return isWordCharBasic(ch) } if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true } return helper.test(ch) } function isEmpty(obj) { for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } } return true } // Extending unicode characters. A series of a non-extending char + // any number of extending chars is treated as a single unit as far // as editing and measuring is concerned. This is not fully correct, // since some scripts/fonts/browsers also treat other configurations // of code points as a group. var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) } // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. function skipExtendingChars(str, pos, dir) { while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; } return pos } // Returns the value from the range [`from`; `to`] that satisfies // `pred` and is closest to `from`. Assumes that at least `to` // satisfies `pred`. Supports `from` being greater than `to`. function findFirst(pred, from, to) { // At any point we are certain `to` satisfies `pred`, don't know // whether `from` does. var dir = from > to ? -1 : 1; for (;;) { if (from == to) { return from } var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF); if (mid == from) { return pred(mid) ? from : to } if (pred(mid)) { to = mid; } else { from = mid + dir; } } } // BIDI HELPERS function iterateBidiSections(order, from, to, f) { if (!order) { return f(from, to, "ltr", 0) } var found = false; for (var i = 0; i < order.length; ++i) { var part = order[i]; if (part.from < to && part.to > from || from == to && part.to == from) { f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i); found = true; } } if (!found) { f(from, to, "ltr"); } } var bidiOther = null; function getBidiPartAt(order, ch, sticky) { var found; bidiOther = null; for (var i = 0; i < order.length; ++i) { var cur = order[i]; if (cur.from < ch && cur.to > ch) { return i } if (cur.to == ch) { if (cur.from != cur.to && sticky == "before") { found = i; } else { bidiOther = i; } } if (cur.from == ch) { if (cur.from != cur.to && sticky != "before") { found = i; } else { bidiOther = i; } } } return found != null ? found : bidiOther } // Bidirectional ordering algorithm // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm // that this (partially) implements. // One-char codes used for character types: // L (L): Left-to-Right // R (R): Right-to-Left // r (AL): Right-to-Left Arabic // 1 (EN): European Number // + (ES): European Number Separator // % (ET): European Number Terminator // n (AN): Arabic Number // , (CS): Common Number Separator // m (NSM): Non-Spacing Mark // b (BN): Boundary Neutral // s (B): Paragraph Separator // t (S): Segment Separator // w (WS): Whitespace // N (ON): Other Neutrals // Returns null if characters are ordered as they appear // (left-to-right), or an array of sections ({from, to, level} // objects) in the order in which they occur visually. var bidiOrdering = (function() { // Character types for codepoints 0 to 0xff var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; // Character types for codepoints 0x600 to 0x6f9 var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"; function charType(code) { if (code <= 0xf7) { return lowTypes.charAt(code) } else if (0x590 <= code && code <= 0x5f4) { return "R" } else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) } else if (0x6ee <= code && code <= 0x8ac) { return "r" } else if (0x2000 <= code && code <= 0x200b) { return "w" } else if (code == 0x200c) { return "b" } else { return "L" } } var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; function BidiSpan(level, from, to) { this.level = level; this.from = from; this.to = to; } return function(str, direction) { var outerType = direction == "ltr" ? "L" : "R"; if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false } var len = str.length, types = []; for (var i = 0; i < len; ++i) { types.push(charType(str.charCodeAt(i))); } // W1. Examine each non-spacing mark (NSM) in the level run, and // change the type of the NSM to the type of the previous // character. If the NSM is at the start of the level run, it will // get the type of sor. for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { var type = types[i$1]; if (type == "m") { types[i$1] = prev; } else { prev = type; } } // W2. Search backwards from each instance of a European number // until the first strong type (R, L, AL, or sor) is found. If an // AL is found, change the type of the European number to Arabic // number. // W3. Change all ALs to R. for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { var type$1 = types[i$2]; if (type$1 == "1" && cur == "r") { types[i$2] = "n"; } else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } } } // W4. A single European separator between two European numbers // changes to a European number. A single common separator between // two numbers of the same type changes to that type. for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { var type$2 = types[i$3]; if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; } else if (type$2 == "," && prev$1 == types[i$3+1] && (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; } prev$1 = type$2; } // W5. A sequence of European terminators adjacent to European // numbers changes to all European numbers. // W6. Otherwise, separators and terminators change to Other // Neutral. for (var i$4 = 0; i$4 < len; ++i$4) { var type$3 = types[i$4]; if (type$3 == ",") { types[i$4] = "N"; } else if (type$3 == "%") { var end = (void 0); for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; for (var j = i$4; j < end; ++j) { types[j] = replace; } i$4 = end - 1; } } // W7. Search backwards from each instance of a European number // until the first strong type (R, L, or sor) is found. If an L is // found, then change the type of the European number to L. for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { var type$4 = types[i$5]; if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; } else if (isStrong.test(type$4)) { cur$1 = type$4; } } // N1. A sequence of neutrals takes the direction of the // surrounding strong text if the text on both sides has the same // direction. European and Arabic numbers act as if they were R in // terms of their influence on neutrals. Start-of-level-run (sor) // and end-of-level-run (eor) are used at level run boundaries. // N2. Any remaining neutrals take the embedding direction. for (var i$6 = 0; i$6 < len; ++i$6) { if (isNeutral.test(types[i$6])) { var end$1 = (void 0); for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} var before = (i$6 ? types[i$6-1] : outerType) == "L"; var after = (end$1 < len ? types[end$1] : outerType) == "L"; var replace$1 = before == after ? (before ? "L" : "R") : outerType; for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; } i$6 = end$1 - 1; } } // Here we depart from the documented algorithm, in order to avoid // building up an actual levels array. Since there are only three // levels (0, 1, 2) in an implementation that doesn't take // explicit embedding into account, we can build up the order on // the fly, without following the level-based algorithm. var order = [], m; for (var i$7 = 0; i$7 < len;) { if (countsAsLeft.test(types[i$7])) { var start = i$7; for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} order.push(new BidiSpan(0, start, i$7)); } else { var pos = i$7, at = order.length; for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} for (var j$2 = pos; j$2 < i$7;) { if (countsAsNum.test(types[j$2])) { if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); } var nstart = j$2; for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} order.splice(at, 0, new BidiSpan(2, nstart, j$2)); pos = j$2; } else { ++j$2; } } if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); } } } if (direction == "ltr") { if (order[0].level == 1 && (m = str.match(/^\s+/))) { order[0].from = m[0].length; order.unshift(new BidiSpan(0, 0, m[0].length)); } if (lst(order).level == 1 && (m = str.match(/\s+$/))) { lst(order).to -= m[0].length; order.push(new BidiSpan(0, len - m[0].length, len)); } } return direction == "rtl" ? order.reverse() : order } })(); // Get the bidi ordering for the given line (and cache it). Returns // false for lines that are fully left-to-right, and an array of // BidiSpan objects otherwise. function getOrder(line, direction) { var order = line.order; if (order == null) { order = line.order = bidiOrdering(line.text, direction); } return order } // EVENT HANDLING // Lightweight event framework. on/off also work on DOM nodes, // registering native DOM handlers. var noHandlers = []; var on = function(emitter, type, f) { if (emitter.addEventListener) { emitter.addEventListener(type, f, false); } else if (emitter.attachEvent) { emitter.attachEvent("on" + type, f); } else { var map$$1 = emitter._handlers || (emitter._handlers = {}); map$$1[type] = (map$$1[type] || noHandlers).concat(f); } }; function getHandlers(emitter, type) { return emitter._handlers && emitter._handlers[type] || noHandlers } function off(emitter, type, f) { if (emitter.removeEventListener) { emitter.removeEventListener(type, f, false); } else if (emitter.detachEvent) { emitter.detachEvent("on" + type, f); } else { var map$$1 = emitter._handlers, arr = map$$1 && map$$1[type]; if (arr) { var index = indexOf(arr, f); if (index > -1) { map$$1[type] = arr.slice(0, index).concat(arr.slice(index + 1)); } } } } function signal(emitter, type /*, values...*/) { var handlers = getHandlers(emitter, type); if (!handlers.length) { return } var args = Array.prototype.slice.call(arguments, 2); for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); } } // The DOM events that CodeMirror handles can be overridden by // registering a (non-DOM) handler on the editor for the event name, // and preventDefault-ing the event in that handler. function signalDOMEvent(cm, e, override) { if (typeof e == "string") { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; } signal(cm, override || e.type, cm, e); return e_defaultPrevented(e) || e.codemirrorIgnore } function signalCursorActivity(cm) { var arr = cm._handlers && cm._handlers.cursorActivity; if (!arr) { return } var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1) { set.push(arr[i]); } } } function hasHandler(emitter, type) { return getHandlers(emitter, type).length > 0 } // Add on and off methods to a constructor's prototype, to make // registering events on such objects more convenient. function eventMixin(ctor) { ctor.prototype.on = function(type, f) {on(this, type, f);}; ctor.prototype.off = function(type, f) {off(this, type, f);}; } // Due to the fact that we still support jurassic IE versions, some // compatibility wrappers are needed. function e_preventDefault(e) { if (e.preventDefault) { e.preventDefault(); } else { e.returnValue = false; } } function e_stopPropagation(e) { if (e.stopPropagation) { e.stopPropagation(); } else { e.cancelBubble = true; } } function e_defaultPrevented(e) { return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false } function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} function e_target(e) {return e.target || e.srcElement} function e_button(e) { var b = e.which; if (b == null) { if (e.button & 1) { b = 1; } else if (e.button & 2) { b = 3; } else if (e.button & 4) { b = 2; } } if (mac && e.ctrlKey && b == 1) { b = 3; } return b } // Detect drag-and-drop var dragAndDrop = function() { // There is *some* kind of drag-and-drop support in IE6-8, but I // couldn't get it to work yet. if (ie && ie_version < 9) { return false } var div = elt('div'); return "draggable" in div || "dragDrop" in div }(); var zwspSupported; function zeroWidthElement(measure) { if (zwspSupported == null) { var test = elt("span", "\u200b"); removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); if (measure.firstChild.offsetHeight != 0) { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); } } var node = zwspSupported ? elt("span", "\u200b") : elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); node.setAttribute("cm-text", ""); return node } // Feature-detect IE's crummy client rect reporting for bidi text var badBidiRects; function hasBadBidiRects(measure) { if (badBidiRects != null) { return badBidiRects } var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); var r0 = range(txt, 0, 1).getBoundingClientRect(); var r1 = range(txt, 1, 2).getBoundingClientRect(); removeChildren(measure); if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780) return badBidiRects = (r1.right - r0.right < 3) } // See if "".split is the broken IE version, if so, provide an // alternative way to split lines. var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { var pos = 0, result = [], l = string.length; while (pos <= l) { var nl = string.indexOf("\n", pos); if (nl == -1) { nl = string.length; } var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); var rt = line.indexOf("\r"); if (rt != -1) { result.push(line.slice(0, rt)); pos += rt + 1; } else { result.push(line); pos = nl + 1; } } return result } : function (string) { return string.split(/\r\n?|\n/); }; var hasSelection = window.getSelection ? function (te) { try { return te.selectionStart != te.selectionEnd } catch(e) { return false } } : function (te) { var range$$1; try {range$$1 = te.ownerDocument.selection.createRange();} catch(e) {} if (!range$$1 || range$$1.parentElement() != te) { return false } return range$$1.compareEndPoints("StartToEnd", range$$1) != 0 }; var hasCopyEvent = (function () { var e = elt("div"); if ("oncopy" in e) { return true } e.setAttribute("oncopy", "return;"); return typeof e.oncopy == "function" })(); var badZoomedRects = null; function hasBadZoomedRects(measure) { if (badZoomedRects != null) { return badZoomedRects } var node = removeChildrenAndAdd(measure, elt("span", "x")); var normal = node.getBoundingClientRect(); var fromRange = range(node, 0, 1).getBoundingClientRect(); return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1 } // Known modes, by name and by MIME var modes = {}, mimeModes = {}; // Extra arguments are stored as the mode's dependencies, which is // used by (legacy) mechanisms like loadmode.js to automatically // load a mode. (Preferred mechanism is the require/define calls.) function defineMode(name, mode) { if (arguments.length > 2) { mode.dependencies = Array.prototype.slice.call(arguments, 2); } modes[name] = mode; } function defineMIME(mime, spec) { mimeModes[mime] = spec; } // Given a MIME type, a {name, ...options} config object, or a name // string, return a mode config object. function resolveMode(spec) { if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { spec = mimeModes[spec]; } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { var found = mimeModes[spec.name]; if (typeof found == "string") { found = {name: found}; } spec = createObj(found, spec); spec.name = found.name; } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { return resolveMode("application/xml") } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { return resolveMode("application/json") } if (typeof spec == "string") { return {name: spec} } else { return spec || {name: "null"} } } // Given a mode spec (anything that resolveMode accepts), find and // initialize an actual mode object. function getMode(options, spec) { spec = resolveMode(spec); var mfactory = modes[spec.name]; if (!mfactory) { return getMode(options, "text/plain") } var modeObj = mfactory(options, spec); if (modeExtensions.hasOwnProperty(spec.name)) { var exts = modeExtensions[spec.name]; for (var prop in exts) { if (!exts.hasOwnProperty(prop)) { continue } if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; } modeObj[prop] = exts[prop]; } } modeObj.name = spec.name; if (spec.helperType) { modeObj.helperType = spec.helperType; } if (spec.modeProps) { for (var prop$1 in spec.modeProps) { modeObj[prop$1] = spec.modeProps[prop$1]; } } return modeObj } // This can be used to attach properties to mode objects from // outside the actual mode definition. var modeExtensions = {}; function extendMode(mode, properties) { var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); copyObj(properties, exts); } function copyState(mode, state) { if (state === true) { return state } if (mode.copyState) { return mode.copyState(state) } var nstate = {}; for (var n in state) { var val = state[n]; if (val instanceof Array) { val = val.concat([]); } nstate[n] = val; } return nstate } // Given a mode and a state (for that mode), find the inner mode and // state at the position that the state refers to. function innerMode(mode, state) { var info; while (mode.innerMode) { info = mode.innerMode(state); if (!info || info.mode == mode) { break } state = info.state; mode = info.mode; } return info || {mode: mode, state: state} } function startState(mode, a1, a2) { return mode.startState ? mode.startState(a1, a2) : true } // STRING STREAM // Fed to the mode parsers, provides helper functions to make // parsers more succinct. var StringStream = function(string, tabSize, lineOracle) { this.pos = this.start = 0; this.string = string; this.tabSize = tabSize || 8; this.lastColumnPos = this.lastColumnValue = 0; this.lineStart = 0; this.lineOracle = lineOracle; }; StringStream.prototype.eol = function () {return this.pos >= this.string.length}; StringStream.prototype.sol = function () {return this.pos == this.lineStart}; StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined}; StringStream.prototype.next = function () { if (this.pos < this.string.length) { return this.string.charAt(this.pos++) } }; StringStream.prototype.eat = function (match) { var ch = this.string.charAt(this.pos); var ok; if (typeof match == "string") { ok = ch == match; } else { ok = ch && (match.test ? match.test(ch) : match(ch)); } if (ok) {++this.pos; return ch} }; StringStream.prototype.eatWhile = function (match) { var start = this.pos; while (this.eat(match)){} return this.pos > start }; StringStream.prototype.eatSpace = function () { var this$1 = this; var start = this.pos; while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos; } return this.pos > start }; StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;}; StringStream.prototype.skipTo = function (ch) { var found = this.string.indexOf(ch, this.pos); if (found > -1) {this.pos = found; return true} }; StringStream.prototype.backUp = function (n) {this.pos -= n;}; StringStream.prototype.column = function () { if (this.lastColumnPos < this.start) { this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); this.lastColumnPos = this.start; } return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) }; StringStream.prototype.indentation = function () { return countColumn(this.string, null, this.tabSize) - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) }; StringStream.prototype.match = function (pattern, consume, caseInsensitive) { if (typeof pattern == "string") { var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; }; var substr = this.string.substr(this.pos, pattern.length); if (cased(substr) == cased(pattern)) { if (consume !== false) { this.pos += pattern.length; } return true } } else { var match = this.string.slice(this.pos).match(pattern); if (match && match.index > 0) { return null } if (match && consume !== false) { this.pos += match[0].length; } return match } }; StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)}; StringStream.prototype.hideFirstChars = function (n, inner) { this.lineStart += n; try { return inner() } finally { this.lineStart -= n; } }; StringStream.prototype.lookAhead = function (n) { var oracle = this.lineOracle; return oracle && oracle.lookAhead(n) }; StringStream.prototype.baseToken = function () { var oracle = this.lineOracle; return oracle && oracle.baseToken(this.pos) }; // Find the line object corresponding to the given line number. function getLine(doc, n) { n -= doc.first; if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } var chunk = doc; while (!chunk.lines) { for (var i = 0;; ++i) { var child = chunk.children[i], sz = child.chunkSize(); if (n < sz) { chunk = child; break } n -= sz; } } return chunk.lines[n] } // Get the part of a document between two positions, as an array of // strings. function getBetween(doc, start, end) { var out = [], n = start.line; doc.iter(start.line, end.line + 1, function (line) { var text = line.text; if (n == end.line) { text = text.slice(0, end.ch); } if (n == start.line) { text = text.slice(start.ch); } out.push(text); ++n; }); return out } // Get the lines between from and to, as array of strings. function getLines(doc, from, to) { var out = []; doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value return out } // Update the height of a line, propagating the height change // upwards to parent nodes. function updateLineHeight(line, height) { var diff = height - line.height; if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } } } // Given a line object, find its line number by walking up through // its parent links. function lineNo(line) { if (line.parent == null) { return null } var cur = line.parent, no = indexOf(cur.lines, line); for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { for (var i = 0;; ++i) { if (chunk.children[i] == cur) { break } no += chunk.children[i].chunkSize(); } } return no + cur.first } // Find the line at the given vertical position, using the height // information in the document tree. function lineAtHeight(chunk, h) { var n = chunk.first; outer: do { for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { var child = chunk.children[i$1], ch = child.height; if (h < ch) { chunk = child; continue outer } h -= ch; n += child.chunkSize(); } return n } while (!chunk.lines) var i = 0; for (; i < chunk.lines.length; ++i) { var line = chunk.lines[i], lh = line.height; if (h < lh) { break } h -= lh; } return n + i } function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} function lineNumberFor(options, i) { return String(options.lineNumberFormatter(i + options.firstLineNumber)) } // A Pos instance represents a position within the text. function Pos(line, ch, sticky) { if ( sticky === void 0 ) sticky = null; if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } this.line = line; this.ch = ch; this.sticky = sticky; } // Compare two positions, return 0 if they are the same, a negative // number when a is less, and a positive number otherwise. function cmp(a, b) { return a.line - b.line || a.ch - b.ch } function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } function copyPos(x) {return Pos(x.line, x.ch)} function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } function minPos(a, b) { return cmp(a, b) < 0 ? a : b } // Most of the external API clips given positions to make sure they // actually exist within the document. function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} function clipPos(doc, pos) { if (pos.line < doc.first) { return Pos(doc.first, 0) } var last = doc.first + doc.size - 1; if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } return clipToLen(pos, getLine(doc, pos.line).text.length) } function clipToLen(pos, linelen) { var ch = pos.ch; if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } else if (ch < 0) { return Pos(pos.line, 0) } else { return pos } } function clipPosArray(doc, array) { var out = []; for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); } return out } var SavedContext = function(state, lookAhead) { this.state = state; this.lookAhead = lookAhead; }; var Context = function(doc, state, line, lookAhead) { this.state = state; this.doc = doc; this.line = line; this.maxLookAhead = lookAhead || 0; this.baseTokens = null; this.baseTokenPos = 1; }; Context.prototype.lookAhead = function (n) { var line = this.doc.getLine(this.line + n); if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; } return line }; Context.prototype.baseToken = function (n) { var this$1 = this; if (!this.baseTokens) { return null } while (this.baseTokens[this.baseTokenPos] <= n) { this$1.baseTokenPos += 2; } var type = this.baseTokens[this.baseTokenPos + 1]; return {type: type && type.replace(/( |^)overlay .*/, ""), size: this.baseTokens[this.baseTokenPos] - n} }; Context.prototype.nextLine = function () { this.line++; if (this.maxLookAhead > 0) { this.maxLookAhead--; } }; Context.fromSaved = function (doc, saved, line) { if (saved instanceof SavedContext) { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) } else { return new Context(doc, copyState(doc.mode, saved), line) } }; Context.prototype.save = function (copy) { var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state; return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state }; // Compute a style array (an array starting with a mode generation // -- for invalidation -- followed by pairs of end positions and // style strings), which is used to highlight the tokens on the // line. function highlightLine(cm, line, context, forceToEnd) { // A styles array always starts with a number identifying the // mode/overlays that it is based on (for easy invalidation). var st = [cm.state.modeGen], lineClasses = {}; // Compute the base array of styles runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); }, lineClasses, forceToEnd); var state = context.state; // Run overlays, adjust style array. var loop = function ( o ) { context.baseTokens = st; var overlay = cm.state.overlays[o], i = 1, at = 0; context.state = true; runMode(cm, line.text, overlay.mode, context, function (end, style) { var start = i; // Ensure there's a token end at the current position, and that i points at it while (at < end) { var i_end = st[i]; if (i_end > end) { st.splice(i, 1, end, st[i+1], i_end); } i += 2; at = Math.min(end, i_end); } if (!style) { return } if (overlay.opaque) { st.splice(start, i - start, end, "overlay " + style); i = start + 2; } else { for (; start < i; start += 2) { var cur = st[start+1]; st[start+1] = (cur ? cur + " " : "") + "overlay " + style; } } }, lineClasses); context.state = state; context.baseTokens = null; context.baseTokenPos = 1; }; for (var o = 0; o < cm.state.overlays.length; ++o) loop( o ); return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null} } function getLineStyles(cm, line, updateFrontier) { if (!line.styles || line.styles[0] != cm.state.modeGen) { var context = getContextBefore(cm, lineNo(line)); var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state); var result = highlightLine(cm, line, context); if (resetState) { context.state = resetState; } line.stateAfter = context.save(!resetState); line.styles = result.styles; if (result.classes) { line.styleClasses = result.classes; } else if (line.styleClasses) { line.styleClasses = null; } if (updateFrontier === cm.doc.highlightFrontier) { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); } } return line.styles } function getContextBefore(cm, n, precise) { var doc = cm.doc, display = cm.display; if (!doc.mode.startState) { return new Context(doc, true, n) } var start = findStartLine(cm, n, precise); var saved = start > doc.first && getLine(doc, start - 1).stateAfter; var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start); doc.iter(start, n, function (line) { processLine(cm, line.text, context); var pos = context.line; line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null; context.nextLine(); }); if (precise) { doc.modeFrontier = context.line; } return context } // Lightweight form of highlight -- proceed over this line and // update state, but don't save a style array. Used for lines that // aren't currently visible. function processLine(cm, text, context, startAt) { var mode = cm.doc.mode; var stream = new StringStream(text, cm.options.tabSize, context); stream.start = stream.pos = startAt || 0; if (text == "") { callBlankLine(mode, context.state); } while (!stream.eol()) { readToken(mode, stream, context.state); stream.start = stream.pos; } } function callBlankLine(mode, state) { if (mode.blankLine) { return mode.blankLine(state) } if (!mode.innerMode) { return } var inner = innerMode(mode, state); if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) } } function readToken(mode, stream, state, inner) { for (var i = 0; i < 10; i++) { if (inner) { inner[0] = innerMode(mode, state).mode; } var style = mode.token(stream, state); if (stream.pos > stream.start) { return style } } throw new Error("Mode " + mode.name + " failed to advance stream.") } var Token = function(stream, type, state) { this.start = stream.start; this.end = stream.pos; this.string = stream.current(); this.type = type || null; this.state = state; }; // Utility for getTokenAt and getLineTokens function takeToken(cm, pos, precise, asArray) { var doc = cm.doc, mode = doc.mode, style; pos = clipPos(doc, pos); var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise); var stream = new StringStream(line.text, cm.options.tabSize, context), tokens; if (asArray) { tokens = []; } while ((asArray || stream.pos < pos.ch) && !stream.eol()) { stream.start = stream.pos; style = readToken(mode, stream, context.state); if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); } } return asArray ? tokens : new Token(stream, style, context.state) } function extractLineClasses(type, output) { if (type) { for (;;) { var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); if (!lineClass) { break } type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); var prop = lineClass[1] ? "bgClass" : "textClass"; if (output[prop] == null) { output[prop] = lineClass[2]; } else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) { output[prop] += " " + lineClass[2]; } } } return type } // Run the given mode's parser over a line, calling f for each token. function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) { var flattenSpans = mode.flattenSpans; if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; } var curStart = 0, curStyle = null; var stream = new StringStream(text, cm.options.tabSize, context), style; var inner = cm.options.addModeClass && [null]; if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); } while (!stream.eol()) { if (stream.pos > cm.options.maxHighlightLength) { flattenSpans = false; if (forceToEnd) { processLine(cm, text, context, stream.pos); } stream.pos = text.length; style = null; } else { style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses); } if (inner) { var mName = inner[0].name; if (mName) { style = "m-" + (style ? mName + " " + style : mName); } } if (!flattenSpans || curStyle != style) { while (curStart < stream.start) { curStart = Math.min(stream.start, curStart + 5000); f(curStart, curStyle); } curStyle = style; } stream.start = stream.pos; } while (curStart < stream.pos) { // Webkit seems to refuse to render text nodes longer than 57444 // characters, and returns inaccurate measurements in nodes // starting around 5000 chars. var pos = Math.min(stream.pos, curStart + 5000); f(pos, curStyle); curStart = pos; } } // Finds the line to start with when starting a parse. Tries to // find a line with a stateAfter, so that it can start with a // valid state. If that fails, it returns the line with the // smallest indentation, which tends to need the least context to // parse correctly. function findStartLine(cm, n, precise) { var minindent, minline, doc = cm.doc; var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); for (var search = n; search > lim; --search) { if (search <= doc.first) { return doc.first } var line = getLine(doc, search - 1), after = line.stateAfter; if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier)) { return search } var indented = countColumn(line.text, null, cm.options.tabSize); if (minline == null || minindent > indented) { minline = search - 1; minindent = indented; } } return minline } function retreatFrontier(doc, n) { doc.modeFrontier = Math.min(doc.modeFrontier, n); if (doc.highlightFrontier < n - 10) { return } var start = doc.first; for (var line = n - 1; line > start; line--) { var saved = getLine(doc, line).stateAfter; // change is on 3 // state on line 1 looked ahead 2 -- so saw 3 // test 1 + 2 < 3 should cover this if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) { start = line + 1; break } } doc.highlightFrontier = Math.min(doc.highlightFrontier, start); } // Optimize some code when these features are not used. var sawReadOnlySpans = false, sawCollapsedSpans = false; function seeReadOnlySpans() { sawReadOnlySpans = true; } function seeCollapsedSpans() { sawCollapsedSpans = true; } // TEXTMARKER SPANS function MarkedSpan(marker, from, to) { this.marker = marker; this.from = from; this.to = to; } // Search an array of spans for a span matching the given marker. function getMarkedSpanFor(spans, marker) { if (spans) { for (var i = 0; i < spans.length; ++i) { var span = spans[i]; if (span.marker == marker) { return span } } } } // Remove a span from an array, returning undefined if no spans are // left (we don't store arrays for lines without spans). function removeMarkedSpan(spans, span) { var r; for (var i = 0; i < spans.length; ++i) { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } } return r } // Add a span to a line. function addMarkedSpan(line, span) { line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; span.marker.attachLine(line); } // Used for the algorithm that adjusts markers for a change in the // document. These functions cut an array of spans at a given // character position, returning an array of remaining chunks (or // undefined if nothing remains). function markedSpansBefore(old, startCh, isInsert) { var nw; if (old) { for (var i = 0; i < old.length; ++i) { var span = old[i], marker = span.marker; var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); } } } return nw } function markedSpansAfter(old, endCh, isInsert) { var nw; if (old) { for (var i = 0; i < old.length; ++i) { var span = old[i], marker = span.marker; var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, span.to == null ? null : span.to - endCh)); } } } return nw } // Given a change object, compute the new set of marker spans that // cover the line in which the change took place. Removes spans // entirely within the change, reconnects spans belonging to the // same marker that appear on both sides of the change, and cuts off // spans partially within the change. Returns an array of span // arrays with one element for each line in (after) the change. function stretchSpansOverChange(doc, change) { if (change.full) { return null } var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; if (!oldFirst && !oldLast) { return null } var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; // Get the spans that 'stick out' on both sides var first = markedSpansBefore(oldFirst, startCh, isInsert); var last = markedSpansAfter(oldLast, endCh, isInsert); // Next, merge those two ends var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); if (first) { // Fix up .to properties of first for (var i = 0; i < first.length; ++i) { var span = first[i]; if (span.to == null) { var found = getMarkedSpanFor(last, span.marker); if (!found) { span.to = startCh; } else if (sameLine) { span.to = found.to == null ? null : found.to + offset; } } } } if (last) { // Fix up .from in last (or move them into first in case of sameLine) for (var i$1 = 0; i$1 < last.length; ++i$1) { var span$1 = last[i$1]; if (span$1.to != null) { span$1.to += offset; } if (span$1.from == null) { var found$1 = getMarkedSpanFor(first, span$1.marker); if (!found$1) { span$1.from = offset; if (sameLine) { (first || (first = [])).push(span$1); } } } else { span$1.from += offset; if (sameLine) { (first || (first = [])).push(span$1); } } } } // Make sure we didn't create any zero-length spans if (first) { first = clearEmptySpans(first); } if (last && last != first) { last = clearEmptySpans(last); } var newMarkers = [first]; if (!sameLine) { // Fill gap with whole-line-spans var gap = change.text.length - 2, gapMarkers; if (gap > 0 && first) { for (var i$2 = 0; i$2 < first.length; ++i$2) { if (first[i$2].to == null) { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } } for (var i$3 = 0; i$3 < gap; ++i$3) { newMarkers.push(gapMarkers); } newMarkers.push(last); } return newMarkers } // Remove spans that are empty and don't have a clearWhenEmpty // option of false. function clearEmptySpans(spans) { for (var i = 0; i < spans.length; ++i) { var span = spans[i]; if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) { spans.splice(i--, 1); } } if (!spans.length) { return null } return spans } // Used to 'clip' out readOnly ranges when making a change. function removeReadOnlyRanges(doc, from, to) { var markers = null; doc.iter(from.line, to.line + 1, function (line) { if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { var mark = line.markedSpans[i].marker; if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) { (markers || (markers = [])).push(mark); } } } }); if (!markers) { return null } var parts = [{from: from, to: to}]; for (var i = 0; i < markers.length; ++i) { var mk = markers[i], m = mk.find(0); for (var j = 0; j < parts.length; ++j) { var p = parts[j]; if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) { newParts.push({from: p.from, to: m.from}); } if (dto > 0 || !mk.inclusiveRight && !dto) { newParts.push({from: m.to, to: p.to}); } parts.splice.apply(parts, newParts); j += newParts.length - 3; } } return parts } // Connect or disconnect spans from a line. function detachMarkedSpans(line) { var spans = line.markedSpans; if (!spans) { return } for (var i = 0; i < spans.length; ++i) { spans[i].marker.detachLine(line); } line.markedSpans = null; } function attachMarkedSpans(line, spans) { if (!spans) { return } for (var i = 0; i < spans.length; ++i) { spans[i].marker.attachLine(line); } line.markedSpans = spans; } // Helpers used when computing which overlapping collapsed span // counts as the larger one. function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } // Returns a number indicating which of two overlapping collapsed // spans is larger (and thus includes the other). Falls back to // comparing ids when the spans cover exactly the same range. function compareCollapsedMarkers(a, b) { var lenDiff = a.lines.length - b.lines.length; if (lenDiff != 0) { return lenDiff } var aPos = a.find(), bPos = b.find(); var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); if (fromCmp) { return -fromCmp } var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); if (toCmp) { return toCmp } return b.id - a.id } // Find out whether a line ends or starts in a collapsed span. If // so, return the marker for that span. function collapsedSpanAtSide(line, start) { var sps = sawCollapsedSpans && line.markedSpans, found; if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { sp = sps[i]; if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; } } } return found } function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } function collapsedSpanAround(line, ch) { var sps = sawCollapsedSpans && line.markedSpans, found; if (sps) { for (var i = 0; i < sps.length; ++i) { var sp = sps[i]; if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) && (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; } } } return found } // Test whether there exists a collapsed span that partially // overlaps (covers the start or end, but not both) of a new span. // Such overlap is not allowed. function conflictingCollapsedRange(doc, lineNo$$1, from, to, marker) { var line = getLine(doc, lineNo$$1); var sps = sawCollapsedSpans && line.markedSpans; if (sps) { for (var i = 0; i < sps.length; ++i) { var sp = sps[i]; if (!sp.marker.collapsed) { continue } var found = sp.marker.find(0); var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) { return true } } } } // A visual line is a line as drawn on the screen. Folding, for // example, can cause multiple logical lines to appear on the same // visual line. This finds the start of the visual line that the // given line is part of (usually that is the line itself). function visualLine(line) { var merged; while (merged = collapsedSpanAtStart(line)) { line = merged.find(-1, true).line; } return line } function visualLineEnd(line) { var merged; while (merged = collapsedSpanAtEnd(line)) { line = merged.find(1, true).line; } return line } // Returns an array of logical lines that continue the visual line // started by the argument, or undefined if there are no such lines. function visualLineContinued(line) { var merged, lines; while (merged = collapsedSpanAtEnd(line)) { line = merged.find(1, true).line ;(lines || (lines = [])).push(line); } return lines } // Get the line number of the start of the visual line that the // given line number is part of. function visualLineNo(doc, lineN) { var line = getLine(doc, lineN), vis = visualLine(line); if (line == vis) { return lineN } return lineNo(vis) } // Get the line number of the start of the next visual line after // the given line. function visualLineEndNo(doc, lineN) { if (lineN > doc.lastLine()) { return lineN } var line = getLine(doc, lineN), merged; if (!lineIsHidden(doc, line)) { return lineN } while (merged = collapsedSpanAtEnd(line)) { line = merged.find(1, true).line; } return lineNo(line) + 1 } // Compute whether a line is hidden. Lines count as hidden when they // are part of a visual line that starts with another line, or when // they are entirely covered by collapsed, non-widget span. function lineIsHidden(doc, line) { var sps = sawCollapsedSpans && line.markedSpans; if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { sp = sps[i]; if (!sp.marker.collapsed) { continue } if (sp.from == null) { return true } if (sp.marker.widgetNode) { continue } if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) { return true } } } } function lineIsHiddenInner(doc, line, span) { if (span.to == null) { var end = span.marker.find(1, true); return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) } if (span.marker.inclusiveRight && span.to == line.text.length) { return true } for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { sp = line.markedSpans[i]; if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && (sp.to == null || sp.to != span.from) && (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && lineIsHiddenInner(doc, line, sp)) { return true } } } // Find the height above the given line. function heightAtLine(lineObj) { lineObj = visualLine(lineObj); var h = 0, chunk = lineObj.parent; for (var i = 0; i < chunk.lines.length; ++i) { var line = chunk.lines[i]; if (line == lineObj) { break } else { h += line.height; } } for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { for (var i$1 = 0; i$1 < p.children.length; ++i$1) { var cur = p.children[i$1]; if (cur == chunk) { break } else { h += cur.height; } } } return h } // Compute the character length of a line, taking into account // collapsed ranges (see markText) that might hide parts, and join // other lines onto it. function lineLength(line) { if (line.height == 0) { return 0 } var len = line.text.length, merged, cur = line; while (merged = collapsedSpanAtStart(cur)) { var found = merged.find(0, true); cur = found.from.line; len += found.from.ch - found.to.ch; } cur = line; while (merged = collapsedSpanAtEnd(cur)) { var found$1 = merged.find(0, true); len -= cur.text.length - found$1.from.ch; cur = found$1.to.line; len += cur.text.length - found$1.to.ch; } return len } // Find the longest line in the document. function findMaxLine(cm) { var d = cm.display, doc = cm.doc; d.maxLine = getLine(doc, doc.first); d.maxLineLength = lineLength(d.maxLine); d.maxLineChanged = true; doc.iter(function (line) { var len = lineLength(line); if (len > d.maxLineLength) { d.maxLineLength = len; d.maxLine = line; } }); } // LINE DATA STRUCTURE // Line objects. These hold state related to a line, including // highlighting info (the styles array). var Line = function(text, markedSpans, estimateHeight) { this.text = text; attachMarkedSpans(this, markedSpans); this.height = estimateHeight ? estimateHeight(this) : 1; }; Line.prototype.lineNo = function () { return lineNo(this) }; eventMixin(Line); // Change the content (text, markers) of a line. Automatically // invalidates cached information and tries to re-estimate the // line's height. function updateLine(line, text, markedSpans, estimateHeight) { line.text = text; if (line.stateAfter) { line.stateAfter = null; } if (line.styles) { line.styles = null; } if (line.order != null) { line.order = null; } detachMarkedSpans(line); attachMarkedSpans(line, markedSpans); var estHeight = estimateHeight ? estimateHeight(line) : 1; if (estHeight != line.height) { updateLineHeight(line, estHeight); } } // Detach a line from the document tree and its markers. function cleanUpLine(line) { line.parent = null; detachMarkedSpans(line); } // Convert a style as returned by a mode (either null, or a string // containing one or more styles) to a CSS style. This is cached, // and also looks for line-wide styles. var styleToClassCache = {}, styleToClassCacheWithMode = {}; function interpretTokenStyle(style, options) { if (!style || /^\s*$/.test(style)) { return null } var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; return cache[style] || (cache[style] = style.replace(/\S+/g, "cm-$&")) } // Render the DOM representation of the text of a line. Also builds // up a 'line map', which points at the DOM nodes that represent // specific stretches of text, and is used by the measuring code. // The returned object contains the DOM node, this map, and // information about line-wide styles that were set by the mode. function buildLineContent(cm, lineView) { // The padding-right forces the element to have a 'border', which // is needed on Webkit to be able to get line-level bounding // rectangles for it (in measureChar). var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null); var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content, col: 0, pos: 0, cm: cm, trailingSpace: false, splitSpaces: cm.getOption("lineWrapping")}; lineView.measure = {}; // Iterate over the logical lines that make up this visual line. for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0); builder.pos = 0; builder.addToken = buildToken; // Optionally wire in some hacks into the token-rendering // algorithm, to deal with browser quirks. if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction))) { builder.addToken = buildTokenBadBidi(builder.addToken, order); } builder.map = []; var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); if (line.styleClasses) { if (line.styleClasses.bgClass) { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); } if (line.styleClasses.textClass) { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); } } // Ensure at least a single node is present, for measuring. if (builder.map.length == 0) { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); } // Store the map and a cache object for the current logical line if (i == 0) { lineView.measure.map = builder.map; lineView.measure.cache = {}; } else { (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map) ;(lineView.measure.caches || (lineView.measure.caches = [])).push({}); } } // See issue #2901 if (webkit) { var last = builder.content.lastChild; if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) { builder.content.className = "cm-tab-wrap-hack"; } } signal(cm, "renderLine", cm, lineView.line, builder.pre); if (builder.pre.className) { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); } return builder } function defaultSpecialCharPlaceholder(ch) { var token = elt("span", "\u2022", "cm-invalidchar"); token.title = "\\u" + ch.charCodeAt(0).toString(16); token.setAttribute("aria-label", token.title); return token } // Build up the DOM representation for a single token, and add it to // the line map. Takes care to render special characters separately. function buildToken(builder, text, style, startStyle, endStyle, css, attributes) { if (!text) { return } var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text; var special = builder.cm.state.specialChars, mustWrap = false; var content; if (!special.test(text)) { builder.col += text.length; content = document.createTextNode(displayText); builder.map.push(builder.pos, builder.pos + text.length, content); if (ie && ie_version < 9) { mustWrap = true; } builder.pos += text.length; } else { content = document.createDocumentFragment(); var pos = 0; while (true) { special.lastIndex = pos; var m = special.exec(text); var skipped = m ? m.index - pos : text.length - pos; if (skipped) { var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); } else { content.appendChild(txt); } builder.map.push(builder.pos, builder.pos + skipped, txt); builder.col += skipped; builder.pos += skipped; } if (!m) { break } pos += skipped + 1; var txt$1 = (void 0); if (m[0] == "\t") { var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); txt$1.setAttribute("role", "presentation"); txt$1.setAttribute("cm-text", "\t"); builder.col += tabWidth; } else if (m[0] == "\r" || m[0] == "\n") { txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); txt$1.setAttribute("cm-text", m[0]); builder.col += 1; } else { txt$1 = builder.cm.options.specialCharPlaceholder(m[0]); txt$1.setAttribute("cm-text", m[0]); if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); } else { content.appendChild(txt$1); } builder.col += 1; } builder.map.push(builder.pos, builder.pos + 1, txt$1); builder.pos++; } } builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32; if (style || startStyle || endStyle || mustWrap || css) { var fullStyle = style || ""; if (startStyle) { fullStyle += startStyle; } if (endStyle) { fullStyle += endStyle; } var token = elt("span", [content], fullStyle, css); if (attributes) { for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class") { token.setAttribute(attr, attributes[attr]); } } } return builder.content.appendChild(token) } builder.content.appendChild(content); } // Change some spaces to NBSP to prevent the browser from collapsing // trailing spaces at the end of a line when rendering text (issue #1362). function splitSpaces(text, trailingBefore) { if (text.length > 1 && !/ /.test(text)) { return text } var spaceBefore = trailingBefore, result = ""; for (var i = 0; i < text.length; i++) { var ch = text.charAt(i); if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) { ch = "\u00a0"; } result += ch; spaceBefore = ch == " "; } return result } // Work around nonsense dimensions being reported for stretches of // right-to-left text. function buildTokenBadBidi(inner, order) { return function (builder, text, style, startStyle, endStyle, css, attributes) { style = style ? style + " cm-force-border" : "cm-force-border"; var start = builder.pos, end = start + text.length; for (;;) { // Find the part that overlaps with the start of this text var part = (void 0); for (var i = 0; i < order.length; i++) { part = order[i]; if (part.to > start && part.from <= start) { break } } if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) } inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes); startStyle = null; text = text.slice(part.to - start); start = part.to; } } } function buildCollapsedSpan(builder, size, marker, ignoreWidget) { var widget = !ignoreWidget && marker.widgetNode; if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); } if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { if (!widget) { widget = builder.content.appendChild(document.createElement("span")); } widget.setAttribute("cm-marker", marker.id); } if (widget) { builder.cm.display.input.setUneditable(widget); builder.content.appendChild(widget); } builder.pos += size; builder.trailingSpace = false; } // Outputs a number of spans to make up a line, taking highlighting // and marked text into account. function insertLineContent(line, builder, styles) { var spans = line.markedSpans, allText = line.text, at = 0; if (!spans) { for (var i$1 = 1; i$1 < styles.length; i$1+=2) { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); } return } var len = allText.length, pos = 0, i = 1, text = "", style, css; var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes; for (;;) { if (nextChange == pos) { // Update current marker set spanStyle = spanEndStyle = spanStartStyle = css = ""; attributes = null; collapsed = null; nextChange = Infinity; var foundBookmarks = [], endStyles = (void 0); for (var j = 0; j < spans.length; ++j) { var sp = spans[j], m = sp.marker; if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { foundBookmarks.push(m); } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { if (sp.to != null && sp.to != pos && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; } if (m.className) { spanStyle += " " + m.className; } if (m.css) { css = (css ? css + ";" : "") + m.css; } if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; } if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); } // support for the old title property // https://github.com/codemirror/CodeMirror/pull/5673 if (m.title) { (attributes || (attributes = {})).title = m.title; } if (m.attributes) { for (var attr in m.attributes) { (attributes || (attributes = {}))[attr] = m.attributes[attr]; } } if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) { collapsed = sp; } } else if (sp.from > pos && nextChange > sp.from) { nextChange = sp.from; } } if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } } if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } } if (collapsed && (collapsed.from || 0) == pos) { buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, collapsed.marker, collapsed.from == null); if (collapsed.to == null) { return } if (collapsed.to == pos) { collapsed = false; } } } if (pos >= len) { break } var upto = Math.min(len, nextChange); while (true) { if (text) { var end = pos + text.length; if (!collapsed) { var tokenText = end > upto ? text.slice(0, upto - pos) : text; builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes); } if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} pos = end; spanStartStyle = ""; } text = allText.slice(at, at = styles[i++]); style = interpretTokenStyle(styles[i++], builder.cm.options); } } } // These objects are used to represent the visible (currently drawn) // part of the document. A LineView may correspond to multiple // logical lines, if those are connected by collapsed ranges. function LineView(doc, line, lineN) { // The starting line this.line = line; // Continuing lines, if any this.rest = visualLineContinued(line); // Number of logical lines in this visual line this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; this.node = this.text = null; this.hidden = lineIsHidden(doc, line); } // Create a range of LineView objects for the given lines. function buildViewArray(cm, from, to) { var array = [], nextPos; for (var pos = from; pos < to; pos = nextPos) { var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); nextPos = pos + view.size; array.push(view); } return array } var operationGroup = null; function pushOperation(op) { if (operationGroup) { operationGroup.ops.push(op); } else { op.ownsGroup = operationGroup = { ops: [op], delayedCallbacks: [] }; } } function fireCallbacksForOps(group) { // Calls delayed callbacks and cursorActivity handlers until no // new ones appear var callbacks = group.delayedCallbacks, i = 0; do { for (; i < callbacks.length; i++) { callbacks[i].call(null); } for (var j = 0; j < group.ops.length; j++) { var op = group.ops[j]; if (op.cursorActivityHandlers) { while (op.cursorActivityCalled < op.cursorActivityHandlers.length) { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } } } } while (i < callbacks.length) } function finishOperation(op, endCb) { var group = op.ownsGroup; if (!group) { return } try { fireCallbacksForOps(group); } finally { operationGroup = null; endCb(group); } } var orphanDelayedCallbacks = null; // Often, we want to signal events at a point where we are in the // middle of some work, but don't want the handler to start calling // other methods on the editor, which might be in an inconsistent // state or simply not expect any other events to happen. // signalLater looks whether there are any handlers, and schedules // them to be executed when the last operation ends, or, if no // operation is active, when a timeout fires. function signalLater(emitter, type /*, values...*/) { var arr = getHandlers(emitter, type); if (!arr.length) { return } var args = Array.prototype.slice.call(arguments, 2), list; if (operationGroup) { list = operationGroup.delayedCallbacks; } else if (orphanDelayedCallbacks) { list = orphanDelayedCallbacks; } else { list = orphanDelayedCallbacks = []; setTimeout(fireOrphanDelayed, 0); } var loop = function ( i ) { list.push(function () { return arr[i].apply(null, args); }); }; for (var i = 0; i < arr.length; ++i) loop( i ); } function fireOrphanDelayed() { var delayed = orphanDelayedCallbacks; orphanDelayedCallbacks = null; for (var i = 0; i < delayed.length; ++i) { delayed[i](); } } // When an aspect of a line changes, a string is added to // lineView.changes. This updates the relevant part of the line's // DOM structure. function updateLineForChanges(cm, lineView, lineN, dims) { for (var j = 0; j < lineView.changes.length; j++) { var type = lineView.changes[j]; if (type == "text") { updateLineText(cm, lineView); } else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); } else if (type == "class") { updateLineClasses(cm, lineView); } else if (type == "widget") { updateLineWidgets(cm, lineView, dims); } } lineView.changes = null; } // Lines with gutter elements, widgets or a background class need to // be wrapped, and have the extra elements added to the wrapper div function ensureLineWrapped(lineView) { if (lineView.node == lineView.text) { lineView.node = elt("div", null, null, "position: relative"); if (lineView.text.parentNode) { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); } lineView.node.appendChild(lineView.text); if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; } } return lineView.node } function updateLineBackground(cm, lineView) { var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; if (cls) { cls += " CodeMirror-linebackground"; } if (lineView.background) { if (cls) { lineView.background.className = cls; } else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } } else if (cls) { var wrap = ensureLineWrapped(lineView); lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); cm.display.input.setUneditable(lineView.background); } } // Wrapper around buildLineContent which will reuse the structure // in display.externalMeasured when possible. function getLineContent(cm, lineView) { var ext = cm.display.externalMeasured; if (ext && ext.line == lineView.line) { cm.display.externalMeasured = null; lineView.measure = ext.measure; return ext.built } return buildLineContent(cm, lineView) } // Redraw the line's text. Interacts with the background and text // classes because the mode may output tokens that influence these // classes. function updateLineText(cm, lineView) { var cls = lineView.text.className; var built = getLineContent(cm, lineView); if (lineView.text == lineView.node) { lineView.node = built.pre; } lineView.text.parentNode.replaceChild(built.pre, lineView.text); lineView.text = built.pre; if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { lineView.bgClass = built.bgClass; lineView.textClass = built.textClass; updateLineClasses(cm, lineView); } else if (cls) { lineView.text.className = cls; } } function updateLineClasses(cm, lineView) { updateLineBackground(cm, lineView); if (lineView.line.wrapClass) { ensureLineWrapped(lineView).className = lineView.line.wrapClass; } else if (lineView.node != lineView.text) { lineView.node.className = ""; } var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; lineView.text.className = textClass || ""; } function updateLineGutter(cm, lineView, lineN, dims) { if (lineView.gutter) { lineView.node.removeChild(lineView.gutter); lineView.gutter = null; } if (lineView.gutterBackground) { lineView.node.removeChild(lineView.gutterBackground); lineView.gutterBackground = null; } if (lineView.line.gutterClass) { var wrap = ensureLineWrapped(lineView); lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px")); cm.display.input.setUneditable(lineView.gutterBackground); wrap.insertBefore(lineView.gutterBackground, lineView.text); } var markers = lineView.line.gutterMarkers; if (cm.options.lineNumbers || markers) { var wrap$1 = ensureLineWrapped(lineView); var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")); cm.display.input.setUneditable(gutterWrap); wrap$1.insertBefore(gutterWrap, lineView.text); if (lineView.line.gutterClass) { gutterWrap.className += " " + lineView.line.gutterClass; } if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) { lineView.lineNumber = gutterWrap.appendChild( elt("div", lineNumberFor(cm.options, lineN), "CodeMirror-linenumber CodeMirror-gutter-elt", ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); } if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) { var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id]; if (found) { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); } } } } } function updateLineWidgets(cm, lineView, dims) { if (lineView.alignable) { lineView.alignable = null; } for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { next = node.nextSibling; if (node.className == "CodeMirror-linewidget") { lineView.node.removeChild(node); } } insertLineWidgets(cm, lineView, dims); } // Build a line's DOM representation from scratch function buildLineElement(cm, lineView, lineN, dims) { var built = getLineContent(cm, lineView); lineView.text = lineView.node = built.pre; if (built.bgClass) { lineView.bgClass = built.bgClass; } if (built.textClass) { lineView.textClass = built.textClass; } updateLineClasses(cm, lineView); updateLineGutter(cm, lineView, lineN, dims); insertLineWidgets(cm, lineView, dims); return lineView.node } // A lineView may contain multiple logical lines (when merged by // collapsed spans). The widgets for all of them need to be drawn. function insertLineWidgets(cm, lineView, dims) { insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } } } function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { if (!line.widgets) { return } var wrap = ensureLineWrapped(lineView); for (var i = 0, ws = line.widgets; i < ws.length; ++i) { var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); } positionLineWidget(widget, node, lineView, dims); cm.display.input.setUneditable(node); if (allowAbove && widget.above) { wrap.insertBefore(node, lineView.gutter || lineView.text); } else { wrap.appendChild(node); } signalLater(widget, "redraw"); } } function positionLineWidget(widget, node, lineView, dims) { if (widget.noHScroll) { (lineView.alignable || (lineView.alignable = [])).push(node); var width = dims.wrapperWidth; node.style.left = dims.fixedPos + "px"; if (!widget.coverGutter) { width -= dims.gutterTotalWidth; node.style.paddingLeft = dims.gutterTotalWidth + "px"; } node.style.width = width + "px"; } if (widget.coverGutter) { node.style.zIndex = 5; node.style.position = "relative"; if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; } } } function widgetHeight(widget) { if (widget.height != null) { return widget.height } var cm = widget.doc.cm; if (!cm) { return 0 } if (!contains(document.body, widget.node)) { var parentStyle = "position: relative;"; if (widget.coverGutter) { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; } if (widget.noHScroll) { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; } removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); } return widget.height = widget.node.parentNode.offsetHeight } // Return true when the given mouse event happened in a widget function eventInWidget(display, e) { for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || (n.parentNode == display.sizer && n != display.mover)) { return true } } } // POSITION MEASUREMENT function paddingTop(display) {return display.lineSpace.offsetTop} function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight} function paddingH(display) { if (display.cachedPaddingH) { return display.cachedPaddingH } var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like")); var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; } return data } function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth } function displayWidth(cm) { return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth } function displayHeight(cm) { return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight } // Ensure the lineView.wrapping.heights array is populated. This is // an array of bottom offsets for the lines that make up a drawn // line. When lineWrapping is on, there might be more than one // height. function ensureLineHeights(cm, lineView, rect) { var wrapping = cm.options.lineWrapping; var curWidth = wrapping && displayWidth(cm); if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { var heights = lineView.measure.heights = []; if (wrapping) { lineView.measure.width = curWidth; var rects = lineView.text.firstChild.getClientRects(); for (var i = 0; i < rects.length - 1; i++) { var cur = rects[i], next = rects[i + 1]; if (Math.abs(cur.bottom - next.bottom) > 2) { heights.push((cur.bottom + next.top) / 2 - rect.top); } } } heights.push(rect.bottom - rect.top); } } // Find a line map (mapping character offsets to text nodes) and a // measurement cache for the given line number. (A line view might // contain multiple lines when collapsed ranges are present.) function mapFromLineView(lineView, line, lineN) { if (lineView.line == line) { return {map: lineView.measure.map, cache: lineView.measure.cache} } for (var i = 0; i < lineView.rest.length; i++) { if (lineView.rest[i] == line) { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } } for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) { if (lineNo(lineView.rest[i$1]) > lineN) { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } } } // Render a line into the hidden node display.externalMeasured. Used // when measurement is needed for a line that's not in the viewport. function updateExternalMeasurement(cm, line) { line = visualLine(line); var lineN = lineNo(line); var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); view.lineN = lineN; var built = view.built = buildLineContent(cm, view); view.text = built.pre; removeChildrenAndAdd(cm.display.lineMeasure, built.pre); return view } // Get a {top, bottom, left, right} box (in line-local coordinates) // for a given character. function measureChar(cm, line, ch, bias) { return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) } // Find a line view that corresponds to the given line number. function findViewForLine(cm, lineN) { if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) { return cm.display.view[findViewIndex(cm, lineN)] } var ext = cm.display.externalMeasured; if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) { return ext } } // Measurement can be split in two steps, the set-up work that // applies to the whole line, and the measurement of the actual // character. Functions like coordsChar, that need to do a lot of // measurements in a row, can thus ensure that the set-up work is // only done once. function prepareMeasureForLine(cm, line) { var lineN = lineNo(line); var view = findViewForLine(cm, lineN); if (view && !view.text) { view = null; } else if (view && view.changes) { updateLineForChanges(cm, view, lineN, getDimensions(cm)); cm.curOp.forceUpdate = true; } if (!view) { view = updateExternalMeasurement(cm, line); } var info = mapFromLineView(view, line, lineN); return { line: line, view: view, rect: null, map: info.map, cache: info.cache, before: info.before, hasHeights: false } } // Given a prepared measurement object, measures the position of an // actual character (or fetches it from the cache). function measureCharPrepared(cm, prepared, ch, bias, varHeight) { if (prepared.before) { ch = -1; } var key = ch + (bias || ""), found; if (prepared.cache.hasOwnProperty(key)) { found = prepared.cache[key]; } else { if (!prepared.rect) { prepared.rect = prepared.view.text.getBoundingClientRect(); } if (!prepared.hasHeights) { ensureLineHeights(cm, prepared.view, prepared.rect); prepared.hasHeights = true; } found = measureCharInner(cm, prepared, ch, bias); if (!found.bogus) { prepared.cache[key] = found; } } return {left: found.left, right: found.right, top: varHeight ? found.rtop : found.top, bottom: varHeight ? found.rbottom : found.bottom} } var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; function nodeAndOffsetInLineMap(map$$1, ch, bias) { var node, start, end, collapse, mStart, mEnd; // First, search the line map for the text node corresponding to, // or closest to, the target character. for (var i = 0; i < map$$1.length; i += 3) { mStart = map$$1[i]; mEnd = map$$1[i + 1]; if (ch < mStart) { start = 0; end = 1; collapse = "left"; } else if (ch < mEnd) { start = ch - mStart; end = start + 1; } else if (i == map$$1.length - 3 || ch == mEnd && map$$1[i + 3] > ch) { end = mEnd - mStart; start = end - 1; if (ch >= mEnd) { collapse = "right"; } } if (start != null) { node = map$$1[i + 2]; if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) { collapse = bias; } if (bias == "left" && start == 0) { while (i && map$$1[i - 2] == map$$1[i - 3] && map$$1[i - 1].insertLeft) { node = map$$1[(i -= 3) + 2]; collapse = "left"; } } if (bias == "right" && start == mEnd - mStart) { while (i < map$$1.length - 3 && map$$1[i + 3] == map$$1[i + 4] && !map$$1[i + 5].insertLeft) { node = map$$1[(i += 3) + 2]; collapse = "right"; } } break } } return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd} } function getUsefulRect(rects, bias) { var rect = nullRect; if (bias == "left") { for (var i = 0; i < rects.length; i++) { if ((rect = rects[i]).left != rect.right) { break } } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { if ((rect = rects[i$1]).left != rect.right) { break } } } return rect } function measureCharInner(cm, prepared, ch, bias) { var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); var node = place.node, start = place.start, end = place.end, collapse = place.collapse; var rect; if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; } while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; } if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) { rect = node.parentNode.getBoundingClientRect(); } else { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); } if (rect.left || rect.right || start == 0) { break } end = start; start = start - 1; collapse = "right"; } if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); } } else { // If it is a widget, simply get the box for the whole widget. if (start > 0) { collapse = bias = "right"; } var rects; if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) { rect = rects[bias == "right" ? rects.length - 1 : 0]; } else { rect = node.getBoundingClientRect(); } } if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { var rSpan = node.parentNode.getClientRects()[0]; if (rSpan) { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; } else { rect = nullRect; } } var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; var mid = (rtop + rbot) / 2; var heights = prepared.view.measure.heights; var i = 0; for (; i < heights.length - 1; i++) { if (mid < heights[i]) { break } } var top = i ? heights[i - 1] : 0, bot = heights[i]; var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, top: top, bottom: bot}; if (!rect.left && !rect.right) { result.bogus = true; } if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } return result } // Work around problem with bounding client rects on ranges being // returned incorrectly when zoomed on IE10 and below. function maybeUpdateRectForZooming(measure, rect) { if (!window.screen || screen.logicalXDPI == null || screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) { return rect } var scaleX = screen.logicalXDPI / screen.deviceXDPI; var scaleY = screen.logicalYDPI / screen.deviceYDPI; return {left: rect.left * scaleX, right: rect.right * scaleX, top: rect.top * scaleY, bottom: rect.bottom * scaleY} } function clearLineMeasurementCacheFor(lineView) { if (lineView.measure) { lineView.measure.cache = {}; lineView.measure.heights = null; if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) { lineView.measure.caches[i] = {}; } } } } function clearLineMeasurementCache(cm) { cm.display.externalMeasure = null; removeChildren(cm.display.lineMeasure); for (var i = 0; i < cm.display.view.length; i++) { clearLineMeasurementCacheFor(cm.display.view[i]); } } function clearCaches(cm) { clearLineMeasurementCache(cm); cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; } cm.display.lineNumChars = null; } function pageScrollX() { // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206 // which causes page_Offset and bounding client rects to use // different reference viewports and invalidate our calculations. if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) } return window.pageXOffset || (document.documentElement || document.body).scrollLeft } function pageScrollY() { if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) } return window.pageYOffset || (document.documentElement || document.body).scrollTop } function widgetTopHeight(lineObj) { var height = 0; if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) { height += widgetHeight(lineObj.widgets[i]); } } } return height } // Converts a {top, bottom, left, right} box from line-local // coordinates into another coordinate system. Context may be one of // "line", "div" (display.lineDiv), "local"./null (editor), "window", // or "page". function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { if (!includeWidgets) { var height = widgetTopHeight(lineObj); rect.top += height; rect.bottom += height; } if (context == "line") { return rect } if (!context) { context = "local"; } var yOff = heightAtLine(lineObj); if (context == "local") { yOff += paddingTop(cm.display); } else { yOff -= cm.display.viewOffset; } if (context == "page" || context == "window") { var lOff = cm.display.lineSpace.getBoundingClientRect(); yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); rect.left += xOff; rect.right += xOff; } rect.top += yOff; rect.bottom += yOff; return rect } // Coverts a box from "div" coords to another coordinate system. // Context may be "window", "page", "div", or "local"./null. function fromCoordSystem(cm, coords, context) { if (context == "div") { return coords } var left = coords.left, top = coords.top; // First move into "page" coordinate system if (context == "page") { left -= pageScrollX(); top -= pageScrollY(); } else if (context == "local" || !context) { var localBox = cm.display.sizer.getBoundingClientRect(); left += localBox.left; top += localBox.top; } var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} } function charCoords(cm, pos, context, lineObj, bias) { if (!lineObj) { lineObj = getLine(cm.doc, pos.line); } return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) } // Returns a box for a given cursor position, which may have an // 'other' property containing the position of the secondary cursor // on a bidi boundary. // A cursor Pos(line, char, "before") is on the same visual line as `char - 1` // and after `char - 1` in writing order of `char - 1` // A cursor Pos(line, char, "after") is on the same visual line as `char` // and before `char` in writing order of `char` // Examples (upper-case letters are RTL, lower-case are LTR): // Pos(0, 1, ...) // before after // ab a|b a|b // aB a|B aB| // Ab |Ab A|b // AB B|A B|A // Every position after the last character on a line is considered to stick // to the last character on the line. function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { lineObj = lineObj || getLine(cm.doc, pos.line); if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } function get(ch, right) { var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); if (right) { m.left = m.right; } else { m.right = m.left; } return intoCoordSystem(cm, lineObj, m, context) } var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky; if (ch >= lineObj.text.length) { ch = lineObj.text.length; sticky = "before"; } else if (ch <= 0) { ch = 0; sticky = "after"; } if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } function getBidi(ch, partPos, invert) { var part = order[partPos], right = part.level == 1; return get(invert ? ch - 1 : ch, right != invert) } var partPos = getBidiPartAt(order, ch, sticky); var other = bidiOther; var val = getBidi(ch, partPos, sticky == "before"); if (other != null) { val.other = getBidi(ch, other, sticky != "before"); } return val } // Used to cheaply estimate the coordinates for a position. Used for // intermediate scroll updates. function estimateCoords(cm, pos) { var left = 0; pos = clipPos(cm.doc, pos); if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; } var lineObj = getLine(cm.doc, pos.line); var top = heightAtLine(lineObj) + paddingTop(cm.display); return {left: left, right: left, top: top, bottom: top + lineObj.height} } // Positions returned by coordsChar contain some extra information. // xRel is the relative x position of the input coordinates compared // to the found position (so xRel > 0 means the coordinates are to // the right of the character position, for example). When outside // is true, that means the coordinates lie outside the line's // vertical range. function PosWithInfo(line, ch, sticky, outside, xRel) { var pos = Pos(line, ch, sticky); pos.xRel = xRel; if (outside) { pos.outside = outside; } return pos } // Compute the character position closest to the given coordinates. // Input must be lineSpace-local ("div" coordinate system). function coordsChar(cm, x, y) { var doc = cm.doc; y += cm.display.viewOffset; if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -1) } var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; if (lineN > last) { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) } if (x < 0) { x = 0; } var lineObj = getLine(doc, lineN); for (;;) { var found = coordsCharInner(cm, lineObj, lineN, x, y); var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0)); if (!collapsed) { return found } var rangeEnd = collapsed.find(1); if (rangeEnd.line == lineN) { return rangeEnd } lineObj = getLine(doc, lineN = rangeEnd.line); } } function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { y -= widgetTopHeight(lineObj); var end = lineObj.text.length; var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0); end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end); return {begin: begin, end: end} } function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top; return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) } // Returns true if the given side of a box is after the given // coordinates, in top-to-bottom, left-to-right order. function boxIsAfter(box, x, y, left) { return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x } function coordsCharInner(cm, lineObj, lineNo$$1, x, y) { // Move y into line-local coordinate space y -= heightAtLine(lineObj); var preparedMeasure = prepareMeasureForLine(cm, lineObj); // When directly calling `measureCharPrepared`, we have to adjust // for the widgets at this line. var widgetHeight$$1 = widgetTopHeight(lineObj); var begin = 0, end = lineObj.text.length, ltr = true; var order = getOrder(lineObj, cm.doc.direction); // If the line isn't plain left-to-right text, first figure out // which bidi section the coordinates fall into. if (order) { var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) (cm, lineObj, lineNo$$1, preparedMeasure, order, x, y); ltr = part.level != 1; // The awkward -1 offsets are needed because findFirst (called // on these below) will treat its first bound as inclusive, // second as exclusive, but we want to actually address the // characters in the part's range begin = ltr ? part.from : part.to - 1; end = ltr ? part.to : part.from - 1; } // A binary search to find the first character whose bounding box // starts after the coordinates. If we run across any whose box wrap // the coordinates, store that. var chAround = null, boxAround = null; var ch = findFirst(function (ch) { var box = measureCharPrepared(cm, preparedMeasure, ch); box.top += widgetHeight$$1; box.bottom += widgetHeight$$1; if (!boxIsAfter(box, x, y, false)) { return false } if (box.top <= y && box.left <= x) { chAround = ch; boxAround = box; } return true }, begin, end); var baseX, sticky, outside = false; // If a box around the coordinates was found, use that if (boxAround) { // Distinguish coordinates nearer to the left or right side of the box var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr; ch = chAround + (atStart ? 0 : 1); sticky = atStart ? "after" : "before"; baseX = atLeft ? boxAround.left : boxAround.right; } else { // (Adjust for extended bound, if necessary.) if (!ltr && (ch == end || ch == begin)) { ch++; } // To determine which side to associate with, get the box to the // left of the character and compare it's vertical position to the // coordinates sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight$$1 <= y) == ltr ? "after" : "before"; // Now get accurate coordinates for this place, in order to get a // base X position var coords = cursorCoords(cm, Pos(lineNo$$1, ch, sticky), "line", lineObj, preparedMeasure); baseX = coords.left; outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0; } ch = skipExtendingChars(lineObj.text, ch, 1); return PosWithInfo(lineNo$$1, ch, sticky, outside, x - baseX) } function coordsBidiPart(cm, lineObj, lineNo$$1, preparedMeasure, order, x, y) { // Bidi parts are sorted left-to-right, and in a non-line-wrapping // situation, we can take this ordering to correspond to the visual // ordering. This finds the first part whose end is after the given // coordinates. var index = findFirst(function (i) { var part = order[i], ltr = part.level != 1; return boxIsAfter(cursorCoords(cm, Pos(lineNo$$1, ltr ? part.to : part.from, ltr ? "before" : "after"), "line", lineObj, preparedMeasure), x, y, true) }, 0, order.length - 1); var part = order[index]; // If this isn't the first part, the part's start is also after // the coordinates, and the coordinates aren't on the same line as // that start, move one part back. if (index > 0) { var ltr = part.level != 1; var start = cursorCoords(cm, Pos(lineNo$$1, ltr ? part.from : part.to, ltr ? "after" : "before"), "line", lineObj, preparedMeasure); if (boxIsAfter(start, x, y, true) && start.top > y) { part = order[index - 1]; } } return part } function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { // In a wrapped line, rtl text on wrapping boundaries can do things // that don't correspond to the ordering in our `order` array at // all, so a binary search doesn't work, and we want to return a // part that only spans one line so that the binary search in // coordsCharInner is safe. As such, we first find the extent of the // wrapped line, and then do a flat search in which we discard any // spans that aren't on the line. var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); var begin = ref.begin; var end = ref.end; if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; } var part = null, closestDist = null; for (var i = 0; i < order.length; i++) { var p = order[i]; if (p.from >= end || p.to <= begin) { continue } var ltr = p.level != 1; var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right; // Weigh against spans ending before this, so that they are only // picked if nothing ends after var dist = endX < x ? x - endX + 1e9 : endX - x; if (!part || closestDist > dist) { part = p; closestDist = dist; } } if (!part) { part = order[order.length - 1]; } // Clip the part to the wrapped line. if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; } if (part.to > end) { part = {from: part.from, to: end, level: part.level}; } return part } var measureText; // Compute the default text height. function textHeight(display) { if (display.cachedTextHeight != null) { return display.cachedTextHeight } if (measureText == null) { measureText = elt("pre", null, "CodeMirror-line-like"); // Measure a bunch of lines, for browsers that compute // fractional heights. for (var i = 0; i < 49; ++i) { measureText.appendChild(document.createTextNode("x")); measureText.appendChild(elt("br")); } measureText.appendChild(document.createTextNode("x")); } removeChildrenAndAdd(display.measure, measureText); var height = measureText.offsetHeight / 50; if (height > 3) { display.cachedTextHeight = height; } removeChildren(display.measure); return height || 1 } // Compute the default character width. function charWidth(display) { if (display.cachedCharWidth != null) { return display.cachedCharWidth } var anchor = elt("span", "xxxxxxxxxx"); var pre = elt("pre", [anchor], "CodeMirror-line-like"); removeChildrenAndAdd(display.measure, pre); var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; if (width > 2) { display.cachedCharWidth = width; } return width || 10 } // Do a bulk-read of the DOM positions and sizes needed to draw the // view, so that we don't interleave reading and writing to the DOM. function getDimensions(cm) { var d = cm.display, left = {}, width = {}; var gutterLeft = d.gutters.clientLeft; for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { var id = cm.display.gutterSpecs[i].className; left[id] = n.offsetLeft + n.clientLeft + gutterLeft; width[id] = n.clientWidth; } return {fixedPos: compensateForHScroll(d), gutterTotalWidth: d.gutters.offsetWidth, gutterLeft: left, gutterWidth: width, wrapperWidth: d.wrapper.clientWidth} } // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, // but using getBoundingClientRect to get a sub-pixel-accurate // result. function compensateForHScroll(display) { return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left } // Returns a function that estimates the height of a line, to use as // first approximation until the line becomes visible (and is thus // properly measurable). function estimateHeight(cm) { var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); return function (line) { if (lineIsHidden(cm.doc, line)) { return 0 } var widgetsHeight = 0; if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; } } } if (wrapping) { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th } else { return widgetsHeight + th } } } function estimateLineHeights(cm) { var doc = cm.doc, est = estimateHeight(cm); doc.iter(function (line) { var estHeight = est(line); if (estHeight != line.height) { updateLineHeight(line, estHeight); } }); } // Given a mouse event, find the corresponding position. If liberal // is false, it checks whether a gutter or scrollbar was clicked, // and returns null if it was. forRect is used by rectangular // selections, and tries to estimate a character position even for // coordinates beyond the right of the text. function posFromMouse(cm, e, liberal, forRect) { var display = cm.display; if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null } var x, y, space = display.lineSpace.getBoundingClientRect(); // Fails unpredictably on IE[67] when mouse is dragged around quickly. try { x = e.clientX - space.left; y = e.clientY - space.top; } catch (e) { return null } var coords = coordsChar(cm, x, y), line; if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); } return coords } // Find the view element corresponding to a given line. Return null // when the line isn't visible. function findViewIndex(cm, n) { if (n >= cm.display.viewTo) { return null } n -= cm.display.viewFrom; if (n < 0) { return null } var view = cm.display.view; for (var i = 0; i < view.length; i++) { n -= view[i].size; if (n < 0) { return i } } } // Updates the display.view data structure for a given change to the // document. From and to are in pre-change coordinates. Lendiff is // the amount of lines added or subtracted by the change. This is // used for changes that span multiple lines, or change the way // lines are divided into visual lines. regLineChange (below) // registers single-line changes. function regChange(cm, from, to, lendiff) { if (from == null) { from = cm.doc.first; } if (to == null) { to = cm.doc.first + cm.doc.size; } if (!lendiff) { lendiff = 0; } var display = cm.display; if (lendiff && to < display.viewTo && (display.updateLineNumbers == null || display.updateLineNumbers > from)) { display.updateLineNumbers = from; } cm.curOp.viewChanged = true; if (from >= display.viewTo) { // Change after if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) { resetView(cm); } } else if (to <= display.viewFrom) { // Change before if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { resetView(cm); } else { display.viewFrom += lendiff; display.viewTo += lendiff; } } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap resetView(cm); } else if (from <= display.viewFrom) { // Top overlap var cut = viewCuttingPoint(cm, to, to + lendiff, 1); if (cut) { display.view = display.view.slice(cut.index); display.viewFrom = cut.lineN; display.viewTo += lendiff; } else { resetView(cm); } } else if (to >= display.viewTo) { // Bottom overlap var cut$1 = viewCuttingPoint(cm, from, from, -1); if (cut$1) { display.view = display.view.slice(0, cut$1.index); display.viewTo = cut$1.lineN; } else { resetView(cm); } } else { // Gap in the middle var cutTop = viewCuttingPoint(cm, from, from, -1); var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); if (cutTop && cutBot) { display.view = display.view.slice(0, cutTop.index) .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) .concat(display.view.slice(cutBot.index)); display.viewTo += lendiff; } else { resetView(cm); } } var ext = display.externalMeasured; if (ext) { if (to < ext.lineN) { ext.lineN += lendiff; } else if (from < ext.lineN + ext.size) { display.externalMeasured = null; } } } // Register a change to a single line. Type must be one of "text", // "gutter", "class", "widget" function regLineChange(cm, line, type) { cm.curOp.viewChanged = true; var display = cm.display, ext = cm.display.externalMeasured; if (ext && line >= ext.lineN && line < ext.lineN + ext.size) { display.externalMeasured = null; } if (line < display.viewFrom || line >= display.viewTo) { return } var lineView = display.view[findViewIndex(cm, line)]; if (lineView.node == null) { return } var arr = lineView.changes || (lineView.changes = []); if (indexOf(arr, type) == -1) { arr.push(type); } } // Clear the view. function resetView(cm) { cm.display.viewFrom = cm.display.viewTo = cm.doc.first; cm.display.view = []; cm.display.viewOffset = 0; } function viewCuttingPoint(cm, oldN, newN, dir) { var index = findViewIndex(cm, oldN), diff, view = cm.display.view; if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) { return {index: index, lineN: newN} } var n = cm.display.viewFrom; for (var i = 0; i < index; i++) { n += view[i].size; } if (n != oldN) { if (dir > 0) { if (index == view.length - 1) { return null } diff = (n + view[index].size) - oldN; index++; } else { diff = n - oldN; } oldN += diff; newN += diff; } while (visualLineNo(cm.doc, newN) != newN) { if (index == (dir < 0 ? 0 : view.length - 1)) { return null } newN += dir * view[index - (dir < 0 ? 1 : 0)].size; index += dir; } return {index: index, lineN: newN} } // Force the view to cover a given range, adding empty view element // or clipping off existing ones as needed. function adjustView(cm, from, to) { var display = cm.display, view = display.view; if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { display.view = buildViewArray(cm, from, to); display.viewFrom = from; } else { if (display.viewFrom > from) { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); } else if (display.viewFrom < from) { display.view = display.view.slice(findViewIndex(cm, from)); } display.viewFrom = from; if (display.viewTo < to) { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); } else if (display.viewTo > to) { display.view = display.view.slice(0, findViewIndex(cm, to)); } } display.viewTo = to; } // Count the number of lines in the view whose DOM representation is // out of date (or nonexistent). function countDirtyView(cm) { var view = cm.display.view, dirty = 0; for (var i = 0; i < view.length; i++) { var lineView = view[i]; if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; } } return dirty } function updateSelection(cm) { cm.display.input.showSelection(cm.display.input.prepareSelection()); } function prepareSelection(cm, primary) { if ( primary === void 0 ) primary = true; var doc = cm.doc, result = {}; var curFragment = result.cursors = document.createDocumentFragment(); var selFragment = result.selection = document.createDocumentFragment(); for (var i = 0; i < doc.sel.ranges.length; i++) { if (!primary && i == doc.sel.primIndex) { continue } var range$$1 = doc.sel.ranges[i]; if (range$$1.from().line >= cm.display.viewTo || range$$1.to().line < cm.display.viewFrom) { continue } var collapsed = range$$1.empty(); if (collapsed || cm.options.showCursorWhenSelecting) { drawSelectionCursor(cm, range$$1.head, curFragment); } if (!collapsed) { drawSelectionRange(cm, range$$1, selFragment); } } return result } // Draws a cursor for the given range function drawSelectionCursor(cm, head, output) { var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); cursor.style.left = pos.left + "px"; cursor.style.top = pos.top + "px"; cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; if (pos.other) { // Secondary cursor, shown when on a 'jump' in bi-directional text var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); otherCursor.style.display = ""; otherCursor.style.left = pos.other.left + "px"; otherCursor.style.top = pos.other.top + "px"; otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; } } function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } // Draws the given range as a highlighted selection function drawSelectionRange(cm, range$$1, output) { var display = cm.display, doc = cm.doc; var fragment = document.createDocumentFragment(); var padding = paddingH(cm.display), leftSide = padding.left; var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; var docLTR = doc.direction == "ltr"; function add(left, top, width, bottom) { if (top < 0) { top = 0; } top = Math.round(top); bottom = Math.round(bottom); fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px"))); } function drawForLine(line, fromArg, toArg) { var lineObj = getLine(doc, line); var lineLen = lineObj.text.length; var start, end; function coords(ch, bias) { return charCoords(cm, Pos(line, ch), "div", lineObj, bias) } function wrapX(pos, dir, side) { var extent = wrappedLineExtentChar(cm, lineObj, null, pos); var prop = (dir == "ltr") == (side == "after") ? "left" : "right"; var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1); return coords(ch, prop)[prop] } var order = getOrder(lineObj, doc.direction); iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { var ltr = dir == "ltr"; var fromPos = coords(from, ltr ? "left" : "right"); var toPos = coords(to - 1, ltr ? "right" : "left"); var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen; var first = i == 0, last = !order || i == order.length - 1; if (toPos.top - fromPos.top <= 3) { // Single line var openLeft = (docLTR ? openStart : openEnd) && first; var openRight = (docLTR ? openEnd : openStart) && last; var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left; var right = openRight ? rightSide : (ltr ? toPos : fromPos).right; add(left, fromPos.top, right - left, fromPos.bottom); } else { // Multiple lines var topLeft, topRight, botLeft, botRight; if (ltr) { topLeft = docLTR && openStart && first ? leftSide : fromPos.left; topRight = docLTR ? rightSide : wrapX(from, dir, "before"); botLeft = docLTR ? leftSide : wrapX(to, dir, "after"); botRight = docLTR && openEnd && last ? rightSide : toPos.right; } else { topLeft = !docLTR ? leftSide : wrapX(from, dir, "before"); topRight = !docLTR && openStart && first ? rightSide : fromPos.right; botLeft = !docLTR && openEnd && last ? leftSide : toPos.left; botRight = !docLTR ? rightSide : wrapX(to, dir, "after"); } add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom); if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); } add(botLeft, toPos.top, botRight - botLeft, toPos.bottom); } if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; } if (cmpCoords(toPos, start) < 0) { start = toPos; } if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; } if (cmpCoords(toPos, end) < 0) { end = toPos; } }); return {start: start, end: end} } var sFrom = range$$1.from(), sTo = range$$1.to(); if (sFrom.line == sTo.line) { drawForLine(sFrom.line, sFrom.ch, sTo.ch); } else { var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); var singleVLine = visualLine(fromLine) == visualLine(toLine); var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; if (singleVLine) { if (leftEnd.top < rightStart.top - 2) { add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); } else { add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); } } if (leftEnd.bottom < rightStart.top) { add(leftSide, leftEnd.bottom, null, rightStart.top); } } output.appendChild(fragment); } // Cursor-blinking function restartBlink(cm) { if (!cm.state.focused) { return } var display = cm.display; clearInterval(display.blinker); var on = true; display.cursorDiv.style.visibility = ""; if (cm.options.cursorBlinkRate > 0) { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; }, cm.options.cursorBlinkRate); } else if (cm.options.cursorBlinkRate < 0) { display.cursorDiv.style.visibility = "hidden"; } } function ensureFocus(cm) { if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); } } function delayBlurEvent(cm) { cm.state.delayingBlurEvent = true; setTimeout(function () { if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false; onBlur(cm); } }, 100); } function onFocus(cm, e) { if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false; } if (cm.options.readOnly == "nocursor") { return } if (!cm.state.focused) { signal(cm, "focus", cm, e); cm.state.focused = true; addClass(cm.display.wrapper, "CodeMirror-focused"); // This test prevents this from firing when a context // menu is closed (since the input reset would kill the // select-all detection hack) if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { cm.display.input.reset(); if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730 } cm.display.input.receivedFocus(); } restartBlink(cm); } function onBlur(cm, e) { if (cm.state.delayingBlurEvent) { return } if (cm.state.focused) { signal(cm, "blur", cm, e); cm.state.focused = false; rmClass(cm.display.wrapper, "CodeMirror-focused"); } clearInterval(cm.display.blinker); setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150); } // Read the actual heights of the rendered lines, and update their // stored heights to match. function updateHeightsInViewport(cm) { var display = cm.display; var prevBottom = display.lineDiv.offsetTop; for (var i = 0; i < display.view.length; i++) { var cur = display.view[i], wrapping = cm.options.lineWrapping; var height = (void 0), width = 0; if (cur.hidden) { continue } if (ie && ie_version < 8) { var bot = cur.node.offsetTop + cur.node.offsetHeight; height = bot - prevBottom; prevBottom = bot; } else { var box = cur.node.getBoundingClientRect(); height = box.bottom - box.top; // Check that lines don't extend past the right of the current // editor width if (!wrapping && cur.text.firstChild) { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; } } var diff = cur.line.height - height; if (diff > .005 || diff < -.005) { updateLineHeight(cur.line, height); updateWidgetHeight(cur.line); if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) { updateWidgetHeight(cur.rest[j]); } } } if (width > cm.display.sizerWidth) { var chWidth = Math.ceil(width / charWidth(cm.display)); if (chWidth > cm.display.maxLineLength) { cm.display.maxLineLength = chWidth; cm.display.maxLine = cur.line; cm.display.maxLineChanged = true; } } } } // Read and store the height of line widgets associated with the // given line. function updateWidgetHeight(line) { if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) { var w = line.widgets[i], parent = w.node.parentNode; if (parent) { w.height = parent.offsetHeight; } } } } // Compute the lines that are visible in a given viewport (defaults // the the current scroll position). viewport may contain top, // height, and ensure (see op.scrollToPos) properties. function visibleLines(display, doc, viewport) { var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; top = Math.floor(top - paddingTop(display)); var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); // Ensure is a {from: {line, ch}, to: {line, ch}} object, and // forces those lines into the viewport (if possible). if (viewport && viewport.ensure) { var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; if (ensureFrom < from) { from = ensureFrom; to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); } else if (Math.min(ensureTo, doc.lastLine()) >= to) { from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); to = ensureTo; } } return {from: from, to: Math.max(to, from + 1)} } // SCROLLING THINGS INTO VIEW // If an editor sits on the top or bottom of the window, partially // scrolled out of view, this ensures that the cursor is visible. function maybeScrollWindow(cm, rect) { if (signalDOMEvent(cm, "scrollCursorIntoView")) { return } var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; if (rect.top + box.top < 0) { doScroll = true; } else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; } if (doScroll != null && !phantom) { var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;")); cm.display.lineSpace.appendChild(scrollNode); scrollNode.scrollIntoView(doScroll); cm.display.lineSpace.removeChild(scrollNode); } } // Scroll a given position into view (immediately), verifying that // it actually became visible (as line heights are accurately // measured, the position of something may 'drift' during drawing). function scrollPosIntoView(cm, pos, end, margin) { if (margin == null) { margin = 0; } var rect; if (!cm.options.lineWrapping && pos == end) { // Set pos and end to the cursor positions around the character pos sticks to // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch // If pos == Pos(_, 0, "before"), pos and end are unchanged pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos; end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos; } for (var limit = 0; limit < 5; limit++) { var changed = false; var coords = cursorCoords(cm, pos); var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); rect = {left: Math.min(coords.left, endCoords.left), top: Math.min(coords.top, endCoords.top) - margin, right: Math.max(coords.left, endCoords.left), bottom: Math.max(coords.bottom, endCoords.bottom) + margin}; var scrollPos = calculateScrollPos(cm, rect); var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; } } if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; } } if (!changed) { break } } return rect } // Scroll a given set of coordinates into view (immediately). function scrollIntoView(cm, rect) { var scrollPos = calculateScrollPos(cm, rect); if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); } if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); } } // Calculate a new scroll position needed to scroll the given // rectangle into view. Returns an object with scrollTop and // scrollLeft properties. When these are undefined, the // vertical/horizontal position does not need to be adjusted. function calculateScrollPos(cm, rect) { var display = cm.display, snapMargin = textHeight(cm.display); if (rect.top < 0) { rect.top = 0; } var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; var screen = displayHeight(cm), result = {}; if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; } var docBottom = cm.doc.height + paddingVert(display); var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin; if (rect.top < screentop) { result.scrollTop = atTop ? 0 : rect.top; } else if (rect.bottom > screentop + screen) { var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen); if (newTop != screentop) { result.scrollTop = newTop; } } var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft; var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0); var tooWide = rect.right - rect.left > screenw; if (tooWide) { rect.right = rect.left + screenw; } if (rect.left < 10) { result.scrollLeft = 0; } else if (rect.left < screenleft) { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); } else if (rect.right > screenw + screenleft - 3) { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; } return result } // Store a relative adjustment to the scroll position in the current // operation (to be applied when the operation finishes). function addToScrollTop(cm, top) { if (top == null) { return } resolveScrollToPos(cm); cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; } // Make sure that at the end of the operation the current cursor is // shown. function ensureCursorVisible(cm) { resolveScrollToPos(cm); var cur = cm.getCursor(); cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin}; } function scrollToCoords(cm, x, y) { if (x != null || y != null) { resolveScrollToPos(cm); } if (x != null) { cm.curOp.scrollLeft = x; } if (y != null) { cm.curOp.scrollTop = y; } } function scrollToRange(cm, range$$1) { resolveScrollToPos(cm); cm.curOp.scrollToPos = range$$1; } // When an operation has its scrollToPos property set, and another // scroll action is applied before the end of the operation, this // 'simulates' scrolling that position into view in a cheap way, so // that the effect of intermediate scroll commands is not ignored. function resolveScrollToPos(cm) { var range$$1 = cm.curOp.scrollToPos; if (range$$1) { cm.curOp.scrollToPos = null; var from = estimateCoords(cm, range$$1.from), to = estimateCoords(cm, range$$1.to); scrollToCoordsRange(cm, from, to, range$$1.margin); } } function scrollToCoordsRange(cm, from, to, margin) { var sPos = calculateScrollPos(cm, { left: Math.min(from.left, to.left), top: Math.min(from.top, to.top) - margin, right: Math.max(from.right, to.right), bottom: Math.max(from.bottom, to.bottom) + margin }); scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop); } // Sync the scrollable area and scrollbars, ensure the viewport // covers the visible area. function updateScrollTop(cm, val) { if (Math.abs(cm.doc.scrollTop - val) < 2) { return } if (!gecko) { updateDisplaySimple(cm, {top: val}); } setScrollTop(cm, val, true); if (gecko) { updateDisplaySimple(cm); } startWorker(cm, 100); } function setScrollTop(cm, val, forceScroll) { val = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val); if (cm.display.scroller.scrollTop == val && !forceScroll) { return } cm.doc.scrollTop = val; cm.display.scrollbars.setScrollTop(val); if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; } } // Sync scroller and scrollbar, ensure the gutter elements are // aligned. function setScrollLeft(cm, val, isScroller, forceScroll) { val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return } cm.doc.scrollLeft = val; alignHorizontally(cm); if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; } cm.display.scrollbars.setScrollLeft(val); } // SCROLLBARS // Prepare DOM reads needed to update the scrollbars. Done in one // shot to minimize update/measure roundtrips. function measureForScrollbars(cm) { var d = cm.display, gutterW = d.gutters.offsetWidth; var docH = Math.round(cm.doc.height + paddingVert(cm.display)); return { clientHeight: d.scroller.clientHeight, viewHeight: d.wrapper.clientHeight, scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, viewWidth: d.wrapper.clientWidth, barLeft: cm.options.fixedGutter ? gutterW : 0, docHeight: docH, scrollHeight: docH + scrollGap(cm) + d.barHeight, nativeBarWidth: d.nativeBarWidth, gutterWidth: gutterW } } var NativeScrollbars = function(place, scroll, cm) { this.cm = cm; var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); vert.tabIndex = horiz.tabIndex = -1; place(vert); place(horiz); on(vert, "scroll", function () { if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); } }); on(horiz, "scroll", function () { if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); } }); this.checkedZeroWidth = false; // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; } }; NativeScrollbars.prototype.update = function (measure) { var needsH = measure.scrollWidth > measure.clientWidth + 1; var needsV = measure.scrollHeight > measure.clientHeight + 1; var sWidth = measure.nativeBarWidth; if (needsV) { this.vert.style.display = "block"; this.vert.style.bottom = needsH ? sWidth + "px" : "0"; var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); // A bug in IE8 can cause this value to be negative, so guard it. this.vert.firstChild.style.height = Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; } else { this.vert.style.display = ""; this.vert.firstChild.style.height = "0"; } if (needsH) { this.horiz.style.display = "block"; this.horiz.style.right = needsV ? sWidth + "px" : "0"; this.horiz.style.left = measure.barLeft + "px"; var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); this.horiz.firstChild.style.width = Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; } else { this.horiz.style.display = ""; this.horiz.firstChild.style.width = "0"; } if (!this.checkedZeroWidth && measure.clientHeight > 0) { if (sWidth == 0) { this.zeroWidthHack(); } this.checkedZeroWidth = true; } return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0} }; NativeScrollbars.prototype.setScrollLeft = function (pos) { if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; } if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); } }; NativeScrollbars.prototype.setScrollTop = function (pos) { if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; } if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); } }; NativeScrollbars.prototype.zeroWidthHack = function () { var w = mac && !mac_geMountainLion ? "12px" : "18px"; this.horiz.style.height = this.vert.style.width = w; this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"; this.disableHoriz = new Delayed; this.disableVert = new Delayed; }; NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) { bar.style.pointerEvents = "auto"; function maybeDisable() { // To find out whether the scrollbar is still visible, we // check whether the element under the pixel in the bottom // right corner of the scrollbar box is the scrollbar box // itself (when the bar is still visible) or its filler child // (when the bar is hidden). If it is still visible, we keep // it enabled, if it's hidden, we disable pointer events. var box = bar.getBoundingClientRect(); var elt$$1 = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2) : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1); if (elt$$1 != bar) { bar.style.pointerEvents = "none"; } else { delay.set(1000, maybeDisable); } } delay.set(1000, maybeDisable); }; NativeScrollbars.prototype.clear = function () { var parent = this.horiz.parentNode; parent.removeChild(this.horiz); parent.removeChild(this.vert); }; var NullScrollbars = function () {}; NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} }; NullScrollbars.prototype.setScrollLeft = function () {}; NullScrollbars.prototype.setScrollTop = function () {}; NullScrollbars.prototype.clear = function () {}; function updateScrollbars(cm, measure) { if (!measure) { measure = measureForScrollbars(cm); } var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; updateScrollbarsInner(cm, measure); for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { if (startWidth != cm.display.barWidth && cm.options.lineWrapping) { updateHeightsInViewport(cm); } updateScrollbarsInner(cm, measureForScrollbars(cm)); startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; } } // Re-synchronize the fake scrollbars with the actual size of the // content. function updateScrollbarsInner(cm, measure) { var d = cm.display; var sizes = d.scrollbars.update(measure); d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"; if (sizes.right && sizes.bottom) { d.scrollbarFiller.style.display = "block"; d.scrollbarFiller.style.height = sizes.bottom + "px"; d.scrollbarFiller.style.width = sizes.right + "px"; } else { d.scrollbarFiller.style.display = ""; } if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { d.gutterFiller.style.display = "block"; d.gutterFiller.style.height = sizes.bottom + "px"; d.gutterFiller.style.width = measure.gutterWidth + "px"; } else { d.gutterFiller.style.display = ""; } } var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; function initScrollbars(cm) { if (cm.display.scrollbars) { cm.display.scrollbars.clear(); if (cm.display.scrollbars.addClass) { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); } } cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); // Prevent clicks in the scrollbars from killing focus on(node, "mousedown", function () { if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); } }); node.setAttribute("cm-not-content", "true"); }, function (pos, axis) { if (axis == "horizontal") { setScrollLeft(cm, pos); } else { updateScrollTop(cm, pos); } }, cm); if (cm.display.scrollbars.addClass) { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); } } // Operations are used to wrap a series of changes to the editor // state in such a way that each change won't have to update the // cursor and display (which would be awkward, slow, and // error-prone). Instead, display updates are batched and then all // combined and executed at once. var nextOpId = 0; // Start a new operation. function startOperation(cm) { cm.curOp = { cm: cm, viewChanged: false, // Flag that indicates that lines might need to be redrawn startHeight: cm.doc.height, // Used to detect need to update scrollbar forceUpdate: false, // Used to force a redraw updateInput: 0, // Whether to reset the input textarea typing: false, // Whether this reset should be careful to leave existing text (for compositing) changeObjs: null, // Accumulated changes, for firing change events cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already selectionChanged: false, // Whether the selection needs to be redrawn updateMaxLine: false, // Set when the widest line needs to be determined anew scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet scrollToPos: null, // Used to scroll to a specific position focus: false, id: ++nextOpId // Unique ID }; pushOperation(cm.curOp); } // Finish an operation, updating the display and signalling delayed events function endOperation(cm) { var op = cm.curOp; if (op) { finishOperation(op, function (group) { for (var i = 0; i < group.ops.length; i++) { group.ops[i].cm.curOp = null; } endOperations(group); }); } } // The DOM updates done when an operation finishes are batched so // that the minimum number of relayouts are required. function endOperations(group) { var ops = group.ops; for (var i = 0; i < ops.length; i++) // Read DOM { endOperation_R1(ops[i]); } for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) { endOperation_W1(ops[i$1]); } for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM { endOperation_R2(ops[i$2]); } for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) { endOperation_W2(ops[i$3]); } for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM { endOperation_finish(ops[i$4]); } } function endOperation_R1(op) { var cm = op.cm, display = cm.display; maybeClipScrollbars(cm); if (op.updateMaxLine) { findMaxLine(cm); } op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || op.scrollToPos.to.line >= display.viewTo) || display.maxLineChanged && cm.options.lineWrapping; op.update = op.mustUpdate && new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); } function endOperation_W1(op) { op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); } function endOperation_R2(op) { var cm = op.cm, display = cm.display; if (op.updatedDisplay) { updateHeightsInViewport(cm); } op.barMeasure = measureForScrollbars(cm); // If the max line changed since it was last measured, measure it, // and ensure the document's width matches it. // updateDisplay_W2 will use these properties to do the actual resizing if (display.maxLineChanged && !cm.options.lineWrapping) { op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; cm.display.sizerWidth = op.adjustWidthTo; op.barMeasure.scrollWidth = Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); } if (op.updatedDisplay || op.selectionChanged) { op.preparedSelection = display.input.prepareSelection(); } } function endOperation_W2(op) { var cm = op.cm; if (op.adjustWidthTo != null) { cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; if (op.maxScrollLeft < cm.doc.scrollLeft) { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); } cm.display.maxLineChanged = false; } var takeFocus = op.focus && op.focus == activeElt(); if (op.preparedSelection) { cm.display.input.showSelection(op.preparedSelection, takeFocus); } if (op.updatedDisplay || op.startHeight != cm.doc.height) { updateScrollbars(cm, op.barMeasure); } if (op.updatedDisplay) { setDocumentHeight(cm, op.barMeasure); } if (op.selectionChanged) { restartBlink(cm); } if (cm.state.focused && op.updateInput) { cm.display.input.reset(op.typing); } if (takeFocus) { ensureFocus(op.cm); } } function endOperation_finish(op) { var cm = op.cm, display = cm.display, doc = cm.doc; if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); } // Abort mouse wheel delta measurement, when scrolling explicitly if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) { display.wheelStartX = display.wheelStartY = null; } // Propagate the scroll position to the actual DOM scroller if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); } if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); } // If we need to scroll a specific position into view, do so. if (op.scrollToPos) { var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); maybeScrollWindow(cm, rect); } // Fire events for markers that are hidden/unidden by editing or // undoing var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; if (hidden) { for (var i = 0; i < hidden.length; ++i) { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } } if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1) { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } } if (display.wrapper.offsetHeight) { doc.scrollTop = cm.display.scroller.scrollTop; } // Fire change events, and delayed event handlers if (op.changeObjs) { signal(cm, "changes", cm, op.changeObjs); } if (op.update) { op.update.finish(); } } // Run the given function in an operation function runInOp(cm, f) { if (cm.curOp) { return f() } startOperation(cm); try { return f() } finally { endOperation(cm); } } // Wraps a function in an operation. Returns the wrapped function. function operation(cm, f) { return function() { if (cm.curOp) { return f.apply(cm, arguments) } startOperation(cm); try { return f.apply(cm, arguments) } finally { endOperation(cm); } } } // Used to add methods to editor and doc instances, wrapping them in // operations. function methodOp(f) { return function() { if (this.curOp) { return f.apply(this, arguments) } startOperation(this); try { return f.apply(this, arguments) } finally { endOperation(this); } } } function docMethodOp(f) { return function() { var cm = this.cm; if (!cm || cm.curOp) { return f.apply(this, arguments) } startOperation(cm); try { return f.apply(this, arguments) } finally { endOperation(cm); } } } // HIGHLIGHT WORKER function startWorker(cm, time) { if (cm.doc.highlightFrontier < cm.display.viewTo) { cm.state.highlight.set(time, bind(highlightWorker, cm)); } } function highlightWorker(cm) { var doc = cm.doc; if (doc.highlightFrontier >= cm.display.viewTo) { return } var end = +new Date + cm.options.workTime; var context = getContextBefore(cm, doc.highlightFrontier); var changedLines = []; doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { if (context.line >= cm.display.viewFrom) { // Visible var oldStyles = line.styles; var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null; var highlighted = highlightLine(cm, line, context, true); if (resetState) { context.state = resetState; } line.styles = highlighted.styles; var oldCls = line.styleClasses, newCls = highlighted.classes; if (newCls) { line.styleClasses = newCls; } else if (oldCls) { line.styleClasses = null; } var ischange = !oldStyles || oldStyles.length != line.styles.length || oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; } if (ischange) { changedLines.push(context.line); } line.stateAfter = context.save(); context.nextLine(); } else { if (line.text.length <= cm.options.maxHighlightLength) { processLine(cm, line.text, context); } line.stateAfter = context.line % 5 == 0 ? context.save() : null; context.nextLine(); } if (+new Date > end) { startWorker(cm, cm.options.workDelay); return true } }); doc.highlightFrontier = context.line; doc.modeFrontier = Math.max(doc.modeFrontier, context.line); if (changedLines.length) { runInOp(cm, function () { for (var i = 0; i < changedLines.length; i++) { regLineChange(cm, changedLines[i], "text"); } }); } } // DISPLAY DRAWING var DisplayUpdate = function(cm, viewport, force) { var display = cm.display; this.viewport = viewport; // Store some values that we'll need later (but don't want to force a relayout for) this.visible = visibleLines(display, cm.doc, viewport); this.editorIsHidden = !display.wrapper.offsetWidth; this.wrapperHeight = display.wrapper.clientHeight; this.wrapperWidth = display.wrapper.clientWidth; this.oldDisplayWidth = displayWidth(cm); this.force = force; this.dims = getDimensions(cm); this.events = []; }; DisplayUpdate.prototype.signal = function (emitter, type) { if (hasHandler(emitter, type)) { this.events.push(arguments); } }; DisplayUpdate.prototype.finish = function () { var this$1 = this; for (var i = 0; i < this.events.length; i++) { signal.apply(null, this$1.events[i]); } }; function maybeClipScrollbars(cm) { var display = cm.display; if (!display.scrollbarsClipped && display.scroller.offsetWidth) { display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; display.heightForcer.style.height = scrollGap(cm) + "px"; display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; display.scrollbarsClipped = true; } } function selectionSnapshot(cm) { if (cm.hasFocus()) { return null } var active = activeElt(); if (!active || !contains(cm.display.lineDiv, active)) { return null } var result = {activeElt: active}; if (window.getSelection) { var sel = window.getSelection(); if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) { result.anchorNode = sel.anchorNode; result.anchorOffset = sel.anchorOffset; result.focusNode = sel.focusNode; result.focusOffset = sel.focusOffset; } } return result } function restoreSelection(snapshot) { if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return } snapshot.activeElt.focus(); if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { var sel = window.getSelection(), range$$1 = document.createRange(); range$$1.setEnd(snapshot.anchorNode, snapshot.anchorOffset); range$$1.collapse(false); sel.removeAllRanges(); sel.addRange(range$$1); sel.extend(snapshot.focusNode, snapshot.focusOffset); } } // Does the actual updating of the line display. Bails out // (returning false) when there is nothing to be done and forced is // false. function updateDisplayIfNeeded(cm, update) { var display = cm.display, doc = cm.doc; if (update.editorIsHidden) { resetView(cm); return false } // Bail out if the visible area is already rendered and nothing changed. if (!update.force && update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && display.renderedView == display.view && countDirtyView(cm) == 0) { return false } if (maybeUpdateLineNumberWidth(cm)) { resetView(cm); update.dims = getDimensions(cm); } // Compute a suitable new viewport (from & to) var end = doc.first + doc.size; var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); var to = Math.min(end, update.visible.to + cm.options.viewportMargin); if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); } if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); } if (sawCollapsedSpans) { from = visualLineNo(cm.doc, from); to = visualLineEndNo(cm.doc, to); } var different = from != display.viewFrom || to != display.viewTo || display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; adjustView(cm, from, to); display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); // Position the mover div to align with the current scroll position cm.display.mover.style.top = display.viewOffset + "px"; var toUpdate = countDirtyView(cm); if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) { return false } // For big changes, we hide the enclosing element during the // update, since that speeds up the operations on most browsers. var selSnapshot = selectionSnapshot(cm); if (toUpdate > 4) { display.lineDiv.style.display = "none"; } patchDisplay(cm, display.updateLineNumbers, update.dims); if (toUpdate > 4) { display.lineDiv.style.display = ""; } display.renderedView = display.view; // There might have been a widget with a focused element that got // hidden or updated, if so re-focus it. restoreSelection(selSnapshot); // Prevent selection and cursors from interfering with the scroll // width and height. removeChildren(display.cursorDiv); removeChildren(display.selectionDiv); display.gutters.style.height = display.sizer.style.minHeight = 0; if (different) { display.lastWrapHeight = update.wrapperHeight; display.lastWrapWidth = update.wrapperWidth; startWorker(cm, 400); } display.updateLineNumbers = null; return true } function postUpdateDisplay(cm, update) { var viewport = update.viewport; for (var first = true;; first = false) { if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { // Clip forced viewport to actual scrollable area. if (viewport && viewport.top != null) { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; } // Updated line heights might result in the drawn area not // actually covering the viewport. Keep looping until it does. update.visible = visibleLines(cm.display, cm.doc, viewport); if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) { break } } if (!updateDisplayIfNeeded(cm, update)) { break } updateHeightsInViewport(cm); var barMeasure = measureForScrollbars(cm); updateSelection(cm); updateScrollbars(cm, barMeasure); setDocumentHeight(cm, barMeasure); update.force = false; } update.signal(cm, "update", cm); if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; } } function updateDisplaySimple(cm, viewport) { var update = new DisplayUpdate(cm, viewport); if (updateDisplayIfNeeded(cm, update)) { updateHeightsInViewport(cm); postUpdateDisplay(cm, update); var barMeasure = measureForScrollbars(cm); updateSelection(cm); updateScrollbars(cm, barMeasure); setDocumentHeight(cm, barMeasure); update.finish(); } } // Sync the actual display DOM structure with display.view, removing // nodes for lines that are no longer in view, and creating the ones // that are not there yet, and updating the ones that are out of // date. function patchDisplay(cm, updateNumbersFrom, dims) { var display = cm.display, lineNumbers = cm.options.lineNumbers; var container = display.lineDiv, cur = container.firstChild; function rm(node) { var next = node.nextSibling; // Works around a throw-scroll bug in OS X Webkit if (webkit && mac && cm.display.currentWheelTarget == node) { node.style.display = "none"; } else { node.parentNode.removeChild(node); } return next } var view = display.view, lineN = display.viewFrom; // Loop over the elements in the view, syncing cur (the DOM nodes // in display.lineDiv) with the view as we go. for (var i = 0; i < view.length; i++) { var lineView = view[i]; if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet var node = buildLineElement(cm, lineView, lineN, dims); container.insertBefore(node, cur); } else { // Already drawn while (cur != lineView.node) { cur = rm(cur); } var updateNumber = lineNumbers && updateNumbersFrom != null && updateNumbersFrom <= lineN && lineView.lineNumber; if (lineView.changes) { if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; } updateLineForChanges(cm, lineView, lineN, dims); } if (updateNumber) { removeChildren(lineView.lineNumber); lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); } cur = lineView.node.nextSibling; } lineN += lineView.size; } while (cur) { cur = rm(cur); } } function updateGutterSpace(display) { var width = display.gutters.offsetWidth; display.sizer.style.marginLeft = width + "px"; } function setDocumentHeight(cm, measure) { cm.display.sizer.style.minHeight = measure.docHeight + "px"; cm.display.heightForcer.style.top = measure.docHeight + "px"; cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"; } // Re-align line numbers and gutter marks to compensate for // horizontal scrolling. function alignHorizontally(cm) { var display = cm.display, view = display.view; if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; var gutterW = display.gutters.offsetWidth, left = comp + "px"; for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { if (cm.options.fixedGutter) { if (view[i].gutter) { view[i].gutter.style.left = left; } if (view[i].gutterBackground) { view[i].gutterBackground.style.left = left; } } var align = view[i].alignable; if (align) { for (var j = 0; j < align.length; j++) { align[j].style.left = left; } } } } if (cm.options.fixedGutter) { display.gutters.style.left = (comp + gutterW) + "px"; } } // Used to ensure that the line number gutter is still the right // size for the current document size. Returns true when an update // is needed. function maybeUpdateLineNumberWidth(cm) { if (!cm.options.lineNumbers) { return false } var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; if (last.length != display.lineNumChars) { var test = display.measure.appendChild(elt("div", [elt("div", last)], "CodeMirror-linenumber CodeMirror-gutter-elt")); var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; display.lineGutter.style.width = ""; display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; display.lineNumWidth = display.lineNumInnerWidth + padding; display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; display.lineGutter.style.width = display.lineNumWidth + "px"; updateGutterSpace(cm.display); return true } return false } function getGutters(gutters, lineNumbers) { var result = [], sawLineNumbers = false; for (var i = 0; i < gutters.length; i++) { var name = gutters[i], style = null; if (typeof name != "string") { style = name.style; name = name.className; } if (name == "CodeMirror-linenumbers") { if (!lineNumbers) { continue } else { sawLineNumbers = true; } } result.push({className: name, style: style}); } if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); } return result } // Rebuild the gutter elements, ensure the margin to the left of the // code matches their width. function renderGutters(display) { var gutters = display.gutters, specs = display.gutterSpecs; removeChildren(gutters); display.lineGutter = null; for (var i = 0; i < specs.length; ++i) { var ref = specs[i]; var className = ref.className; var style = ref.style; var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className)); if (style) { gElt.style.cssText = style; } if (className == "CodeMirror-linenumbers") { display.lineGutter = gElt; gElt.style.width = (display.lineNumWidth || 1) + "px"; } } gutters.style.display = specs.length ? "" : "none"; updateGutterSpace(display); } function updateGutters(cm) { renderGutters(cm.display); regChange(cm); alignHorizontally(cm); } // The display handles the DOM integration, both for input reading // and content drawing. It holds references to DOM nodes and // display-related state. function Display(place, doc, input, options) { var d = this; this.input = input; // Covers bottom-right square when both scrollbars are present. d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); d.scrollbarFiller.setAttribute("cm-not-content", "true"); // Covers bottom of gutter when coverGutterNextToScrollbar is on // and h scrollbar is present. d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); d.gutterFiller.setAttribute("cm-not-content", "true"); // Will contain the actual code, positioned to cover the viewport. d.lineDiv = eltP("div", null, "CodeMirror-code"); // Elements are added to these to represent selection and cursors. d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); d.cursorDiv = elt("div", null, "CodeMirror-cursors"); // A visibility: hidden element used to find the size of things. d.measure = elt("div", null, "CodeMirror-measure"); // When lines outside of the viewport are measured, they are drawn in this. d.lineMeasure = elt("div", null, "CodeMirror-measure"); // Wraps everything that needs to exist inside the vertically-padded coordinate system d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], null, "position: relative; outline: none"); var lines = eltP("div", [d.lineSpace], "CodeMirror-lines"); // Moved around its parent to cover visible view. d.mover = elt("div", [lines], null, "position: relative"); // Set to the height of the document, allowing scrolling. d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); d.sizerWidth = null; // Behavior of elts with overflow: auto and padding is // inconsistent across browsers. This is used to ensure the // scrollable area is big enough. d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); // Will contain the gutters, if any. d.gutters = elt("div", null, "CodeMirror-gutters"); d.lineGutter = null; // Actual scrollable element. d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); d.scroller.setAttribute("tabIndex", "-1"); // The element in which the editor lives. d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; } if (place) { if (place.appendChild) { place.appendChild(d.wrapper); } else { place(d.wrapper); } } // Current rendered range (may be bigger than the view window). d.viewFrom = d.viewTo = doc.first; d.reportedViewFrom = d.reportedViewTo = doc.first; // Information about the rendered lines. d.view = []; d.renderedView = null; // Holds info about a single rendered line when it was rendered // for measurement, while not in view. d.externalMeasured = null; // Empty space (in pixels) above the view d.viewOffset = 0; d.lastWrapHeight = d.lastWrapWidth = 0; d.updateLineNumbers = null; d.nativeBarWidth = d.barHeight = d.barWidth = 0; d.scrollbarsClipped = false; // Used to only resize the line number gutter when necessary (when // the amount of lines crosses a boundary that makes its width change) d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; // Set to true when a non-horizontal-scrolling line widget is // added. As an optimization, line widget aligning is skipped when // this is false. d.alignWidgets = false; d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; // Tracks the maximum line length so that the horizontal scrollbar // can be kept static when scrolling. d.maxLine = null; d.maxLineLength = 0; d.maxLineChanged = false; // Used for measuring wheel scrolling granularity d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; // True when shift is held down. d.shift = false; // Used to track whether anything happened since the context menu // was opened. d.selForContextMenu = null; d.activeTouch = null; d.gutterSpecs = getGutters(options.gutters, options.lineNumbers); renderGutters(d); input.init(d); } // Since the delta values reported on mouse wheel events are // unstandardized between browsers and even browser versions, and // generally horribly unpredictable, this code starts by measuring // the scroll effect that the first few mouse wheel events have, // and, from that, detects the way it can convert deltas to pixel // offsets afterwards. // // The reason we want to know the amount a wheel event will scroll // is that it gives us a chance to update the display before the // actual scrolling happens, reducing flickering. var wheelSamples = 0, wheelPixelsPerUnit = null; // Fill in a browser-detected starting value on browsers where we // know one. These don't have to be accurate -- the result of them // being wrong would just be a slight flicker on the first wheel // scroll (if it is large enough). if (ie) { wheelPixelsPerUnit = -.53; } else if (gecko) { wheelPixelsPerUnit = 15; } else if (chrome) { wheelPixelsPerUnit = -.7; } else if (safari) { wheelPixelsPerUnit = -1/3; } function wheelEventDelta(e) { var dx = e.wheelDeltaX, dy = e.wheelDeltaY; if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; } if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; } else if (dy == null) { dy = e.wheelDelta; } return {x: dx, y: dy} } function wheelEventPixels(e) { var delta = wheelEventDelta(e); delta.x *= wheelPixelsPerUnit; delta.y *= wheelPixelsPerUnit; return delta } function onScrollWheel(cm, e) { var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; var display = cm.display, scroll = display.scroller; // Quit if there's nothing to scroll here var canScrollX = scroll.scrollWidth > scroll.clientWidth; var canScrollY = scroll.scrollHeight > scroll.clientHeight; if (!(dx && canScrollX || dy && canScrollY)) { return } // Webkit browsers on OS X abort momentum scrolls when the target // of the scroll event is removed from the scrollable element. // This hack (see related code in patchDisplay) makes sure the // element is kept around. if (dy && mac && webkit) { outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { for (var i = 0; i < view.length; i++) { if (view[i].node == cur) { cm.display.currentWheelTarget = cur; break outer } } } } // On some browsers, horizontal scrolling will cause redraws to // happen before the gutter has been realigned, causing it to // wriggle around in a most unseemly way. When we have an // estimated pixels/delta value, we just handle horizontal // scrolling entirely here. It'll be slightly off from native, but // better than glitching out. if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { if (dy && canScrollY) { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); } setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit)); // Only prevent default scrolling if vertical scrolling is // actually possible. Otherwise, it causes vertical scroll // jitter on OSX trackpads when deltaX is small and deltaY // is large (issue #3579) if (!dy || (dy && canScrollY)) { e_preventDefault(e); } display.wheelStartX = null; // Abort measurement, if in progress return } // 'Project' the visible viewport to cover the area that is being // scrolled into view (if we know enough to estimate it). if (dy && wheelPixelsPerUnit != null) { var pixels = dy * wheelPixelsPerUnit; var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; if (pixels < 0) { top = Math.max(0, top + pixels - 50); } else { bot = Math.min(cm.doc.height, bot + pixels + 50); } updateDisplaySimple(cm, {top: top, bottom: bot}); } if (wheelSamples < 20) { if (display.wheelStartX == null) { display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; display.wheelDX = dx; display.wheelDY = dy; setTimeout(function () { if (display.wheelStartX == null) { return } var movedX = scroll.scrollLeft - display.wheelStartX; var movedY = scroll.scrollTop - display.wheelStartY; var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || (movedX && display.wheelDX && movedX / display.wheelDX); display.wheelStartX = display.wheelStartY = null; if (!sample) { return } wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); ++wheelSamples; }, 200); } else { display.wheelDX += dx; display.wheelDY += dy; } } } // Selection objects are immutable. A new one is created every time // the selection changes. A selection is one or more non-overlapping // (and non-touching) ranges, sorted, and an integer that indicates // which one is the primary selection (the one that's scrolled into // view, that getCursor returns, etc). var Selection = function(ranges, primIndex) { this.ranges = ranges; this.primIndex = primIndex; }; Selection.prototype.primary = function () { return this.ranges[this.primIndex] }; Selection.prototype.equals = function (other) { var this$1 = this; if (other == this) { return true } if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false } for (var i = 0; i < this.ranges.length; i++) { var here = this$1.ranges[i], there = other.ranges[i]; if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false } } return true }; Selection.prototype.deepCopy = function () { var this$1 = this; var out = []; for (var i = 0; i < this.ranges.length; i++) { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)); } return new Selection(out, this.primIndex) }; Selection.prototype.somethingSelected = function () { var this$1 = this; for (var i = 0; i < this.ranges.length; i++) { if (!this$1.ranges[i].empty()) { return true } } return false }; Selection.prototype.contains = function (pos, end) { var this$1 = this; if (!end) { end = pos; } for (var i = 0; i < this.ranges.length; i++) { var range = this$1.ranges[i]; if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) { return i } } return -1 }; var Range = function(anchor, head) { this.anchor = anchor; this.head = head; }; Range.prototype.from = function () { return minPos(this.anchor, this.head) }; Range.prototype.to = function () { return maxPos(this.anchor, this.head) }; Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch }; // Take an unsorted, potentially overlapping set of ranges, and // build a selection out of it. 'Consumes' ranges array (modifying // it). function normalizeSelection(cm, ranges, primIndex) { var mayTouch = cm && cm.options.selectionsMayTouch; var prim = ranges[primIndex]; ranges.sort(function (a, b) { return cmp(a.from(), b.from()); }); primIndex = indexOf(ranges, prim); for (var i = 1; i < ranges.length; i++) { var cur = ranges[i], prev = ranges[i - 1]; var diff = cmp(prev.to(), cur.from()); if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) { var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; if (i <= primIndex) { --primIndex; } ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); } } return new Selection(ranges, primIndex) } function simpleSelection(anchor, head) { return new Selection([new Range(anchor, head || anchor)], 0) } // Compute the position of the end of a change (its 'to' property // refers to the pre-change end). function changeEnd(change) { if (!change.text) { return change.to } return Pos(change.from.line + change.text.length - 1, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) } // Adjust a position to refer to the post-change position of the // same text, or the end of the change if the change covers it. function adjustForChange(pos, change) { if (cmp(pos, change.from) < 0) { return pos } if (cmp(pos, change.to) <= 0) { return changeEnd(change) } var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; } return Pos(line, ch) } function computeSelAfterChange(doc, change) { var out = []; for (var i = 0; i < doc.sel.ranges.length; i++) { var range = doc.sel.ranges[i]; out.push(new Range(adjustForChange(range.anchor, change), adjustForChange(range.head, change))); } return normalizeSelection(doc.cm, out, doc.sel.primIndex) } function offsetPos(pos, old, nw) { if (pos.line == old.line) { return Pos(nw.line, pos.ch - old.ch + nw.ch) } else { return Pos(nw.line + (pos.line - old.line), pos.ch) } } // Used by replaceSelections to allow moving the selection to the // start or around the replaced test. Hint may be "start" or "around". function computeReplacedSel(doc, changes, hint) { var out = []; var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; for (var i = 0; i < changes.length; i++) { var change = changes[i]; var from = offsetPos(change.from, oldPrev, newPrev); var to = offsetPos(changeEnd(change), oldPrev, newPrev); oldPrev = change.to; newPrev = to; if (hint == "around") { var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; out[i] = new Range(inv ? to : from, inv ? from : to); } else { out[i] = new Range(from, from); } } return new Selection(out, doc.sel.primIndex) } // Used to get the editor into a consistent state again when options change. function loadMode(cm) { cm.doc.mode = getMode(cm.options, cm.doc.modeOption); resetModeState(cm); } function resetModeState(cm) { cm.doc.iter(function (line) { if (line.stateAfter) { line.stateAfter = null; } if (line.styles) { line.styles = null; } }); cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first; startWorker(cm, 100); cm.state.modeGen++; if (cm.curOp) { regChange(cm); } } // DOCUMENT DATA STRUCTURE // By default, updates that start and end at the beginning of a line // are treated specially, in order to make the association of line // widgets and marker elements with the text behave more intuitive. function isWholeLineUpdate(doc, change) { return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && (!doc.cm || doc.cm.options.wholeLineUpdateBefore) } // Perform a change on the document data structure. function updateDoc(doc, change, markedSpans, estimateHeight$$1) { function spansFor(n) {return markedSpans ? markedSpans[n] : null} function update(line, text, spans) { updateLine(line, text, spans, estimateHeight$$1); signalLater(line, "change", line, change); } function linesFor(start, end) { var result = []; for (var i = start; i < end; ++i) { result.push(new Line(text[i], spansFor(i), estimateHeight$$1)); } return result } var from = change.from, to = change.to, text = change.text; var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; // Adjust the line structure if (change.full) { doc.insert(0, linesFor(0, text.length)); doc.remove(text.length, doc.size - text.length); } else if (isWholeLineUpdate(doc, change)) { // This is a whole-line replace. Treated specially to make // sure line objects move the way they are supposed to. var added = linesFor(0, text.length - 1); update(lastLine, lastLine.text, lastSpans); if (nlines) { doc.remove(from.line, nlines); } if (added.length) { doc.insert(from.line, added); } } else if (firstLine == lastLine) { if (text.length == 1) { update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); } else { var added$1 = linesFor(1, text.length - 1); added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight$$1)); update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); doc.insert(from.line + 1, added$1); } } else if (text.length == 1) { update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); doc.remove(from.line + 1, nlines); } else { update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); var added$2 = linesFor(1, text.length - 1); if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); } doc.insert(from.line + 1, added$2); } signalLater(doc, "change", doc, change); } // Call f for all linked documents. function linkedDocs(doc, f, sharedHistOnly) { function propagate(doc, skip, sharedHist) { if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) { var rel = doc.linked[i]; if (rel.doc == skip) { continue } var shared = sharedHist && rel.sharedHist; if (sharedHistOnly && !shared) { continue } f(rel.doc, shared); propagate(rel.doc, doc, shared); } } } propagate(doc, null, true); } // Attach a document to an editor. function attachDoc(cm, doc) { if (doc.cm) { throw new Error("This document is already in use.") } cm.doc = doc; doc.cm = cm; estimateLineHeights(cm); loadMode(cm); setDirectionClass(cm); if (!cm.options.lineWrapping) { findMaxLine(cm); } cm.options.mode = doc.modeOption; regChange(cm); } function setDirectionClass(cm) { (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl"); } function directionChanged(cm) { runInOp(cm, function () { setDirectionClass(cm); regChange(cm); }); } function History(startGen) { // Arrays of change events and selections. Doing something adds an // event to done and clears undo. Undoing moves events from done // to undone, redoing moves them in the other direction. this.done = []; this.undone = []; this.undoDepth = Infinity; // Used to track when changes can be merged into a single undo // event this.lastModTime = this.lastSelTime = 0; this.lastOp = this.lastSelOp = null; this.lastOrigin = this.lastSelOrigin = null; // Used by the isClean() method this.generation = this.maxGeneration = startGen || 1; } // Create a history change event from an updateDoc-style change // object. function historyChangeFromChange(doc, change) { var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true); return histChange } // Pop all selection events off the end of a history array. Stop at // a change event. function clearSelectionEvents(array) { while (array.length) { var last = lst(array); if (last.ranges) { array.pop(); } else { break } } } // Find the top change event in the history. Pop off selection // events that are in the way. function lastChangeEvent(hist, force) { if (force) { clearSelectionEvents(hist.done); return lst(hist.done) } else if (hist.done.length && !lst(hist.done).ranges) { return lst(hist.done) } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { hist.done.pop(); return lst(hist.done) } } // Register a change in the history. Merges changes that are within // a single operation, or are close together with an origin that // allows merging (starting with "+") into a single event. function addChangeToHistory(doc, change, selAfter, opId) { var hist = doc.history; hist.undone.length = 0; var time = +new Date, cur; var last; if ((hist.lastOp == opId || hist.lastOrigin == change.origin && change.origin && ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) || change.origin.charAt(0) == "*")) && (cur = lastChangeEvent(hist, hist.lastOp == opId))) { // Merge this change into the last event last = lst(cur.changes); if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { // Optimized case for simple insertion -- don't want to add // new changesets for every character typed last.to = changeEnd(change); } else { // Add new sub-event cur.changes.push(historyChangeFromChange(doc, change)); } } else { // Can not be merged, start a new event. var before = lst(hist.done); if (!before || !before.ranges) { pushSelectionToHistory(doc.sel, hist.done); } cur = {changes: [historyChangeFromChange(doc, change)], generation: hist.generation}; hist.done.push(cur); while (hist.done.length > hist.undoDepth) { hist.done.shift(); if (!hist.done[0].ranges) { hist.done.shift(); } } } hist.done.push(selAfter); hist.generation = ++hist.maxGeneration; hist.lastModTime = hist.lastSelTime = time; hist.lastOp = hist.lastSelOp = opId; hist.lastOrigin = hist.lastSelOrigin = change.origin; if (!last) { signal(doc, "historyAdded"); } } function selectionEventCanBeMerged(doc, origin, prev, sel) { var ch = origin.charAt(0); return ch == "*" || ch == "+" && prev.ranges.length == sel.ranges.length && prev.somethingSelected() == sel.somethingSelected() && new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500) } // Called whenever the selection changes, sets the new selection as // the pending selection in the history, and pushes the old pending // selection into the 'done' array when it was significantly // different (in number of selected ranges, emptiness, or time). function addSelectionToHistory(doc, sel, opId, options) { var hist = doc.history, origin = options && options.origin; // A new event is started when the previous origin does not match // the current, or the origins don't allow matching. Origins // starting with * are always merged, those starting with + are // merged when similar and close together in time. if (opId == hist.lastSelOp || (origin && hist.lastSelOrigin == origin && (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) { hist.done[hist.done.length - 1] = sel; } else { pushSelectionToHistory(sel, hist.done); } hist.lastSelTime = +new Date; hist.lastSelOrigin = origin; hist.lastSelOp = opId; if (options && options.clearRedo !== false) { clearSelectionEvents(hist.undone); } } function pushSelectionToHistory(sel, dest) { var top = lst(dest); if (!(top && top.ranges && top.equals(sel))) { dest.push(sel); } } // Used to store marked span information in the history. function attachLocalSpans(doc, change, from, to) { var existing = change["spans_" + doc.id], n = 0; doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { if (line.markedSpans) { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; } ++n; }); } // When un/re-doing restores text containing marked spans, those // that have been explicitly cleared should not be restored. function removeClearedSpans(spans) { if (!spans) { return null } var out; for (var i = 0; i < spans.length; ++i) { if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } } else if (out) { out.push(spans[i]); } } return !out ? spans : out.length ? out : null } // Retrieve and filter the old marked spans stored in a change event. function getOldSpans(doc, change) { var found = change["spans_" + doc.id]; if (!found) { return null } var nw = []; for (var i = 0; i < change.text.length; ++i) { nw.push(removeClearedSpans(found[i])); } return nw } // Used for un/re-doing changes from the history. Combines the // result of computing the existing spans with the set of spans that // existed in the history (so that deleting around a span and then // undoing brings back the span). function mergeOldSpans(doc, change) { var old = getOldSpans(doc, change); var stretched = stretchSpansOverChange(doc, change); if (!old) { return stretched } if (!stretched) { return old } for (var i = 0; i < old.length; ++i) { var oldCur = old[i], stretchCur = stretched[i]; if (oldCur && stretchCur) { spans: for (var j = 0; j < stretchCur.length; ++j) { var span = stretchCur[j]; for (var k = 0; k < oldCur.length; ++k) { if (oldCur[k].marker == span.marker) { continue spans } } oldCur.push(span); } } else if (stretchCur) { old[i] = stretchCur; } } return old } // Used both to provide a JSON-safe object in .getHistory, and, when // detaching a document, to split the history in two function copyHistoryArray(events, newGroup, instantiateSel) { var copy = []; for (var i = 0; i < events.length; ++i) { var event = events[i]; if (event.ranges) { copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); continue } var changes = event.changes, newChanges = []; copy.push({changes: newChanges}); for (var j = 0; j < changes.length; ++j) { var change = changes[j], m = (void 0); newChanges.push({from: change.from, to: change.to, text: change.text}); if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) { if (indexOf(newGroup, Number(m[1])) > -1) { lst(newChanges)[prop] = change[prop]; delete change[prop]; } } } } } } return copy } // The 'scroll' parameter given to many of these indicated whether // the new cursor position should be scrolled into view after // modifying the selection. // If shift is held or the extend flag is set, extends a range to // include a given position (and optionally a second position). // Otherwise, simply returns the range between the given positions. // Used for cursor motion and such. function extendRange(range, head, other, extend) { if (extend) { var anchor = range.anchor; if (other) { var posBefore = cmp(head, anchor) < 0; if (posBefore != (cmp(other, anchor) < 0)) { anchor = head; head = other; } else if (posBefore != (cmp(head, other) < 0)) { head = other; } } return new Range(anchor, head) } else { return new Range(other || head, head) } } // Extend the primary selection range, discard the rest. function extendSelection(doc, head, other, options, extend) { if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); } setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options); } // Extend all selections (pos is an array of selections with length // equal the number of selections) function extendSelections(doc, heads, options) { var out = []; var extend = doc.cm && (doc.cm.display.shift || doc.extend); for (var i = 0; i < doc.sel.ranges.length; i++) { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); } var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex); setSelection(doc, newSel, options); } // Updates a single range in the selection. function replaceOneSelection(doc, i, range, options) { var ranges = doc.sel.ranges.slice(0); ranges[i] = range; setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options); } // Reset the selection to a single range. function setSimpleSelection(doc, anchor, head, options) { setSelection(doc, simpleSelection(anchor, head), options); } // Give beforeSelectionChange handlers a change to influence a // selection update. function filterSelectionChange(doc, sel, options) { var obj = { ranges: sel.ranges, update: function(ranges) { var this$1 = this; this.ranges = []; for (var i = 0; i < ranges.length; i++) { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), clipPos(doc, ranges[i].head)); } }, origin: options && options.origin }; signal(doc, "beforeSelectionChange", doc, obj); if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); } if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) } else { return sel } } function setSelectionReplaceHistory(doc, sel, options) { var done = doc.history.done, last = lst(done); if (last && last.ranges) { done[done.length - 1] = sel; setSelectionNoUndo(doc, sel, options); } else { setSelection(doc, sel, options); } } // Set a new selection. function setSelection(doc, sel, options) { setSelectionNoUndo(doc, sel, options); addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); } function setSelectionNoUndo(doc, sel, options) { if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) { sel = filterSelectionChange(doc, sel, options); } var bias = options && options.bias || (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); if (!(options && options.scroll === false) && doc.cm) { ensureCursorVisible(doc.cm); } } function setSelectionInner(doc, sel) { if (sel.equals(doc.sel)) { return } doc.sel = sel; if (doc.cm) { doc.cm.curOp.updateInput = 1; doc.cm.curOp.selectionChanged = true; signalCursorActivity(doc.cm); } signalLater(doc, "cursorActivity", doc); } // Verify that the selection does not partially select any atomic // marked ranges. function reCheckSelection(doc) { setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false)); } // Return a selection that does not partially select any atomic // ranges. function skipAtomicInSelection(doc, sel, bias, mayClear) { var out; for (var i = 0; i < sel.ranges.length; i++) { var range = sel.ranges[i]; var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]; var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear); var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear); if (out || newAnchor != range.anchor || newHead != range.head) { if (!out) { out = sel.ranges.slice(0, i); } out[i] = new Range(newAnchor, newHead); } } return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel } function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { var line = getLine(doc, pos.line); if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { var sp = line.markedSpans[i], m = sp.marker; // Determine if we should prevent the cursor being placed to the left/right of an atomic marker // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it // is with selectLeft/Right var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft; var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight; if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) { if (mayClear) { signal(m, "beforeCursorEnter"); if (m.explicitlyCleared) { if (!line.markedSpans) { break } else {--i; continue} } } if (!m.atomic) { continue } if (oldPos) { var near = m.find(dir < 0 ? 1 : -1), diff = (void 0); if (dir < 0 ? preventCursorRight : preventCursorLeft) { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); } if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) { return skipAtomicInner(doc, near, pos, dir, mayClear) } } var far = m.find(dir < 0 ? -1 : 1); if (dir < 0 ? preventCursorLeft : preventCursorRight) { far = movePos(doc, far, dir, far.line == pos.line ? line : null); } return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null } } } return pos } // Ensure a given position is not inside an atomic range. function skipAtomic(doc, pos, oldPos, bias, mayClear) { var dir = bias || 1; var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)); if (!found) { doc.cantEdit = true; return Pos(doc.first, 0) } return found } function movePos(doc, pos, dir, line) { if (dir < 0 && pos.ch == 0) { if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) } else { return null } } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) } else { return null } } else { return new Pos(pos.line, pos.ch + dir) } } function selectAll(cm) { cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll); } // UPDATING // Allow "beforeChange" event handlers to influence a change function filterChange(doc, change, update) { var obj = { canceled: false, from: change.from, to: change.to, text: change.text, origin: change.origin, cancel: function () { return obj.canceled = true; } }; if (update) { obj.update = function (from, to, text, origin) { if (from) { obj.from = clipPos(doc, from); } if (to) { obj.to = clipPos(doc, to); } if (text) { obj.text = text; } if (origin !== undefined) { obj.origin = origin; } }; } signal(doc, "beforeChange", doc, obj); if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); } if (obj.canceled) { if (doc.cm) { doc.cm.curOp.updateInput = 2; } return null } return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} } // Apply a change to a document, and add it to the document's // history, and propagating it to all linked documents. function makeChange(doc, change, ignoreReadOnly) { if (doc.cm) { if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) } if (doc.cm.state.suppressEdits) { return } } if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { change = filterChange(doc, change, true); if (!change) { return } } // Possibly split or suppress the update based on the presence // of read-only spans in its range. var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); if (split) { for (var i = split.length - 1; i >= 0; --i) { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); } } else { makeChangeInner(doc, change); } } function makeChangeInner(doc, change) { if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return } var selAfter = computeSelAfterChange(doc, change); addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); var rebased = []; linkedDocs(doc, function (doc, sharedHist) { if (!sharedHist && indexOf(rebased, doc.history) == -1) { rebaseHist(doc.history, change); rebased.push(doc.history); } makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); }); } // Revert a change stored in a document's history. function makeChangeFromHistory(doc, type, allowSelectionOnly) { var suppress = doc.cm && doc.cm.state.suppressEdits; if (suppress && !allowSelectionOnly) { return } var hist = doc.history, event, selAfter = doc.sel; var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; // Verify that there is a useable event (so that ctrl-z won't // needlessly clear selection events) var i = 0; for (; i < source.length; i++) { event = source[i]; if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) { break } } if (i == source.length) { return } hist.lastOrigin = hist.lastSelOrigin = null; for (;;) { event = source.pop(); if (event.ranges) { pushSelectionToHistory(event, dest); if (allowSelectionOnly && !event.equals(doc.sel)) { setSelection(doc, event, {clearRedo: false}); return } selAfter = event; } else if (suppress) { source.push(event); return } else { break } } // Build up a reverse change object to add to the opposite history // stack (redo when undoing, and vice versa). var antiChanges = []; pushSelectionToHistory(selAfter, dest); dest.push({changes: antiChanges, generation: hist.generation}); hist.generation = event.generation || ++hist.maxGeneration; var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); var loop = function ( i ) { var change = event.changes[i]; change.origin = type; if (filter && !filterChange(doc, change, false)) { source.length = 0; return {} } antiChanges.push(historyChangeFromChange(doc, change)); var after = i ? computeSelAfterChange(doc, change) : lst(source); makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); } var rebased = []; // Propagate to the linked documents linkedDocs(doc, function (doc, sharedHist) { if (!sharedHist && indexOf(rebased, doc.history) == -1) { rebaseHist(doc.history, change); rebased.push(doc.history); } makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); }); }; for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { var returned = loop( i$1 ); if ( returned ) return returned.v; } } // Sub-views need their line numbers shifted when text is added // above or below them in the parent document. function shiftDoc(doc, distance) { if (distance == 0) { return } doc.first += distance; doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range( Pos(range.anchor.line + distance, range.anchor.ch), Pos(range.head.line + distance, range.head.ch) ); }), doc.sel.primIndex); if (doc.cm) { regChange(doc.cm, doc.first, doc.first - distance, distance); for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) { regLineChange(doc.cm, l, "gutter"); } } } // More lower-level change function, handling only a single document // (not linked ones). function makeChangeSingleDoc(doc, change, selAfter, spans) { if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) } if (change.to.line < doc.first) { shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); return } if (change.from.line > doc.lastLine()) { return } // Clip the change to the size of this doc if (change.from.line < doc.first) { var shift = change.text.length - 1 - (doc.first - change.from.line); shiftDoc(doc, shift); change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), text: [lst(change.text)], origin: change.origin}; } var last = doc.lastLine(); if (change.to.line > last) { change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), text: [change.text[0]], origin: change.origin}; } change.removed = getBetween(doc, change.from, change.to); if (!selAfter) { selAfter = computeSelAfterChange(doc, change); } if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); } else { updateDoc(doc, change, spans); } setSelectionNoUndo(doc, selAfter, sel_dontScroll); if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0))) { doc.cantEdit = false; } } // Handle the interaction of a change to a document with the editor // that this document is part of. function makeChangeSingleDocInEditor(cm, change, spans) { var doc = cm.doc, display = cm.display, from = change.from, to = change.to; var recomputeMaxLength = false, checkWidthStart = from.line; if (!cm.options.lineWrapping) { checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); doc.iter(checkWidthStart, to.line + 1, function (line) { if (line == display.maxLine) { recomputeMaxLength = true; return true } }); } if (doc.sel.contains(change.from, change.to) > -1) { signalCursorActivity(cm); } updateDoc(doc, change, spans, estimateHeight(cm)); if (!cm.options.lineWrapping) { doc.iter(checkWidthStart, from.line + change.text.length, function (line) { var len = lineLength(line); if (len > display.maxLineLength) { display.maxLine = line; display.maxLineLength = len; display.maxLineChanged = true; recomputeMaxLength = false; } }); if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; } } retreatFrontier(doc, from.line); startWorker(cm, 400); var lendiff = change.text.length - (to.line - from.line) - 1; // Remember that these lines changed, for updating the display if (change.full) { regChange(cm); } else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) { regLineChange(cm, from.line, "text"); } else { regChange(cm, from.line, to.line + 1, lendiff); } var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); if (changeHandler || changesHandler) { var obj = { from: from, to: to, text: change.text, removed: change.removed, origin: change.origin }; if (changeHandler) { signalLater(cm, "change", cm, obj); } if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); } } cm.display.selForContextMenu = null; } function replaceRange(doc, code, from, to, origin) { var assign; if (!to) { to = from; } if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); } if (typeof code == "string") { code = doc.splitLines(code); } makeChange(doc, {from: from, to: to, text: code, origin: origin}); } // Rebasing/resetting history to deal with externally-sourced changes function rebaseHistSelSingle(pos, from, to, diff) { if (to < pos.line) { pos.line += diff; } else if (from < pos.line) { pos.line = from; pos.ch = 0; } } // Tries to rebase an array of history events given a change in the // document. If the change touches the same lines as the event, the // event, and everything 'behind' it, is discarded. If the change is // before the event, the event's positions are updated. Uses a // copy-on-write scheme for the positions, to avoid having to // reallocate them all on every rebase, but also avoid problems with // shared position objects being unsafely updated. function rebaseHistArray(array, from, to, diff) { for (var i = 0; i < array.length; ++i) { var sub = array[i], ok = true; if (sub.ranges) { if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } for (var j = 0; j < sub.ranges.length; j++) { rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); } continue } for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { var cur = sub.changes[j$1]; if (to < cur.from.line) { cur.from = Pos(cur.from.line + diff, cur.from.ch); cur.to = Pos(cur.to.line + diff, cur.to.ch); } else if (from <= cur.to.line) { ok = false; break } } if (!ok) { array.splice(0, i + 1); i = 0; } } } function rebaseHist(hist, change) { var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; rebaseHistArray(hist.done, from, to, diff); rebaseHistArray(hist.undone, from, to, diff); } // Utility for applying a change to a line by handle or number, // returning the number and optionally registering the line as // changed. function changeLine(doc, handle, changeType, op) { var no = handle, line = handle; if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); } else { no = lineNo(handle); } if (no == null) { return null } if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); } return line } // The document is represented as a BTree consisting of leaves, with // chunk of lines in them, and branches, with up to ten leaves or // other branch nodes below them. The top node is always a branch // node, and is the document object itself (meaning it has // additional methods and properties). // // All nodes have parent links. The tree is used both to go from // line numbers to line objects, and to go from objects to numbers. // It also indexes by height, and is used to convert between height // and line object, and to find the total height of the document. // // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html function LeafChunk(lines) { var this$1 = this; this.lines = lines; this.parent = null; var height = 0; for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1; height += lines[i].height; } this.height = height; } LeafChunk.prototype = { chunkSize: function() { return this.lines.length }, // Remove the n lines at offset 'at'. removeInner: function(at, n) { var this$1 = this; for (var i = at, e = at + n; i < e; ++i) { var line = this$1.lines[i]; this$1.height -= line.height; cleanUpLine(line); signalLater(line, "delete"); } this.lines.splice(at, n); }, // Helper used to collapse a small branch into a single leaf. collapse: function(lines) { lines.push.apply(lines, this.lines); }, // Insert the given array of lines at offset 'at', count them as // having the given height. insertInner: function(at, lines, height) { var this$1 = this; this.height += height; this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1; } }, // Used to iterate over a part of the tree. iterN: function(at, n, op) { var this$1 = this; for (var e = at + n; at < e; ++at) { if (op(this$1.lines[at])) { return true } } } }; function BranchChunk(children) { var this$1 = this; this.children = children; var size = 0, height = 0; for (var i = 0; i < children.length; ++i) { var ch = children[i]; size += ch.chunkSize(); height += ch.height; ch.parent = this$1; } this.size = size; this.height = height; this.parent = null; } BranchChunk.prototype = { chunkSize: function() { return this.size }, removeInner: function(at, n) { var this$1 = this; this.size -= n; for (var i = 0; i < this.children.length; ++i) { var child = this$1.children[i], sz = child.chunkSize(); if (at < sz) { var rm = Math.min(n, sz - at), oldHeight = child.height; child.removeInner(at, rm); this$1.height -= oldHeight - child.height; if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null; } if ((n -= rm) == 0) { break } at = 0; } else { at -= sz; } } // If the result is smaller than 25 lines, ensure that it is a // single leaf node. if (this.size - n < 25 && (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { var lines = []; this.collapse(lines); this.children = [new LeafChunk(lines)]; this.children[0].parent = this; } }, collapse: function(lines) { var this$1 = this; for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines); } }, insertInner: function(at, lines, height) { var this$1 = this; this.size += lines.length; this.height += height; for (var i = 0; i < this.children.length; ++i) { var child = this$1.children[i], sz = child.chunkSize(); if (at <= sz) { child.insertInner(at, lines, height); if (child.lines && child.lines.length > 50) { // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. var remaining = child.lines.length % 25 + 25; for (var pos = remaining; pos < child.lines.length;) { var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)); child.height -= leaf.height; this$1.children.splice(++i, 0, leaf); leaf.parent = this$1; } child.lines = child.lines.slice(0, remaining); this$1.maybeSpill(); } break } at -= sz; } }, // When a node has grown, check whether it should be split. maybeSpill: function() { if (this.children.length <= 10) { return } var me = this; do { var spilled = me.children.splice(me.children.length - 5, 5); var sibling = new BranchChunk(spilled); if (!me.parent) { // Become the parent node var copy = new BranchChunk(me.children); copy.parent = me; me.children = [copy, sibling]; me = copy; } else { me.size -= sibling.size; me.height -= sibling.height; var myIndex = indexOf(me.parent.children, me); me.parent.children.splice(myIndex + 1, 0, sibling); } sibling.parent = me.parent; } while (me.children.length > 10) me.parent.maybeSpill(); }, iterN: function(at, n, op) { var this$1 = this; for (var i = 0; i < this.children.length; ++i) { var child = this$1.children[i], sz = child.chunkSize(); if (at < sz) { var used = Math.min(n, sz - at); if (child.iterN(at, used, op)) { return true } if ((n -= used) == 0) { break } at = 0; } else { at -= sz; } } } }; // Line widgets are block elements displayed above or below a line. var LineWidget = function(doc, node, options) { var this$1 = this; if (options) { for (var opt in options) { if (options.hasOwnProperty(opt)) { this$1[opt] = options[opt]; } } } this.doc = doc; this.node = node; }; LineWidget.prototype.clear = function () { var this$1 = this; var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); if (no == null || !ws) { return } for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1); } } if (!ws.length) { line.widgets = null; } var height = widgetHeight(this); updateLineHeight(line, Math.max(0, line.height - height)); if (cm) { runInOp(cm, function () { adjustScrollWhenAboveVisible(cm, line, -height); regLineChange(cm, no, "widget"); }); signalLater(cm, "lineWidgetCleared", cm, this, no); } }; LineWidget.prototype.changed = function () { var this$1 = this; var oldH = this.height, cm = this.doc.cm, line = this.line; this.height = null; var diff = widgetHeight(this) - oldH; if (!diff) { return } if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); } if (cm) { runInOp(cm, function () { cm.curOp.forceUpdate = true; adjustScrollWhenAboveVisible(cm, line, diff); signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line)); }); } }; eventMixin(LineWidget); function adjustScrollWhenAboveVisible(cm, line, diff) { if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) { addToScrollTop(cm, diff); } } function addLineWidget(doc, handle, node, options) { var widget = new LineWidget(doc, node, options); var cm = doc.cm; if (cm && widget.noHScroll) { cm.display.alignWidgets = true; } changeLine(doc, handle, "widget", function (line) { var widgets = line.widgets || (line.widgets = []); if (widget.insertAt == null) { widgets.push(widget); } else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); } widget.line = line; if (cm && !lineIsHidden(doc, line)) { var aboveVisible = heightAtLine(line) < doc.scrollTop; updateLineHeight(line, line.height + widgetHeight(widget)); if (aboveVisible) { addToScrollTop(cm, widget.height); } cm.curOp.forceUpdate = true; } return true }); if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); } return widget } // TEXTMARKERS // Created with markText and setBookmark methods. A TextMarker is a // handle that can be used to clear or find a marked position in the // document. Line objects hold arrays (markedSpans) containing // {from, to, marker} object pointing to such marker objects, and // indicating that such a marker is present on that line. Multiple // lines may point to the same marker when it spans across lines. // The spans will have null for their from/to properties when the // marker continues beyond the start/end of the line. Markers have // links back to the lines they currently touch. // Collapsed markers have unique ids, in order to be able to order // them, which is needed for uniquely determining an outer marker // when they overlap (they may nest, but not partially overlap). var nextMarkerId = 0; var TextMarker = function(doc, type) { this.lines = []; this.type = type; this.doc = doc; this.id = ++nextMarkerId; }; // Clear the marker. TextMarker.prototype.clear = function () { var this$1 = this; if (this.explicitlyCleared) { return } var cm = this.doc.cm, withOp = cm && !cm.curOp; if (withOp) { startOperation(cm); } if (hasHandler(this, "clear")) { var found = this.find(); if (found) { signalLater(this, "clear", found.from, found.to); } } var min = null, max = null; for (var i = 0; i < this.lines.length; ++i) { var line = this$1.lines[i]; var span = getMarkedSpanFor(line.markedSpans, this$1); if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text"); } else if (cm) { if (span.to != null) { max = lineNo(line); } if (span.from != null) { min = lineNo(line); } } line.markedSpans = removeMarkedSpan(line.markedSpans, span); if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm) { updateLineHeight(line, textHeight(cm.display)); } } if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual); if (len > cm.display.maxLineLength) { cm.display.maxLine = visual; cm.display.maxLineLength = len; cm.display.maxLineChanged = true; } } } if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); } this.lines.length = 0; this.explicitlyCleared = true; if (this.atomic && this.doc.cantEdit) { this.doc.cantEdit = false; if (cm) { reCheckSelection(cm.doc); } } if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); } if (withOp) { endOperation(cm); } if (this.parent) { this.parent.clear(); } }; // Find the position of the marker in the document. Returns a {from, // to} object by default. Side can be passed to get a specific side // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the // Pos objects returned contain a line object, rather than a line // number (used to prevent looking up the same line twice). TextMarker.prototype.find = function (side, lineObj) { var this$1 = this; if (side == null && this.type == "bookmark") { side = 1; } var from, to; for (var i = 0; i < this.lines.length; ++i) { var line = this$1.lines[i]; var span = getMarkedSpanFor(line.markedSpans, this$1); if (span.from != null) { from = Pos(lineObj ? line : lineNo(line), span.from); if (side == -1) { return from } } if (span.to != null) { to = Pos(lineObj ? line : lineNo(line), span.to); if (side == 1) { return to } } } return from && {from: from, to: to} }; // Signals that the marker's widget changed, and surrounding layout // should be recomputed. TextMarker.prototype.changed = function () { var this$1 = this; var pos = this.find(-1, true), widget = this, cm = this.doc.cm; if (!pos || !cm) { return } runInOp(cm, function () { var line = pos.line, lineN = lineNo(pos.line); var view = findViewForLine(cm, lineN); if (view) { clearLineMeasurementCacheFor(view); cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; } cm.curOp.updateMaxLine = true; if (!lineIsHidden(widget.doc, line) && widget.height != null) { var oldHeight = widget.height; widget.height = null; var dHeight = widgetHeight(widget) - oldHeight; if (dHeight) { updateLineHeight(line, line.height + dHeight); } } signalLater(cm, "markerChanged", cm, this$1); }); }; TextMarker.prototype.attachLine = function (line) { if (!this.lines.length && this.doc.cm) { var op = this.doc.cm.curOp; if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); } } this.lines.push(line); }; TextMarker.prototype.detachLine = function (line) { this.lines.splice(indexOf(this.lines, line), 1); if (!this.lines.length && this.doc.cm) { var op = this.doc.cm.curOp ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); } }; eventMixin(TextMarker); // Create a marker, wire it up to the right lines, and function markText(doc, from, to, options, type) { // Shared markers (across linked documents) are handled separately // (markTextShared will call out to this again, once per // document). if (options && options.shared) { return markTextShared(doc, from, to, options, type) } // Ensure we are in an operation. if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) } var marker = new TextMarker(doc, type), diff = cmp(from, to); if (options) { copyObj(options, marker, false); } // Don't connect empty markers unless clearWhenEmpty is false if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) { return marker } if (marker.replacedWith) { // Showing up as a widget implies collapsed (widget replaces text) marker.collapsed = true; marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget"); if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); } if (options.insertLeft) { marker.widgetNode.insertLeft = true; } } if (marker.collapsed) { if (conflictingCollapsedRange(doc, from.line, from, to, marker) || from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) { throw new Error("Inserting collapsed marker partially overlapping an existing one") } seeCollapsedSpans(); } if (marker.addToHistory) { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); } var curLine = from.line, cm = doc.cm, updateMaxLine; doc.iter(curLine, to.line + 1, function (line) { if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) { updateMaxLine = true; } if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); } addMarkedSpan(line, new MarkedSpan(marker, curLine == from.line ? from.ch : null, curLine == to.line ? to.ch : null)); ++curLine; }); // lineIsHidden depends on the presence of the spans, so needs a second pass if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) { if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); } }); } if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); } if (marker.readOnly) { seeReadOnlySpans(); if (doc.history.done.length || doc.history.undone.length) { doc.clearHistory(); } } if (marker.collapsed) { marker.id = ++nextMarkerId; marker.atomic = true; } if (cm) { // Sync editor state if (updateMaxLine) { cm.curOp.updateMaxLine = true; } if (marker.collapsed) { regChange(cm, from.line, to.line + 1); } else if (marker.className || marker.startStyle || marker.endStyle || marker.css || marker.attributes || marker.title) { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } } if (marker.atomic) { reCheckSelection(cm.doc); } signalLater(cm, "markerAdded", cm, marker); } return marker } // SHARED TEXTMARKERS // A shared marker spans multiple linked documents. It is // implemented as a meta-marker-object controlling multiple normal // markers. var SharedTextMarker = function(markers, primary) { var this$1 = this; this.markers = markers; this.primary = primary; for (var i = 0; i < markers.length; ++i) { markers[i].parent = this$1; } }; SharedTextMarker.prototype.clear = function () { var this$1 = this; if (this.explicitlyCleared) { return } this.explicitlyCleared = true; for (var i = 0; i < this.markers.length; ++i) { this$1.markers[i].clear(); } signalLater(this, "clear"); }; SharedTextMarker.prototype.find = function (side, lineObj) { return this.primary.find(side, lineObj) }; eventMixin(SharedTextMarker); function markTextShared(doc, from, to, options, type) { options = copyObj(options); options.shared = false; var markers = [markText(doc, from, to, options, type)], primary = markers[0]; var widget = options.widgetNode; linkedDocs(doc, function (doc) { if (widget) { options.widgetNode = widget.cloneNode(true); } markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); for (var i = 0; i < doc.linked.length; ++i) { if (doc.linked[i].isParent) { return } } primary = lst(markers); }); return new SharedTextMarker(markers, primary) } function findSharedMarkers(doc) { return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; }) } function copySharedMarkers(doc, markers) { for (var i = 0; i < markers.length; i++) { var marker = markers[i], pos = marker.find(); var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); if (cmp(mFrom, mTo)) { var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); marker.markers.push(subMark); subMark.parent = marker; } } } function detachSharedMarkers(markers) { var loop = function ( i ) { var marker = markers[i], linked = [marker.primary.doc]; linkedDocs(marker.primary.doc, function (d) { return linked.push(d); }); for (var j = 0; j < marker.markers.length; j++) { var subMarker = marker.markers[j]; if (indexOf(linked, subMarker.doc) == -1) { subMarker.parent = null; marker.markers.splice(j--, 1); } } }; for (var i = 0; i < markers.length; i++) loop( i ); } var nextDocId = 0; var Doc = function(text, mode, firstLine, lineSep, direction) { if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) } if (firstLine == null) { firstLine = 0; } BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); this.first = firstLine; this.scrollTop = this.scrollLeft = 0; this.cantEdit = false; this.cleanGeneration = 1; this.modeFrontier = this.highlightFrontier = firstLine; var start = Pos(firstLine, 0); this.sel = simpleSelection(start); this.history = new History(null); this.id = ++nextDocId; this.modeOption = mode; this.lineSep = lineSep; this.direction = (direction == "rtl") ? "rtl" : "ltr"; this.extend = false; if (typeof text == "string") { text = this.splitLines(text); } updateDoc(this, {from: start, to: start, text: text}); setSelection(this, simpleSelection(start), sel_dontScroll); }; Doc.prototype = createObj(BranchChunk.prototype, { constructor: Doc, // Iterate over the document. Supports two forms -- with only one // argument, it calls that for each line in the document. With // three, it iterates over the range given by the first two (with // the second being non-inclusive). iter: function(from, to, op) { if (op) { this.iterN(from - this.first, to - from, op); } else { this.iterN(this.first, this.first + this.size, from); } }, // Non-public interface for adding and removing lines. insert: function(at, lines) { var height = 0; for (var i = 0; i < lines.length; ++i) { height += lines[i].height; } this.insertInner(at - this.first, lines, height); }, remove: function(at, n) { this.removeInner(at - this.first, n); }, // From here, the methods are part of the public interface. Most // are also available from CodeMirror (editor) instances. getValue: function(lineSep) { var lines = getLines(this, this.first, this.first + this.size); if (lineSep === false) { return lines } return lines.join(lineSep || this.lineSeparator()) }, setValue: docMethodOp(function(code) { var top = Pos(this.first, 0), last = this.first + this.size - 1; makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), text: this.splitLines(code), origin: "setValue", full: true}, true); if (this.cm) { scrollToCoords(this.cm, 0, 0); } setSelection(this, simpleSelection(top), sel_dontScroll); }), replaceRange: function(code, from, to, origin) { from = clipPos(this, from); to = to ? clipPos(this, to) : from; replaceRange(this, code, from, to, origin); }, getRange: function(from, to, lineSep) { var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); if (lineSep === false) { return lines } return lines.join(lineSep || this.lineSeparator()) }, getLine: function(line) {var l = this.getLineHandle(line); return l && l.text}, getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }}, getLineNumber: function(line) {return lineNo(line)}, getLineHandleVisualStart: function(line) { if (typeof line == "number") { line = getLine(this, line); } return visualLine(line) }, lineCount: function() {return this.size}, firstLine: function() {return this.first}, lastLine: function() {return this.first + this.size - 1}, clipPos: function(pos) {return clipPos(this, pos)}, getCursor: function(start) { var range$$1 = this.sel.primary(), pos; if (start == null || start == "head") { pos = range$$1.head; } else if (start == "anchor") { pos = range$$1.anchor; } else if (start == "end" || start == "to" || start === false) { pos = range$$1.to(); } else { pos = range$$1.from(); } return pos }, listSelections: function() { return this.sel.ranges }, somethingSelected: function() {return this.sel.somethingSelected()}, setCursor: docMethodOp(function(line, ch, options) { setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); }), setSelection: docMethodOp(function(anchor, head, options) { setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); }), extendSelection: docMethodOp(function(head, other, options) { extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); }), extendSelections: docMethodOp(function(heads, options) { extendSelections(this, clipPosArray(this, heads), options); }), extendSelectionsBy: docMethodOp(function(f, options) { var heads = map(this.sel.ranges, f); extendSelections(this, clipPosArray(this, heads), options); }), setSelections: docMethodOp(function(ranges, primary, options) { var this$1 = this; if (!ranges.length) { return } var out = []; for (var i = 0; i < ranges.length; i++) { out[i] = new Range(clipPos(this$1, ranges[i].anchor), clipPos(this$1, ranges[i].head)); } if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); } setSelection(this, normalizeSelection(this.cm, out, primary), options); }), addSelection: docMethodOp(function(anchor, head, options) { var ranges = this.sel.ranges.slice(0); ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options); }), getSelection: function(lineSep) { var this$1 = this; var ranges = this.sel.ranges, lines; for (var i = 0; i < ranges.length; i++) { var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()); lines = lines ? lines.concat(sel) : sel; } if (lineSep === false) { return lines } else { return lines.join(lineSep || this.lineSeparator()) } }, getSelections: function(lineSep) { var this$1 = this; var parts = [], ranges = this.sel.ranges; for (var i = 0; i < ranges.length; i++) { var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()); if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()); } parts[i] = sel; } return parts }, replaceSelection: function(code, collapse, origin) { var dup = []; for (var i = 0; i < this.sel.ranges.length; i++) { dup[i] = code; } this.replaceSelections(dup, collapse, origin || "+input"); }, replaceSelections: docMethodOp(function(code, collapse, origin) { var this$1 = this; var changes = [], sel = this.sel; for (var i = 0; i < sel.ranges.length; i++) { var range$$1 = sel.ranges[i]; changes[i] = {from: range$$1.from(), to: range$$1.to(), text: this$1.splitLines(code[i]), origin: origin}; } var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) { makeChange(this$1, changes[i$1]); } if (newSel) { setSelectionReplaceHistory(this, newSel); } else if (this.cm) { ensureCursorVisible(this.cm); } }), undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), setExtending: function(val) {this.extend = val;}, getExtending: function() {return this.extend}, historySize: function() { var hist = this.history, done = 0, undone = 0; for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } } for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } } return {undo: done, redo: undone} }, clearHistory: function() {this.history = new History(this.history.maxGeneration);}, markClean: function() { this.cleanGeneration = this.changeGeneration(true); }, changeGeneration: function(forceSplit) { if (forceSplit) { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; } return this.history.generation }, isClean: function (gen) { return this.history.generation == (gen || this.cleanGeneration) }, getHistory: function() { return {done: copyHistoryArray(this.history.done), undone: copyHistoryArray(this.history.undone)} }, setHistory: function(histData) { var hist = this.history = new History(this.history.maxGeneration); hist.done = copyHistoryArray(histData.done.slice(0), null, true); hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); }, setGutterMarker: docMethodOp(function(line, gutterID, value) { return changeLine(this, line, "gutter", function (line) { var markers = line.gutterMarkers || (line.gutterMarkers = {}); markers[gutterID] = value; if (!value && isEmpty(markers)) { line.gutterMarkers = null; } return true }) }), clearGutter: docMethodOp(function(gutterID) { var this$1 = this; this.iter(function (line) { if (line.gutterMarkers && line.gutterMarkers[gutterID]) { changeLine(this$1, line, "gutter", function () { line.gutterMarkers[gutterID] = null; if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; } return true }); } }); }), lineInfo: function(line) { var n; if (typeof line == "number") { if (!isLine(this, line)) { return null } n = line; line = getLine(this, line); if (!line) { return null } } else { n = lineNo(line); if (n == null) { return null } } return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, widgets: line.widgets} }, addLineClass: docMethodOp(function(handle, where, cls) { return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : where == "gutter" ? "gutterClass" : "wrapClass"; if (!line[prop]) { line[prop] = cls; } else if (classTest(cls).test(line[prop])) { return false } else { line[prop] += " " + cls; } return true }) }), removeLineClass: docMethodOp(function(handle, where, cls) { return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : where == "gutter" ? "gutterClass" : "wrapClass"; var cur = line[prop]; if (!cur) { return false } else if (cls == null) { line[prop] = null; } else { var found = cur.match(classTest(cls)); if (!found) { return false } var end = found.index + found[0].length; line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; } return true }) }), addLineWidget: docMethodOp(function(handle, node, options) { return addLineWidget(this, handle, node, options) }), removeLineWidget: function(widget) { widget.clear(); }, markText: function(from, to, options) { return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range") }, setBookmark: function(pos, options) { var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), insertLeft: options && options.insertLeft, clearWhenEmpty: false, shared: options && options.shared, handleMouseEvents: options && options.handleMouseEvents}; pos = clipPos(this, pos); return markText(this, pos, pos, realOpts, "bookmark") }, findMarksAt: function(pos) { pos = clipPos(this, pos); var markers = [], spans = getLine(this, pos.line).markedSpans; if (spans) { for (var i = 0; i < spans.length; ++i) { var span = spans[i]; if ((span.from == null || span.from <= pos.ch) && (span.to == null || span.to >= pos.ch)) { markers.push(span.marker.parent || span.marker); } } } return markers }, findMarks: function(from, to, filter) { from = clipPos(this, from); to = clipPos(this, to); var found = [], lineNo$$1 = from.line; this.iter(from.line, to.line + 1, function (line) { var spans = line.markedSpans; if (spans) { for (var i = 0; i < spans.length; i++) { var span = spans[i]; if (!(span.to != null && lineNo$$1 == from.line && from.ch >= span.to || span.from == null && lineNo$$1 != from.line || span.from != null && lineNo$$1 == to.line && span.from >= to.ch) && (!filter || filter(span.marker))) { found.push(span.marker.parent || span.marker); } } } ++lineNo$$1; }); return found }, getAllMarks: function() { var markers = []; this.iter(function (line) { var sps = line.markedSpans; if (sps) { for (var i = 0; i < sps.length; ++i) { if (sps[i].from != null) { markers.push(sps[i].marker); } } } }); return markers }, posFromIndex: function(off) { var ch, lineNo$$1 = this.first, sepSize = this.lineSeparator().length; this.iter(function (line) { var sz = line.text.length + sepSize; if (sz > off) { ch = off; return true } off -= sz; ++lineNo$$1; }); return clipPos(this, Pos(lineNo$$1, ch)) }, indexFromPos: function (coords) { coords = clipPos(this, coords); var index = coords.ch; if (coords.line < this.first || coords.ch < 0) { return 0 } var sepSize = this.lineSeparator().length; this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value index += line.text.length + sepSize; }); return index }, copy: function(copyHistory) { var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first, this.lineSep, this.direction); doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; doc.sel = this.sel; doc.extend = false; if (copyHistory) { doc.history.undoDepth = this.history.undoDepth; doc.setHistory(this.getHistory()); } return doc }, linkedDoc: function(options) { if (!options) { options = {}; } var from = this.first, to = this.first + this.size; if (options.from != null && options.from > from) { from = options.from; } if (options.to != null && options.to < to) { to = options.to; } var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction); if (options.sharedHist) { copy.history = this.history ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; copySharedMarkers(copy, findSharedMarkers(this)); return copy }, unlinkDoc: function(other) { var this$1 = this; if (other instanceof CodeMirror) { other = other.doc; } if (this.linked) { for (var i = 0; i < this.linked.length; ++i) { var link = this$1.linked[i]; if (link.doc != other) { continue } this$1.linked.splice(i, 1); other.unlinkDoc(this$1); detachSharedMarkers(findSharedMarkers(this$1)); break } } // If the histories were shared, split them again if (other.history == this.history) { var splitIds = [other.id]; linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true); other.history = new History(null); other.history.done = copyHistoryArray(this.history.done, splitIds); other.history.undone = copyHistoryArray(this.history.undone, splitIds); } }, iterLinkedDocs: function(f) {linkedDocs(this, f);}, getMode: function() {return this.mode}, getEditor: function() {return this.cm}, splitLines: function(str) { if (this.lineSep) { return str.split(this.lineSep) } return splitLinesAuto(str) }, lineSeparator: function() { return this.lineSep || "\n" }, setDirection: docMethodOp(function (dir) { if (dir != "rtl") { dir = "ltr"; } if (dir == this.direction) { return } this.direction = dir; this.iter(function (line) { return line.order = null; }); if (this.cm) { directionChanged(this.cm); } }) }); // Public alias. Doc.prototype.eachLine = Doc.prototype.iter; // Kludge to work around strange IE behavior where it'll sometimes // re-fire a series of drag-related events right after the drop (#1551) var lastDrop = 0; function onDrop(e) { var cm = this; clearDragCursor(cm); if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } e_preventDefault(e); if (ie) { lastDrop = +new Date; } var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; if (!pos || cm.isReadOnly()) { return } // Might be a file drop, in which case we simply extract the text // and insert it. if (files && files.length && window.FileReader && window.File) { var n = files.length, text = Array(n), read = 0; var loadFile = function (file, i) { if (cm.options.allowDropFileTypes && indexOf(cm.options.allowDropFileTypes, file.type) == -1) { return } var reader = new FileReader; reader.onload = operation(cm, function () { var content = reader.result; if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { content = ""; } text[i] = content; if (++read == n) { pos = clipPos(cm.doc, pos); var change = {from: pos, to: pos, text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), origin: "paste"}; makeChange(cm.doc, change); setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))); } }); reader.readAsText(file); }; for (var i = 0; i < n; ++i) { loadFile(files[i], i); } } else { // Normal drop // Don't do a replace if the drop happened inside of the selected text. if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { cm.state.draggingText(e); // Ensure the editor is re-focused setTimeout(function () { return cm.display.input.focus(); }, 20); return } try { var text$1 = e.dataTransfer.getData("Text"); if (text$1) { var selected; if (cm.state.draggingText && !cm.state.draggingText.copy) { selected = cm.listSelections(); } setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1) { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } } cm.replaceSelection(text$1, "around", "paste"); cm.display.input.focus(); } } catch(e){} } } function onDragStart(cm, e) { if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } e.dataTransfer.setData("Text", cm.getSelection()); e.dataTransfer.effectAllowed = "copyMove"; // Use dummy image instead of default browsers image. // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. if (e.dataTransfer.setDragImage && !safari) { var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; if (presto) { img.width = img.height = 1; cm.display.wrapper.appendChild(img); // Force a relayout, or Opera won't use our image for some obscure reason img._top = img.offsetTop; } e.dataTransfer.setDragImage(img, 0, 0); if (presto) { img.parentNode.removeChild(img); } } } function onDragOver(cm, e) { var pos = posFromMouse(cm, e); if (!pos) { return } var frag = document.createDocumentFragment(); drawSelectionCursor(cm, pos, frag); if (!cm.display.dragCursor) { cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); } removeChildrenAndAdd(cm.display.dragCursor, frag); } function clearDragCursor(cm) { if (cm.display.dragCursor) { cm.display.lineSpace.removeChild(cm.display.dragCursor); cm.display.dragCursor = null; } } // These must be handled carefully, because naively registering a // handler for each editor will cause the editors to never be // garbage collected. function forEachCodeMirror(f) { if (!document.getElementsByClassName) { return } var byClass = document.getElementsByClassName("CodeMirror"), editors = []; for (var i = 0; i < byClass.length; i++) { var cm = byClass[i].CodeMirror; if (cm) { editors.push(cm); } } if (editors.length) { editors[0].operation(function () { for (var i = 0; i < editors.length; i++) { f(editors[i]); } }); } } var globalsRegistered = false; function ensureGlobalHandlers() { if (globalsRegistered) { return } registerGlobalHandlers(); globalsRegistered = true; } function registerGlobalHandlers() { // When the window resizes, we need to refresh active editors. var resizeTimer; on(window, "resize", function () { if (resizeTimer == null) { resizeTimer = setTimeout(function () { resizeTimer = null; forEachCodeMirror(onResize); }, 100); } }); // When the window loses focus, we want to show the editor as blurred on(window, "blur", function () { return forEachCodeMirror(onBlur); }); } // Called when the window resizes function onResize(cm) { var d = cm.display; // Might be a text scaling operation, clear size caches. d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; d.scrollbarsClipped = false; cm.setSize(); } var keyNames = { 3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock", 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" }; // Number keys for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); } // Alphabetic keys for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); } // Function keys for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; } var keyMap = {}; keyMap.basic = { "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto", "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", "Esc": "singleSelection" }; // Note that the save and find-related commands aren't defined by // default. User code or addons can define them. Unknown commands // are simply ignored. keyMap.pcDefault = { "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", "fallthrough": "basic" }; // Very basic readline/emacs-style bindings, which are standard on Mac. keyMap.emacsy = { "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", "Ctrl-O": "openLine" }; keyMap.macDefault = { "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", "fallthrough": ["basic", "emacsy"] }; keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; // KEYMAP DISPATCH function normalizeKeyName(name) { var parts = name.split(/-(?!$)/); name = parts[parts.length - 1]; var alt, ctrl, shift, cmd; for (var i = 0; i < parts.length - 1; i++) { var mod = parts[i]; if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; } else if (/^a(lt)?$/i.test(mod)) { alt = true; } else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; } else if (/^s(hift)?$/i.test(mod)) { shift = true; } else { throw new Error("Unrecognized modifier name: " + mod) } } if (alt) { name = "Alt-" + name; } if (ctrl) { name = "Ctrl-" + name; } if (cmd) { name = "Cmd-" + name; } if (shift) { name = "Shift-" + name; } return name } // This is a kludge to keep keymaps mostly working as raw objects // (backwards compatibility) while at the same time support features // like normalization and multi-stroke key bindings. It compiles a // new normalized keymap, and then updates the old object to reflect // this. function normalizeKeyMap(keymap) { var copy = {}; for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) { var value = keymap[keyname]; if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue } if (value == "...") { delete keymap[keyname]; continue } var keys = map(keyname.split(" "), normalizeKeyName); for (var i = 0; i < keys.length; i++) { var val = (void 0), name = (void 0); if (i == keys.length - 1) { name = keys.join(" "); val = value; } else { name = keys.slice(0, i + 1).join(" "); val = "..."; } var prev = copy[name]; if (!prev) { copy[name] = val; } else if (prev != val) { throw new Error("Inconsistent bindings for " + name) } } delete keymap[keyname]; } } for (var prop in copy) { keymap[prop] = copy[prop]; } return keymap } function lookupKey(key, map$$1, handle, context) { map$$1 = getKeyMap(map$$1); var found = map$$1.call ? map$$1.call(key, context) : map$$1[key]; if (found === false) { return "nothing" } if (found === "...") { return "multi" } if (found != null && handle(found)) { return "handled" } if (map$$1.fallthrough) { if (Object.prototype.toString.call(map$$1.fallthrough) != "[object Array]") { return lookupKey(key, map$$1.fallthrough, handle, context) } for (var i = 0; i < map$$1.fallthrough.length; i++) { var result = lookupKey(key, map$$1.fallthrough[i], handle, context); if (result) { return result } } } } // Modifier key presses don't count as 'real' key presses for the // purpose of keymap fallthrough. function isModifierKey(value) { var name = typeof value == "string" ? value : keyNames[value.keyCode]; return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod" } function addModifierNames(name, event, noShift) { var base = name; if (event.altKey && base != "Alt") { name = "Alt-" + name; } if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; } if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name; } if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; } return name } // Look up the name of a key as indicated by an event object. function keyName(event, noShift) { if (presto && event.keyCode == 34 && event["char"]) { return false } var name = keyNames[event.keyCode]; if (name == null || event.altGraphKey) { return false } // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause, // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+) if (event.keyCode == 3 && event.code) { name = event.code; } return addModifierNames(name, event, noShift) } function getKeyMap(val) { return typeof val == "string" ? keyMap[val] : val } // Helper for deleting text near the selection(s), used to implement // backspace, delete, and similar functionality. function deleteNearSelection(cm, compute) { var ranges = cm.doc.sel.ranges, kill = []; // Build up a set of ranges to kill first, merging overlapping // ranges. for (var i = 0; i < ranges.length; i++) { var toKill = compute(ranges[i]); while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { var replaced = kill.pop(); if (cmp(replaced.from, toKill.from) < 0) { toKill.from = replaced.from; break } } kill.push(toKill); } // Next, remove those actual ranges. runInOp(cm, function () { for (var i = kill.length - 1; i >= 0; i--) { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); } ensureCursorVisible(cm); }); } function moveCharLogically(line, ch, dir) { var target = skipExtendingChars(line.text, ch + dir, dir); return target < 0 || target > line.text.length ? null : target } function moveLogically(line, start, dir) { var ch = moveCharLogically(line, start.ch, dir); return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") } function endOfLine(visually, cm, lineObj, lineNo, dir) { if (visually) { var order = getOrder(lineObj, cm.doc.direction); if (order) { var part = dir < 0 ? lst(order) : order[0]; var moveInStorageOrder = (dir < 0) == (part.level == 1); var sticky = moveInStorageOrder ? "after" : "before"; var ch; // With a wrapped rtl chunk (possibly spanning multiple bidi parts), // it could be that the last bidi part is not on the last visual line, // since visual lines contain content order-consecutive chunks. // Thus, in rtl, we are looking for the first (content-order) character // in the rtl chunk that is on the last line (that is, the same line // as the last (content-order) character). if (part.level > 0 || cm.doc.direction == "rtl") { var prep = prepareMeasureForLine(cm, lineObj); ch = dir < 0 ? lineObj.text.length - 1 : 0; var targetTop = measureCharPrepared(cm, prep, ch).top; ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch); if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); } } else { ch = dir < 0 ? part.to : part.from; } return new Pos(lineNo, ch, sticky) } } return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") } function moveVisually(cm, line, start, dir) { var bidi = getOrder(line, cm.doc.direction); if (!bidi) { return moveLogically(line, start, dir) } if (start.ch >= line.text.length) { start.ch = line.text.length; start.sticky = "before"; } else if (start.ch <= 0) { start.ch = 0; start.sticky = "after"; } var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos]; if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, // nothing interesting happens. return moveLogically(line, start, dir) } var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); }; var prep; var getWrappedLineExtent = function (ch) { if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } prep = prep || prepareMeasureForLine(cm, line); return wrappedLineExtentChar(cm, line, prep, ch) }; var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch); if (cm.doc.direction == "rtl" || part.level == 1) { var moveInStorageOrder = (part.level == 1) == (dir < 0); var ch = mv(start, moveInStorageOrder ? 1 : -1); if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { // Case 2: We move within an rtl part or in an rtl editor on the same visual line var sticky = moveInStorageOrder ? "before" : "after"; return new Pos(start.line, ch, sticky) } } // Case 3: Could not move within this bidi part in this visual line, so leave // the current bidi part var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder ? new Pos(start.line, mv(ch, 1), "before") : new Pos(start.line, ch, "after"); }; for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { var part = bidi[partPos]; var moveInStorageOrder = (dir > 0) == (part.level != 1); var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1); if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } ch = moveInStorageOrder ? part.from : mv(part.to, -1); if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } } }; // Case 3a: Look for other bidi parts on the same visual line var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent); if (res) { return res } // Case 3b: Look for other bidi parts on the next visual line var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1); if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)); if (res) { return res } } // Case 4: Nowhere to move return null } // Commands are parameter-less actions that can be performed on an // editor, mostly used for keybindings. var commands = { selectAll: selectAll, singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, killLine: function (cm) { return deleteNearSelection(cm, function (range) { if (range.empty()) { var len = getLine(cm.doc, range.head.line).text.length; if (range.head.ch == len && range.head.line < cm.lastLine()) { return {from: range.head, to: Pos(range.head.line + 1, 0)} } else { return {from: range.head, to: Pos(range.head.line, len)} } } else { return {from: range.from(), to: range.to()} } }); }, deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({ from: Pos(range.from().line, 0), to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) }); }); }, delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({ from: Pos(range.from().line, 0), to: range.from() }); }); }, delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { var top = cm.charCoords(range.head, "div").top + 5; var leftPos = cm.coordsChar({left: 0, top: top}, "div"); return {from: leftPos, to: range.from()} }); }, delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) { var top = cm.charCoords(range.head, "div").top + 5; var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); return {from: range.from(), to: rightPos } }); }, undo: function (cm) { return cm.undo(); }, redo: function (cm) { return cm.redo(); }, undoSelection: function (cm) { return cm.undoSelection(); }, redoSelection: function (cm) { return cm.redoSelection(); }, goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); }, goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); }, goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); }, {origin: "+move", bias: 1} ); }, goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); }, {origin: "+move", bias: 1} ); }, goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); }, {origin: "+move", bias: -1} ); }, goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) { var top = cm.cursorCoords(range.head, "div").top + 5; return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") }, sel_move); }, goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) { var top = cm.cursorCoords(range.head, "div").top + 5; return cm.coordsChar({left: 0, top: top}, "div") }, sel_move); }, goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) { var top = cm.cursorCoords(range.head, "div").top + 5; var pos = cm.coordsChar({left: 0, top: top}, "div"); if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) } return pos }, sel_move); }, goLineUp: function (cm) { return cm.moveV(-1, "line"); }, goLineDown: function (cm) { return cm.moveV(1, "line"); }, goPageUp: function (cm) { return cm.moveV(-1, "page"); }, goPageDown: function (cm) { return cm.moveV(1, "page"); }, goCharLeft: function (cm) { return cm.moveH(-1, "char"); }, goCharRight: function (cm) { return cm.moveH(1, "char"); }, goColumnLeft: function (cm) { return cm.moveH(-1, "column"); }, goColumnRight: function (cm) { return cm.moveH(1, "column"); }, goWordLeft: function (cm) { return cm.moveH(-1, "word"); }, goGroupRight: function (cm) { return cm.moveH(1, "group"); }, goGroupLeft: function (cm) { return cm.moveH(-1, "group"); }, goWordRight: function (cm) { return cm.moveH(1, "word"); }, delCharBefore: function (cm) { return cm.deleteH(-1, "char"); }, delCharAfter: function (cm) { return cm.deleteH(1, "char"); }, delWordBefore: function (cm) { return cm.deleteH(-1, "word"); }, delWordAfter: function (cm) { return cm.deleteH(1, "word"); }, delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); }, delGroupAfter: function (cm) { return cm.deleteH(1, "group"); }, indentAuto: function (cm) { return cm.indentSelection("smart"); }, indentMore: function (cm) { return cm.indentSelection("add"); }, indentLess: function (cm) { return cm.indentSelection("subtract"); }, insertTab: function (cm) { return cm.replaceSelection("\t"); }, insertSoftTab: function (cm) { var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; for (var i = 0; i < ranges.length; i++) { var pos = ranges[i].from(); var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); spaces.push(spaceStr(tabSize - col % tabSize)); } cm.replaceSelections(spaces); }, defaultTab: function (cm) { if (cm.somethingSelected()) { cm.indentSelection("add"); } else { cm.execCommand("insertTab"); } }, // Swap the two chars left and right of each selection's head. // Move cursor behind the two swapped characters afterwards. // // Doesn't consider line feeds a character. // Doesn't scan more than one line above to find a character. // Doesn't do anything on an empty line. // Doesn't do anything with non-empty selections. transposeChars: function (cm) { return runInOp(cm, function () { var ranges = cm.listSelections(), newSel = []; for (var i = 0; i < ranges.length; i++) { if (!ranges[i].empty()) { continue } var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; if (line) { if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); } if (cur.ch > 0) { cur = new Pos(cur.line, cur.ch + 1); cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), Pos(cur.line, cur.ch - 2), cur, "+transpose"); } else if (cur.line > cm.doc.first) { var prev = getLine(cm.doc, cur.line - 1).text; if (prev) { cur = new Pos(cur.line, 1); cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + prev.charAt(prev.length - 1), Pos(cur.line - 1, prev.length - 1), cur, "+transpose"); } } } newSel.push(new Range(cur, cur)); } cm.setSelections(newSel); }); }, newlineAndIndent: function (cm) { return runInOp(cm, function () { var sels = cm.listSelections(); for (var i = sels.length - 1; i >= 0; i--) { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); } sels = cm.listSelections(); for (var i$1 = 0; i$1 < sels.length; i$1++) { cm.indentLine(sels[i$1].from().line, null, true); } ensureCursorVisible(cm); }); }, openLine: function (cm) { return cm.replaceSelection("\n", "start"); }, toggleOverwrite: function (cm) { return cm.toggleOverwrite(); } }; function lineStart(cm, lineN) { var line = getLine(cm.doc, lineN); var visual = visualLine(line); if (visual != line) { lineN = lineNo(visual); } return endOfLine(true, cm, visual, lineN, 1) } function lineEnd(cm, lineN) { var line = getLine(cm.doc, lineN); var visual = visualLineEnd(line); if (visual != line) { lineN = lineNo(visual); } return endOfLine(true, cm, line, lineN, -1) } function lineStartSmart(cm, pos) { var start = lineStart(cm, pos.line); var line = getLine(cm.doc, start.line); var order = getOrder(line, cm.doc.direction); if (!order || order[0].level == 0) { var firstNonWS = Math.max(0, line.text.search(/\S/)); var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) } return start } // Run a handler that was bound to a key. function doHandleBinding(cm, bound, dropShift) { if (typeof bound == "string") { bound = commands[bound]; if (!bound) { return false } } // Ensure previous input has been read, so that the handler sees a // consistent view of the document cm.display.input.ensurePolled(); var prevShift = cm.display.shift, done = false; try { if (cm.isReadOnly()) { cm.state.suppressEdits = true; } if (dropShift) { cm.display.shift = false; } done = bound(cm) != Pass; } finally { cm.display.shift = prevShift; cm.state.suppressEdits = false; } return done } function lookupKeyForEditor(cm, name, handle) { for (var i = 0; i < cm.state.keyMaps.length; i++) { var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); if (result) { return result } } return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) || lookupKey(name, cm.options.keyMap, handle, cm) } // Note that, despite the name, this function is also used to check // for bound mouse clicks. var stopSeq = new Delayed; function dispatchKey(cm, name, e, handle) { var seq = cm.state.keySeq; if (seq) { if (isModifierKey(name)) { return "handled" } if (/\'$/.test(name)) { cm.state.keySeq = null; } else { stopSeq.set(50, function () { if (cm.state.keySeq == seq) { cm.state.keySeq = null; cm.display.input.reset(); } }); } if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true } } return dispatchKeyInner(cm, name, e, handle) } function dispatchKeyInner(cm, name, e, handle) { var result = lookupKeyForEditor(cm, name, handle); if (result == "multi") { cm.state.keySeq = name; } if (result == "handled") { signalLater(cm, "keyHandled", cm, name, e); } if (result == "handled" || result == "multi") { e_preventDefault(e); restartBlink(cm); } return !!result } // Handle a key from the keydown event. function handleKeyBinding(cm, e) { var name = keyName(e, true); if (!name) { return false } if (e.shiftKey && !cm.state.keySeq) { // First try to resolve full name (including 'Shift-'). Failing // that, see if there is a cursor-motion command (starting with // 'go') bound to the keyname without 'Shift-'. return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); }) || dispatchKey(cm, name, e, function (b) { if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) { return doHandleBinding(cm, b) } }) } else { return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); }) } } // Handle a key from the keypress event function handleCharBinding(cm, e, ch) { return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); }) } var lastStoppedKey = null; function onKeyDown(e) { var cm = this; cm.curOp.focus = activeElt(); if (signalDOMEvent(cm, e)) { return } // IE does strange things with escape. if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; } var code = e.keyCode; cm.display.shift = code == 16 || e.shiftKey; var handled = handleKeyBinding(cm, e); if (presto) { lastStoppedKey = handled ? code : null; // Opera has no cut event... we try to at least catch the key combo if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) { cm.replaceSelection("", null, "cut"); } } // Turn mouse into crosshair when Alt is held on Mac. if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) { showCrossHair(cm); } } function showCrossHair(cm) { var lineDiv = cm.display.lineDiv; addClass(lineDiv, "CodeMirror-crosshair"); function up(e) { if (e.keyCode == 18 || !e.altKey) { rmClass(lineDiv, "CodeMirror-crosshair"); off(document, "keyup", up); off(document, "mouseover", up); } } on(document, "keyup", up); on(document, "mouseover", up); } function onKeyUp(e) { if (e.keyCode == 16) { this.doc.sel.shift = false; } signalDOMEvent(this, e); } function onKeyPress(e) { var cm = this; if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return } var keyCode = e.keyCode, charCode = e.charCode; if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return } var ch = String.fromCharCode(charCode == null ? keyCode : charCode); // Some browsers fire keypress events for backspace if (ch == "\x08") { return } if (handleCharBinding(cm, e, ch)) { return } cm.display.input.onKeyPress(e); } var DOUBLECLICK_DELAY = 400; var PastClick = function(time, pos, button) { this.time = time; this.pos = pos; this.button = button; }; PastClick.prototype.compare = function (time, pos, button) { return this.time + DOUBLECLICK_DELAY > time && cmp(pos, this.pos) == 0 && button == this.button }; var lastClick, lastDoubleClick; function clickRepeat(pos, button) { var now = +new Date; if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) { lastClick = lastDoubleClick = null; return "triple" } else if (lastClick && lastClick.compare(now, pos, button)) { lastDoubleClick = new PastClick(now, pos, button); lastClick = null; return "double" } else { lastClick = new PastClick(now, pos, button); lastDoubleClick = null; return "single" } } // A mouse down can be a single click, double click, triple click, // start of selection drag, start of text drag, new cursor // (ctrl-click), rectangle drag (alt-drag), or xwin // middle-click-paste. Or it might be a click on something we should // not interfere with, such as a scrollbar or widget. function onMouseDown(e) { var cm = this, display = cm.display; if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return } display.input.ensurePolled(); display.shift = e.shiftKey; if (eventInWidget(display, e)) { if (!webkit) { // Briefly turn off draggability, to allow widgets to do // normal dragging things. display.scroller.draggable = false; setTimeout(function () { return display.scroller.draggable = true; }, 100); } return } if (clickInGutter(cm, e)) { return } var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single"; window.focus(); // #3261: make sure, that we're not starting a second selection if (button == 1 && cm.state.selectingText) { cm.state.selectingText(e); } if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return } if (button == 1) { if (pos) { leftButtonDown(cm, pos, repeat, e); } else if (e_target(e) == display.scroller) { e_preventDefault(e); } } else if (button == 2) { if (pos) { extendSelection(cm.doc, pos); } setTimeout(function () { return display.input.focus(); }, 20); } else if (button == 3) { if (captureRightClick) { cm.display.input.onContextMenu(e); } else { delayBlurEvent(cm); } } } function handleMappedButton(cm, button, pos, repeat, event) { var name = "Click"; if (repeat == "double") { name = "Double" + name; } else if (repeat == "triple") { name = "Triple" + name; } name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name; return dispatchKey(cm, addModifierNames(name, event), event, function (bound) { if (typeof bound == "string") { bound = commands[bound]; } if (!bound) { return false } var done = false; try { if (cm.isReadOnly()) { cm.state.suppressEdits = true; } done = bound(cm, pos) != Pass; } finally { cm.state.suppressEdits = false; } return done }) } function configureMouse(cm, repeat, event) { var option = cm.getOption("configureMouse"); var value = option ? option(cm, repeat, event) : {}; if (value.unit == null) { var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey; value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line"; } if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; } if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; } if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); } return value } function leftButtonDown(cm, pos, repeat, event) { if (ie) { setTimeout(bind(ensureFocus, cm), 0); } else { cm.curOp.focus = activeElt(); } var behavior = configureMouse(cm, repeat, event); var sel = cm.doc.sel, contained; if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && repeat == "single" && (contained = sel.contains(pos)) > -1 && (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) && (cmp(contained.to(), pos) > 0 || pos.xRel < 0)) { leftButtonStartDrag(cm, event, pos, behavior); } else { leftButtonSelect(cm, event, pos, behavior); } } // Start a text drag. When it ends, see if any dragging actually // happen, and treat as a click if it didn't. function leftButtonStartDrag(cm, event, pos, behavior) { var display = cm.display, moved = false; var dragEnd = operation(cm, function (e) { if (webkit) { display.scroller.draggable = false; } cm.state.draggingText = false; off(display.wrapper.ownerDocument, "mouseup", dragEnd); off(display.wrapper.ownerDocument, "mousemove", mouseMove); off(display.scroller, "dragstart", dragStart); off(display.scroller, "drop", dragEnd); if (!moved) { e_preventDefault(e); if (!behavior.addNew) { extendSelection(cm.doc, pos, null, null, behavior.extend); } // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) if (webkit || ie && ie_version == 9) { setTimeout(function () {display.wrapper.ownerDocument.body.focus(); display.input.focus();}, 20); } else { display.input.focus(); } } }); var mouseMove = function(e2) { moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10; }; var dragStart = function () { return moved = true; }; // Let the drag handler handle this. if (webkit) { display.scroller.draggable = true; } cm.state.draggingText = dragEnd; dragEnd.copy = !behavior.moveOnDrag; // IE's approach to draggable if (display.scroller.dragDrop) { display.scroller.dragDrop(); } on(display.wrapper.ownerDocument, "mouseup", dragEnd); on(display.wrapper.ownerDocument, "mousemove", mouseMove); on(display.scroller, "dragstart", dragStart); on(display.scroller, "drop", dragEnd); delayBlurEvent(cm); setTimeout(function () { return display.input.focus(); }, 20); } function rangeForUnit(cm, pos, unit) { if (unit == "char") { return new Range(pos, pos) } if (unit == "word") { return cm.findWordAt(pos) } if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } var result = unit(cm, pos); return new Range(result.from, result.to) } // Normal selection, as opposed to text dragging. function leftButtonSelect(cm, event, start, behavior) { var display = cm.display, doc = cm.doc; e_preventDefault(event); var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; if (behavior.addNew && !behavior.extend) { ourIndex = doc.sel.contains(start); if (ourIndex > -1) { ourRange = ranges[ourIndex]; } else { ourRange = new Range(start, start); } } else { ourRange = doc.sel.primary(); ourIndex = doc.sel.primIndex; } if (behavior.unit == "rectangle") { if (!behavior.addNew) { ourRange = new Range(start, start); } start = posFromMouse(cm, event, true, true); ourIndex = -1; } else { var range$$1 = rangeForUnit(cm, start, behavior.unit); if (behavior.extend) { ourRange = extendRange(ourRange, range$$1.anchor, range$$1.head, behavior.extend); } else { ourRange = range$$1; } } if (!behavior.addNew) { ourIndex = 0; setSelection(doc, new Selection([ourRange], 0), sel_mouse); startSel = doc.sel; } else if (ourIndex == -1) { ourIndex = ranges.length; setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex), {scroll: false, origin: "*mouse"}); } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) { setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), {scroll: false, origin: "*mouse"}); startSel = doc.sel; } else { replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); } var lastPos = start; function extendTo(pos) { if (cmp(lastPos, pos) == 0) { return } lastPos = pos; if (behavior.unit == "rectangle") { var ranges = [], tabSize = cm.options.tabSize; var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); line <= end; line++) { var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); if (left == right) { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); } else if (text.length > leftPos) { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); } } if (!ranges.length) { ranges.push(new Range(start, start)); } setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), {origin: "*mouse", scroll: false}); cm.scrollIntoView(pos); } else { var oldRange = ourRange; var range$$1 = rangeForUnit(cm, pos, behavior.unit); var anchor = oldRange.anchor, head; if (cmp(range$$1.anchor, anchor) > 0) { head = range$$1.head; anchor = minPos(oldRange.from(), range$$1.anchor); } else { head = range$$1.anchor; anchor = maxPos(oldRange.to(), range$$1.head); } var ranges$1 = startSel.ranges.slice(0); ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head)); setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse); } } var editorSize = display.wrapper.getBoundingClientRect(); // Used to ensure timeout re-tries don't fire when another extend // happened in the meantime (clearTimeout isn't reliable -- at // least on Chrome, the timeouts still happen even when cleared, // if the clear happens after their scheduled firing time). var counter = 0; function extend(e) { var curCount = ++counter; var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle"); if (!cur) { return } if (cmp(cur, lastPos) != 0) { cm.curOp.focus = activeElt(); extendTo(cur); var visible = visibleLines(display, doc); if (cur.line >= visible.to || cur.line < visible.from) { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); } } else { var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; if (outside) { setTimeout(operation(cm, function () { if (counter != curCount) { return } display.scroller.scrollTop += outside; extend(e); }), 50); } } } function done(e) { cm.state.selectingText = false; counter = Infinity; // If e is null or undefined we interpret this as someone trying // to explicitly cancel the selection rather than the user // letting go of the mouse button. if (e) { e_preventDefault(e); display.input.focus(); } off(display.wrapper.ownerDocument, "mousemove", move); off(display.wrapper.ownerDocument, "mouseup", up); doc.history.lastSelOrigin = null; } var move = operation(cm, function (e) { if (e.buttons === 0 || !e_button(e)) { done(e); } else { extend(e); } }); var up = operation(cm, done); cm.state.selectingText = up; on(display.wrapper.ownerDocument, "mousemove", move); on(display.wrapper.ownerDocument, "mouseup", up); } // Used when mouse-selecting to adjust the anchor to the proper side // of a bidi jump depending on the visual position of the head. function bidiSimplify(cm, range$$1) { var anchor = range$$1.anchor; var head = range$$1.head; var anchorLine = getLine(cm.doc, anchor.line); if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range$$1 } var order = getOrder(anchorLine); if (!order) { return range$$1 } var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index]; if (part.from != anchor.ch && part.to != anchor.ch) { return range$$1 } var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1); if (boundary == 0 || boundary == order.length) { return range$$1 } // Compute the relative visual position of the head compared to the // anchor (<0 is to the left, >0 to the right) var leftSide; if (head.line != anchor.line) { leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0; } else { var headIndex = getBidiPartAt(order, head.ch, head.sticky); var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1); if (headIndex == boundary - 1 || headIndex == boundary) { leftSide = dir < 0; } else { leftSide = dir > 0; } } var usePart = order[boundary + (leftSide ? -1 : 0)]; var from = leftSide == (usePart.level == 1); var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before"; return anchor.ch == ch && anchor.sticky == sticky ? range$$1 : new Range(new Pos(anchor.line, ch, sticky), head) } // Determines whether an event happened in the gutter, and fires the // handlers for the corresponding event. function gutterEvent(cm, e, type, prevent) { var mX, mY; if (e.touches) { mX = e.touches[0].clientX; mY = e.touches[0].clientY; } else { try { mX = e.clientX; mY = e.clientY; } catch(e) { return false } } if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } if (prevent) { e_preventDefault(e); } var display = cm.display; var lineBox = display.lineDiv.getBoundingClientRect(); if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } mY -= lineBox.top - display.viewOffset; for (var i = 0; i < cm.display.gutterSpecs.length; ++i) { var g = display.gutters.childNodes[i]; if (g && g.getBoundingClientRect().right >= mX) { var line = lineAtHeight(cm.doc, mY); var gutter = cm.display.gutterSpecs[i]; signal(cm, type, cm, line, gutter.className, e); return e_defaultPrevented(e) } } } function clickInGutter(cm, e) { return gutterEvent(cm, e, "gutterClick", true) } // CONTEXT MENU HANDLING // To make the context menu work, we need to briefly unhide the // textarea (making it as unobtrusive as possible) to let the // right-click take effect on it. function onContextMenu(cm, e) { if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return } if (signalDOMEvent(cm, e, "contextmenu")) { return } if (!captureRightClick) { cm.display.input.onContextMenu(e); } } function contextMenuInGutter(cm, e) { if (!hasHandler(cm, "gutterContextMenu")) { return false } return gutterEvent(cm, e, "gutterContextMenu", false) } function themeChanged(cm) { cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); clearCaches(cm); } var Init = {toString: function(){return "CodeMirror.Init"}}; var defaults = {}; var optionHandlers = {}; function defineOptions(CodeMirror) { var optionHandlers = CodeMirror.optionHandlers; function option(name, deflt, handle, notOnInit) { CodeMirror.defaults[name] = deflt; if (handle) { optionHandlers[name] = notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; } } CodeMirror.defineOption = option; // Passed to option handlers when there is no old value. CodeMirror.Init = Init; // These two are, on init, called from the constructor because they // have to be initialized before the editor can start at all. option("value", "", function (cm, val) { return cm.setValue(val); }, true); option("mode", null, function (cm, val) { cm.doc.modeOption = val; loadMode(cm); }, true); option("indentUnit", 2, loadMode, true); option("indentWithTabs", false); option("smartIndent", true); option("tabSize", 4, function (cm) { resetModeState(cm); clearCaches(cm); regChange(cm); }, true); option("lineSeparator", null, function (cm, val) { cm.doc.lineSep = val; if (!val) { return } var newBreaks = [], lineNo = cm.doc.first; cm.doc.iter(function (line) { for (var pos = 0;;) { var found = line.text.indexOf(val, pos); if (found == -1) { break } pos = found + val.length; newBreaks.push(Pos(lineNo, found)); } lineNo++; }); for (var i = newBreaks.length - 1; i >= 0; i--) { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); } }); option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) { cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); if (old != Init) { cm.refresh(); } }); option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true); option("electricChars", true); option("inputStyle", mobile ? "contenteditable" : "textarea", function () { throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME }, true); option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true); option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true); option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true); option("rtlMoveVisually", !windows); option("wholeLineUpdateBefore", true); option("theme", "default", function (cm) { themeChanged(cm); updateGutters(cm); }, true); option("keyMap", "default", function (cm, val, old) { var next = getKeyMap(val); var prev = old != Init && getKeyMap(old); if (prev && prev.detach) { prev.detach(cm, next); } if (next.attach) { next.attach(cm, prev || null); } }); option("extraKeys", null); option("configureMouse", null); option("lineWrapping", false, wrappingChanged, true); option("gutters", [], function (cm, val) { cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers); updateGutters(cm); }, true); option("fixedGutter", true, function (cm, val) { cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; cm.refresh(); }, true); option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true); option("scrollbarStyle", "native", function (cm) { initScrollbars(cm); updateScrollbars(cm); cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); }, true); option("lineNumbers", false, function (cm, val) { cm.display.gutterSpecs = getGutters(cm.options.gutters, val); updateGutters(cm); }, true); option("firstLineNumber", 1, updateGutters, true); option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true); option("showCursorWhenSelecting", false, updateSelection, true); option("resetSelectionOnContextMenu", true); option("lineWiseCopyCut", true); option("pasteLinesPerSelection", true); option("selectionsMayTouch", false); option("readOnly", false, function (cm, val) { if (val == "nocursor") { onBlur(cm); cm.display.input.blur(); } cm.display.input.readOnlyChanged(val); }); option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true); option("dragDrop", true, dragDropChanged); option("allowDropFileTypes", null); option("cursorBlinkRate", 530); option("cursorScrollMargin", 0); option("cursorHeight", 1, updateSelection, true); option("singleCursorHeightPerLine", true, updateSelection, true); option("workTime", 100); option("workDelay", 100); option("flattenSpans", true, resetModeState, true); option("addModeClass", false, resetModeState, true); option("pollInterval", 100); option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; }); option("historyEventDelay", 1250); option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true); option("maxHighlightLength", 10000, resetModeState, true); option("moveInputWithCursor", true, function (cm, val) { if (!val) { cm.display.input.resetPosition(); } }); option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; }); option("autofocus", null); option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true); option("phrases", null); } function dragDropChanged(cm, value, old) { var wasOn = old && old != Init; if (!value != !wasOn) { var funcs = cm.display.dragFunctions; var toggle = value ? on : off; toggle(cm.display.scroller, "dragstart", funcs.start); toggle(cm.display.scroller, "dragenter", funcs.enter); toggle(cm.display.scroller, "dragover", funcs.over); toggle(cm.display.scroller, "dragleave", funcs.leave); toggle(cm.display.scroller, "drop", funcs.drop); } } function wrappingChanged(cm) { if (cm.options.lineWrapping) { addClass(cm.display.wrapper, "CodeMirror-wrap"); cm.display.sizer.style.minWidth = ""; cm.display.sizerWidth = null; } else { rmClass(cm.display.wrapper, "CodeMirror-wrap"); findMaxLine(cm); } estimateLineHeights(cm); regChange(cm); clearCaches(cm); setTimeout(function () { return updateScrollbars(cm); }, 100); } // A CodeMirror instance represents an editor. This is the object // that user code is usually dealing with. function CodeMirror(place, options) { var this$1 = this; if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) } this.options = options = options ? copyObj(options) : {}; // Determine effective options based on given values and defaults. copyObj(defaults, options, false); var doc = options.value; if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); } else if (options.mode) { doc.modeOption = options.mode; } this.doc = doc; var input = new CodeMirror.inputStyles[options.inputStyle](this); var display = this.display = new Display(place, doc, input, options); display.wrapper.CodeMirror = this; themeChanged(this); if (options.lineWrapping) { this.display.wrapper.className += " CodeMirror-wrap"; } initScrollbars(this); this.state = { keyMaps: [], // stores maps added by addKeyMap overlays: [], // highlighting overlays, as added by addOverlay modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info overwrite: false, delayingBlurEvent: false, focused: false, suppressEdits: false, // used to disable editing during key handlers when in readOnly mode pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll selectingText: false, draggingText: false, highlight: new Delayed(), // stores highlight worker timeout keySeq: null, // Unfinished key sequence specialChars: null }; if (options.autofocus && !mobile) { display.input.focus(); } // Override magic textarea content restore that IE sometimes does // on our hidden textarea on reload if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); } registerEventHandlers(this); ensureGlobalHandlers(); startOperation(this); this.curOp.forceUpdate = true; attachDoc(this, doc); if ((options.autofocus && !mobile) || this.hasFocus()) { setTimeout(bind(onFocus, this), 20); } else { onBlur(this); } for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt)) { optionHandlers[opt](this$1, options[opt], Init); } } maybeUpdateLineNumberWidth(this); if (options.finishInit) { options.finishInit(this); } for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1); } endOperation(this); // Suppress optimizelegibility in Webkit, since it breaks text // measuring on line wrapping boundaries. if (webkit && options.lineWrapping && getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") { display.lineDiv.style.textRendering = "auto"; } } // The default configuration options. CodeMirror.defaults = defaults; // Functions to run when options are changed. CodeMirror.optionHandlers = optionHandlers; // Attach the necessary event handlers when initializing the editor function registerEventHandlers(cm) { var d = cm.display; on(d.scroller, "mousedown", operation(cm, onMouseDown)); // Older IE's will not fire a second mousedown for a double click if (ie && ie_version < 11) { on(d.scroller, "dblclick", operation(cm, function (e) { if (signalDOMEvent(cm, e)) { return } var pos = posFromMouse(cm, e); if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return } e_preventDefault(e); var word = cm.findWordAt(pos); extendSelection(cm.doc, word.anchor, word.head); })); } else { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); } // Some browsers fire contextmenu *after* opening the menu, at // which point we can't mess with it anymore. Context menu is // handled in onMouseDown for these browsers. on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }); // Used to suppress mouse event handling when a touch happens var touchFinished, prevTouch = {end: 0}; function finishTouch() { if (d.activeTouch) { touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000); prevTouch = d.activeTouch; prevTouch.end = +new Date; } } function isMouseLikeTouchEvent(e) { if (e.touches.length != 1) { return false } var touch = e.touches[0]; return touch.radiusX <= 1 && touch.radiusY <= 1 } function farAway(touch, other) { if (other.left == null) { return true } var dx = other.left - touch.left, dy = other.top - touch.top; return dx * dx + dy * dy > 20 * 20 } on(d.scroller, "touchstart", function (e) { if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { d.input.ensurePolled(); clearTimeout(touchFinished); var now = +new Date; d.activeTouch = {start: now, moved: false, prev: now - prevTouch.end <= 300 ? prevTouch : null}; if (e.touches.length == 1) { d.activeTouch.left = e.touches[0].pageX; d.activeTouch.top = e.touches[0].pageY; } } }); on(d.scroller, "touchmove", function () { if (d.activeTouch) { d.activeTouch.moved = true; } }); on(d.scroller, "touchend", function (e) { var touch = d.activeTouch; if (touch && !eventInWidget(d, e) && touch.left != null && !touch.moved && new Date - touch.start < 300) { var pos = cm.coordsChar(d.activeTouch, "page"), range; if (!touch.prev || farAway(touch, touch.prev)) // Single tap { range = new Range(pos, pos); } else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap { range = cm.findWordAt(pos); } else // Triple tap { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); } cm.setSelection(range.anchor, range.head); cm.focus(); e_preventDefault(e); } finishTouch(); }); on(d.scroller, "touchcancel", finishTouch); // Sync scrolling between fake scrollbars and real scrollable // area, ensure viewport is updated when scrolling. on(d.scroller, "scroll", function () { if (d.scroller.clientHeight) { updateScrollTop(cm, d.scroller.scrollTop); setScrollLeft(cm, d.scroller.scrollLeft, true); signal(cm, "scroll", cm); } }); // Listen to wheel events in order to try and update the viewport on time. on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); }); on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); }); // Prevent wrapper from ever scrolling on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); d.dragFunctions = { enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }}, over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, start: function (e) { return onDragStart(cm, e); }, drop: operation(cm, onDrop), leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }} }; var inp = d.input.getField(); on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); }); on(inp, "keydown", operation(cm, onKeyDown)); on(inp, "keypress", operation(cm, onKeyPress)); on(inp, "focus", function (e) { return onFocus(cm, e); }); on(inp, "blur", function (e) { return onBlur(cm, e); }); } var initHooks = []; CodeMirror.defineInitHook = function (f) { return initHooks.push(f); }; // Indent the given line. The how parameter can be "smart", // "add"/null, "subtract", or "prev". When aggressive is false // (typically set to true for forced single-line indents), empty // lines are not indented, and places where the mode returns Pass // are left alone. function indentLine(cm, n, how, aggressive) { var doc = cm.doc, state; if (how == null) { how = "add"; } if (how == "smart") { // Fall back to "prev" when the mode doesn't have an indentation // method. if (!doc.mode.indent) { how = "prev"; } else { state = getContextBefore(cm, n).state; } } var tabSize = cm.options.tabSize; var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); if (line.stateAfter) { line.stateAfter = null; } var curSpaceString = line.text.match(/^\s*/)[0], indentation; if (!aggressive && !/\S/.test(line.text)) { indentation = 0; how = "not"; } else if (how == "smart") { indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); if (indentation == Pass || indentation > 150) { if (!aggressive) { return } how = "prev"; } } if (how == "prev") { if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); } else { indentation = 0; } } else if (how == "add") { indentation = curSpace + cm.options.indentUnit; } else if (how == "subtract") { indentation = curSpace - cm.options.indentUnit; } else if (typeof how == "number") { indentation = curSpace + how; } indentation = Math.max(0, indentation); var indentString = "", pos = 0; if (cm.options.indentWithTabs) { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} } if (pos < indentation) { indentString += spaceStr(indentation - pos); } if (indentString != curSpaceString) { replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); line.stateAfter = null; return true } else { // Ensure that, if the cursor was in the whitespace at the start // of the line, it is moved to the end of that space. for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { var range = doc.sel.ranges[i$1]; if (range.head.line == n && range.head.ch < curSpaceString.length) { var pos$1 = Pos(n, curSpaceString.length); replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)); break } } } } // This will be set to a {lineWise: bool, text: [string]} object, so // that, when pasting, we know what kind of selections the copied // text was made out of. var lastCopied = null; function setLastCopied(newLastCopied) { lastCopied = newLastCopied; } function applyTextInput(cm, inserted, deleted, sel, origin) { var doc = cm.doc; cm.display.shift = false; if (!sel) { sel = doc.sel; } var recent = +new Date - 200; var paste = origin == "paste" || cm.state.pasteIncoming > recent; var textLines = splitLinesAuto(inserted), multiPaste = null; // When pasting N lines into N selections, insert one line per selection if (paste && sel.ranges.length > 1) { if (lastCopied && lastCopied.text.join("\n") == inserted) { if (sel.ranges.length % lastCopied.text.length == 0) { multiPaste = []; for (var i = 0; i < lastCopied.text.length; i++) { multiPaste.push(doc.splitLines(lastCopied.text[i])); } } } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) { multiPaste = map(textLines, function (l) { return [l]; }); } } var updateInput = cm.curOp.updateInput; // Normal behavior is to insert the new text into every selection for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { var range$$1 = sel.ranges[i$1]; var from = range$$1.from(), to = range$$1.to(); if (range$$1.empty()) { if (deleted && deleted > 0) // Handle deletion { from = Pos(from.line, from.ch - deleted); } else if (cm.state.overwrite && !paste) // Handle overwrite { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); } else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted) { from = to = Pos(from.line, 0); } } var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")}; makeChange(cm.doc, changeEvent); signalLater(cm, "inputRead", cm, changeEvent); } if (inserted && !paste) { triggerElectric(cm, inserted); } ensureCursorVisible(cm); if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; } cm.curOp.typing = true; cm.state.pasteIncoming = cm.state.cutIncoming = -1; } function handlePaste(e, cm) { var pasted = e.clipboardData && e.clipboardData.getData("Text"); if (pasted) { e.preventDefault(); if (!cm.isReadOnly() && !cm.options.disableInput) { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); } return true } } function triggerElectric(cm, inserted) { // When an 'electric' character is inserted, immediately trigger a reindent if (!cm.options.electricChars || !cm.options.smartIndent) { return } var sel = cm.doc.sel; for (var i = sel.ranges.length - 1; i >= 0; i--) { var range$$1 = sel.ranges[i]; if (range$$1.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range$$1.head.line)) { continue } var mode = cm.getModeAt(range$$1.head); var indented = false; if (mode.electricChars) { for (var j = 0; j < mode.electricChars.length; j++) { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { indented = indentLine(cm, range$$1.head.line, "smart"); break } } } else if (mode.electricInput) { if (mode.electricInput.test(getLine(cm.doc, range$$1.head.line).text.slice(0, range$$1.head.ch))) { indented = indentLine(cm, range$$1.head.line, "smart"); } } if (indented) { signalLater(cm, "electricInput", cm, range$$1.head.line); } } } function copyableRanges(cm) { var text = [], ranges = []; for (var i = 0; i < cm.doc.sel.ranges.length; i++) { var line = cm.doc.sel.ranges[i].head.line; var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; ranges.push(lineRange); text.push(cm.getRange(lineRange.anchor, lineRange.head)); } return {text: text, ranges: ranges} } function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) { field.setAttribute("autocorrect", autocorrect ? "" : "off"); field.setAttribute("autocapitalize", autocapitalize ? "" : "off"); field.setAttribute("spellcheck", !!spellcheck); } function hiddenTextarea() { var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"); var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); // The textarea is kept positioned near the cursor to prevent the // fact that it'll be scrolled into view on input from scrolling // our fake cursor out of view. On webkit, when wrap=off, paste is // very slow. So make the area wide instead. if (webkit) { te.style.width = "1000px"; } else { te.setAttribute("wrap", "off"); } // If border: 0; -- iOS fails to open keyboard (issue #1287) if (ios) { te.style.border = "1px solid black"; } disableBrowserMagic(te); return div } // The publicly visible API. Note that methodOp(f) means // 'wrap f in an operation, performed on its `this` parameter'. // This is not the complete set of editor methods. Most of the // methods defined on the Doc type are also injected into // CodeMirror.prototype, for backwards compatibility and // convenience. function addEditorMethods(CodeMirror) { var optionHandlers = CodeMirror.optionHandlers; var helpers = CodeMirror.helpers = {}; CodeMirror.prototype = { constructor: CodeMirror, focus: function(){window.focus(); this.display.input.focus();}, setOption: function(option, value) { var options = this.options, old = options[option]; if (options[option] == value && option != "mode") { return } options[option] = value; if (optionHandlers.hasOwnProperty(option)) { operation(this, optionHandlers[option])(this, value, old); } signal(this, "optionChange", this, option); }, getOption: function(option) {return this.options[option]}, getDoc: function() {return this.doc}, addKeyMap: function(map$$1, bottom) { this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map$$1)); }, removeKeyMap: function(map$$1) { var maps = this.state.keyMaps; for (var i = 0; i < maps.length; ++i) { if (maps[i] == map$$1 || maps[i].name == map$$1) { maps.splice(i, 1); return true } } }, addOverlay: methodOp(function(spec, options) { var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); if (mode.startState) { throw new Error("Overlays may not be stateful.") } insertSorted(this.state.overlays, {mode: mode, modeSpec: spec, opaque: options && options.opaque, priority: (options && options.priority) || 0}, function (overlay) { return overlay.priority; }); this.state.modeGen++; regChange(this); }), removeOverlay: methodOp(function(spec) { var this$1 = this; var overlays = this.state.overlays; for (var i = 0; i < overlays.length; ++i) { var cur = overlays[i].modeSpec; if (cur == spec || typeof spec == "string" && cur.name == spec) { overlays.splice(i, 1); this$1.state.modeGen++; regChange(this$1); return } } }), indentLine: methodOp(function(n, dir, aggressive) { if (typeof dir != "string" && typeof dir != "number") { if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; } else { dir = dir ? "add" : "subtract"; } } if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); } }), indentSelection: methodOp(function(how) { var this$1 = this; var ranges = this.doc.sel.ranges, end = -1; for (var i = 0; i < ranges.length; i++) { var range$$1 = ranges[i]; if (!range$$1.empty()) { var from = range$$1.from(), to = range$$1.to(); var start = Math.max(end, from.line); end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; for (var j = start; j < end; ++j) { indentLine(this$1, j, how); } var newRanges = this$1.doc.sel.ranges; if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); } } else if (range$$1.head.line > end) { indentLine(this$1, range$$1.head.line, how, true); end = range$$1.head.line; if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1); } } } }), // Fetch the parser token for a given character. Useful for hacks // that want to inspect the mode state (say, for completion). getTokenAt: function(pos, precise) { return takeToken(this, pos, precise) }, getLineTokens: function(line, precise) { return takeToken(this, Pos(line), precise, true) }, getTokenTypeAt: function(pos) { pos = clipPos(this.doc, pos); var styles = getLineStyles(this, getLine(this.doc, pos.line)); var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; var type; if (ch == 0) { type = styles[2]; } else { for (;;) { var mid = (before + after) >> 1; if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; } else if (styles[mid * 2 + 1] < ch) { before = mid + 1; } else { type = styles[mid * 2 + 2]; break } } } var cut = type ? type.indexOf("overlay ") : -1; return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) }, getModeAt: function(pos) { var mode = this.doc.mode; if (!mode.innerMode) { return mode } return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode }, getHelper: function(pos, type) { return this.getHelpers(pos, type)[0] }, getHelpers: function(pos, type) { var this$1 = this; var found = []; if (!helpers.hasOwnProperty(type)) { return found } var help = helpers[type], mode = this.getModeAt(pos); if (typeof mode[type] == "string") { if (help[mode[type]]) { found.push(help[mode[type]]); } } else if (mode[type]) { for (var i = 0; i < mode[type].length; i++) { var val = help[mode[type][i]]; if (val) { found.push(val); } } } else if (mode.helperType && help[mode.helperType]) { found.push(help[mode.helperType]); } else if (help[mode.name]) { found.push(help[mode.name]); } for (var i$1 = 0; i$1 < help._global.length; i$1++) { var cur = help._global[i$1]; if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1) { found.push(cur.val); } } return found }, getStateAfter: function(line, precise) { var doc = this.doc; line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); return getContextBefore(this, line + 1, precise).state }, cursorCoords: function(start, mode) { var pos, range$$1 = this.doc.sel.primary(); if (start == null) { pos = range$$1.head; } else if (typeof start == "object") { pos = clipPos(this.doc, start); } else { pos = start ? range$$1.from() : range$$1.to(); } return cursorCoords(this, pos, mode || "page") }, charCoords: function(pos, mode) { return charCoords(this, clipPos(this.doc, pos), mode || "page") }, coordsChar: function(coords, mode) { coords = fromCoordSystem(this, coords, mode || "page"); return coordsChar(this, coords.left, coords.top) }, lineAtHeight: function(height, mode) { height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; return lineAtHeight(this.doc, height + this.display.viewOffset) }, heightAtLine: function(line, mode, includeWidgets) { var end = false, lineObj; if (typeof line == "number") { var last = this.doc.first + this.doc.size - 1; if (line < this.doc.first) { line = this.doc.first; } else if (line > last) { line = last; end = true; } lineObj = getLine(this.doc, line); } else { lineObj = line; } return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top + (end ? this.doc.height - heightAtLine(lineObj) : 0) }, defaultTextHeight: function() { return textHeight(this.display) }, defaultCharWidth: function() { return charWidth(this.display) }, getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, addWidget: function(pos, node, scroll, vert, horiz) { var display = this.display; pos = cursorCoords(this, clipPos(this.doc, pos)); var top = pos.bottom, left = pos.left; node.style.position = "absolute"; node.setAttribute("cm-ignore-events", "true"); this.display.input.setUneditable(node); display.sizer.appendChild(node); if (vert == "over") { top = pos.top; } else if (vert == "above" || vert == "near") { var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); // Default to positioning above (if specified and possible); otherwise default to positioning below if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) { top = pos.top - node.offsetHeight; } else if (pos.bottom + node.offsetHeight <= vspace) { top = pos.bottom; } if (left + node.offsetWidth > hspace) { left = hspace - node.offsetWidth; } } node.style.top = top + "px"; node.style.left = node.style.right = ""; if (horiz == "right") { left = display.sizer.clientWidth - node.offsetWidth; node.style.right = "0px"; } else { if (horiz == "left") { left = 0; } else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; } node.style.left = left + "px"; } if (scroll) { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); } }, triggerOnKeyDown: methodOp(onKeyDown), triggerOnKeyPress: methodOp(onKeyPress), triggerOnKeyUp: onKeyUp, triggerOnMouseDown: methodOp(onMouseDown), execCommand: function(cmd) { if (commands.hasOwnProperty(cmd)) { return commands[cmd].call(null, this) } }, triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), findPosH: function(from, amount, unit, visually) { var this$1 = this; var dir = 1; if (amount < 0) { dir = -1; amount = -amount; } var cur = clipPos(this.doc, from); for (var i = 0; i < amount; ++i) { cur = findPosH(this$1.doc, cur, dir, unit, visually); if (cur.hitSide) { break } } return cur }, moveH: methodOp(function(dir, unit) { var this$1 = this; this.extendSelectionsBy(function (range$$1) { if (this$1.display.shift || this$1.doc.extend || range$$1.empty()) { return findPosH(this$1.doc, range$$1.head, dir, unit, this$1.options.rtlMoveVisually) } else { return dir < 0 ? range$$1.from() : range$$1.to() } }, sel_move); }), deleteH: methodOp(function(dir, unit) { var sel = this.doc.sel, doc = this.doc; if (sel.somethingSelected()) { doc.replaceSelection("", null, "+delete"); } else { deleteNearSelection(this, function (range$$1) { var other = findPosH(doc, range$$1.head, dir, unit, false); return dir < 0 ? {from: other, to: range$$1.head} : {from: range$$1.head, to: other} }); } }), findPosV: function(from, amount, unit, goalColumn) { var this$1 = this; var dir = 1, x = goalColumn; if (amount < 0) { dir = -1; amount = -amount; } var cur = clipPos(this.doc, from); for (var i = 0; i < amount; ++i) { var coords = cursorCoords(this$1, cur, "div"); if (x == null) { x = coords.left; } else { coords.left = x; } cur = findPosV(this$1, coords, dir, unit); if (cur.hitSide) { break } } return cur }, moveV: methodOp(function(dir, unit) { var this$1 = this; var doc = this.doc, goals = []; var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected(); doc.extendSelectionsBy(function (range$$1) { if (collapse) { return dir < 0 ? range$$1.from() : range$$1.to() } var headPos = cursorCoords(this$1, range$$1.head, "div"); if (range$$1.goalColumn != null) { headPos.left = range$$1.goalColumn; } goals.push(headPos.left); var pos = findPosV(this$1, headPos, dir, unit); if (unit == "page" && range$$1 == doc.sel.primary()) { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); } return pos }, sel_move); if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++) { doc.sel.ranges[i].goalColumn = goals[i]; } } }), // Find the word at the given position (as returned by coordsChar). findWordAt: function(pos) { var doc = this.doc, line = getLine(doc, pos.line).text; var start = pos.ch, end = pos.ch; if (line) { var helper = this.getHelper(pos, "wordChars"); if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; } var startChar = line.charAt(start); var check = isWordChar(startChar, helper) ? function (ch) { return isWordChar(ch, helper); } : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); } : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); }; while (start > 0 && check(line.charAt(start - 1))) { --start; } while (end < line.length && check(line.charAt(end))) { ++end; } } return new Range(Pos(pos.line, start), Pos(pos.line, end)) }, toggleOverwrite: function(value) { if (value != null && value == this.state.overwrite) { return } if (this.state.overwrite = !this.state.overwrite) { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); } else { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); } signal(this, "overwriteToggle", this, this.state.overwrite); }, hasFocus: function() { return this.display.input.getField() == activeElt() }, isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }), getScrollInfo: function() { var scroller = this.display.scroller; return {left: scroller.scrollLeft, top: scroller.scrollTop, height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, clientHeight: displayHeight(this), clientWidth: displayWidth(this)} }, scrollIntoView: methodOp(function(range$$1, margin) { if (range$$1 == null) { range$$1 = {from: this.doc.sel.primary().head, to: null}; if (margin == null) { margin = this.options.cursorScrollMargin; } } else if (typeof range$$1 == "number") { range$$1 = {from: Pos(range$$1, 0), to: null}; } else if (range$$1.from == null) { range$$1 = {from: range$$1, to: null}; } if (!range$$1.to) { range$$1.to = range$$1.from; } range$$1.margin = margin || 0; if (range$$1.from.line != null) { scrollToRange(this, range$$1); } else { scrollToCoordsRange(this, range$$1.from, range$$1.to, range$$1.margin); } }), setSize: methodOp(function(width, height) { var this$1 = this; var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; }; if (width != null) { this.display.wrapper.style.width = interpret(width); } if (height != null) { this.display.wrapper.style.height = interpret(height); } if (this.options.lineWrapping) { clearLineMeasurementCache(this); } var lineNo$$1 = this.display.viewFrom; this.doc.iter(lineNo$$1, this.display.viewTo, function (line) { if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo$$1, "widget"); break } } } ++lineNo$$1; }); this.curOp.forceUpdate = true; signal(this, "refresh", this); }), operation: function(f){return runInOp(this, f)}, startOperation: function(){return startOperation(this)}, endOperation: function(){return endOperation(this)}, refresh: methodOp(function() { var oldHeight = this.display.cachedTextHeight; regChange(this); this.curOp.forceUpdate = true; clearCaches(this); scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop); updateGutterSpace(this.display); if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) { estimateLineHeights(this); } signal(this, "refresh", this); }), swapDoc: methodOp(function(doc) { var old = this.doc; old.cm = null; // Cancel the current text selection if any (#5821) if (this.state.selectingText) { this.state.selectingText(); } attachDoc(this, doc); clearCaches(this); this.display.input.reset(); scrollToCoords(this, doc.scrollLeft, doc.scrollTop); this.curOp.forceScroll = true; signalLater(this, "swapDoc", this, old); return old }), phrase: function(phraseText) { var phrases = this.options.phrases; return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText }, getInputField: function(){return this.display.input.getField()}, getWrapperElement: function(){return this.display.wrapper}, getScrollerElement: function(){return this.display.scroller}, getGutterElement: function(){return this.display.gutters} }; eventMixin(CodeMirror); CodeMirror.registerHelper = function(type, name, value) { if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; } helpers[type][name] = value; }; CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { CodeMirror.registerHelper(type, name, value); helpers[type]._global.push({pred: predicate, val: value}); }; } // Used for horizontal relative motion. Dir is -1 or 1 (left or // right), unit can be "char", "column" (like char, but doesn't // cross line boundaries), "word" (across next word), or "group" (to // the start of next group of word or non-word-non-whitespace // chars). The visually param controls whether, in right-to-left // text, direction 1 means to move towards the next index in the // string, or towards the character to the right of the current // position. The resulting position will have a hitSide=true // property if it reached the end of the document. function findPosH(doc, pos, dir, unit, visually) { var oldPos = pos; var origDir = dir; var lineObj = getLine(doc, pos.line); function findNextLine() { var l = pos.line + dir; if (l < doc.first || l >= doc.first + doc.size) { return false } pos = new Pos(l, pos.ch, pos.sticky); return lineObj = getLine(doc, l) } function moveOnce(boundToLine) { var next; if (visually) { next = moveVisually(doc.cm, lineObj, pos, dir); } else { next = moveLogically(lineObj, pos, dir); } if (next == null) { if (!boundToLine && findNextLine()) { pos = endOfLine(visually, doc.cm, lineObj, pos.line, dir); } else { return false } } else { pos = next; } return true } if (unit == "char") { moveOnce(); } else if (unit == "column") { moveOnce(true); } else if (unit == "word" || unit == "group") { var sawType = null, group = unit == "group"; var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); for (var first = true;; first = false) { if (dir < 0 && !moveOnce(!first)) { break } var cur = lineObj.text.charAt(pos.ch) || "\n"; var type = isWordChar(cur, helper) ? "w" : group && cur == "\n" ? "n" : !group || /\s/.test(cur) ? null : "p"; if (group && !first && !type) { type = "s"; } if (sawType && sawType != type) { if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";} break } if (type) { sawType = type; } if (dir > 0 && !moveOnce(!first)) { break } } } var result = skipAtomic(doc, pos, oldPos, origDir, true); if (equalCursorPos(oldPos, result)) { result.hitSide = true; } return result } // For relative vertical movement. Dir may be -1 or 1. Unit can be // "page" or "line". The resulting position will have a hitSide=true // property if it reached the end of the document. function findPosV(cm, pos, dir, unit) { var doc = cm.doc, x = pos.left, y; if (unit == "page") { var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3); y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount; } else if (unit == "line") { y = dir > 0 ? pos.bottom + 3 : pos.top - 3; } var target; for (;;) { target = coordsChar(cm, x, y); if (!target.outside) { break } if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } y += dir * 5; } return target } // CONTENTEDITABLE INPUT STYLE var ContentEditableInput = function(cm) { this.cm = cm; this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; this.polling = new Delayed(); this.composing = null; this.gracePeriod = false; this.readDOMTimeout = null; }; ContentEditableInput.prototype.init = function (display) { var this$1 = this; var input = this, cm = input.cm; var div = input.div = display.lineDiv; disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize); on(div, "paste", function (e) { if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } // IE doesn't fire input events, so we schedule a read for the pasted content in this way if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); } }); on(div, "compositionstart", function (e) { this$1.composing = {data: e.data, done: false}; }); on(div, "compositionupdate", function (e) { if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; } }); on(div, "compositionend", function (e) { if (this$1.composing) { if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); } this$1.composing.done = true; } }); on(div, "touchstart", function () { return input.forceCompositionEnd(); }); on(div, "input", function () { if (!this$1.composing) { this$1.readFromDOMSoon(); } }); function onCopyCut(e) { if (signalDOMEvent(cm, e)) { return } if (cm.somethingSelected()) { setLastCopied({lineWise: false, text: cm.getSelections()}); if (e.type == "cut") { cm.replaceSelection("", null, "cut"); } } else if (!cm.options.lineWiseCopyCut) { return } else { var ranges = copyableRanges(cm); setLastCopied({lineWise: true, text: ranges.text}); if (e.type == "cut") { cm.operation(function () { cm.setSelections(ranges.ranges, 0, sel_dontScroll); cm.replaceSelection("", null, "cut"); }); } } if (e.clipboardData) { e.clipboardData.clearData(); var content = lastCopied.text.join("\n"); // iOS exposes the clipboard API, but seems to discard content inserted into it e.clipboardData.setData("Text", content); if (e.clipboardData.getData("Text") == content) { e.preventDefault(); return } } // Old-fashioned briefly-focus-a-textarea hack var kludge = hiddenTextarea(), te = kludge.firstChild; cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); te.value = lastCopied.text.join("\n"); var hadFocus = document.activeElement; selectInput(te); setTimeout(function () { cm.display.lineSpace.removeChild(kludge); hadFocus.focus(); if (hadFocus == div) { input.showPrimarySelection(); } }, 50); } on(div, "copy", onCopyCut); on(div, "cut", onCopyCut); }; ContentEditableInput.prototype.prepareSelection = function () { var result = prepareSelection(this.cm, false); result.focus = this.cm.state.focused; return result }; ContentEditableInput.prototype.showSelection = function (info, takeFocus) { if (!info || !this.cm.display.view.length) { return } if (info.focus || takeFocus) { this.showPrimarySelection(); } this.showMultipleSelections(info); }; ContentEditableInput.prototype.getSelection = function () { return this.cm.display.wrapper.ownerDocument.getSelection() }; ContentEditableInput.prototype.showPrimarySelection = function () { var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary(); var from = prim.from(), to = prim.to(); if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) { sel.removeAllRanges(); return } var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset); if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && cmp(minPos(curAnchor, curFocus), from) == 0 && cmp(maxPos(curAnchor, curFocus), to) == 0) { return } var view = cm.display.view; var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) || {node: view[0].measure.map[2], offset: 0}; var end = to.line < cm.display.viewTo && posToDOM(cm, to); if (!end) { var measure = view[view.length - 1].measure; var map$$1 = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; end = {node: map$$1[map$$1.length - 1], offset: map$$1[map$$1.length - 2] - map$$1[map$$1.length - 3]}; } if (!start || !end) { sel.removeAllRanges(); return } var old = sel.rangeCount && sel.getRangeAt(0), rng; try { rng = range(start.node, start.offset, end.offset, end.node); } catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible if (rng) { if (!gecko && cm.state.focused) { sel.collapse(start.node, start.offset); if (!rng.collapsed) { sel.removeAllRanges(); sel.addRange(rng); } } else { sel.removeAllRanges(); sel.addRange(rng); } if (old && sel.anchorNode == null) { sel.addRange(old); } else if (gecko) { this.startGracePeriod(); } } this.rememberSelection(); }; ContentEditableInput.prototype.startGracePeriod = function () { var this$1 = this; clearTimeout(this.gracePeriod); this.gracePeriod = setTimeout(function () { this$1.gracePeriod = false; if (this$1.selectionChanged()) { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); } }, 20); }; ContentEditableInput.prototype.showMultipleSelections = function (info) { removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); }; ContentEditableInput.prototype.rememberSelection = function () { var sel = this.getSelection(); this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; }; ContentEditableInput.prototype.selectionInEditor = function () { var sel = this.getSelection(); if (!sel.rangeCount) { return false } var node = sel.getRangeAt(0).commonAncestorContainer; return contains(this.div, node) }; ContentEditableInput.prototype.focus = function () { if (this.cm.options.readOnly != "nocursor") { if (!this.selectionInEditor()) { this.showSelection(this.prepareSelection(), true); } this.div.focus(); } }; ContentEditableInput.prototype.blur = function () { this.div.blur(); }; ContentEditableInput.prototype.getField = function () { return this.div }; ContentEditableInput.prototype.supportsTouch = function () { return true }; ContentEditableInput.prototype.receivedFocus = function () { var input = this; if (this.selectionInEditor()) { this.pollSelection(); } else { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); } function poll() { if (input.cm.state.focused) { input.pollSelection(); input.polling.set(input.cm.options.pollInterval, poll); } } this.polling.set(this.cm.options.pollInterval, poll); }; ContentEditableInput.prototype.selectionChanged = function () { var sel = this.getSelection(); return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset }; ContentEditableInput.prototype.pollSelection = function () { if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return } var sel = this.getSelection(), cm = this.cm; // On Android Chrome (version 56, at least), backspacing into an // uneditable block element will put the cursor in that element, // and then, because it's not editable, hide the virtual keyboard. // Because Android doesn't allow us to actually detect backspace // presses in a sane way, this code checks for when that happens // and simulates a backspace press in this case. if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) { this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs}); this.blur(); this.focus(); return } if (this.composing) { return } this.rememberSelection(); var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); var head = domToPos(cm, sel.focusNode, sel.focusOffset); if (anchor && head) { runInOp(cm, function () { setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; } }); } }; ContentEditableInput.prototype.pollContent = function () { if (this.readDOMTimeout != null) { clearTimeout(this.readDOMTimeout); this.readDOMTimeout = null; } var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); var from = sel.from(), to = sel.to(); if (from.ch == 0 && from.line > cm.firstLine()) { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); } if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) { to = Pos(to.line + 1, 0); } if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false } var fromIndex, fromLine, fromNode; if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { fromLine = lineNo(display.view[0].line); fromNode = display.view[0].node; } else { fromLine = lineNo(display.view[fromIndex].line); fromNode = display.view[fromIndex - 1].node.nextSibling; } var toIndex = findViewIndex(cm, to.line); var toLine, toNode; if (toIndex == display.view.length - 1) { toLine = display.viewTo - 1; toNode = display.lineDiv.lastChild; } else { toLine = lineNo(display.view[toIndex + 1].line) - 1; toNode = display.view[toIndex + 1].node.previousSibling; } if (!fromNode) { return false } var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); while (newText.length > 1 && oldText.length > 1) { if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } else { break } } var cutFront = 0, cutEnd = 0; var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) { ++cutFront; } var newBot = lst(newText), oldBot = lst(oldText); var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), oldBot.length - (oldText.length == 1 ? cutFront : 0)); while (cutEnd < maxCutEnd && newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { ++cutEnd; } // Try to move start of change to start of selection if ambiguous if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) { while (cutFront && cutFront > from.ch && newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { cutFront--; cutEnd++; } } newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, ""); newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, ""); var chFrom = Pos(fromLine, cutFront); var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { replaceRange(cm.doc, newText, chFrom, chTo, "+input"); return true } }; ContentEditableInput.prototype.ensurePolled = function () { this.forceCompositionEnd(); }; ContentEditableInput.prototype.reset = function () { this.forceCompositionEnd(); }; ContentEditableInput.prototype.forceCompositionEnd = function () { if (!this.composing) { return } clearTimeout(this.readDOMTimeout); this.composing = null; this.updateFromDOM(); this.div.blur(); this.div.focus(); }; ContentEditableInput.prototype.readFromDOMSoon = function () { var this$1 = this; if (this.readDOMTimeout != null) { return } this.readDOMTimeout = setTimeout(function () { this$1.readDOMTimeout = null; if (this$1.composing) { if (this$1.composing.done) { this$1.composing = null; } else { return } } this$1.updateFromDOM(); }, 80); }; ContentEditableInput.prototype.updateFromDOM = function () { var this$1 = this; if (this.cm.isReadOnly() || !this.pollContent()) { runInOp(this.cm, function () { return regChange(this$1.cm); }); } }; ContentEditableInput.prototype.setUneditable = function (node) { node.contentEditable = "false"; }; ContentEditableInput.prototype.onKeyPress = function (e) { if (e.charCode == 0 || this.composing) { return } e.preventDefault(); if (!this.cm.isReadOnly()) { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); } }; ContentEditableInput.prototype.readOnlyChanged = function (val) { this.div.contentEditable = String(val != "nocursor"); }; ContentEditableInput.prototype.onContextMenu = function () {}; ContentEditableInput.prototype.resetPosition = function () {}; ContentEditableInput.prototype.needsContentAttribute = true; function posToDOM(cm, pos) { var view = findViewForLine(cm, pos.line); if (!view || view.hidden) { return null } var line = getLine(cm.doc, pos.line); var info = mapFromLineView(view, line, pos.line); var order = getOrder(line, cm.doc.direction), side = "left"; if (order) { var partPos = getBidiPartAt(order, pos.ch); side = partPos % 2 ? "right" : "left"; } var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); result.offset = result.collapse == "right" ? result.end : result.start; return result } function isInGutter(node) { for (var scan = node; scan; scan = scan.parentNode) { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } } return false } function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos } function domTextBetween(cm, from, to, fromLine, toLine) { var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false; function recognizeMarker(id) { return function (marker) { return marker.id == id; } } function close() { if (closing) { text += lineSep; if (extraLinebreak) { text += lineSep; } closing = extraLinebreak = false; } } function addText(str) { if (str) { close(); text += str; } } function walk(node) { if (node.nodeType == 1) { var cmText = node.getAttribute("cm-text"); if (cmText) { addText(cmText); return } var markerID = node.getAttribute("cm-marker"), range$$1; if (markerID) { var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); if (found.length && (range$$1 = found[0].find(0))) { addText(getBetween(cm.doc, range$$1.from, range$$1.to).join(lineSep)); } return } if (node.getAttribute("contenteditable") == "false") { return } var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName); if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return } if (isBlock) { close(); } for (var i = 0; i < node.childNodes.length; i++) { walk(node.childNodes[i]); } if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; } if (isBlock) { closing = true; } } else if (node.nodeType == 3) { addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " ")); } } for (;;) { walk(from); if (from == to) { break } from = from.nextSibling; extraLinebreak = false; } return text } function domToPos(cm, node, offset) { var lineNode; if (node == cm.display.lineDiv) { lineNode = cm.display.lineDiv.childNodes[offset]; if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) } node = null; offset = 0; } else { for (lineNode = node;; lineNode = lineNode.parentNode) { if (!lineNode || lineNode == cm.display.lineDiv) { return null } if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break } } } for (var i = 0; i < cm.display.view.length; i++) { var lineView = cm.display.view[i]; if (lineView.node == lineNode) { return locateNodeInLineView(lineView, node, offset) } } } function locateNodeInLineView(lineView, node, offset) { var wrapper = lineView.text.firstChild, bad = false; if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) } if (node == wrapper) { bad = true; node = wrapper.childNodes[offset]; offset = 0; if (!node) { var line = lineView.rest ? lst(lineView.rest) : lineView.line; return badPos(Pos(lineNo(line), line.text.length), bad) } } var textNode = node.nodeType == 3 ? node : null, topNode = node; if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { textNode = node.firstChild; if (offset) { offset = textNode.nodeValue.length; } } while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; } var measure = lineView.measure, maps = measure.maps; function find(textNode, topNode, offset) { for (var i = -1; i < (maps ? maps.length : 0); i++) { var map$$1 = i < 0 ? measure.map : maps[i]; for (var j = 0; j < map$$1.length; j += 3) { var curNode = map$$1[j + 2]; if (curNode == textNode || curNode == topNode) { var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); var ch = map$$1[j] + offset; if (offset < 0 || curNode != textNode) { ch = map$$1[j + (offset ? 1 : 0)]; } return Pos(line, ch) } } } } var found = find(textNode, topNode, offset); if (found) { return badPos(found, bad) } // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { found = find(after, after.firstChild, 0); if (found) { return badPos(Pos(found.line, found.ch - dist), bad) } else { dist += after.textContent.length; } } for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { found = find(before, before.firstChild, -1); if (found) { return badPos(Pos(found.line, found.ch + dist$1), bad) } else { dist$1 += before.textContent.length; } } } // TEXTAREA INPUT STYLE var TextareaInput = function(cm) { this.cm = cm; // See input.poll and input.reset this.prevInput = ""; // Flag that indicates whether we expect input to appear real soon // now (after some event like 'keypress' or 'input') and are // polling intensively. this.pollingFast = false; // Self-resetting timeout for the poller this.polling = new Delayed(); // Used to work around IE issue with selection being forgotten when focus moves away from textarea this.hasSelection = false; this.composing = null; }; TextareaInput.prototype.init = function (display) { var this$1 = this; var input = this, cm = this.cm; this.createField(display); var te = this.textarea; display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild); // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) if (ios) { te.style.width = "0px"; } on(te, "input", function () { if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; } input.poll(); }); on(te, "paste", function (e) { if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } cm.state.pasteIncoming = +new Date; input.fastPoll(); }); function prepareCopyCut(e) { if (signalDOMEvent(cm, e)) { return } if (cm.somethingSelected()) { setLastCopied({lineWise: false, text: cm.getSelections()}); } else if (!cm.options.lineWiseCopyCut) { return } else { var ranges = copyableRanges(cm); setLastCopied({lineWise: true, text: ranges.text}); if (e.type == "cut") { cm.setSelections(ranges.ranges, null, sel_dontScroll); } else { input.prevInput = ""; te.value = ranges.text.join("\n"); selectInput(te); } } if (e.type == "cut") { cm.state.cutIncoming = +new Date; } } on(te, "cut", prepareCopyCut); on(te, "copy", prepareCopyCut); on(display.scroller, "paste", function (e) { if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } if (!te.dispatchEvent) { cm.state.pasteIncoming = +new Date; input.focus(); return } // Pass the `paste` event to the textarea so it's handled by its event listener. var event = new Event("paste"); event.clipboardData = e.clipboardData; te.dispatchEvent(event); }); // Prevent normal selection in the editor (we handle our own) on(display.lineSpace, "selectstart", function (e) { if (!eventInWidget(display, e)) { e_preventDefault(e); } }); on(te, "compositionstart", function () { var start = cm.getCursor("from"); if (input.composing) { input.composing.range.clear(); } input.composing = { start: start, range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) }; }); on(te, "compositionend", function () { if (input.composing) { input.poll(); input.composing.range.clear(); input.composing = null; } }); }; TextareaInput.prototype.createField = function (_display) { // Wraps and hides input textarea this.wrapper = hiddenTextarea(); // The semihidden textarea that is focused when the editor is // focused, and receives input. this.textarea = this.wrapper.firstChild; }; TextareaInput.prototype.prepareSelection = function () { // Redraw the selection and/or cursor var cm = this.cm, display = cm.display, doc = cm.doc; var result = prepareSelection(cm); // Move the hidden textarea near the cursor to prevent scrolling artifacts if (cm.options.moveInputWithCursor) { var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, headPos.top + lineOff.top - wrapOff.top)); result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, headPos.left + lineOff.left - wrapOff.left)); } return result }; TextareaInput.prototype.showSelection = function (drawn) { var cm = this.cm, display = cm.display; removeChildrenAndAdd(display.cursorDiv, drawn.cursors); removeChildrenAndAdd(display.selectionDiv, drawn.selection); if (drawn.teTop != null) { this.wrapper.style.top = drawn.teTop + "px"; this.wrapper.style.left = drawn.teLeft + "px"; } }; // Reset the input to correspond to the selection (or to be empty, // when not typing and nothing is selected) TextareaInput.prototype.reset = function (typing) { if (this.contextMenuPending || this.composing) { return } var cm = this.cm; if (cm.somethingSelected()) { this.prevInput = ""; var content = cm.getSelection(); this.textarea.value = content; if (cm.state.focused) { selectInput(this.textarea); } if (ie && ie_version >= 9) { this.hasSelection = content; } } else if (!typing) { this.prevInput = this.textarea.value = ""; if (ie && ie_version >= 9) { this.hasSelection = null; } } }; TextareaInput.prototype.getField = function () { return this.textarea }; TextareaInput.prototype.supportsTouch = function () { return false }; TextareaInput.prototype.focus = function () { if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { try { this.textarea.focus(); } catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM } }; TextareaInput.prototype.blur = function () { this.textarea.blur(); }; TextareaInput.prototype.resetPosition = function () { this.wrapper.style.top = this.wrapper.style.left = 0; }; TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); }; // Poll for input changes, using the normal rate of polling. This // runs as long as the editor is focused. TextareaInput.prototype.slowPoll = function () { var this$1 = this; if (this.pollingFast) { return } this.polling.set(this.cm.options.pollInterval, function () { this$1.poll(); if (this$1.cm.state.focused) { this$1.slowPoll(); } }); }; // When an event has just come in that is likely to add or change // something in the input textarea, we poll faster, to ensure that // the change appears on the screen quickly. TextareaInput.prototype.fastPoll = function () { var missed = false, input = this; input.pollingFast = true; function p() { var changed = input.poll(); if (!changed && !missed) {missed = true; input.polling.set(60, p);} else {input.pollingFast = false; input.slowPoll();} } input.polling.set(20, p); }; // Read input from the textarea, and update the document to match. // When something is selected, it is present in the textarea, and // selected (unless it is huge, in which case a placeholder is // used). When nothing is selected, the cursor sits after previously // seen text (can be empty), which is stored in prevInput (we must // not reset the textarea when typing, because that breaks IME). TextareaInput.prototype.poll = function () { var this$1 = this; var cm = this.cm, input = this.textarea, prevInput = this.prevInput; // Since this is called a *lot*, try to bail out as cheaply as // possible when it is clear that nothing happened. hasSelection // will be the case when there is a lot of text in the textarea, // in which case reading its value would be expensive. if (this.contextMenuPending || !cm.state.focused || (hasSelection(input) && !prevInput && !this.composing) || cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) { return false } var text = input.value; // If nothing changed, bail. if (text == prevInput && !cm.somethingSelected()) { return false } // Work around nonsensical selection resetting in IE9/10, and // inexplicable appearance of private area unicode characters on // some key combos in Mac (#2689). if (ie && ie_version >= 9 && this.hasSelection === text || mac && /[\uf700-\uf7ff]/.test(text)) { cm.display.input.reset(); return false } if (cm.doc.sel == cm.display.selForContextMenu) { var first = text.charCodeAt(0); if (first == 0x200b && !prevInput) { prevInput = "\u200b"; } if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } } // Find the part of the input that is actually new var same = 0, l = Math.min(prevInput.length, text.length); while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; } runInOp(cm, function () { applyTextInput(cm, text.slice(same), prevInput.length - same, null, this$1.composing ? "*compose" : null); // Don't leave long text in the textarea, since it makes further polling slow if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = ""; } else { this$1.prevInput = text; } if (this$1.composing) { this$1.composing.range.clear(); this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), {className: "CodeMirror-composing"}); } }); return true }; TextareaInput.prototype.ensurePolled = function () { if (this.pollingFast && this.poll()) { this.pollingFast = false; } }; TextareaInput.prototype.onKeyPress = function () { if (ie && ie_version >= 9) { this.hasSelection = null; } this.fastPoll(); }; TextareaInput.prototype.onContextMenu = function (e) { var input = this, cm = input.cm, display = cm.display, te = input.textarea; if (input.contextMenuPending) { input.contextMenuPending(); } var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; if (!pos || presto) { return } // Opera is difficult. // Reset the current text selection only if the click is done outside of the selection // and 'resetSelectionOnContextMenu' option is true. var reset = cm.options.resetSelectionOnContextMenu; if (reset && cm.doc.sel.contains(pos) == -1) { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); } var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText; var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect(); input.wrapper.style.cssText = "position: static"; te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; var oldScrollY; if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712) display.input.focus(); if (webkit) { window.scrollTo(null, oldScrollY); } display.input.reset(); // Adds "Select all" to context menu in FF if (!cm.somethingSelected()) { te.value = input.prevInput = " "; } input.contextMenuPending = rehide; display.selForContextMenu = cm.doc.sel; clearTimeout(display.detectingSelectAll); // Select-all will be greyed out if there's nothing to select, so // this adds a zero-width space so that we can later check whether // it got selected. function prepareSelectAllHack() { if (te.selectionStart != null) { var selected = cm.somethingSelected(); var extval = "\u200b" + (selected ? te.value : ""); te.value = "\u21da"; // Used to catch context-menu undo te.value = extval; input.prevInput = selected ? "" : "\u200b"; te.selectionStart = 1; te.selectionEnd = extval.length; // Re-set this, in case some other handler touched the // selection in the meantime. display.selForContextMenu = cm.doc.sel; } } function rehide() { if (input.contextMenuPending != rehide) { return } input.contextMenuPending = false; input.wrapper.style.cssText = oldWrapperCSS; te.style.cssText = oldCSS; if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); } // Try to detect the user choosing select-all if (te.selectionStart != null) { if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); } var i = 0, poll = function () { if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && te.selectionEnd > 0 && input.prevInput == "\u200b") { operation(cm, selectAll)(cm); } else if (i++ < 10) { display.detectingSelectAll = setTimeout(poll, 500); } else { display.selForContextMenu = null; display.input.reset(); } }; display.detectingSelectAll = setTimeout(poll, 200); } } if (ie && ie_version >= 9) { prepareSelectAllHack(); } if (captureRightClick) { e_stop(e); var mouseup = function () { off(window, "mouseup", mouseup); setTimeout(rehide, 20); }; on(window, "mouseup", mouseup); } else { setTimeout(rehide, 50); } }; TextareaInput.prototype.readOnlyChanged = function (val) { if (!val) { this.reset(); } this.textarea.disabled = val == "nocursor"; }; TextareaInput.prototype.setUneditable = function () {}; TextareaInput.prototype.needsContentAttribute = false; function fromTextArea(textarea, options) { options = options ? copyObj(options) : {}; options.value = textarea.value; if (!options.tabindex && textarea.tabIndex) { options.tabindex = textarea.tabIndex; } if (!options.placeholder && textarea.placeholder) { options.placeholder = textarea.placeholder; } // Set autofocus to true if this textarea is focused, or if it has // autofocus and no other element is focused. if (options.autofocus == null) { var hasFocus = activeElt(); options.autofocus = hasFocus == textarea || textarea.getAttribute("autofocus") != null && hasFocus == document.body; } function save() {textarea.value = cm.getValue();} var realSubmit; if (textarea.form) { on(textarea.form, "submit", save); // Deplorable hack to make the submit method do the right thing. if (!options.leaveSubmitMethodAlone) { var form = textarea.form; realSubmit = form.submit; try { var wrappedSubmit = form.submit = function () { save(); form.submit = realSubmit; form.submit(); form.submit = wrappedSubmit; }; } catch(e) {} } } options.finishInit = function (cm) { cm.save = save; cm.getTextArea = function () { return textarea; }; cm.toTextArea = function () { cm.toTextArea = isNaN; // Prevent this from being ran twice save(); textarea.parentNode.removeChild(cm.getWrapperElement()); textarea.style.display = ""; if (textarea.form) { off(textarea.form, "submit", save); if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function") { textarea.form.submit = realSubmit; } } }; }; textarea.style.display = "none"; var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); }, options); return cm } function addLegacyProps(CodeMirror) { CodeMirror.off = off; CodeMirror.on = on; CodeMirror.wheelEventPixels = wheelEventPixels; CodeMirror.Doc = Doc; CodeMirror.splitLines = splitLinesAuto; CodeMirror.countColumn = countColumn; CodeMirror.findColumn = findColumn; CodeMirror.isWordChar = isWordCharBasic; CodeMirror.Pass = Pass; CodeMirror.signal = signal; CodeMirror.Line = Line; CodeMirror.changeEnd = changeEnd; CodeMirror.scrollbarModel = scrollbarModel; CodeMirror.Pos = Pos; CodeMirror.cmpPos = cmp; CodeMirror.modes = modes; CodeMirror.mimeModes = mimeModes; CodeMirror.resolveMode = resolveMode; CodeMirror.getMode = getMode; CodeMirror.modeExtensions = modeExtensions; CodeMirror.extendMode = extendMode; CodeMirror.copyState = copyState; CodeMirror.startState = startState; CodeMirror.innerMode = innerMode; CodeMirror.commands = commands; CodeMirror.keyMap = keyMap; CodeMirror.keyName = keyName; CodeMirror.isModifierKey = isModifierKey; CodeMirror.lookupKey = lookupKey; CodeMirror.normalizeKeyMap = normalizeKeyMap; CodeMirror.StringStream = StringStream; CodeMirror.SharedTextMarker = SharedTextMarker; CodeMirror.TextMarker = TextMarker; CodeMirror.LineWidget = LineWidget; CodeMirror.e_preventDefault = e_preventDefault; CodeMirror.e_stopPropagation = e_stopPropagation; CodeMirror.e_stop = e_stop; CodeMirror.addClass = addClass; CodeMirror.contains = contains; CodeMirror.rmClass = rmClass; CodeMirror.keyNames = keyNames; } // EDITOR CONSTRUCTOR defineOptions(CodeMirror); addEditorMethods(CodeMirror); // Set up methods on CodeMirror's prototype to redirect to the editor's document. var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) { CodeMirror.prototype[prop] = (function(method) { return function() {return method.apply(this.doc, arguments)} })(Doc.prototype[prop]); } } eventMixin(Doc); CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; // Extra arguments are stored as the mode's dependencies, which is // used by (legacy) mechanisms like loadmode.js to automatically // load a mode. (Preferred mechanism is the require/define calls.) CodeMirror.defineMode = function(name/*, mode, …*/) { if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; } defineMode.apply(this, arguments); }; CodeMirror.defineMIME = defineMIME; // Minimal default mode. CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); }); CodeMirror.defineMIME("text/plain", "null"); // EXTENSIONS CodeMirror.defineExtension = function (name, func) { CodeMirror.prototype[name] = func; }; CodeMirror.defineDocExtension = function (name, func) { Doc.prototype[name] = func; }; CodeMirror.fromTextArea = fromTextArea; addLegacyProps(CodeMirror); CodeMirror.version = "5.49.2"; return CodeMirror; }))); admin/vendors/codemirror.css000064400000021001146725417150012201 0ustar00/* BASICS */ .CodeMirror { /* Set height, width, borders, and global font properties here */ font-family: monospace; height: 300px; color: black; direction: ltr; } /* PADDING */ .CodeMirror-lines { padding: 4px 0; /* Vertical padding around content */ } .CodeMirror pre.CodeMirror-line, .CodeMirror pre.CodeMirror-line-like { padding: 0 4px; /* Horizontal padding of content */ } .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { background-color: white; /* The little square between H and V scrollbars */ } /* GUTTER */ .CodeMirror-gutters { border-right: 1px solid #ddd; background-color: #f7f7f7; white-space: nowrap; } .CodeMirror-linenumbers {} .CodeMirror-linenumber { padding: 0 3px 0 5px; min-width: 20px; text-align: right; color: #999; white-space: nowrap; } .CodeMirror-guttermarker { color: black; } .CodeMirror-guttermarker-subtle { color: #999; } /* CURSOR */ .CodeMirror-cursor { border-left: 1px solid black; border-right: none; width: 0; } /* Shown when moving in bi-directional text */ .CodeMirror div.CodeMirror-secondarycursor { border-left: 1px solid silver; } .cm-fat-cursor .CodeMirror-cursor { width: auto; border: 0 !important; background: #7e7; } .cm-fat-cursor div.CodeMirror-cursors { z-index: 1; } .cm-fat-cursor-mark { background-color: rgba(20, 255, 20, 0.5); -webkit-animation: blink 1.06s steps(1) infinite; -moz-animation: blink 1.06s steps(1) infinite; animation: blink 1.06s steps(1) infinite; } .cm-animate-fat-cursor { width: auto; border: 0; -webkit-animation: blink 1.06s steps(1) infinite; -moz-animation: blink 1.06s steps(1) infinite; animation: blink 1.06s steps(1) infinite; background-color: #7e7; } @-moz-keyframes blink { 0% {} 50% { background-color: transparent; } 100% {} } @-webkit-keyframes blink { 0% {} 50% { background-color: transparent; } 100% {} } @keyframes blink { 0% {} 50% { background-color: transparent; } 100% {} } /* Can style cursor different in overwrite (non-insert) mode */ .CodeMirror-overwrite .CodeMirror-cursor {} .cm-tab { display: inline-block; text-decoration: inherit; } .CodeMirror-rulers { position: absolute; left: 0; right: 0; top: -50px; bottom: 0; overflow: hidden; } .CodeMirror-ruler { border-left: 1px solid #ccc; top: 0; bottom: 0; position: absolute; } /* DEFAULT THEME */ .cm-s-default .cm-header {color: blue;} .cm-s-default .cm-quote {color: #090;} .cm-negative {color: #d44;} .cm-positive {color: #292;} .cm-header, .cm-strong {font-weight: bold;} .cm-em {font-style: italic;} .cm-link {text-decoration: underline;} .cm-strikethrough {text-decoration: line-through;} .cm-s-default .cm-keyword {color: #708;} .cm-s-default .cm-atom {color: #219;} .cm-s-default .cm-number {color: #164;} .cm-s-default .cm-def {color: #00f;} .cm-s-default .cm-variable, .cm-s-default .cm-punctuation, .cm-s-default .cm-property, .cm-s-default .cm-operator {} .cm-s-default .cm-variable-2 {color: #05a;} .cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;} .cm-s-default .cm-comment {color: #a50;} .cm-s-default .cm-string {color: #a11;} .cm-s-default .cm-string-2 {color: #f50;} .cm-s-default .cm-meta {color: #555;} .cm-s-default .cm-qualifier {color: #555;} .cm-s-default .cm-builtin {color: #30a;} .cm-s-default .cm-bracket {color: #997;} .cm-s-default .cm-tag {color: #170;} .cm-s-default .cm-attribute {color: #00c;} .cm-s-default .cm-hr {color: #999;} .cm-s-default .cm-link {color: #00c;} .cm-s-default .cm-error {color: #f00;} .cm-invalidchar {color: #f00;} .CodeMirror-composing { border-bottom: 2px solid; } /* Default styles for common addons */ div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;} div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } .CodeMirror-activeline-background {background: #e8f2ff;} /* STOP */ /* The rest of this file contains styles related to the mechanics of the editor. You probably shouldn't touch them. */ .CodeMirror { position: relative; overflow: hidden; background: white; } .CodeMirror-scroll { overflow: scroll !important; /* Things will break if this is overridden */ /* 30px is the magic margin used to hide the element's real scrollbars */ /* See overflow: hidden in .CodeMirror */ margin-bottom: -30px; margin-right: -30px; padding-bottom: 30px; height: 100%; outline: none; /* Prevent dragging from highlighting the element */ position: relative; } .CodeMirror-sizer { position: relative; border-right: 30px solid transparent; } /* The fake, visible scrollbars. Used to force redraw during scrolling before actual scrolling happens, thus preventing shaking and flickering artifacts. */ .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { position: absolute; z-index: 6; display: none; } .CodeMirror-vscrollbar { right: 0; top: 0; overflow-x: hidden; overflow-y: scroll; } .CodeMirror-hscrollbar { bottom: 0; left: 0; overflow-y: hidden; overflow-x: scroll; } .CodeMirror-scrollbar-filler { right: 0; bottom: 0; } .CodeMirror-gutter-filler { left: 0; bottom: 0; } .CodeMirror-gutters { position: absolute; left: 0; top: 0; min-height: 100%; z-index: 3; } .CodeMirror-gutter { white-space: normal; height: 100%; display: inline-block; vertical-align: top; margin-bottom: -30px; } .CodeMirror-gutter-wrapper { position: absolute; z-index: 4; background: none !important; border: none !important; } .CodeMirror-gutter-background { position: absolute; top: 0; bottom: 0; z-index: 4; } .CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; } .CodeMirror-gutter-wrapper ::selection { background-color: transparent } .CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } .CodeMirror-lines { cursor: text; min-height: 1px; /* prevents collapsing before first draw */ } .CodeMirror pre.CodeMirror-line, .CodeMirror pre.CodeMirror-line-like { /* Reset some styles that the rest of the page might have set */ -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; border-width: 0; background: transparent; font-family: inherit; font-size: inherit; margin: 0; white-space: pre; word-wrap: normal; line-height: inherit; color: inherit; z-index: 2; position: relative; overflow: visible; -webkit-tap-highlight-color: transparent; -webkit-font-variant-ligatures: contextual; font-variant-ligatures: contextual; } .CodeMirror-wrap pre.CodeMirror-line, .CodeMirror-wrap pre.CodeMirror-line-like { word-wrap: break-word; white-space: pre-wrap; word-break: normal; } .CodeMirror-linebackground { position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 0; } .CodeMirror-linewidget { position: relative; z-index: 2; padding: 0.1px; /* Force widget margins to stay inside of the container */ } .CodeMirror-widget {} .CodeMirror-rtl pre { direction: rtl; } .CodeMirror-code { outline: none; } /* Force content-box sizing for the elements where we expect it */ .CodeMirror-scroll, .CodeMirror-sizer, .CodeMirror-gutter, .CodeMirror-gutters, .CodeMirror-linenumber { -moz-box-sizing: content-box; box-sizing: content-box; } .CodeMirror-measure { position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden; } .CodeMirror-cursor { position: absolute; pointer-events: none; } .CodeMirror-measure pre { position: static; } div.CodeMirror-cursors { visibility: hidden; position: relative; z-index: 3; } div.CodeMirror-dragcursors { visibility: visible; } .CodeMirror-focused div.CodeMirror-cursors { visibility: visible; } .CodeMirror-selected { background: #d9d9d9; } .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } .CodeMirror-crosshair { cursor: crosshair; } .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } .cm-searching { background-color: #ffa; background-color: rgba(255, 255, 0, .4); } /* Used to force a border model for a node */ .cm-force-border { padding-right: .1px; } @media print { /* Hide the cursor when printing */ .CodeMirror div.CodeMirror-cursors { visibility: hidden; } } /* See issue #2901 */ .cm-tab-wrap-hack:after { content: ''; } /* Help users use markselection to safely style text background */ span.CodeMirror-selectedtext { background: none; } admin/js/cf7-customizer-admin.js000064400000140105146725417150012572 0ustar00(function( $ ) { 'use strict'; var editor; window.refreshTimer = false; $(document.body).on('click', '#cf7cstmzr_to_fw', function() { $(this).hide(); var currentUrl = $('#cf7cstmzr-current-url').val(); window.history.replaceState(null, null, currentUrl + '&fw=1'); $('#cf7cstmzr-main-container').addClass('fw'); $('#cf7cstmzr_exit_fw').show(); $('body').addClass('my-body-noscroll-class'); recalculateContainersSizes(); }); $(document.body).on('click', '#cf7cstmzr_exit_fw', function() { var currentUrl = $('#cf7cstmzr-current-url').val(); window.history.replaceState(null, null, currentUrl); $(this).hide(); $('#cf7cstmzr-main-container').removeClass('fw'); $('#cf7cstmzr_to_fw').show(); $('body').removeClass('my-body-noscroll-class'); recalculateContainersSizes(); }); $(document.body).on('click', '.cf7cstmzr-preview-control-icons .dashicons', function() { var control = $(this); var container = $('#form-preview-container_inner'); var styles = { width : '100%', height: '100%' }; if (control.hasClass('dashicons-tablet')) { styles = { width : 768, height: 1024, "max-height" : '100%' }; } else if (control.hasClass('dashicons-smartphone')) { styles = { width : 375, height: 667, "max-height" : '100%' }; } container.css(styles); }); $(document.body).on('click', '.cf7cstmzr-settings-item-header', function() { var header = $(this); var item = header.parents('.cf7cstmzr-settings-item'); var body = item.find('.cf7cstmzr-settings-item-body'); var items = $('.cf7cstmzr-settings-item'); if (item.hasClass('active')) { item.removeClass('active'); if (items.length > 0) { items.each(function () { $(this).removeClass('disabled'); }); } header.addClass('last-active'); } else { if (items.length > 0) { items.each(function () { $(this).removeClass('active').addClass('disabled'); $(this).find('.cf7cstmzr-settings-item-header').removeClass('last-active'); }); } item.removeClass('disabled').addClass('active'); } }); $(document.body).on('click', '.cf7cstmzr-settings-save', function() { var control = $('.cf7cstmzr-settings-save'); var formData = $("#cf7cstmzr-settings-form").serializeArray(); var titleInput = $('#cf7cstmzr-current-title'); var slugInput = $('#cf7cstmzr-current-slug'); var enableButton = $('#cf7cstmzr-enable-globally'); var enableForm = $('#cf7cstmzr-enable-for-form'); var data = { action: 'cf7cstmzr_save_form_customizer_settings', formData: formData }; if (titleInput.length) { data.styleSchemeTitle = titleInput.val(); } if (slugInput.length) { data.styleSchemeSlug = slugInput.val(); } $.ajax({ type: 'post', url: ajaxurl, data: data, success: function (response) { var decoded; try { decoded = $.parseJSON(response); } catch(err) { console.log(err); decoded = false; } if (decoded) { if (decoded.success) { control.attr('disabled', true).removeClass('button-success'); enableButton.attr('disabled', false).addClass('button-success'); enableForm.attr('disabled', false).addClass('button-success'); // alert(decoded.message); alert_sticky(decoded.message, 'cf7cstmzr-success'); refreshPreview(); if (decoded.url) { setTimeout(function() { window.location.replace(decoded.url); }, 2000); } } else { // var fragments = response.message.fragments; // updateFragments(fragments); alert_sticky(decoded.message, 'cf7cstmzr-error'); // alert(decoded.message); } } else { alert_sticky('Something went wrong', 'cf7cstmzr-error'); // alert('Something went wrong'); } } }); }); function alert_sticky(message, type) { var messageContainer = $('#cf7cstmzr-sticky-message'); messageContainer.text(message).removeClass('cf7cstmzr-success').removeClass('cf7cstmzr-success').addClass(type).addClass('active'); setTimeout(function () { messageContainer.removeClass('active'); }, 3000); } $(document.body).on('click', '.cf7cstmzr-settings-reset', function() { resetStyleSettings(); }); $(document.body).on('click', '.cf7cstmzr-settings-default', function() { var control = $(this); var defaultSettings = control.data('default-settings'); resetStyleSettings(); console.log(defaultSettings); // Form Default Styling $('#cf7cstmzr_form_padding').next('.dashicons').click(); $('#cf7cstmzr_form_padding-top').val(defaultSettings.form.padding.top); $('#cf7cstmzr_form_padding-right').val(defaultSettings.form.padding.right); $('#cf7cstmzr_form_padding-bottom').val(defaultSettings.form.padding.bottom); $('#cf7cstmzr_form_padding-left').val(defaultSettings.form.padding.left); $('#cf7cstmzr_form_margin').next('.dashicons').click(); $('#cf7cstmzr_form_margin-top').val(defaultSettings.form.margin.top); $('#cf7cstmzr_form_margin-right').val(defaultSettings.form.margin.right); $('#cf7cstmzr_form_margin-bottom').val(defaultSettings.form.margin.bottom); $('#cf7cstmzr_form_margin-left').val(defaultSettings.form.margin.left); $('#cf7cstmzr_form_border_color').iris('color', defaultSettings.form.border.color); $('#cf7cstmzr_form_border_radius').val(defaultSettings.form.border.radius); $('#cf7cstmzr_form_border_width').next('.dashicons').click(); $('#cf7cstmzr_form_border_width-top').val(defaultSettings.form.border.width.top); $('#cf7cstmzr_form_border_width-right').val(defaultSettings.form.border.width.right); $('#cf7cstmzr_form_border_width-bottom').val(defaultSettings.form.border.width.bottom); $('#cf7cstmzr_form_border_width-left').val(defaultSettings.form.border.width.left); // Input $('#cf7cstmzr_input_bg_color').iris('color', defaultSettings.input.bg.color); $('#cf7cstmzr_input_border_color').iris('color', defaultSettings.input.border.color); $('#cf7cstmzr_input_border_radius').val(defaultSettings.input.border.radius); $('#cf7cstmzr_input_border_width').next('.dashicons').click(); $('#cf7cstmzr_input_border_width-top').val(defaultSettings.input.border.width.top); $('#cf7cstmzr_input_border_width-right').val(defaultSettings.input.border.width.right); $('#cf7cstmzr_input_border_width-bottom').val(defaultSettings.input.border.width.bottom); $('#cf7cstmzr_input_border_width-left').val(defaultSettings.input.border.width.left); $('#cf7cstmzr_input_padding').next('.dashicons').click(); $('#cf7cstmzr_input_padding-top').val(defaultSettings.input.padding.top); $('#cf7cstmzr_input_padding-right').val(defaultSettings.input.padding.right); $('#cf7cstmzr_input_padding-bottom').val(defaultSettings.input.padding.bottom); $('#cf7cstmzr_input_padding-left').val(defaultSettings.input.padding.left); $('#cf7cstmzr_input_text_line-height').val(defaultSettings.input.text["line-height"]); if ('yes' === defaultSettings.input["full-width"]) { $('#cf7cstmzr_input_width_yes').prop('checked', true); } else { $('#cf7cstmzr_input_width_no').prop('checked', true); } // Button Default Styling $('#cf7cstmzr_button_bg_color').iris('color', defaultSettings.button.bg.color); $('#cf7cstmzr_button_bg_color-hover').iris('color', defaultSettings.button.bg["color-hover"]); $('#cf7cstmzr_button_border_color').iris('color', defaultSettings.button.border.color); $('#cf7cstmzr_button_border_color-hover').iris('color', defaultSettings.button.border["color-hover"]); $('#cf7cstmzr_button_border_radius').val(defaultSettings.button.border.radius); $('#cf7cstmzr_button_border_width').val(defaultSettings.button.border.width); $('#cf7cstmzr_button_padding').val(defaultSettings.button.padding); $('#cf7cstmzr_button_shadow_vertical-length').val(defaultSettings.button.shadow["vertical-length"]); $('#cf7cstmzr_button_shadow_blur-radius').val(defaultSettings.button.shadow["blur-radius"]); $('#cf7cstmzr_button_shadow_spread-radius').val(defaultSettings.button.shadow["spread-radius"]); $('#cf7cstmzr_button_shadow_opacity').val(defaultSettings.button.shadow["opacity"]); $('#cf7cstmzr_button_shadow_position').val(defaultSettings.button.shadow["position"]); $('#cf7cstmzr_button_shadow_color').iris('color', defaultSettings.button.shadow.color); $('#cf7cstmzr_button_text_color').iris('color', defaultSettings.button.text.color); $('#cf7cstmzr_button_text_color-hover').iris('color', defaultSettings.button.text["color-hover"]); $('#cf7cstmzr_button_text_line-height').val(defaultSettings.button.text["line-height"]); refreshPreview(); }); $(document.body).on('change', '#cf7cstmzr-preview-unstyle', function() { refreshPreview(); }); $(document.body).on('change', '#cf7cstmzr-preview-mode', function() { var selected = $(this).val(); if ('split-mode' === selected) { $('#split-mode-settings').css('display', 'inline-block'); } else { $('#split-mode-settings').css('display', 'none'); } refreshPreview(); }); $(document.body).on('change', '#cf7cstmzr-load-body-tag', function() { var control = $(this); var loadBody = false; if (control.is(':checked')) { loadBody = true; } var data = { action: 'cf7cstmzr_load_body_tag', loadBody: loadBody, } ajaxRequest(data); }); $(document.body).on('click', '#cf7cstmzr-enable-globally', function() { var control = $(this); var scheme = control.data('scheme'); $.ajax({ type: 'post', url: ajaxurl, data: { action: 'cf7cstmzr_enable_globally', scheme: scheme }, success: function (response) { var decoded; try { decoded = $.parseJSON(response); } catch(err) { console.log(err); decoded = false; } if (decoded) { if (decoded.success) { // var fragments = response.message.fragments; // updateFragments(fragments); alert_sticky(decoded.message, 'cf7cstmzr-success'); // alert(decoded.message); setTimeout(function() { window.location.reload(); }, 2000); } else { alert_sticky(decoded.message, 'cf7cstmzr-error'); // alert(decoded.message); } } else { alert_sticky('Something went wrong', 'cf7cstmzr-error'); //alert('Something went wrong'); } } }); }); $(document.body).on('click', '#cf7cstmzr-disable-globally', function() { var control = $(this); $.ajax({ type: 'post', url: ajaxurl, data: { action: 'cf7cstmzr_disable_globally' }, success: function (response) { var decoded; try { decoded = $.parseJSON(response); } catch(err) { console.log(err); decoded = false; } if (decoded) { if (decoded.success) { // var fragments = response.message.fragments; // updateFragments(fragments); alert_sticky(decoded.message, 'cf7cstmzr-success'); // alert(decoded.message); setTimeout(function() { window.location.reload(); }, 2000); } else { alert_sticky(decoded.message, 'cf7cstmzr-error'); //alert(decoded.message); } } else { alert_sticky('Something went wrong', 'cf7cstmzr-error'); // alert('Something went wrong'); } } }); }); $(document.body).on('click', '#cf7cstmzr-enable-for-form', function() { var control = $(this); var scheme = control.data('scheme'); var form = $('#cf7cstmzr_select_form').val(); var mode = $('#cf7cstmzr_select_form').data('mode'); $.ajax({ type: 'post', url: ajaxurl, data: { action: 'cf7cstmzr_enable_for_form', scheme: scheme, form: form, }, success: function (response) { var decoded; try { decoded = $.parseJSON(response); } catch(err) { console.log(err); decoded = false; } if (decoded) { if (decoded.success) { if ('free' === mode) { $('#cf7cstmzr_select_form option').each(function() { $(this).data('scheme', ''); }); } $('#cf7cstmzr_select_form option:selected').data('scheme', scheme); var single_form_description = $('#cf7cstmzr-select-single-form-description'); if (single_form_description.length) { // console.log($('#cf7cstmzr_select_form option:selected').text()); // console.log($('#cf7cstmzr_selected_style_scheme').text()); single_form_description.data('form', form); single_form_description.data('form-title', $.trim($('#cf7cstmzr_select_form option:selected').text())); single_form_description.data('scheme', scheme); single_form_description.data('scheme-title', $.trim($('#cf7cstmzr_selected_style_scheme').text())); } show_select_form_message_button(); alert_sticky(decoded.message, 'cf7cstmzr-success'); // alert(decoded.message); } else { alert_sticky(decoded.message, 'cf7cstmzr-error'); // alert(decoded.message); } } else { alert_sticky('Something went wrong', 'cf7cstmzr-error'); // alert('Something went wrong'); } } }); }); $(document.body).on('click', '#cf7cstmzr-disable-for-form', function() { var form = $('#cf7cstmzr_select_form').val(); $.ajax({ type: 'post', url: ajaxurl, data: { action: 'cf7cstmzr_disable_for_form', form: form, }, success: function (response) { var decoded; try { decoded = $.parseJSON(response); } catch(err) { console.log(err); decoded = false; } if (decoded) { if (decoded.success) { $('#cf7cstmzr_select_form option:selected').data('scheme', ''); var single_form_description = $('#cf7cstmzr-select-single-form-description'); if (single_form_description.length) { single_form_description.data('form', ''); single_form_description.data('form-title', ''); single_form_description.data('scheme', ''); single_form_description.data('scheme-title', ''); } show_select_form_message_button(); alert_sticky(decoded.message, 'cf7cstmzr-success'); // alert(decoded.message); } else { alert_sticky(decoded.message, 'cf7cstmzr-error'); // alert(decoded.message); } } else { alert_sticky('Something went wrong', 'cf7cstmzr-error'); // alert('Something went wrong'); } } }); }); $(document.body).on('click', '#cf7cstmzr-settings-save-as', function() { var control = $(this); var container = $('#cf7cstmzr-settings-create-new'); var saveBtn = $('#cf7cstmzr-settings-save'); var defaultBtn = $('#cf7cstmzr-settings-default'); var deleteBtn = $('#cf7cstmzr-settings-delete'); var resetBtn = $('#cf7cstmzr-settings-reset'); control.hide(); saveBtn.hide(); defaultBtn.hide(); deleteBtn.hide(); resetBtn.hide(); container.show(); recalculateContainersSizes(); }); $(document.body).on('click', '#cf7cstmzr-settings-create', function() { var control = $('.cf7cstmzr-settings-save'); var formData = $("#cf7cstmzr-settings-form").serializeArray(); var title = $('#cf7cstmzr_settings_title_new').val(); var copySettingsControl = $('#cf7cstmzr_settings_copy_new'); var copySettings = false; var isFw = $('#cf7cstmzr-main-container').hasClass('fw'); if (copySettingsControl.is(':checked')) { copySettings = true; } $.ajax({ type: 'post', url: ajaxurl, data: { title: title, action: 'cf7cstmzr_new_form_customizer_settings', formData: formData, copySettings: copySettings, isFw: isFw }, success: function (response) { var decoded; try { decoded = $.parseJSON(response); } catch(err) { console.log(err); decoded = false; } if (decoded) { if (decoded.success) { // var fragments = response.message.fragments; // updateFragments(fragments); alert_sticky(decoded.message, 'cf7cstmzr-success'); // alert(decoded.message); setTimeout(function() { window.location.replace(decoded.url); }, 2000); } else { alert_sticky(decoded.message, 'cf7cstmzr-error'); // alert(decoded.message); } } else { alert_sticky('Something went wrong', 'cf7cstmzr-error'); // alert('Something went wrong'); } } }); }); $(document.body).on('click', '#cf7cstmzr-settings-delete', function() { var scheme = $('#cf7cstmzr_select_style_scheme').val(); var isFw = $('#cf7cstmzr-main-container').hasClass('fw'); var data = { action: 'cf7cstmzr_delete_form_customizer_settings', scheme: scheme, isFw: isFw }; ajaxRequest(data); }); $(document.body).on('click', '.cf7cstmzr-close-welcome', function() { var data = { action: 'cf7cstmzr_close_welcome' }; ajaxRequest(data); }); $(document.body).on('click', '#cf7cstmzr-settings-save-as-cancel', function() { var control = $(this); var saveAsBtn = $('#cf7cstmzr-settings-save-as'); var container = $('#cf7cstmzr-settings-create-new'); var title = container.find('#cf7cstmzr_settings_title_new'); title.val(''); container.hide(); saveAsBtn.show(); var saveBtn = $('#cf7cstmzr-settings-save'); var defaultBtn = $('#cf7cstmzr-settings-default'); var deleteBtn = $('#cf7cstmzr-settings-delete'); var resetBtn = $('#cf7cstmzr-settings-reset'); saveBtn.show(); defaultBtn.show(); deleteBtn.show(); resetBtn.show(); recalculateContainersSizes(); }); $(document.body).on('click', '.cf7cstmzr-refresh', function() { var formData = $("#cf7cstmzr-settings-form").serializeArray(); var previewButton = $('.cf7cstmzr-refresh'); previewButton.each(function() { $(this).attr('disabled', true); }); $.ajax({ type: 'post', url: ajaxurl, data: { action: 'cf7cstmzr_preview_form_customizer_settings', formData: formData }, success: function (response) { var decoded; try { decoded = $.parseJSON(response); } catch(err) { console.log(err); decoded = false; } if (decoded) { if (decoded.success) { var frame_top = $('#formPreviewFrame').contents().scrollTop(); var formId = $('#cf7cstmzr_select_form').val(); var url = $('#cf7cstmzr-url').val(); var iframe = $( ' Open KB in a new tab/window Idea: Have the KB in one half of the screen and the cf7 form in the other half.
    admin/partials/tutorials/welcome-en.php000064400000001270146725417150014261 0ustar00
    Open KB in a new tab/window Idea: Have the KB in one half of the screen and the cf7 form in the other half. Open KB in a new tab/window Idea: Have the KB in one half of the screen and the cf7 form in the other half.
    admin/partials/tutorials/welcome-de.php000064400000001501146725417150014244 0ustar00
    Hanbuch in einem neuen Tab/Fenster öffnen Idee: Das Handbuch in einer Hälfte des Bildschirms und das cf7-Formular in der anderen Hälfte anzeigen zu lassen. Hanbuch in einem neuen Tab/Fenster öffnen Idee: Das Handbuch in einer Hälfte des Bildschirms und das cf7-Formular in der anderen Hälfte anzeigen zu lassen.
    admin/partials/tutorials/tutorials-de.php000064400000001035146725417150014641 0ustar00
    Handbuch in einem neuen Tab/Fenster öffnen Idee: Das Handbuch in einer Hälfte des Bildschirms und das cf7-Formular in der anderen Hälfte anzeigen zu lassen.
    admin/partials/cf7-customizer-admin-tab-form-customize.php000064400000356335146725417150017713 0ustar00 -1, 'orderby' => 'title', 'order' => 'ASC', 'post_type' => 'wpcf7_contact_form', 'post_status' => 'publish', 'suppress_filters' => false, // подавление работы фильтров Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ SQL запроÑа ); $cf7_forms = get_posts($args); $cf7_scheme_args = array ( 'numberposts' => -1, 'orderby' => 'title', 'order' => 'ASC', 'post_type' => 'wpcf7_contact_form', 'post_status' => 'publish', 'suppress_filters' => false, // подавление работы фильтров Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ SQL запроÑа 'meta_query' => array( 'relation' => 'EXISTS', array( 'key' => 'cf7cstmzr_style_scheme', ) ) ); $forms_group_by_style_scheme = Cf7_Style_Scheme::get_forms_group_by_style_scheme(); $current_url_state = get_site_url() . '/wp-admin/admin.php?page=cf7cstmzr_page'; if (!empty($_GET['tab'])) { $current_url_state .= '&tab=' . sanitize_text_field($_GET['tab']); } if (!empty($_GET['style_scheme'])) { $current_url_state .= '&style_scheme=' . sanitize_text_field($_GET['style_scheme']); } $permalink_structure = get_option('permalink_structure'); ?>
    >

    > <body> tag', 'cf7-styler') ?>

    <body> tag', 'cf7-styler') ?>


    > > > > > > > > >
    >
    >
    >
    >

    >
    >
    >
    >
    >
    >

    style="display: inline-block;"> ID); } else { echo __('Contact form 7 list', 'cf7-styler'); } // if ($show_description) { if (true) { ?>

    > > %s, you can style it with current Style scheme.', 'cf7-styler' ), $first_form_scheme_title ); ?> > %s globally, you can style it with current Style scheme.', 'cf7-styler' ), $enabled_globally_title ); ?> >

    >
    $styled_form_style) { $styled_form = get_post($styled_id); if (!empty($styled_form)) { $styled_form_id = $styled_id; $styled_form_title = $styled_form->post_title; $styled_form_style_title = $style_schemes[$styled_form_style]['title']; $styled_form_style_slug = $styled_form_style; } } } ?>
    > %s form is styled with %s. As in free version you can style only one form at a time and if you activate style for current form, style will be removed from other form.', 'cf7-styler' ), $styled_form_title, $styled_form_style_title ); ?> >

    first Contact Form 7', 'cf7-styler') ?>

    ID; if (!empty($cache_form)) { $cf7_form_id = $cache_form; } if (false) { ?>

    first Contact Form 7', 'cf7-styler') ?>

    admin/partials/cf7-customizer-admin-tutorial.php000064400000002624146725417150016014 0ustar00

    admin/partials/cf7-customizer-admin-tab-required-plugin.php000064400000004330146725417150020025 0ustar00

    $data) { $plugin_installed = Cf7_Required_Plugin::is_plugin_installed($data['slug']); ?>