(Grav GitSync) Automatic Commit from smokephil
This commit is contained in:
commit
4267db646d
2765 changed files with 462171 additions and 0 deletions
167
plugins/git-sync/.eslintrc
Normal file
167
plugins/git-sync/.eslintrc
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
|
||||
"parser": "babel-eslint",
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 7,
|
||||
"sourceType": "module"
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"accessor-pairs": 2,
|
||||
"array-bracket-spacing": 0,
|
||||
"block-scoped-var": 0,
|
||||
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||
"camelcase": 0,
|
||||
"comma-dangle": [2, "never"],
|
||||
"comma-spacing": [2, { "before": false, "after": true }],
|
||||
"comma-style": [2, "last"],
|
||||
"complexity": 0,
|
||||
"computed-property-spacing": 0,
|
||||
"consistent-return": 0,
|
||||
"consistent-this": 0,
|
||||
"constructor-super": 2,
|
||||
"curly": [2, "multi-line"],
|
||||
"default-case": 0,
|
||||
"dot-location": [2, "property"],
|
||||
"dot-notation": 0,
|
||||
"eol-last": 2,
|
||||
"eqeqeq": [2, "allow-null"],
|
||||
"func-names": 0,
|
||||
"func-style": 0,
|
||||
"generator-star-spacing": [2, { "before": true, "after": true }],
|
||||
"guard-for-in": 0,
|
||||
"handle-callback-err": [2, "^(err|error)$" ],
|
||||
"indent": [2, 4, { "SwitchCase": 1 }],
|
||||
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
|
||||
"linebreak-style": 0,
|
||||
"lines-around-comment": 0,
|
||||
"max-nested-callbacks": 0,
|
||||
"new-cap": [2, { "newIsCap": true, "capIsNew": false }],
|
||||
"new-parens": 2,
|
||||
"newline-after-var": 0,
|
||||
"no-alert": 0,
|
||||
"no-array-constructor": 2,
|
||||
"no-caller": 2,
|
||||
"no-catch-shadow": 0,
|
||||
"no-cond-assign": 2,
|
||||
"no-console": 0,
|
||||
"no-constant-condition": 0,
|
||||
"no-continue": 0,
|
||||
"no-control-regex": 2,
|
||||
"no-debugger": 2,
|
||||
"no-delete-var": 2,
|
||||
"no-div-regex": 0,
|
||||
"no-dupe-args": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
"no-else-return": 0,
|
||||
"no-empty": 0,
|
||||
"no-empty-character-class": 2,
|
||||
"no-eq-null": 0,
|
||||
"no-eval": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-bind": 2,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-parens": 0,
|
||||
"no-extra-semi": 0,
|
||||
"no-fallthrough": 2,
|
||||
"no-floating-decimal": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-implied-eval": 2,
|
||||
"no-inline-comments": 0,
|
||||
"no-inner-declarations": [2, "functions"],
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-iterator": 2,
|
||||
"no-label-var": 2,
|
||||
"no-labels": 2,
|
||||
"no-lone-blocks": 2,
|
||||
"no-lonely-if": 0,
|
||||
"no-loop-func": 0,
|
||||
"no-mixed-requires": 0,
|
||||
"no-mixed-spaces-and-tabs": 2,
|
||||
"no-multi-spaces": 2,
|
||||
"no-multi-str": 2,
|
||||
"no-multiple-empty-lines": [2, { "max": 1 }],
|
||||
"no-native-reassign": 2,
|
||||
"no-negated-in-lhs": 2,
|
||||
"no-nested-ternary": 0,
|
||||
"no-new": 2,
|
||||
"no-new-func": 0,
|
||||
"no-new-object": 2,
|
||||
"no-new-require": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-octal": 2,
|
||||
"no-octal-escape": 2,
|
||||
"no-param-reassign": 0,
|
||||
"no-path-concat": 0,
|
||||
"no-process-env": 0,
|
||||
"no-process-exit": 0,
|
||||
"no-proto": 0,
|
||||
"no-redeclare": 2,
|
||||
"no-regex-spaces": 2,
|
||||
"no-restricted-modules": 0,
|
||||
"no-return-assign": 2,
|
||||
"no-script-url": 0,
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
"no-shadow": 0,
|
||||
"no-shadow-restricted-names": 2,
|
||||
"no-spaced-func": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-sync": 0,
|
||||
"no-ternary": 0,
|
||||
"no-this-before-super": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-trailing-spaces": 2,
|
||||
"no-undef": 2,
|
||||
"no-undef-init": 2,
|
||||
"no-undefined": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-unexpected-multiline": 2,
|
||||
"no-unneeded-ternary": 2,
|
||||
"no-unreachable": 2,
|
||||
"no-unused-expressions": 0,
|
||||
"no-unused-vars": [2, { "vars": "all", "args": "none" }],
|
||||
"no-use-before-define": 0,
|
||||
"no-var": 0,
|
||||
"no-void": 0,
|
||||
"no-warning-comments": 0,
|
||||
"no-with": 2,
|
||||
"object-curly-spacing": 0,
|
||||
"object-shorthand": 0,
|
||||
"one-var": [2, { "initialized": "never" }],
|
||||
"operator-assignment": 0,
|
||||
"operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }],
|
||||
"padded-blocks": 0,
|
||||
"prefer-const": 0,
|
||||
"quote-props": 0,
|
||||
"quotes": [2, "single", "avoid-escape"],
|
||||
"radix": 2,
|
||||
"semi": [2, "always"],
|
||||
"semi-spacing": 0,
|
||||
"sort-vars": 0,
|
||||
"keyword-spacing": [2, {"after": true, "overrides": {"throw": { "after": true}, "return": { "before": true }}}],
|
||||
"space-before-blocks": [2, "always"],
|
||||
"space-before-function-paren": [2, "never"],
|
||||
"space-in-parens": [2, "never"],
|
||||
"space-infix-ops": 2,
|
||||
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||
"spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }],
|
||||
"strict": 0,
|
||||
"use-isnan": 2,
|
||||
"valid-jsdoc": 0,
|
||||
"valid-typeof": 2,
|
||||
"vars-on-top": 0,
|
||||
"wrap-iife": [2, "any"],
|
||||
"wrap-regex": 0,
|
||||
"yoda": [2, "never"]
|
||||
}
|
||||
}
|
||||
4
plugins/git-sync/.gitignore
vendored
Normal file
4
plugins/git-sync/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
node_modules
|
||||
*.js.map
|
||||
*.css.map
|
||||
/.idea
|
||||
200
plugins/git-sync/CHANGELOG.md
Normal file
200
plugins/git-sync/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
# v2.3.2
|
||||
## 06/03/2021
|
||||
|
||||
1. [](#bugfix)
|
||||
* Better validation for Git Repository value on both Wizard and Backend.
|
||||
* Prevent malicious commands from being executed in Wizard when "Verifying Authentication, Connection and Branch".
|
||||
|
||||
# v2.3.1
|
||||
## 04/30/2021
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed regression where `testRepository` would erroneously pass with invalid credentials [#200](https://github.com/trilbymedia/grav-plugin-git-sync/issues/200)
|
||||
* Fixed Exception thrown with `bin/plugin git-sync status` command, preventing `sync` [#200](https://github.com/trilbymedia/grav-plugin-git-sync/issues/200)
|
||||
|
||||
# v2.3.0
|
||||
## 04/27/2021
|
||||
|
||||
1. [](#new)
|
||||
* Added new Advanced Git Ignore field where it is possible to specify custom git ignore entries to play along with GitSync [#197](https://github.com/trilbymedia/grav-plugin-git-sync/issues/197) [#117](https://github.com/trilbymedia/grav-plugin-git-sync/issues/117)
|
||||
* Support `ssh://` protocol and SSH Key authentication ([read more](https://github.com/trilbymedia/grav-plugin-git-sync#ssh--enterprise)) [#110](https://github.com/trilbymedia/grav-plugin-git-sync/issues/110)
|
||||
1. [](#improved)
|
||||
* Updated PHP Encryption dependency
|
||||
1. [](#bugfix)
|
||||
* Fixed issue with Flex Objects, preventing GitSync's settings to get refreshed `onAdminSave` when "Sync on Page Save" disabled
|
||||
* Return raw URL for repositories setup with `ssh://` protocol, instead of injecting the password like `git://` and `http://` protocols do [#104](https://github.com/trilbymedia/grav-plugin-git-sync/issues/104)
|
||||
|
||||
# v2.2.0
|
||||
## 04/17/2021
|
||||
|
||||
1. [](#improved)
|
||||
* Better support for branches other than `master`. This includes the transition to `main` from GitHub and the groundwork to support other big providers making the change as announced soon. GitSync is now capable of preset the branch based on the provider selected. You are now also able to specify any custom branch and when testing the repository connection it will also ensure the branch exists and provide feedback if not.
|
||||
1. [](#bugfix)
|
||||
* Changing remote branch is now going to properly reference it instead of remaining stuck to `master` [#192](https://github.com/trilbymedia/grav-plugin-git-sync/issues/192), [#183](https://github.com/trilbymedia/grav-plugin-git-sync/issues/183)
|
||||
* Fixed issue where the Folders to synchronize from the Wizard wouldn't get properly saved [#178](https://github.com/trilbymedia/grav-plugin-git-sync/issues/178)
|
||||
|
||||
# v2.1.1
|
||||
## 07/17/2020
|
||||
|
||||
1. [](#new)
|
||||
* Added `No User` option to allow disabling the username requirement. This is useful for when you have a token and the user is not required. (#166, thanks GwynethLlewelyn)
|
||||
* Added `passwd` command for programmatically change user/password (use: `bin/plugin git-sync passwd`) (#146)
|
||||
* Fixed regression wrongly returning the installed Git version and causing all sort of problems, including unrelated histories not kicking off (#61, #168, #171, #173)
|
||||
* Fixed potential issue where the new feature `no_user` my throw an error
|
||||
* Fixed issue with autoload
|
||||
1. [](#bugfix)
|
||||
* Fixed classes not being loaded in `cli` commands due to Grav changes (#167)
|
||||
* Updated dependencies / recompiled JS for production
|
||||
1. [](#improved)
|
||||
* Bumped modules versions
|
||||
|
||||
# v2.1.0
|
||||
## 03/13/2020
|
||||
|
||||
1. [](#new)
|
||||
* Requires Grav v1.6.0
|
||||
* Pass phpstan level 2 tests
|
||||
1. [](#improved)
|
||||
* Code cleanup
|
||||
* Added support for Gitea / Gogs webhook secret (#149, thanks @Aisbergg)
|
||||
|
||||
# v2.0.5
|
||||
## 05/06/2019
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed validation error with commalist in Folders to Sync field (#141)
|
||||
|
||||
# v2.0.4
|
||||
## 04/22/2019
|
||||
|
||||
1. [](#improved)
|
||||
* urlencode username to allow for special characters (#139)
|
||||
|
||||
# v2.0.3
|
||||
## 03/07/2019
|
||||
|
||||
1. [](#bugifx)
|
||||
* Properly fallback to config message if not there yet (#134)
|
||||
|
||||
# v2.0.2
|
||||
## 02/21/2019
|
||||
|
||||
1. [](#improved)
|
||||
* Fixed InitCommand spelling (#132, thanks @alex-mohemian)
|
||||
1. [](#bugfix)
|
||||
* Fixed PHP 5.6 incompatibility introduced by latest release.
|
||||
|
||||
# v2.0.1
|
||||
## 02/19/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added new `init` CLI command (`bin/plugin git-sync init`) (#128, thanks @LeonRyan and @alex-mohemian)
|
||||
1. [](#improved)
|
||||
* Allow setting a personalised commit message (#123, thanks @kyed)
|
||||
* Added better directions for Azure + IIS users for the Git Binary
|
||||
1. [](#bugfix)
|
||||
* Fixed `LC_ALL` to use `C` instead of en_US.UTF-8`, to be more flexible (#124, #125, thanks @lambopedia)
|
||||
|
||||
# v2.0.0
|
||||
## 10/15/2018
|
||||
|
||||
1. [](#new)
|
||||
* Added support for new awesome Grav 1.6 Scheduler
|
||||
* Added logic to display custom nested folders in wizard
|
||||
* Other than `pages`, it is now possible to enable `config`, `data`, `plugins` and `themes` for synchronization. You can also add any custom folder you have in your `user` (#4, #21, #34, #58, #63, #83)
|
||||
* Allow users with `admin.pages` permissions to synchronize through quick tray (#79, thanks @apfrod)
|
||||
* When using Grav as committer, the user email will be now used for the commit (#81, thanks @apfrod)
|
||||
* Added support for Webhook Secret (Bitbucket does not yet support them) (#72, #73, thanks @pathmissing)
|
||||
* Added options to turn automatic synchronization on/off with page saves, delete and media changes (#105, thanks @AmauryCarrade)
|
||||
1. [](#improved)
|
||||
* Fixed alignment of the git icon in the Wizard (#115)
|
||||
* Prevent Wizard modal to get canceled when clicking on the overlay background (#115)
|
||||
* Quick tray icon is now smarter. If GitSync has not been initialized yet, it will take you straight to wizard, otherwise it would perform a synchronization (#115)
|
||||
* Rearranged blueprint order (thanks @paulhibbitts)
|
||||
* GitLab: Updated wizard instructions to be inline with the new GitLab UI (#90)
|
||||
* Tweaked alignment of links in the wizard (#57)
|
||||
* Properly support local branches that aren't `master` (#56)
|
||||
* Allow to specify custom local_repository (default, `USER_DIR`) (#95, thanks @Hydraner, also #54, #33, #25)
|
||||
* Webhook URL is now more robust and secure, by default it is generated with a random value
|
||||
* Git icon from Admin has been replaced to use the `git` text icon instead of the logo
|
||||
* Prevent next step if Step 1 and Step 2 are not filled in (#92)
|
||||
* Added notice in Step 2 explaning what GitSync expect from the repository structure (#92)
|
||||
1. [](#bugfix)
|
||||
* Fixed issue where on first initialization the checkout process would error out
|
||||
* Fixed issue with Pages save.
|
||||
* Fixed JS error in plugins list
|
||||
* Fixed nested folders not synchronizing
|
||||
* Fixed issue where Wizard wouldn't work in case the `admin` path was modified (#27, #94, #77, thanks @pathmissing)
|
||||
* Fixed webhook generated URL when multi-lang active (#71)
|
||||
* Resolved issue with untracked/uncommited files at the root of the `sync` folder. (#101, thanks @ScottHamper)
|
||||
|
||||
# v1.0.4
|
||||
## 08/16/2017
|
||||
|
||||
1. [](#new)
|
||||
* CLI: Added `status` command to check config and git (#52, thanks @karfau)
|
||||
* Allow local branches to be named differently than the remote branches (#48, thanks @denniswebb)
|
||||
* Added support for new Admin Navigation Tray
|
||||
1. [](#bugfix)
|
||||
* Fixed minimum Git required version to support `--all` (#32,#49, thanks @redrohX)
|
||||
|
||||
# v1.0.3
|
||||
## 02/21/2017
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed issue with new 'author' option that could trigger errors when settings were not saved. (#23)
|
||||
* Fixed the 'More Details' button triggering the Modal to close instead of just expanding the details
|
||||
|
||||
# v1.0.2
|
||||
## 02/18/2017
|
||||
|
||||
1. [](#new)
|
||||
* It is now possible to change the committer name. You can choose between Git User, GitSync Committer Name, Grav User Name, Grav User Fullname (#14).
|
||||
2. [](#improved)
|
||||
* Added more documentation and description about the support of 2FA and Access Tokens (#16, #19, thanks @OleVik)
|
||||
* Added 4th Generic Git choice in the wizard for self-hosted and custom git services (Gogs/Gitea) (#7 - #22 - thanks @erlepereira)
|
||||
1. [](#bugfix)
|
||||
* Fixed issue preventing the custom Git Binary Path from getting used (#15)
|
||||
* Fixed issue with Webhook auto-generated URL where it would display double slashes in case of root domain (#15)
|
||||
* Fixed issue with the modal not properly restoring the tutorial steps of the active selected service
|
||||
|
||||
# v1.0.1
|
||||
## 01/29/2017
|
||||
|
||||
1. [](#bugfix)
|
||||
* Changed default GitSync email for commits
|
||||
|
||||
# v1.0.0
|
||||
## 01/25/2017
|
||||
|
||||
1. [](#new)
|
||||
* Released plugin to stable GPM channel
|
||||
|
||||
# v1.0.0-rc.3
|
||||
## 01/19/2017
|
||||
|
||||
1. [](#new)
|
||||
* Added logger setting to log Git command executions
|
||||
1. [](#improved)
|
||||
* Improved Windows compatibility
|
||||
|
||||
# v1.0.0-rc.2
|
||||
## 01/16/2017
|
||||
|
||||
1. [](#new)
|
||||
* Allow to change the path for the `git` binary (#1)
|
||||
* Added CLI for synchronizing `bin/plugin git-sync sync` (#2)
|
||||
* More security: Git password will now get encrypted and won't load in admin
|
||||
1. [](#improved)
|
||||
* Wizard: Improved Bitbucket explanation about stripping out `user@` from the copied HTTPS url (#3)
|
||||
1. [](#bugfix)
|
||||
* Fixed potential issue when retrieving the currently installed git version
|
||||
* Fixed issue that would not properly hide the password from error messages if the password contained special chars
|
||||
* Fixed issue preventing the plugin to properly get setup the very first time and causing 401 error (#4)
|
||||
* Workaround for error thrown when removing the plugin
|
||||
|
||||
# v1.0.0-rc.1
|
||||
## 12/19/2016
|
||||
|
||||
1. [](#new)
|
||||
* Initial Release
|
||||
201
plugins/git-sync/LICENSE
Normal file
201
plugins/git-sync/LICENSE
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
90
plugins/git-sync/README.md
Normal file
90
plugins/git-sync/README.md
Normal file
|
|
@ -0,0 +1,90 @@
|
|||

|
||||
|
||||
**Git Sync** is a Plugin for [Grav CMS](http://github.com/getgrav/grav) that allows to seamlessly synchronize a Git repository with your Grav site, and vice-versa.
|
||||
|
||||
Git Sync captures any change that you make on your site and instantly updates your git repository. In the same way, Git Sync supports _webhooks_, allowing to automatically synchronize your site if the repository changes.
|
||||
|
||||
Thanks to this powerful bi-directional flow, Git Sync can now turn your site into a collaborative environment where the source of truth is always your git repository and unlimited collaborators and sites can share and contribute to the same content.
|
||||
|
||||
|
||||
## Videos: Setup and Demo
|
||||
|
||||
| Up and Running in 2 mins | 2-way Sync Demonstration |
|
||||
| ------------ | ----------------- |
|
||||
| [](https://www.youtube.com/watch?v=avcGP0FAzB8) | [](https://www.youtube.com/watch?v=3fy78afacyw) |
|
||||
|
||||
## Installation using the GPM (Grav Package Manager)
|
||||
|
||||
To install git-sync simply run this command from the Grav root folder
|
||||
```
|
||||
bin/gpm install git-sync
|
||||
```
|
||||
|
||||
After having installed the plugin, make sure to go in the plugin settings in order to get the Wizard configuration started.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
<img src="wizard.png" width="500" />
|
||||
|
||||
* Easy step-by-step Wizard setup will guide you through a detailed process for setting things up
|
||||
* Supported hosting services: [GitHub](https://github.com), [BitBucket](https://bitbucket.org), [GitLab](https://gitlab.com) as well as any self-hosted and git service with webhooks support.
|
||||
* Private repositories
|
||||
* Basic SSH / Enterprise support (You will need SSH Key properly setup on your machine)
|
||||
* Synchronize any folder under `user` (pages, themes, config)
|
||||
* 2FA (Two-Factor Authentication) and Access Token support
|
||||
* Webhooks support allow for automatic synchronization from the Git Repository with secure Webhook URL auto-generated and support for Webhook Secret (when available)
|
||||
* Automatically handles simple merges behind the scenes
|
||||
* Easy one-click button to reset your local changes and restores it to the actual state of the git repository
|
||||
* Easy one-click button for manual synchronization
|
||||
* Support for Admin Quick Tray, so you can synchronize from anywhere in Admin
|
||||
* Ability to customize whether GitSync should synchronize upon save or just manually
|
||||
* Customize the Committer Name, choose between Git User, GitSync Commiter Name, Grav User Name and Grav user Fullname
|
||||
* With the built-in Form Process action `gitsync`, you can trigger the synchronization anytime someone submits a post.
|
||||
* Any 3rd party plugin can integrate with Git Sync and trigger the synchronization through the `gitsync` event.
|
||||
* Built-in CLI commands to automate synchronizations
|
||||
* Log any command performed by GitSync to ensure everything runs smoothly or debug potential issues
|
||||
|
||||
# Command Line Interface
|
||||
|
||||
Git Sync comes with a CLI that allows running synchronizations right within your terminal. This feature is extremely useful in case you'd like to run an autonomous periodic crontab jobs to synchronize with your repository.
|
||||
|
||||
To execute the command simply run:
|
||||
|
||||
```bash
|
||||
bin/plugin git-sync sync
|
||||
```
|
||||
|
||||
You can also get a status by running:
|
||||
```bash
|
||||
bin/plugin git-sync status
|
||||
```
|
||||
|
||||
Since version 2.1.1 you can now also programmatically change user/password via the `bin/plugin git-sync passwd`. This is useful if you have a container that resets your password, or you have some running scripts that require to programmatically update the password.
|
||||
|
||||
# Requirements
|
||||
|
||||
In order for the plugin to work, the server needs to run `git` 1.7.1 and above.
|
||||
|
||||
The PHP `exec()` and `escapeshellarg()` functions are mandatory. Ensure the options to be enabled in your PHP.
|
||||
|
||||
# SSH / Enterprise
|
||||
|
||||
Since version v2.3.0, GitSync supports SSH authentication. This means you can omit password altogether and rely on the Repository URL and SSH key on your machine, that you can point to from the Advanced settings in GitSync.
|
||||
|
||||
Please note that In order to be able to sparse-checkout and push changes, it is expected you have an ssh-key configured for accessing the repository. This is usually found under `~/.ssh` and it needs to be configured for the same user that runs the web-server.
|
||||
|
||||
Point it to the secret (not the public) and make also sure you have strict permissions to the file. (`-rw-------`).
|
||||
|
||||
Example: private_key: `/home/www-data/.ssh/id_rsa`
|
||||
|
||||
> **IMPORTANT**: SSH keys with passphrase are **NOT** supported. To remove a passphrase, run the `ssh-keygen -p` command and when asked for the new passphrase leave blank and return.
|
||||
|
||||
# Known Issues and Resolutions
|
||||
**Q:** `error: The requested URL returned error: 403 Forbidden while accessing...` [#39](https://github.com/trilbymedia/grav-plugin-git-sync/issues/39)
|
||||
**A:** This might be caused by your computer having stored in the registry a user/password that might conflict with the one you are intending to use.
|
||||
[Follow the instructions for resolving the issue...](https://github.com/trilbymedia/grav-plugin-git-sync/issues/39#issuecomment-538867548)
|
||||
|
||||
# Sponsored by
|
||||
|
||||
This plugin could not have been realized without the sponsorship of [Hibbitts Design](http://www.hibbittsdesign.org/blog/) and the development of [Trilby Media](http://trilby.media).
|
||||
1
plugins/git-sync/app/main.js
Normal file
1
plugins/git-sync/app/main.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
import './wizard';
|
||||
379
plugins/git-sync/app/wizard/index.js
Normal file
379
plugins/git-sync/app/wizard/index.js
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
import Settings from 'git-sync';
|
||||
import request from 'admin/utils/request';
|
||||
import toastr from 'admin/utils/toastr';
|
||||
import { config } from 'grav-config';
|
||||
import $ from 'jquery';
|
||||
import 'whatwg-fetch';
|
||||
|
||||
const GIT_REGEX = /(?:git|ssh|https?|git@[-\w.]+):(\/\/)?(.*?)(\.git)(\/?|\#[-\d\w._]+?)$/;
|
||||
const WIZARD = $('[data-remodal-id="wizard"]');
|
||||
const RESET_LOCAL = $('[data-remodal-id="reset-local"]');
|
||||
const SERVICES = { 'github': 'github.com', 'bitbucket': 'bitbucket.org', 'gitlab': 'gitlab.com', 'allothers': 'allothers.repo' };
|
||||
const BRANCHES = { 'github': 'main', 'bitbucket': 'master', 'gitlab': 'master', 'allothers': 'master' };
|
||||
const TEMPLATES = {
|
||||
REPO_URL: 'https://{placeholder}/getgrav/grav.git'
|
||||
};
|
||||
|
||||
const openWizard = () => {
|
||||
const modal = WIZARD.remodal({ closeOnConfirm: false });
|
||||
const previous = WIZARD.find('[data-gitsync-action="previous"]');
|
||||
const next = WIZARD.find('[data-gitsync-action="next"]');
|
||||
const save = WIZARD.find('[data-gitsync-action="save"]');
|
||||
|
||||
STEP = 0;
|
||||
|
||||
WIZARD.find(`form > [class^=step-]:not(.step-${STEP}) > .panel`).hide().removeClass('hidden');
|
||||
WIZARD.find(`form > [class="step-${STEP}"] > .panel`).show();
|
||||
|
||||
next.removeClass('hidden');
|
||||
previous.addClass('hidden');
|
||||
save.addClass('hidden');
|
||||
|
||||
const webhook = $('[name="data[webhook]"]').val();
|
||||
const webhook_secret = $('[name="data[webhook_secret]"]').val();
|
||||
$('[name="gitsync[repository]"]').trigger('change');
|
||||
$('[name="gitsync[webhook]"]').val(webhook);
|
||||
$('[name="gitsync[webhook_secret]"]').val(webhook_secret);
|
||||
$('.gitsync-webhook').text(webhook);
|
||||
|
||||
modal.open();
|
||||
};
|
||||
|
||||
const disableButton = (next) => {
|
||||
next
|
||||
.attr('disabled', 'disabled')
|
||||
.addClass('hint--top');
|
||||
};
|
||||
|
||||
const enableButton = (next) => {
|
||||
next
|
||||
.attr('disabled', null)
|
||||
.removeClass('hint--top');
|
||||
};
|
||||
|
||||
let STEP = 0;
|
||||
let STEPS = 0;
|
||||
let SERVICE = null;
|
||||
|
||||
$(document).on('closed', WIZARD, function(e) {
|
||||
STEP = 0;
|
||||
});
|
||||
|
||||
$(document).on('click', '[data-gitsync-useraction]', (event) => {
|
||||
event.preventDefault();
|
||||
const target = $(event.target).closest('[data-gitsync-useraction]');
|
||||
const action = target.data('gitsyncUseraction');
|
||||
const URI = `${config.current_url}.json`;
|
||||
|
||||
switch (action) {
|
||||
case 'wizard':
|
||||
openWizard();
|
||||
break;
|
||||
case 'sync':
|
||||
const relativeURI = target.data('gitsync-uri');
|
||||
target.find('i').removeClass('fa-cloud fa-git').addClass('fa-circle-o-notch fa-spin');
|
||||
|
||||
request(relativeURI || URI, {
|
||||
method: 'post',
|
||||
body: { task: 'synchronize' }
|
||||
}, () => {
|
||||
target.find('i').removeClass('fa-circle-o-notch fa-spin').addClass(relativeURI ? 'fa-git' : 'fa-cloud');
|
||||
});
|
||||
break;
|
||||
case 'reset':
|
||||
const modal = RESET_LOCAL.remodal({ closeOnConfirm: false });
|
||||
modal.open();
|
||||
|
||||
if (!RESET_LOCAL.data('_reset_event_set_')) {
|
||||
RESET_LOCAL.find('[data-gitsync-action="reset-local"]').one('click', () => {
|
||||
modal.close();
|
||||
RESET_LOCAL.data('_reset_event_set_', true);
|
||||
target.find('i').removeClass('fa-history').addClass('fa-circle-o-notch fa-spin');
|
||||
request(URI, {
|
||||
method: 'post',
|
||||
body: { task: 'resetlocal' }
|
||||
}, () => {
|
||||
RESET_LOCAL.data('_reset_event_set_', false);
|
||||
target.find('i').removeClass('fa-circle-o-notch fa-spin').addClass('fa-history');
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '[data-gitsync-action]', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const target = $(event.target).closest('[data-gitsync-action]');
|
||||
const previous = WIZARD.find('[data-gitsync-action="previous"]');
|
||||
const next = WIZARD.find('[data-gitsync-action="next"]');
|
||||
const save = WIZARD.find('[data-gitsync-action="save"]');
|
||||
const action = target.data('gitsyncAction');
|
||||
const user = $('[name="gitsync[repo_user]"]').val();
|
||||
const noUser = $('[name="gitsync[no_user]"]').is(':checked');
|
||||
const password = $('[name="gitsync[repo_password]"]').val();
|
||||
const repository = $('[name="gitsync[repo_url]"]').val();
|
||||
const branch = $('[name="gitsync[branch]"]').val();
|
||||
const webhook = $('[name="gitsync[webhook]"]').val();
|
||||
const webhook_enabled = $('[name="gitsync[webhook_enabled]"]').is(':checked');
|
||||
const webhook_secret = $('[name="gitsync[webhook_secret]"]').val();
|
||||
|
||||
if (target.attr('disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let error = [];
|
||||
|
||||
if (!user && !noUser) {
|
||||
error.push('Username is missing.');
|
||||
}
|
||||
/*
|
||||
if (!password) {
|
||||
error.push('Password is missing.');
|
||||
}
|
||||
*/
|
||||
if (!repository) {
|
||||
error.push('Repository is missing.');
|
||||
}
|
||||
|
||||
if (['save', 'test'].includes(action)) {
|
||||
target.find('.fa').removeClass(action === 'test' ? 'fa-plug' : 'fa-check').addClass('fa-spin fa-circle-o-notch');
|
||||
|
||||
if (error.length) {
|
||||
toastr.error(error.join('<br />'));
|
||||
target.find('.fa').removeClass('fa-spin fa-circle-o-notch').addClass(action === 'test' ? 'fa-plug' : 'fa-check');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (action === 'save') {
|
||||
const folders = $('[name="gitsync[folders]"]:checked').map((i, item) => item.value);
|
||||
$('[name="data[repository]"]').val(repository);
|
||||
$('[name="data[no_user]"]').val(noUser ? '1' : '0');
|
||||
$('[name="data[user]"]').val(user);
|
||||
$('[name="data[password]"]').val(password);
|
||||
$('[name="data[branch]"]').val(branch);
|
||||
$('[name="data[remote][branch]"]').val(branch);
|
||||
$('[name="data[webhook]"]').val(webhook);
|
||||
$(`[name="data[webhook_enabled]"][value="${webhook_enabled ? 1 : 0}"]`).prop('checked', true);
|
||||
$('[name="data[webhook_secret]"]').val(webhook_secret);
|
||||
|
||||
const dataFolders = $('[name="data[folders][]"]');
|
||||
if (dataFolders && dataFolders[0] && dataFolders[0].selectize) {
|
||||
dataFolders[0].selectize.setValue(folders.toArray());
|
||||
}
|
||||
|
||||
$('[name="task"][value="save"]').trigger('click');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (action === 'test') {
|
||||
const URI = `${config.current_url}.json`;
|
||||
const test = global.btoa(JSON.stringify({
|
||||
user: noUser ? '' : user,
|
||||
password,
|
||||
repository,
|
||||
branch
|
||||
}));
|
||||
|
||||
request(URI, {
|
||||
method: 'post',
|
||||
body: { test, task: 'testConnection' }
|
||||
});
|
||||
|
||||
target.find('.fa').removeClass('fa-spin fa-circle-o-notch').addClass('fa-plug');
|
||||
return false;
|
||||
}
|
||||
|
||||
WIZARD.find(`.step-${STEP} > .panel`).slideUp();
|
||||
STEP += action === 'next' ? +1 : -1;
|
||||
WIZARD.find(`.step-${STEP} > .panel`).slideDown();
|
||||
|
||||
save.addClass('hidden');
|
||||
|
||||
if (action === 'next') {
|
||||
previous.removeClass('hidden');
|
||||
}
|
||||
|
||||
if (STEP <= 0) {
|
||||
previous.addClass('hidden');
|
||||
enableButton(next);
|
||||
}
|
||||
|
||||
if (STEP > 0) {
|
||||
next.removeClass('hidden');
|
||||
}
|
||||
|
||||
if (STEP === 1) {
|
||||
const selectedRepo = $('[name="gitsync[repository]"]:checked');
|
||||
if (!selectedRepo.length) {
|
||||
disableButton(next);
|
||||
} else {
|
||||
enableButton(next);
|
||||
}
|
||||
}
|
||||
|
||||
if (STEP === 2) {
|
||||
const repoURL = $('[name="gitsync[repo_url]"]').val();
|
||||
if (!repoURL.length || !branch) {
|
||||
disableButton(next);
|
||||
} else {
|
||||
enableButton(next);
|
||||
}
|
||||
}
|
||||
|
||||
if (STEP === STEPS) {
|
||||
next.addClass('hidden');
|
||||
previous.removeClass('hidden');
|
||||
save.removeClass('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('input', '[name="gitsync[no_user]"]', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
const user = $('[name="gitsync[repo_user]"]');
|
||||
if (target.is(':checked')) {
|
||||
user
|
||||
.val('')
|
||||
.prop('disabled', 'disabled')
|
||||
.attr('placeholder', '<username not required>');
|
||||
} else {
|
||||
user
|
||||
.prop('disabled', null)
|
||||
.attr('placeholder', 'Username, not email');
|
||||
}
|
||||
});
|
||||
$(document).on('change', '[name="gitsync[repository]"]', () => {
|
||||
enableButton(WIZARD.find('[data-gitsync-action="next"]'));
|
||||
});
|
||||
|
||||
$(document).on('input', '[name="gitsync[repo_url]"]', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
const value = target.val();
|
||||
const isGitURL = GIT_REGEX.test(value);
|
||||
const next = WIZARD.find('[data-gitsync-action="next"]');
|
||||
|
||||
target.removeClass('invalid');
|
||||
|
||||
if (!isGitURL) {
|
||||
target.addClass('invalid');
|
||||
}
|
||||
|
||||
if (isGitURL && value.length) {
|
||||
enableButton(next);
|
||||
} else {
|
||||
disableButton(next);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('keyup', '[data-gitsync-uribase] [name="gitsync[webhook]"]', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
const value = target.val();
|
||||
$('.gitsync-webhook').text(value);
|
||||
});
|
||||
|
||||
$(document).on('keyup', '[data-gitsync-uribase] [name="gitsync[webhook_secret]"]', (event) => {
|
||||
$('[data-gitsync-uribase] [name="gitsync[webhook_enabled]"]').trigger('change');
|
||||
});
|
||||
|
||||
$(document).on('change', '[data-gitsync-uribase] [name="gitsync[webhook_enabled]"]', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
const checked = target.is(':checked');
|
||||
const secret = $('[name="gitsync[webhook_secret]"]').val();
|
||||
target.closest('.webhook-secret-wrapper').find('label:last-child')[checked ? 'removeClass' : 'addClass']('hidden');
|
||||
$('.gitsync-webhook-secret').html(!checked || !secret.length ? '<em>leave empty</em>' : `<code>${secret}</code>`);
|
||||
});
|
||||
|
||||
$(document).on('change', '[name="gitsync[repository]"]', (event) => {
|
||||
const target = $(event.target);
|
||||
if (!target.is(':checked')) {
|
||||
return;
|
||||
}
|
||||
|
||||
SERVICE = target.val();
|
||||
|
||||
Object.keys(SERVICES).forEach((service) => {
|
||||
WIZARD.find(`.hidden-step-${service}`)[service === SERVICE ? 'removeClass' : 'addClass']('hidden');
|
||||
if (service === SERVICE) {
|
||||
WIZARD.find('.webhook-secret-wrapper')[service === 'bitbucket' ? 'addClass' : 'removeClass']('hidden');
|
||||
WIZARD
|
||||
.find('input[name="gitsync[repo_url]"][placeholder]')
|
||||
.attr('placeholder', TEMPLATES.REPO_URL.replace(/\{placeholder\}/, SERVICES[service]))
|
||||
.end()
|
||||
.find('input[name="gitsync[branch]"]')
|
||||
.attr('placeholder', BRANCHES[service])
|
||||
.val(BRANCHES[service]);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$(document).on('click', '[data-access-tokens-details]', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const button = $(event.currentTarget);
|
||||
const panel = button.closest('.access-tokens').find('.access-tokens-details');
|
||||
|
||||
panel.slideToggle(250, () => {
|
||||
const isVisible = panel.is(':visible');
|
||||
const icon = button.find('.fa');
|
||||
|
||||
icon.removeClass('fa-chevron-down fa-chevron-up').addClass(`fa-chevron-${isVisible ? 'up' : 'down'}`);
|
||||
});
|
||||
});
|
||||
|
||||
const showNotices = (element) => {
|
||||
const target = $(element);
|
||||
|
||||
const selection = target.val().replace(/\//g, '-');
|
||||
const column = target.closest('.columns').find('.column:last');
|
||||
|
||||
column.find('[class*="description-"]').addClass('hidden');
|
||||
column.find(`.description-${selection}`).removeClass('hidden').hide().fadeIn({
|
||||
duration: 250
|
||||
});
|
||||
};
|
||||
|
||||
$(document).on('input', '[data-remodal-id="wizard"] .step-4 input[type="checkbox"]', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
if (!target.is(':checked')) {
|
||||
return;
|
||||
}
|
||||
|
||||
showNotices(target);
|
||||
});
|
||||
|
||||
$(document).on('mouseenter', '[data-remodal-id="wizard"] .step-4 .info-desc', (event) => {
|
||||
const target = $(event.currentTarget).siblings('input[type="checkbox"]');
|
||||
showNotices(target);
|
||||
});
|
||||
|
||||
$(document).on('mouseleave', '[data-remodal-id="wizard"] .step-4 label', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
const container = target.closest('.columns');
|
||||
const column = container.find('.column:last-child');
|
||||
|
||||
column.find('[class*="description-"]').addClass('hidden');
|
||||
});
|
||||
|
||||
$(document).on('mouseleave', '[data-remodal-id="wizard"] .columns .column:first-child', (event) => {
|
||||
const target = $(event.currentTarget);
|
||||
const column = target.siblings('.column');
|
||||
|
||||
column.find('[class*="description-"]').addClass('hidden');
|
||||
});
|
||||
|
||||
$(document).ready(() => {
|
||||
STEPS = WIZARD.find('[class^="step-"]').length - 1;
|
||||
WIZARD.wrapInner('<form></form>');
|
||||
RESET_LOCAL.wrapInner('<form></form>');
|
||||
|
||||
if (WIZARD.length && (Settings.first_time || !Settings.git_installed)) {
|
||||
openWizard();
|
||||
}
|
||||
});
|
||||
|
||||
export default Settings;
|
||||
289
plugins/git-sync/blueprints.yaml
Normal file
289
plugins/git-sync/blueprints.yaml
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
name: Git Sync
|
||||
type: plugin
|
||||
slug: git-sync
|
||||
version: 2.3.2
|
||||
description: Allows to synchronize portions of Grav with Git Repositories (GitHub, BitBucket, GitLab)
|
||||
icon: git
|
||||
author:
|
||||
name: Trilby Media, LLC
|
||||
email: hello@trilby.media
|
||||
url: http://trilby.media
|
||||
homepage: http://trilby.media
|
||||
keywords: grav, plugin, git, sync, github, bitbucket, gitlab
|
||||
issues: https://github.com/trilbymedia/grav-plugin-git-sync/issues
|
||||
docs: https://github.com/trilbymedia/grav-plugin-git-sync
|
||||
license: MIT
|
||||
|
||||
dependencies:
|
||||
- { name: grav, version: '>=1.6.0' }
|
||||
- { name: form, version: '>=2.16.3' }
|
||||
|
||||
form:
|
||||
validation: strict
|
||||
fields:
|
||||
Basic:
|
||||
type: section
|
||||
title: Basic Settings
|
||||
underline: true
|
||||
|
||||
enabled:
|
||||
type: toggle
|
||||
label: Plugin Status
|
||||
highlight: 1
|
||||
default: 0
|
||||
options:
|
||||
1: Enabled
|
||||
0: Disabled
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
folders:
|
||||
type: select
|
||||
multiple: true
|
||||
label: Folders to Sync
|
||||
classes: fancy
|
||||
description: Removing folders after they have been synced may cause undesired results.
|
||||
default:
|
||||
- pages
|
||||
options:
|
||||
- pages
|
||||
- themes
|
||||
- plugins
|
||||
- config
|
||||
- data
|
||||
selectize:
|
||||
create: true
|
||||
validate:
|
||||
type: commalist
|
||||
|
||||
Sync:
|
||||
type: section
|
||||
title: Automatic Synchronization Settings
|
||||
underline: true
|
||||
|
||||
SyncNotice:
|
||||
type: hidden
|
||||
markdown: true
|
||||
text: |
|
||||
! To improve the speed of saving pages you can disable automatic sync. Then, changes to a page will not be sent to the remote repository on every save. To sync your changes to the repository tap the GitSync button (<i class="fa fa-git"></i>) in the top left of the Administration Panel, or use the below Scheduler option to add the GitSync Syncronization Job to the Scheduler (<strong>Grav 1.6 required</strong>).
|
||||
|
||||
sync.on_save:
|
||||
type: toggle
|
||||
label: Sync on Page Save
|
||||
help: Sync with the remote directory when a page is saved through the admin
|
||||
default: 1
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
sync.on_delete:
|
||||
type: toggle
|
||||
label: Sync on Page Delete
|
||||
help: Sync with the remote directory when a page is deleted through the admin
|
||||
default: 1
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
sync.on_media:
|
||||
type: toggle
|
||||
label: Sync on Media Changes
|
||||
help: Sync with the remote directory when a media is uploaded or deleted through the admin immediately (instead of only syncing when the page is saved)
|
||||
default: 1
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
sync.cron_enable:
|
||||
type: toggle
|
||||
label: Add Sync to Scheduler
|
||||
help: Add GitSync Job to the Scheduler so it can automatically perform synchronization at the given time
|
||||
default: 0
|
||||
highlight: 1
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
sync.cron_at:
|
||||
type: cron
|
||||
label: Run Sync at
|
||||
help: When should the Scheduler run the automatic GitSync synchronization job
|
||||
default: '0 12,23 * * *'
|
||||
|
||||
Repo:
|
||||
type: section
|
||||
title: Git Repository Settings
|
||||
underline: true
|
||||
|
||||
local_repository:
|
||||
type: hidden
|
||||
multiple: false
|
||||
size: medium
|
||||
label: Local Repository Path
|
||||
|
||||
repository:
|
||||
type: text
|
||||
label: Git Repository
|
||||
placeholder: https://github.com/user/repository.git
|
||||
|
||||
no_user:
|
||||
type: toggle
|
||||
label: User not required
|
||||
highlight: 0
|
||||
default: 0
|
||||
options:
|
||||
1: Enabled
|
||||
0: Disabled
|
||||
description: With this setting enabled, the user can be left blank and it will be ignored from the authentication. Useful when only needing access tokens `token@host` rather than `user:password@host`
|
||||
|
||||
user:
|
||||
type: text
|
||||
label: Git User
|
||||
placeholder: Username, not email
|
||||
autocomplete: off
|
||||
|
||||
password:
|
||||
type: enc-password
|
||||
label: Git Password or Token
|
||||
placeholder: Your Git Password or Token
|
||||
description: Enter your password or token to encrypt and securely store it, then save the settings. It will not show up here for security reasons.
|
||||
autocomplete: off
|
||||
|
||||
webhook:
|
||||
type: text
|
||||
label: Repository Web Hook URL
|
||||
placeholder: /_git-sync
|
||||
data-default@: '\Grav\Plugin\GitSyncPlugin::generateRandomWebhook'
|
||||
|
||||
webhook_enabled:
|
||||
type: toggle
|
||||
label: Web Hook Secret
|
||||
highlight: 1
|
||||
default: 0
|
||||
options:
|
||||
1: Enabled
|
||||
0: Disabled
|
||||
description: With this setting enabled, only authorized webhook calls will be able to trigger a synchronization (recommended)
|
||||
|
||||
webhook_secret:
|
||||
type: text
|
||||
label: Repository Web Hook Secret
|
||||
placeholder: Your Web Hook Secret
|
||||
data-default@: '\Grav\Plugin\GitSyncPlugin::generateWebhookSecret'
|
||||
description: You can either use this randomly generated string or enter your own secret. <br /> **Bitbucket** does not yet support Webhook Secrets.
|
||||
markdown: true
|
||||
|
||||
Advanced:
|
||||
type: section
|
||||
title: Advanced Git Settings
|
||||
underline: true
|
||||
|
||||
branch:
|
||||
type: text
|
||||
default: master
|
||||
label: Local Branch
|
||||
placeholder: master
|
||||
|
||||
remote.name:
|
||||
type: text
|
||||
default: origin
|
||||
label: Remote Name
|
||||
placeholder: origin
|
||||
|
||||
remote.branch:
|
||||
type: text
|
||||
default: master
|
||||
label: Remote Branch
|
||||
placeholder: master
|
||||
|
||||
git.author:
|
||||
type: select
|
||||
default: gituser
|
||||
label: Commits Author
|
||||
options:
|
||||
gituser: Use Git User Name
|
||||
gitsync: Use GitSync Committer Name
|
||||
gravuser: Use Grav User Name
|
||||
gravfull: Use Grav User Full Name
|
||||
|
||||
git.message:
|
||||
type: text
|
||||
default: (Grav GitSync) Automatic Commit
|
||||
label: Commit message
|
||||
placeholder: (Grav GitSync) Automatic Commit
|
||||
help: You can use {{pageTitle}} or {{pageRoute}} in your message as placeholders for the title or route of the page being saved
|
||||
|
||||
git.name:
|
||||
type: text
|
||||
default: GitSync
|
||||
label: Committer Name
|
||||
placeholder: GitSync
|
||||
|
||||
git.email:
|
||||
type: text
|
||||
default: git-sync@trilby.media
|
||||
label: Committer Email
|
||||
placeholder: git-sync@trilby.media
|
||||
|
||||
git.bin:
|
||||
type: text
|
||||
default: git
|
||||
label: Git Binary Path
|
||||
help: If the default `git` command doesn't work on your machine or if you want to specify a custom path, do it in here
|
||||
placeholder: /usr/bin/git
|
||||
|
||||
git.ignore:
|
||||
type: textarea
|
||||
label: Git Ignore
|
||||
help: Add custom git ignore rules to go along with GitSync. One per line
|
||||
rows: 6
|
||||
placeholder: |
|
||||
node_modules
|
||||
/.idea
|
||||
|
||||
git.private_key:
|
||||
type: text
|
||||
label: Private SSH Key
|
||||
placeholder: ~/.ssh/id_rsa
|
||||
markdown: true
|
||||
description: >
|
||||
In order to be able to sparse-checkout and push changes, it is expected you have an ssh-key configured for accessing the repository. This is usually found under `~/.ssh` and it needs to be configured for the same user that runs the web-server. <br />
|
||||
<br />
|
||||
Point it to the secret (not the public) and make also sure you have strict permissions to the file. (`-rw-------`). <br />
|
||||
<br />
|
||||
Example: `private_key: /home/www-data/.ssh/id_rsa`<br />
|
||||
<br />
|
||||
**IMPORTANT**: SSH keys with passphrase are __NOT__ supported. To remove a passphrase, run the `ssh-keygen -p` command and when asked for the new passphrase leave blank and return.
|
||||
|
||||
logging:
|
||||
type: toggle
|
||||
default: 0
|
||||
label: Log Git Commands
|
||||
help: Logs git commands. Useful to debug and troubleshoot git execution
|
||||
highlight: 0
|
||||
options:
|
||||
1: PLUGIN_ADMIN.YES
|
||||
0: PLUGIN_ADMIN.NO
|
||||
validate:
|
||||
type: bool
|
||||
|
||||
Actions:
|
||||
type: section
|
||||
title: Actions
|
||||
underline: true
|
||||
|
||||
_wizard:
|
||||
type: git-wizard
|
||||
label: Text Variable
|
||||
help: Text to add to the top of a page
|
||||
177
plugins/git-sync/classes/AdminController.php
Normal file
177
plugins/git-sync/classes/AdminController.php
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
|
||||
namespace Grav\Plugin\GitSync;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Plugin;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Plugin\Admin\AdminBaseController;
|
||||
|
||||
class AdminController extends AdminBaseController
|
||||
{
|
||||
protected $action;
|
||||
protected $target;
|
||||
protected $active;
|
||||
protected $plugin;
|
||||
protected $task_prefix = 'task';
|
||||
|
||||
/** @var GitSync */
|
||||
public $git;
|
||||
|
||||
/**
|
||||
* @param Plugin $plugin
|
||||
*/
|
||||
public function __construct(Plugin $plugin)
|
||||
{
|
||||
$this->grav = Grav::instance();
|
||||
$this->active = false;
|
||||
$uri = $this->grav['uri'];
|
||||
$this->plugin = $plugin;
|
||||
|
||||
$post = !empty($_POST) ? $_POST : [];
|
||||
$this->post = $this->getPost($post);
|
||||
|
||||
// Ensure the controller should be running
|
||||
if (Utils::isAdminPlugin()) {
|
||||
$routeDetails = $this->grav['admin']->getRouteDetails();
|
||||
$target = array_pop($routeDetails);
|
||||
$this->git = new GitSync();
|
||||
|
||||
// return null if this is not running
|
||||
if ($target !== $plugin->name) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->action = !empty($this->post['action']) ? $this->post['action'] : $uri->param('action');
|
||||
$this->target = $target;
|
||||
$this->active = true;
|
||||
$this->admin = Grav::instance()['admin'];
|
||||
|
||||
$task = !empty($post['task']) ? $post['task'] : $uri->param('task');
|
||||
if ($task && ($this->target === $plugin->name || $uri->route() === '/lessons')) {
|
||||
$this->task = $task;
|
||||
$this->active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function taskTestConnection()
|
||||
{
|
||||
$post = $this->post;
|
||||
$test = base64_decode($post['test']) ?: null;
|
||||
$data = $test ? json_decode($test, false) : new \stdClass();
|
||||
|
||||
try {
|
||||
$testResult = Helper::testRepository($data->user, $data->password, $data->repository, $data->branch);
|
||||
|
||||
if (!empty($testResult)) {
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'message' => 'The connection to the repository has been successful.'
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'Branch "' . $data->branch .'" not found in the repository.'
|
||||
]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$invalid = str_replace($data->password, '{password}', $e->getMessage());
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $invalid
|
||||
]);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
public function taskSynchronize()
|
||||
{
|
||||
try {
|
||||
$this->plugin->synchronize();
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'message' => 'GitSync has successfully synchronized with the repository.'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$invalid = str_replace($this->git->getConfig('password', null), '{password}', $e->getMessage());
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $invalid
|
||||
]);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
public function taskResetLocal()
|
||||
{
|
||||
try {
|
||||
$this->plugin->reset();
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'message' => 'GitSync has successfully reset your local changes and synchronized with the repository.'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$invalid = str_replace($this->git->getConfig('password', null), '{password}', $e->getMessage());
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $invalid
|
||||
]);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a task or action on a post or target.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$params = [];
|
||||
|
||||
// Handle Task & Action
|
||||
if ($this->post && $this->task) {
|
||||
// validate nonce
|
||||
if (!$this->validateNonce()) {
|
||||
return false;
|
||||
}
|
||||
$method = $this->task_prefix . ucfirst($this->task);
|
||||
} elseif ($this->target) {
|
||||
if (!$this->action) {
|
||||
return false;
|
||||
}
|
||||
$method = strtolower($this->action) . ucfirst($this->target);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!method_exists($this, $method)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$success = $this->{$method}(...$params);
|
||||
|
||||
// Grab redirect parameter.
|
||||
$redirect = $this->post['_redirect'] ?? null;
|
||||
unset($this->post['_redirect']);
|
||||
|
||||
// Redirect if requested.
|
||||
if ($redirect) {
|
||||
$this->setRedirect($redirect);
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isActive()
|
||||
{
|
||||
return (bool) $this->active;
|
||||
}
|
||||
}
|
||||
536
plugins/git-sync/classes/GitSync.php
Normal file
536
plugins/git-sync/classes/GitSync.php
Normal file
|
|
@ -0,0 +1,536 @@
|
|||
<?php
|
||||
namespace Grav\Plugin\GitSync;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Plugin;
|
||||
use Grav\Common\Utils;
|
||||
use http\Exception\RuntimeException;
|
||||
use RocketTheme\Toolbox\File\File;
|
||||
use SebastianBergmann\Git\Git;
|
||||
|
||||
class GitSync extends Git
|
||||
{
|
||||
/** @var static */
|
||||
static public $instance;
|
||||
|
||||
/** @var Grav */
|
||||
protected $grav;
|
||||
/** @var Plugin */
|
||||
protected $plugin;
|
||||
/** @var array */
|
||||
protected $config;
|
||||
/** @var string */
|
||||
protected $repositoryPath;
|
||||
|
||||
/** @var string|null */
|
||||
private $user;
|
||||
/** @var string|null */
|
||||
private $password;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->grav = Grav::instance();
|
||||
$this->config = $this->grav['config']->get('plugins.git-sync');
|
||||
$this->repositoryPath = isset($this->config['local_repository']) && $this->config['local_repository'] ? $this->config['local_repository'] : USER_DIR;
|
||||
|
||||
parent::__construct($this->repositoryPath);
|
||||
|
||||
static::$instance = $this;
|
||||
|
||||
$this->user = isset($this->config['no_user']) && $this->config['no_user'] ? '' : ($this->config['user'] ?? null);
|
||||
$this->password = $this->config['password'] ?? null;
|
||||
|
||||
unset($this->config['user'], $this->config['password']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
if (null === static::$instance) {
|
||||
static::$instance = new static;
|
||||
}
|
||||
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function setConfig($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->user = $this->config['user'];
|
||||
$this->password = $this->config['password'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getRuntimeInformation()
|
||||
{
|
||||
$result = [
|
||||
'repositoryPath' => $this->repositoryPath,
|
||||
'username' => $this->user,
|
||||
'password' => $this->password
|
||||
];
|
||||
|
||||
foreach ($this->config as $key => $item) {
|
||||
if (is_array($item)) {
|
||||
$count = count($item);
|
||||
$arr = $item;
|
||||
if ($count === 0) {// empty array, could still be associative
|
||||
$arr = '[]';
|
||||
} else if (isset($item[0])) {// fast check for plain array with numeric keys
|
||||
$arr = '[\'' . implode('\', \'', $item) . '\']';
|
||||
}
|
||||
$result[$key] = $arr;
|
||||
} else {
|
||||
$result[$key] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return string[]
|
||||
*/
|
||||
public function testRepository($url, $branch)
|
||||
{
|
||||
if (!preg_match(Helper::GIT_REGEX, $url)) {
|
||||
throw new \RuntimeException("Git Repository value does not match the supported format.");
|
||||
}
|
||||
|
||||
$branch = $branch ? '"' . $branch . '"' : '';
|
||||
return $this->execute("ls-remote \"{$url}\" {$branch}");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function initializeRepository()
|
||||
{
|
||||
if (!Helper::isGitInitialized()) {
|
||||
$branch = $this->getRemote('branch', null);
|
||||
$local_branch = $this->getConfig('branch', $branch);
|
||||
$this->execute('init');
|
||||
$this->execute('checkout -b ' . $local_branch, true);
|
||||
}
|
||||
|
||||
$this->enableSparseCheckout();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
* @param string|null $email
|
||||
* @return bool
|
||||
*/
|
||||
public function setUser($name = null, $email = null)
|
||||
{
|
||||
$name = $this->getConfig('git', $name)['name'];
|
||||
$email = $this->getConfig('git', $email)['email'];
|
||||
$privateKey = $this->getGitConfig('private_key', null);
|
||||
|
||||
$this->execute("config user.name \"{$name}\"");
|
||||
$this->execute("config user.email \"{$email}\"");
|
||||
|
||||
if ($privateKey) {
|
||||
$this->execute('config core.sshCommand "ssh -i ' . $privateKey . ' -F /dev/null"');
|
||||
} else {
|
||||
$this->execute('config --unset core.sshCommand');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRemote($name = null)
|
||||
{
|
||||
$name = $this->getRemote('name', $name);
|
||||
|
||||
try {
|
||||
/** @var string $version */
|
||||
$version = Helper::isGitInstalled(true);
|
||||
// remote get-url 'name' supported from 2.7.0 and above
|
||||
if (version_compare($version, '2.7.0', '>=')) {
|
||||
$command = "remote get-url \"{$name}\"";
|
||||
} else {
|
||||
$command = "config --get remote.{$name}.url";
|
||||
}
|
||||
|
||||
$this->execute($command);
|
||||
} catch (\Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function enableSparseCheckout()
|
||||
{
|
||||
$folders = $this->config['folders'];
|
||||
$this->execute('config core.sparsecheckout true');
|
||||
|
||||
$sparse = [];
|
||||
foreach ($folders as $folder) {
|
||||
$sparse[] = $folder . '/';
|
||||
$sparse[] = $folder . '/*';
|
||||
}
|
||||
|
||||
$file = File::instance(rtrim($this->repositoryPath, '/') . '/.git/info/sparse-checkout');
|
||||
$file->save(implode("\r\n", $sparse));
|
||||
$file->free();
|
||||
|
||||
$ignore = ['/*'];
|
||||
foreach ($folders as $folder) {
|
||||
$folder = rtrim($folder,'/');
|
||||
$nested = substr_count($folder, '/');
|
||||
|
||||
if ($nested) {
|
||||
$subfolders = explode('/', $folder);
|
||||
$nested_tracking = '';
|
||||
foreach ($subfolders as $index => $subfolder) {
|
||||
$last = $index === (count($subfolders) - 1);
|
||||
$nested_tracking .= $subfolder . '/';
|
||||
if (!in_array('!/' . $nested_tracking, $ignore, true)) {
|
||||
$ignore[] = rtrim($nested_tracking . (!$last ? '*' : ''), '/');
|
||||
$ignore[] = rtrim('!/' . $nested_tracking, '/');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$ignore[] = '!/' . $folder;
|
||||
}
|
||||
}
|
||||
|
||||
$ignoreEntries = explode("\n", $this->getGitConfig('ignore', ''));
|
||||
$ignore = array_merge($ignore, $ignoreEntries);
|
||||
|
||||
$file = File::instance(rtrim($this->repositoryPath, '/') . '/.gitignore');
|
||||
$file->save(implode("\r\n", $ignore));
|
||||
$file->free();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $alias
|
||||
* @param string|null $url
|
||||
* @param bool $authenticated
|
||||
* @return string[]
|
||||
*/
|
||||
public function addRemote($alias = null, $url = null, $authenticated = false)
|
||||
{
|
||||
$alias = $this->getRemote('name', $alias);
|
||||
$url = $this->getConfig('repository', $url);
|
||||
|
||||
if ($authenticated) {
|
||||
$user = $this->user ?? '';
|
||||
$password = $this->password ? Helper::decrypt($this->password) : '';
|
||||
$url = Helper::prepareRepository($user, $password, $url);
|
||||
}
|
||||
|
||||
$command = $this->hasRemote($alias) ? 'set-url' : 'add';
|
||||
|
||||
return $this->execute("remote {$command} {$alias} \"{$url}\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
/** @var string $version */
|
||||
$version = Helper::isGitInstalled(true);
|
||||
$add = 'add';
|
||||
|
||||
// With the introduction of customizable paths,
|
||||
// it appears that the add command should always
|
||||
// add everything that is not committed to ensure
|
||||
// there are no orphan changes left behind
|
||||
|
||||
/*
|
||||
$folders = $this->config['folders'];
|
||||
$paths = [];
|
||||
foreach ($folders as $folder) {
|
||||
$paths[] = $folder;
|
||||
}
|
||||
*/
|
||||
|
||||
$paths = ['.'];
|
||||
|
||||
if (version_compare($version, '2.0', '<')) {
|
||||
$add .= ' --all';
|
||||
}
|
||||
|
||||
return $this->execute($add . ' ' . implode(' ', $paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @return string[]
|
||||
*/
|
||||
public function commit($message = '(Grav GitSync) Automatic Commit')
|
||||
{
|
||||
$authorType = $this->getGitConfig('author', 'gituser');
|
||||
if (defined('GRAV_CLI') && in_array($authorType, ['gravuser', 'gravfull'])) {
|
||||
$authorType = 'gituser';
|
||||
}
|
||||
|
||||
// get message from config, it any, or stick to the default one
|
||||
$config = $this->getConfig('git', null);
|
||||
$message = $config['message'] ?? $message;
|
||||
|
||||
// get Page Title and Route from Post
|
||||
$uri = $this->grav['uri'];
|
||||
$page_title = $uri->post('data.header.title');
|
||||
$page_route = $uri->post('data.route');
|
||||
|
||||
$pageTitle = $page_title ?: 'NO TITLE FOUND';
|
||||
$pageRoute = $page_route ?: 'NO ROUTE FOUND';
|
||||
|
||||
// include page title and route in the message, if placeholders exist
|
||||
$message = str_replace('{{pageTitle}}', $pageTitle, $message);
|
||||
/** @var string $message */
|
||||
$message = str_replace('{{pageRoute}}', $pageRoute, $message);
|
||||
|
||||
switch ($authorType) {
|
||||
case 'gitsync':
|
||||
$user = $this->getConfig('git', null)['name'];
|
||||
$email = $this->getConfig('git', null)['email'];
|
||||
break;
|
||||
case 'gravuser':
|
||||
$user = $this->grav['session']->user->username;
|
||||
$email = $this->grav['session']->user->email;
|
||||
break;
|
||||
case 'gravfull':
|
||||
$user = $this->grav['session']->user->fullname;
|
||||
$email = $this->grav['session']->user->email;
|
||||
break;
|
||||
case 'gituser':
|
||||
default:
|
||||
$user = $this->user;
|
||||
$email = $this->getConfig('git', null)['email'];
|
||||
break;
|
||||
}
|
||||
|
||||
$author = $user . ' <' . $email . '>';
|
||||
$author = '--author="' . $author . '"';
|
||||
$message .= ' from ' . $user;
|
||||
$this->add();
|
||||
|
||||
return $this->execute('commit ' . $author . ' -m ' . escapeshellarg($message));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
* @param string|null $branch
|
||||
* @return string[]
|
||||
*/
|
||||
public function fetch($name = null, $branch = null)
|
||||
{
|
||||
$name = $this->getRemote('name', $name);
|
||||
$branch = $this->getRemote('branch', $branch);
|
||||
|
||||
return $this->execute("fetch {$name} {$branch}");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
* @param string|null $branch
|
||||
* @return string[]
|
||||
*/
|
||||
public function pull($name = null, $branch = null)
|
||||
{
|
||||
$name = $this->getRemote('name', $name);
|
||||
$branch = $this->getRemote('branch', $branch);
|
||||
/** @var string $version */
|
||||
$version = Helper::isGitInstalled(true);
|
||||
$unrelated_histories = '--allow-unrelated-histories';
|
||||
|
||||
// --allow-unrelated-histories starts at 2.9.0
|
||||
if (version_compare($version, '2.9.0', '<')) {
|
||||
$unrelated_histories = '';
|
||||
}
|
||||
|
||||
return $this->execute("pull {$unrelated_histories} -X theirs {$name} {$branch}");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
* @param string|null $branch
|
||||
* @return string[]
|
||||
*/
|
||||
public function push($name = null, $branch = null)
|
||||
{
|
||||
$name = $this->getRemote('name', $name);
|
||||
$branch = $this->getRemote('branch', $branch);
|
||||
$local_branch = $this->getConfig('branch', null);
|
||||
|
||||
return $this->execute("push {$name} {$local_branch}:{$branch}");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $name
|
||||
* @param string|null $branch
|
||||
* @return bool
|
||||
*/
|
||||
public function sync($name = null, $branch = null)
|
||||
{
|
||||
$name = $this->getRemote('name', $name);
|
||||
$branch = $this->getRemote('branch', $branch);
|
||||
$this->addRemote(null, null, true);
|
||||
|
||||
$this->fetch($name, $branch);
|
||||
$this->pull($name, $branch);
|
||||
$this->push($name, $branch);
|
||||
|
||||
$this->addRemote();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
return $this->execute('reset --hard HEAD');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isWorkingCopyClean()
|
||||
{
|
||||
$message = 'nothing to commit';
|
||||
$output = $this->execute('status');
|
||||
|
||||
return strpos($output[count($output) - 1], $message) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasChangesToCommit()
|
||||
{
|
||||
$folders = $this->config['folders'];
|
||||
$paths = [];
|
||||
|
||||
foreach ($folders as $folder) {
|
||||
$folder = explode('/', $folder);
|
||||
$paths[] = array_shift($folder);
|
||||
}
|
||||
|
||||
$message = 'nothing to commit';
|
||||
$output = $this->execute('status ' . implode(' ', $paths));
|
||||
|
||||
return strpos($output[count($output) - 1], $message) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $command
|
||||
* @param bool $quiet
|
||||
* @return string[]
|
||||
*/
|
||||
public function execute($command, $quiet = false)
|
||||
{
|
||||
try {
|
||||
$bin = Helper::getGitBinary($this->getGitConfig('bin', 'git'));
|
||||
/** @var string $version */
|
||||
$version = Helper::isGitInstalled(true);
|
||||
|
||||
// -C <path> supported from 1.8.5 and above
|
||||
if (version_compare($version, '1.8.5', '>=')) {
|
||||
$command = $bin . ' -C ' . escapeshellarg($this->repositoryPath) . ' ' . $command;
|
||||
} else {
|
||||
$command = 'cd ' . $this->repositoryPath . ' && ' . $bin . ' ' . $command;
|
||||
}
|
||||
|
||||
$command .= ' 2>&1';
|
||||
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
$command = 'LC_ALL=C ' . $command;
|
||||
}
|
||||
|
||||
if ($this->getConfig('logging', false)) {
|
||||
$log_command = Helper::preventReadablePassword($command, $this->password ?? '');
|
||||
$this->grav['log']->notice('gitsync[command]: ' . $log_command);
|
||||
|
||||
exec($command, $output, $returnValue);
|
||||
|
||||
$log_output = Helper::preventReadablePassword(implode("\n", $output), $this->password ?? '');
|
||||
$this->grav['log']->notice('gitsync[output]: ' . $log_output);
|
||||
} else {
|
||||
exec($command, $output, $returnValue);
|
||||
}
|
||||
|
||||
if ($returnValue !== 0 && $returnValue !== 5 && !$quiet) {
|
||||
throw new \RuntimeException(implode("\r\n", $output));
|
||||
}
|
||||
|
||||
return $output;
|
||||
} catch (\RuntimeException $e) {
|
||||
$message = $e->getMessage();
|
||||
$message = Helper::preventReadablePassword($message, $this->password ?? '');
|
||||
|
||||
// handle scary messages
|
||||
if (Utils::contains($message, 'remote: error: cannot lock ref')) {
|
||||
$message = 'GitSync: An error occurred while trying to synchronize. This could mean GitSync is already running. Please try again.';
|
||||
}
|
||||
|
||||
throw new \RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function getGitConfig($type, $value)
|
||||
{
|
||||
return $this->config['git'][$type] ?? $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRemote($type, $value)
|
||||
{
|
||||
return $value ?: ($this->config['remote'][$type] ?? $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function getConfig($type, $value)
|
||||
{
|
||||
return $value ?: ($this->config[$type] ?? $value);
|
||||
}
|
||||
}
|
||||
158
plugins/git-sync/classes/Helper.php
Normal file
158
plugins/git-sync/classes/Helper.php
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
|
||||
namespace Grav\Plugin\GitSync;
|
||||
|
||||
use Defuse\Crypto\Crypto;
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Utils;
|
||||
use SebastianBergmann\Git\RuntimeException;
|
||||
|
||||
class Helper
|
||||
{
|
||||
/** @var string */
|
||||
private static $hash = '594ef69d-6c29-45f7-893a-f1b4342687d3';
|
||||
|
||||
/** @var string */
|
||||
const GIT_REGEX = '/(?:git|ssh|https?|git@[-\w.]+):(\/\/)?(.*?)(\.git)(\/?|\#[-\d\w._]+?)$/';
|
||||
|
||||
/**
|
||||
* Checks if the user/ folder is already initialized
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isGitInitialized()
|
||||
{
|
||||
return file_exists(rtrim(USER_DIR, '/') . '/.git');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $version
|
||||
* @return bool|string
|
||||
*/
|
||||
public static function isGitInstalled($version = false)
|
||||
{
|
||||
$bin = Helper::getGitBinary();
|
||||
|
||||
exec($bin . ' --version', $output, $returnValue);
|
||||
|
||||
$installed = $returnValue === 0;
|
||||
|
||||
if ($version && $output) {
|
||||
$output = explode(' ', array_shift($output));
|
||||
$versions = array_filter($output, static function($item) {
|
||||
return version_compare($item, '0.0.1', '>=');
|
||||
});
|
||||
|
||||
$installed = array_shift($versions);
|
||||
}
|
||||
|
||||
return $installed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $override
|
||||
* @return string
|
||||
*/
|
||||
public static function getGitBinary($override = false)
|
||||
{
|
||||
/** @var Config $grav */
|
||||
$config = Grav::instance()['config'];
|
||||
|
||||
return $override ?: $config->get('plugins.git-sync.git.bin', 'git');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $password
|
||||
* @param string $repository
|
||||
* @return string
|
||||
*/
|
||||
public static function prepareRepository($user, $password, $repository)
|
||||
{
|
||||
$user = $user ? urlencode($user) . ':' : '';
|
||||
$password = urlencode($password);
|
||||
|
||||
if (Utils::startsWith($repository, 'ssh://')) {
|
||||
return $repository;
|
||||
}
|
||||
|
||||
return str_replace('://', "://${user}${password}@", $repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param string $password
|
||||
* @param string $repository
|
||||
* @return string[]
|
||||
*/
|
||||
public static function testRepository($user, $password, $repository, $branch)
|
||||
{
|
||||
$git = new GitSync();
|
||||
$repository = self::prepareRepository($user, $password, $repository);
|
||||
|
||||
try {
|
||||
return $git->testRepository($repository, $branch);
|
||||
} catch (RuntimeException $e) {
|
||||
return [$e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $password
|
||||
* @return string
|
||||
* @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException
|
||||
*/
|
||||
public static function encrypt($password)
|
||||
{
|
||||
return 'gitsync-' . Crypto::encryptWithPassword($password, self::$hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $enc_password
|
||||
* @return string
|
||||
*/
|
||||
public static function decrypt($enc_password)
|
||||
{
|
||||
if (strpos($enc_password, 'gitsync-') === 0) {
|
||||
$enc_password = substr($enc_password, 8);
|
||||
|
||||
return Crypto::decryptWithPassword($enc_password, self::$hash);
|
||||
}
|
||||
|
||||
return $enc_password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function synchronize()
|
||||
{
|
||||
if (!self::isGitInstalled() || !self::isGitInitialized()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$git = new GitSync();
|
||||
|
||||
if ($git->hasChangesToCommit()) {
|
||||
$git->commit();
|
||||
}
|
||||
|
||||
// synchronize with remote
|
||||
$git->sync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function preventReadablePassword($str, $password)
|
||||
{
|
||||
$encoded = urlencode(self::decrypt($password));
|
||||
|
||||
return str_replace($encoded, '{password}', $str);
|
||||
}
|
||||
}
|
||||
45
plugins/git-sync/cli/InitCommand.php
Normal file
45
plugins/git-sync/cli/InitCommand.php
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?php namespace Grav\Plugin\Console;
|
||||
|
||||
use Grav\Console\ConsoleCommand;
|
||||
use Grav\Plugin\GitSync\GitSync;
|
||||
|
||||
/**
|
||||
* Class InitCommand
|
||||
*
|
||||
* @package Grav\Plugin\Console
|
||||
*/
|
||||
class InitCommand extends ConsoleCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('init')
|
||||
->setDescription('Initializes your git repository')
|
||||
->setHelp('The <info>init</info> command runs the same git commands as the onAdminAfterSave function. Use this to manually initialize git-sync (useful for automated deployments).')
|
||||
;
|
||||
}
|
||||
|
||||
protected function serve()
|
||||
{
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$plugin = new GitSync();
|
||||
$repository = $plugin->getConfig('repository', false);
|
||||
|
||||
$this->output->writeln('');
|
||||
|
||||
if (!$repository) {
|
||||
$this->output->writeln('<red>ERROR:</red> No repository has been configured!');
|
||||
}
|
||||
|
||||
$this->output->writeln('Initializing <cyan>' . $repository . '</cyan>');
|
||||
|
||||
$this->output->write('Starting initialization...');
|
||||
|
||||
$plugin->initializeRepository();
|
||||
$plugin->setUser();
|
||||
$plugin->addRemote();
|
||||
|
||||
$this->output->writeln('completed.');
|
||||
}
|
||||
}
|
||||
91
plugins/git-sync/cli/PasswdCommand.php
Normal file
91
plugins/git-sync/cli/PasswdCommand.php
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
namespace Grav\Plugin\Console;
|
||||
|
||||
use Grav\Console\ConsoleCommand;
|
||||
use Grav\Plugin\GitSync\GitSync;
|
||||
use Grav\Plugin\GitSync\Helper;
|
||||
use Grav\Common\Grav;
|
||||
use RocketTheme\Toolbox\File\YamlFile;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
/**
|
||||
* Class LogCommand
|
||||
*
|
||||
* @package Grav\Plugin\Console
|
||||
*/
|
||||
class PasswdCommand extends ConsoleCommand
|
||||
{
|
||||
/** @var array */
|
||||
protected $options = [];
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('passwd')
|
||||
->setDescription('Allows to change the user and/or password programmatically')
|
||||
->addOption(
|
||||
'user',
|
||||
'u',
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'The username. Use empty double quotes if you need an empty username.'
|
||||
)
|
||||
->addOption(
|
||||
'password',
|
||||
'p',
|
||||
InputOption::VALUE_REQUIRED,
|
||||
"The password."
|
||||
)
|
||||
->setHelp('The <info>%command.name%</info> command allows to change the user and/or password. Useful when running automated scripts or needing to programmatically set them without admin access.')
|
||||
;
|
||||
}
|
||||
|
||||
protected function serve()
|
||||
{
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
$grav = Grav::instance();
|
||||
$config = $grav['config'];
|
||||
$locator = $grav['locator'];
|
||||
$filename = 'config://plugins/git-sync.yaml';
|
||||
$file = YamlFile::instance($locator->findResource($filename, true, true));
|
||||
|
||||
$this->options = [
|
||||
'user' => $this->input->getOption('user'),
|
||||
'password' => $this->input->getOption('password')
|
||||
];
|
||||
|
||||
if ($this->options['password'] !== null) {
|
||||
$this->options['password'] = Helper::encrypt($this->options['password']);
|
||||
}
|
||||
|
||||
$user = $this->options['user'] !== null ? $this->options['user'] : $config->get('plugins.git-sync.user');
|
||||
$password = $this->options['password'] !== null ? $this->options['password'] : $config->get('plugins.git-sync.password');
|
||||
|
||||
$config->set('plugins.git-sync.user', $user);
|
||||
$config->set('plugins.git-sync.password', $password);
|
||||
|
||||
$content = $grav['config']->get('plugins.git-sync');
|
||||
$file->save($content);
|
||||
$file->free();
|
||||
|
||||
$this->output->writeln('');
|
||||
$this->output->writeln('<green>User / Password updated.</green>');
|
||||
$this->output->writeln('');
|
||||
}
|
||||
|
||||
private function console_header($readable, $cmd = '', $remote_action = false)
|
||||
{
|
||||
$this->output->writeln(
|
||||
"<yellow>$readable</yellow>" . ($cmd ? "(<info>$cmd</info>)" : ''). ($remote_action ? '...' : '')
|
||||
);
|
||||
}
|
||||
|
||||
private function console_log($lines, $password)
|
||||
{
|
||||
foreach ($lines as $line) {
|
||||
$this->output->writeln(' ' . Helper::preventReadablePassword($line, $password));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
149
plugins/git-sync/cli/StatusCommand.php
Normal file
149
plugins/git-sync/cli/StatusCommand.php
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
namespace Grav\Plugin\Console;
|
||||
|
||||
use Grav\Console\ConsoleCommand;
|
||||
use Grav\Plugin\GitSync\GitSync;
|
||||
use Grav\Plugin\GitSync\Helper;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
/**
|
||||
* Class LogCommand
|
||||
*
|
||||
* @package Grav\Plugin\Console
|
||||
*/
|
||||
class StatusCommand extends ConsoleCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('status')
|
||||
->setDescription('Checks the status of plugin config, git and git workspace. No files get modified!')
|
||||
->addOption(
|
||||
'fetch', 'f',
|
||||
InputOption::VALUE_NONE,
|
||||
'additionally do a git fetch to look updates (changes not files in workspace)'
|
||||
)
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> command checks if the plugin is usable the way it has been configured.
|
||||
While doing this it prints the available information for your inspection.
|
||||
|
||||
<comment>No files in the workspace are modified when running this test.</comment>
|
||||
|
||||
The <info>--fetch</info> option can be used to see differences between the remote in the <info>git status</info> (last check)
|
||||
|
||||
It also returns with an error code and a helpful message when something is not normal:
|
||||
|
||||
<error>100</error> : <info>git</info> binary not working as expected
|
||||
<error>50</error> : <info>repositoryFolder</info> and git workspace root do not match
|
||||
<error>10</error> : <info>repository</info> is not configured
|
||||
<error>5</error> : state of workspace not clean
|
||||
<error>1</error> : Some checks can throw a <info>RuntimeException</info> which is not caught, read the message for details
|
||||
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function serve()
|
||||
{
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$plugin = new GitSync();
|
||||
$this->output->writeln('');
|
||||
|
||||
|
||||
$this->console_header('plugin runtime information:');
|
||||
$info = $plugin->getRuntimeInformation();
|
||||
$info['isGitInitialized'] = Helper::isGitInitialized();
|
||||
$info['gitVersion'] = Helper::isGitInstalled(true);
|
||||
ksort($info);
|
||||
dump($info);
|
||||
if (!Helper::isGitInstalled()) {
|
||||
throw new RuntimeException('git binary not found', 100);
|
||||
}
|
||||
|
||||
$this->console_header('detect git workspace root:');
|
||||
$git_root = $plugin->execute('rev-parse --show-toplevel');
|
||||
$this->console_log($git_root, '');
|
||||
if (rtrim($info['repositoryPath'], '/') !== rtrim($git_root[0], '/')) {
|
||||
throw new RuntimeException('git root and repositoryPath do not match', 50);
|
||||
}
|
||||
|
||||
// needed to prevent output in logs:
|
||||
$password = Helper::decrypt($plugin->getPassword() ?? '');
|
||||
|
||||
$this->console_header('local git config:');
|
||||
$this->console_log(
|
||||
$plugin->execute('config --local -l'), $password
|
||||
);
|
||||
|
||||
|
||||
$this->console_header(
|
||||
'Testing connection to repository', 'git ls-remote', true
|
||||
);
|
||||
$repository = $plugin->getConfig('repository', false);
|
||||
if (!$repository) {
|
||||
throw new RuntimeException('No repository has been configured', 10);
|
||||
}
|
||||
$testRepository = $plugin->testRepository(
|
||||
Helper::prepareRepository(
|
||||
$plugin->getUser() ?? '',
|
||||
$password,
|
||||
$repository),
|
||||
$plugin->getRemote('branch', null),
|
||||
);
|
||||
$this->console_log($testRepository, $password);
|
||||
|
||||
$fetched = false;
|
||||
if ($this->input->getOption('fetch')) {
|
||||
$remote = $plugin->getRemote('name', '');
|
||||
$this->console_header(
|
||||
'Looking for updates', "git fetch $remote", true
|
||||
);
|
||||
$this->console_log($plugin->fetch($remote), $password);
|
||||
$fetched = true;
|
||||
}
|
||||
|
||||
$this->console_header(
|
||||
'Checking workspace status', 'git status', true
|
||||
);
|
||||
$git_status = $plugin->execute('status');
|
||||
$this->console_log($git_status, $password);
|
||||
if (!$plugin->isWorkingCopyClean()) {
|
||||
throw new RuntimeException('Working state is not clean.', 5);
|
||||
}
|
||||
|
||||
|
||||
if ($fetched) {
|
||||
$uptodate = strpos($git_status[1], 'branch is up-to-date with') > 0;
|
||||
if ($uptodate) {
|
||||
$this->console_header(
|
||||
'Congrats: You should be able to run the <info>sync</info> command without problems!'
|
||||
);
|
||||
} else {
|
||||
$this->output->writeln('<yellow>You are not in sync!</yellow>');
|
||||
$this->output->writeln('Take a look at the output of git status to see more details.');
|
||||
$this->output->writeln('In most cases the <info>sync</info> command is able to fix this.');
|
||||
}
|
||||
} else {
|
||||
$this->console_header('Looks good: use <info>--fetch</info> option to check for updates.');
|
||||
}
|
||||
}
|
||||
|
||||
private function console_header($readable, $cmd = '', $remote_action = false)
|
||||
{
|
||||
$this->output->writeln(
|
||||
"<yellow>$readable</yellow>" . ($cmd ? "(<info>$cmd</info>)" : ''). ($remote_action ? '...' : '')
|
||||
);
|
||||
}
|
||||
|
||||
private function console_log($lines, $password)
|
||||
{
|
||||
foreach ($lines as $line) {
|
||||
$this->output->writeln(' ' . Helper::preventReadablePassword($line, $password));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
51
plugins/git-sync/cli/SyncCommand.php
Normal file
51
plugins/git-sync/cli/SyncCommand.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
namespace Grav\Plugin\Console;
|
||||
|
||||
use Grav\Console\ConsoleCommand;
|
||||
use Grav\Plugin\GitSync\GitSync;
|
||||
|
||||
/**
|
||||
* Class LogCommand
|
||||
*
|
||||
* @package Grav\Plugin\Console
|
||||
*/
|
||||
class SyncCommand extends ConsoleCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('sync')
|
||||
->setDescription('Performs a synchronization of your site')
|
||||
->setHelp('The <info>sync</info> command performs a synchronization of your site. Useful if you want to run a periodic crontab job to automate it.')
|
||||
;
|
||||
}
|
||||
|
||||
protected function serve()
|
||||
{
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$plugin = new GitSync();
|
||||
$repository = $plugin->getConfig('repository', false);
|
||||
|
||||
$this->output->writeln('');
|
||||
|
||||
if (!$repository) {
|
||||
$this->output->writeln('<red>ERROR:</red> No repository has been configured');
|
||||
}
|
||||
|
||||
$this->output->writeln('Synchronizing with <cyan>' . $repository . '</cyan>');
|
||||
|
||||
if ($plugin->hasChangesToCommit()) {
|
||||
$this->output->writeln('Changes detected, adding and committing...');
|
||||
$plugin->add();
|
||||
$plugin->commit();
|
||||
}
|
||||
|
||||
$this->output->write('Starting Synchronization...');
|
||||
|
||||
$plugin->sync();
|
||||
|
||||
$this->output->writeln('completed.');
|
||||
}
|
||||
}
|
||||
|
||||
28
plugins/git-sync/composer.json
Normal file
28
plugins/git-sync/composer.json
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"require": {
|
||||
"php": ">=7.1.3",
|
||||
"ext-json": "*",
|
||||
"ext-openssl": "*",
|
||||
"sebastian/git": "^2.1",
|
||||
"defuse/php-encryption": "^2.0"
|
||||
},
|
||||
"replace": {
|
||||
"paragonie/random_compat": "9.99.99"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Grav\\Plugin\\GitSync\\": "classes/",
|
||||
"Grav\\Plugin\\Console\\": "cli/"
|
||||
},
|
||||
"classmap": [
|
||||
"git-sync.php"
|
||||
]
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Trilby Media, LLC",
|
||||
"email": "devs@trilbymedia.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
139
plugins/git-sync/composer.lock
generated
Normal file
139
plugins/git-sync/composer.lock
generated
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "5e875c300e0af3cf13a009bb9c591afd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "defuse/php-encryption",
|
||||
"version": "v2.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/defuse/php-encryption.git",
|
||||
"reference": "77880488b9954b7884c25555c2a0ea9e7053f9d2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/defuse/php-encryption/zipball/77880488b9954b7884c25555c2a0ea9e7053f9d2",
|
||||
"reference": "77880488b9954b7884c25555c2a0ea9e7053f9d2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-openssl": "*",
|
||||
"paragonie/random_compat": ">= 2",
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4|^5|^6|^7|^8|^9"
|
||||
},
|
||||
"bin": [
|
||||
"bin/generate-defuse-key"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Defuse\\Crypto\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Hornby",
|
||||
"email": "taylor@defuse.ca",
|
||||
"homepage": "https://defuse.ca/"
|
||||
},
|
||||
{
|
||||
"name": "Scott Arciszewski",
|
||||
"email": "info@paragonie.com",
|
||||
"homepage": "https://paragonie.com"
|
||||
}
|
||||
],
|
||||
"description": "Secure PHP Encryption Library",
|
||||
"keywords": [
|
||||
"aes",
|
||||
"authenticated encryption",
|
||||
"cipher",
|
||||
"crypto",
|
||||
"cryptography",
|
||||
"encrypt",
|
||||
"encryption",
|
||||
"openssl",
|
||||
"security",
|
||||
"symmetric key cryptography"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/defuse/php-encryption/issues",
|
||||
"source": "https://github.com/defuse/php-encryption/tree/v2.3.1"
|
||||
},
|
||||
"time": "2021-04-09T23:57:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/git",
|
||||
"version": "2.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/git.git",
|
||||
"reference": "815bbbc963cf35e5413df195aa29df58243ecd24"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/git/zipball/815bbbc963cf35e5413df195aa29df58243ecd24",
|
||||
"reference": "815bbbc963cf35e5413df195aa29df58243ecd24",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"email": "sebastian@phpunit.de"
|
||||
}
|
||||
],
|
||||
"description": "Simple wrapper for Git",
|
||||
"homepage": "http://www.github.com/sebastianbergmann/git",
|
||||
"keywords": [
|
||||
"git"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/git/issues",
|
||||
"source": "https://github.com/sebastianbergmann/git/tree/master"
|
||||
},
|
||||
"abandoned": true,
|
||||
"time": "2017-01-23T20:57:12+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.1.3",
|
||||
"ext-json": "*",
|
||||
"ext-openssl": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.0.0"
|
||||
}
|
||||
22
plugins/git-sync/css-compiled/git-sync-icon.css
Normal file
22
plugins/git-sync/css-compiled/git-sync-icon.css
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
@font-face {
|
||||
font-family: 'gitsync';
|
||||
src:
|
||||
url('../fonts/gitsync.ttf?ivrc6k') format('truetype'),
|
||||
url('../fonts/gitsync.woff?ivrc6k') format('woff'),
|
||||
url('../fonts/gitsync.svg?ivrc6k#gitsync') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.fa.fa-git,
|
||||
.fa.fa-git-square {
|
||||
font-family: 'gitsync' !important;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.fa-git-square:before {
|
||||
content: "\e900" !important;
|
||||
}
|
||||
.fa-git:before {
|
||||
content: "\e901" !important;
|
||||
}
|
||||
137
plugins/git-sync/css-compiled/git-sync.css
Normal file
137
plugins/git-sync/css-compiled/git-sync.css
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
[data-remodal-id="wizard"] .button[disabled], [data-remodal-id="wizard"] .button[disabled]:hover, [data-remodal-id="reset-local"] .button[disabled], [data-remodal-id="reset-local"] .button[disabled]:hover {
|
||||
background: #ccc;
|
||||
cursor: default; }
|
||||
|
||||
[data-remodal-id="wizard"] .button[disabled]:active, [data-remodal-id="reset-local"] .button[disabled]:active {
|
||||
margin: 0; }
|
||||
|
||||
[data-remodal-id="wizard"] form [class^="step-"] a:not(.button):not([target]), [data-remodal-id="reset-local"] form [class^="step-"] a:not(.button):not([target]) {
|
||||
vertical-align: middle;
|
||||
color: #5591c7; }
|
||||
[data-remodal-id="wizard"] form [class^="step-"] a:not(.button):not([target]):hover, [data-remodal-id="reset-local"] form [class^="step-"] a:not(.button):not([target]):hover {
|
||||
color: #366188; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-1 a, [data-remodal-id="reset-local"] .step-1 a {
|
||||
vertical-align: middle; }
|
||||
|
||||
[data-remodal-id="wizard"] .access-tokens h3, [data-remodal-id="reset-local"] .access-tokens h3 {
|
||||
margin-top: 1rem; }
|
||||
|
||||
[data-remodal-id="wizard"] .access-tokens a, [data-remodal-id="reset-local"] .access-tokens a {
|
||||
vertical-align: inherit !important; }
|
||||
|
||||
[data-remodal-id="wizard"] .access-tokens-details > p, [data-remodal-id="reset-local"] .access-tokens-details > p {
|
||||
margin-top: 0; }
|
||||
|
||||
[data-remodal-id="wizard"] .access-tokens-details > div > ul, [data-remodal-id="reset-local"] .access-tokens-details > div > ul {
|
||||
margin-bottom: 0; }
|
||||
|
||||
[data-remodal-id="wizard"] .center, [data-remodal-id="reset-local"] .center {
|
||||
text-align: center; }
|
||||
|
||||
[data-remodal-id="wizard"] h1, [data-remodal-id="reset-local"] h1 {
|
||||
margin-bottom: 0;
|
||||
padding-top: 0.5rem;
|
||||
border-top: 3px solid transparent; }
|
||||
|
||||
[data-remodal-id="wizard"] .wizard-padding, [data-remodal-id="reset-local"] .wizard-padding {
|
||||
padding: 0 3rem; }
|
||||
[data-remodal-id="wizard"] .wizard-padding p, [data-remodal-id="reset-local"] .wizard-padding p {
|
||||
padding: 0; }
|
||||
|
||||
[data-remodal-id="wizard"] input[disabled], [data-remodal-id="reset-local"] input[disabled] {
|
||||
background: #efefef;
|
||||
border-color: #ddd; }
|
||||
|
||||
[data-remodal-id="wizard"] input.invalid, [data-remodal-id="reset-local"] input.invalid {
|
||||
border-color: #f4516d;
|
||||
color: #f4516d; }
|
||||
|
||||
[data-remodal-id="wizard"] label.disabled, [data-remodal-id="reset-local"] label.disabled {
|
||||
color: #ccc; }
|
||||
|
||||
[data-remodal-id="wizard"] label img, [data-remodal-id="reset-local"] label img {
|
||||
max-width: 100px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: 0.5rem; }
|
||||
|
||||
[data-remodal-id="wizard"] label a, [data-remodal-id="reset-local"] label a {
|
||||
margin-left: 0.5rem; }
|
||||
|
||||
[data-remodal-id="wizard"] .columns, [data-remodal-id="reset-local"] .columns {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center; }
|
||||
[data-remodal-id="wizard"] .columns .column, [data-remodal-id="reset-local"] .columns .column {
|
||||
flex: 1; }
|
||||
[data-remodal-id="wizard"] .columns .column:first-child, [data-remodal-id="reset-local"] .columns .column:first-child {
|
||||
width: 35%;
|
||||
flex: none;
|
||||
border-right: 1px solid #ddd;
|
||||
margin-right: 2rem; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-1 div.column:nth-child(1), [data-remodal-id="reset-local"] .step-1 div.column:nth-child(1) {
|
||||
flex-grow: 1.5;
|
||||
width: 15%; }
|
||||
[data-remodal-id="wizard"] .step-1 div.column:nth-child(1) > label:nth-child(4), [data-remodal-id="reset-local"] .step-1 div.column:nth-child(1) > label:nth-child(4) {
|
||||
width: 110%; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-1 div.column:nth-child(2), [data-remodal-id="reset-local"] .step-1 div.column:nth-child(2) {
|
||||
margin-left: 25px; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-1 div.column:nth-child(2) > label:nth-child(1) > input:nth-child(1), [data-remodal-id="wizard"] .step-1 div.column:nth-child(2) > label:nth-child(2) > input:nth-child(1), [data-remodal-id="reset-local"] .step-1 div.column:nth-child(2) > label:nth-child(1) > input:nth-child(1), [data-remodal-id="reset-local"] .step-1 div.column:nth-child(2) > label:nth-child(2) > input:nth-child(1) {
|
||||
width: 100%; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-1 .no_user, [data-remodal-id="reset-local"] .step-1 .no_user {
|
||||
float: right;
|
||||
font-size: .8rem;
|
||||
padding: 0; }
|
||||
[data-remodal-id="wizard"] .step-1 .no_user input, [data-remodal-id="reset-local"] .step-1 .no_user input {
|
||||
margin-right: 0; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-2 .info, [data-remodal-id="reset-local"] .step-2 .info {
|
||||
margin: 0.2rem 0;
|
||||
padding: 0.5rem 1.5rem; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-2 ol, [data-remodal-id="wizard"] .step-2 ul, [data-remodal-id="reset-local"] .step-2 ol, [data-remodal-id="reset-local"] .step-2 ul {
|
||||
padding-left: 1rem; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-4 .info, [data-remodal-id="reset-local"] .step-4 .info {
|
||||
font-size: 100%;
|
||||
margin: 0.2rem 0; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-4 .alert, [data-remodal-id="wizard"] .step-4 .warning, [data-remodal-id="reset-local"] .step-4 .alert, [data-remodal-id="reset-local"] .step-4 .warning {
|
||||
padding: 0.5rem 1.5rem; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-4 .fa.fa-warning, [data-remodal-id="reset-local"] .step-4 .fa.fa-warning {
|
||||
color: #ff7d3b;
|
||||
font-size: 1.2rem; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-4 .wizard-padding label > *, [data-remodal-id="reset-local"] .step-4 .wizard-padding label > * {
|
||||
vertical-align: middle; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-4 .info-desc, [data-remodal-id="reset-local"] .step-4 .info-desc {
|
||||
color: #0091ff;
|
||||
float: right;
|
||||
margin-right: .5rem;
|
||||
font-size: 1.2rem; }
|
||||
|
||||
[data-remodal-id="wizard"] .step-4 hr, [data-remodal-id="reset-local"] .step-4 hr {
|
||||
margin: .5rem 0; }
|
||||
|
||||
#admin-main [data-grav-field="git-wizard"] {
|
||||
margin: 0 1rem; }
|
||||
#admin-main [data-grav-field="git-wizard"] .danger.button-bar {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: transparent; }
|
||||
#admin-main [data-grav-field="git-wizard"] .button {
|
||||
top: 0 !important;
|
||||
-webkit-transform: translateY(0) !important;
|
||||
-moz-transform: translateY(0) !important;
|
||||
-ms-transform: translateY(0) !important;
|
||||
-o-transform: translateY(0) !important;
|
||||
transform: translateY(0) !important; }
|
||||
|
||||
/*# sourceMappingURL=git-sync.css.map */
|
||||
12
plugins/git-sync/fonts/gitsync.svg
Normal file
12
plugins/git-sync/fonts/gitsync.svg
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="gitsync" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="git-square" horiz-adv-x="878" d="M332.571 203.428c0-30.857-28-37.714-53.143-37.714-24.571 0-61.143 4-61.143 36 0 31.429 30.857 36.571 56 36.571 24 0 58.286-4 58.286-34.857zM312 469.714c0-28.571-11.429-48.571-42.286-48.571-31.429 0-44 18.286-44 48s11.429 51.429 44 51.429c29.143 0 42.286-24 42.286-50.857zM406.857 512.571v71.429c-24.571-9.143-50.857-16.571-77.143-16.571-18.857 10.857-40.571 16.571-62.857 16.571-65.143 0-116.571-48-116.571-114.286 0-35.429 23.429-84.571 58.857-96.571v-1.714c-18.286-8-21.714-30.286-21.714-48.571 0-18.857 6.857-34.286 23.429-44v-1.714c-38.857-12.571-64.571-37.143-64.571-79.429 0-72.571 69.143-93.143 129.714-93.143 73.143 0 128 26.857 128 107.429 0 57.143-52 74.286-99.429 82.857-16 2.857-43.429 14.286-43.429 34.286 0 18.857 10.286 26.857 28 29.714 58.286 11.429 95.429 56.571 95.429 116.571 0 10.286-2.286 20-5.714 29.714 9.143 2.286 18.857 4.571 28 7.429zM440.571 273.143h78.286c-1.143 15.429-1.143 31.429-1.143 46.857v221.143c0 13.143 0 26.286 1.143 39.429h-78.286c1.714-13.143 1.714-27.429 1.714-40.571v-224c0-14.286 0-28.571-1.714-42.857zM731.429 282.286v69.143c-11.429-8-25.143-12-38.857-12-25.714 0-30.286 25.714-30.286 46.857v128.571h29.714c10.286 0 20-1.143 30.286-1.143v66.857h-60c0 19.429-1.143 38.857 1.714 58.286h-80c1.714-10.286 2.286-20.571 2.286-31.429v-26.857h-34.286v-66.857c6.857 0.571 13.714 1.714 21.143 1.714 4 0 8.571-0.571 13.143-0.571v-1.143h-1.143v-124c0-61.714 9.143-121.143 84.571-121.143 21.143 0 42.857 3.429 61.714 13.714zM528 685.714c0 26.857-20 52-48 52s-48.571-24.571-48.571-52c0-26.857 21.143-50.857 48.571-50.857s48 24.571 48 50.857zM877.714 713.143v-548.571c0-90.857-73.714-164.571-164.571-164.571h-548.571c-90.857 0-164.571 73.714-164.571 164.571v548.571c0 90.857 73.714 164.571 164.571 164.571h548.571c90.857 0 164.571-73.714 164.571-164.571z" />
|
||||
<glyph unicode="" glyph-name="git" d="M340 85.714c0 50.286-55.429 57.143-94.286 57.143-40.571 0-90.286-8.571-90.286-59.429 0-51.429 58.857-57.714 98.286-57.714 41.714 0 86.286 10.286 86.286 60zM306.286 517.143c0 42.857-20.571 81.714-68 81.714-52.571 0-70.857-34.857-70.857-82.857 0-47.429 20.571-77.143 70.857-77.143 49.714 0 68 32 68 78.286zM460 702.286v-115.429c-14.857-5.143-29.714-9.143-45.143-12.571 5.714-15.429 9.143-31.429 9.143-48 0-96.571-59.429-170.286-154.286-188-28.571-5.714-45.143-17.714-45.143-48.571 0-87.429 230.857-28 230.857-189.143 0-130.857-88.571-173.714-207.429-173.714-97.714 0-209.143 32.571-209.143 150.286 0 68.571 41.714 108 104 128.571v2.286c-26.286 16-38.286 41.143-38.286 72 0 29.143 6.286 65.143 36 78.286v2.286c-57.714 19.429-95.429 98.857-95.429 156.571 0 106.857 82.857 185.143 188.571 185.143 35.429 0 70.857-9.143 101.714-26.857 42.857 0 85.143 11.429 124.571 26.857zM641.714 198.857h-126.857c2.286 25.714 2.286 50.857 2.286 76.571v348c0 24.571 0.571 49.143-2.286 73.143h126.857c-2.857-23.429-2.286-47.429-2.286-70.857v-350.286c0-25.714 0-50.857 2.286-76.571zM985.143 325.714v-112c-30.286-16.571-65.143-22.286-99.429-22.286-122.286 0-136.571 96.571-136.571 196v200.571h1.143v2.286c-7.429 0-14.286 1.143-21.143 1.143-11.429 0-22.857-1.714-33.714-3.429v108.571h54.857v43.429c0 17.143-0.571 34.286-3.429 50.857h129.714c-4.571-31.429-3.429-62.857-3.429-94.286h97.714v-108.571c-16.571 0-33.143 2.286-49.143 2.286h-48.571v-208.571c0-33.714 7.429-74.857 49.714-74.857 22.286 0 44 6.286 62.286 18.857zM656 866.857c0-42.857-33.143-82.857-77.143-82.857-45.143 0-78.857 39.429-78.857 82.857 0 44 33.143 84 78.857 84 45.143 0 77.143-41.143 77.143-84z" />
|
||||
</font></defs></svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
BIN
plugins/git-sync/fonts/gitsync.ttf
Normal file
BIN
plugins/git-sync/fonts/gitsync.ttf
Normal file
Binary file not shown.
BIN
plugins/git-sync/fonts/gitsync.woff
Normal file
BIN
plugins/git-sync/fonts/gitsync.woff
Normal file
Binary file not shown.
490
plugins/git-sync/git-sync.php
Normal file
490
plugins/git-sync/git-sync.php
Normal file
|
|
@ -0,0 +1,490 @@
|
|||
<?php
|
||||
|
||||
namespace Grav\Plugin;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Data\Data;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use Grav\Common\Plugin;
|
||||
use Grav\Common\Scheduler\Scheduler;
|
||||
use Grav\Plugin\GitSync\AdminController;
|
||||
use Grav\Plugin\GitSync\GitSync;
|
||||
use Grav\Plugin\GitSync\Helper;
|
||||
use RocketTheme\Toolbox\Event\Event;
|
||||
|
||||
/**
|
||||
* Class GitSyncPlugin
|
||||
*
|
||||
* @package Grav\Plugin
|
||||
*/
|
||||
class GitSyncPlugin extends Plugin
|
||||
{
|
||||
/** @var AdminController|null */
|
||||
protected $controller;
|
||||
/** @var GitSync */
|
||||
protected $git;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
'onPluginsInitialized' => [
|
||||
['autoload', 100000],
|
||||
['onPluginsInitialized', 1000]
|
||||
],
|
||||
'onPageInitialized' => ['onPageInitialized', 0],
|
||||
'onFormProcessed' => ['onFormProcessed', 0],
|
||||
'onSchedulerInitialized' => ['onSchedulerInitialized', 0]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* [onPluginsInitialized:100000] Composer autoload.
|
||||
*
|
||||
* @return ClassLoader
|
||||
*/
|
||||
public function autoload() : ClassLoader
|
||||
{
|
||||
return require __DIR__ . '/vendor/autoload.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function generateWebhookSecret()
|
||||
{
|
||||
return static::generateHash(24);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function generateRandomWebhook()
|
||||
{
|
||||
return '/_git-sync-' . static::generateHash(6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the plugin
|
||||
*/
|
||||
public function onPluginsInitialized()
|
||||
{
|
||||
$this->enable(['gitsync' => ['synchronize', 0]]);
|
||||
$this->init();
|
||||
|
||||
if ($this->isAdmin()) {
|
||||
$this->enable([
|
||||
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
|
||||
'onTwigSiteVariables' => ['onTwigSiteVariables', 0],
|
||||
'onAdminMenu' => ['onAdminMenu', 0],
|
||||
'onAdminSave' => ['onAdminSave', 0],
|
||||
'onAdminAfterSave' => ['onAdminAfterSave', 0],
|
||||
'onAdminAfterSaveAs' => ['onAdminAfterSaveAs', 0],
|
||||
'onAdminAfterDelete' => ['onAdminAfterDelete', 0],
|
||||
'onAdminAfterAddMedia' => ['onAdminAfterMedia', 0],
|
||||
'onAdminAfterDelMedia' => ['onAdminAfterMedia', 0],
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$config = $this->config->get('plugins.' . $this->name);
|
||||
$route = $this->grav['uri']->route();
|
||||
$webhook = $config['webhook'] ?? false;
|
||||
$secret = $config['webhook_secret'] ?? false;
|
||||
$enabled = $config['webhook_enabled'] ?? false;
|
||||
|
||||
if ($route === $webhook && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if ($secret && $enabled) {
|
||||
if (!$this->isRequestAuthorized($secret)) {
|
||||
http_response_code(401);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'Unauthorized request'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$this->synchronize();
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'message' => 'GitSync completed the synchronization'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
http_response_code(500);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'GitSync failed to synchronize'
|
||||
]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the request contains a valid signature or token
|
||||
* @param string $secret local secret
|
||||
* @return bool whether or not the request is authorized
|
||||
*/
|
||||
public function isRequestAuthorized($secret)
|
||||
{
|
||||
if (isset($_SERVER['HTTP_X_HUB_SIGNATURE'])) {
|
||||
$payload = file_get_contents('php://input') ?: '';
|
||||
|
||||
return $this->isGithubSignatureValid($secret, $_SERVER['HTTP_X_HUB_SIGNATURE'], $payload);
|
||||
}
|
||||
if (isset($_SERVER['HTTP_X_GITLAB_TOKEN'])) {
|
||||
return $this->isGitlabTokenValid($secret, $_SERVER['HTTP_X_GITLAB_TOKEN']);
|
||||
} else {
|
||||
$payload = file_get_contents('php://input');
|
||||
return $this->isGiteaSecretValid($secret, $payload);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes the webhook request body with the client secret and
|
||||
* checks if it matches the webhook signature header
|
||||
* @param string $secret The webhook secret
|
||||
* @param string $signatureHeader The signature of the webhook request
|
||||
* @param string $payload The webhook request body
|
||||
* @return bool Whether the signature is valid or not
|
||||
*/
|
||||
public function isGithubSignatureValid($secret, $signatureHeader, $payload)
|
||||
{
|
||||
[$algorithm, $signature] = explode('=', $signatureHeader);
|
||||
|
||||
return $signature === hash_hmac($algorithm, $payload, $secret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if given Gitlab token matches secret
|
||||
* @param string $secret local secret
|
||||
* @param string $token token received from Gitlab webhook request
|
||||
* @return bool whether or not secret and token match
|
||||
*/
|
||||
public function isGitlabTokenValid($secret, $token)
|
||||
{
|
||||
return $secret === $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if secret contained in the payload matches the client
|
||||
* secret
|
||||
* @param string $secret The webhook secret
|
||||
* @param string $payload The webhook request body
|
||||
* @return boolean Whether the client secret matches the payload secret or
|
||||
* not
|
||||
*/
|
||||
public function isGiteaSecretValid($secret, $payload)
|
||||
{
|
||||
$payload = json_decode($payload, true);
|
||||
if (!empty($payload) && isset($payload['secret'])) {
|
||||
return $secret === $payload['secret'];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onAdminMenu()
|
||||
{
|
||||
$base = rtrim($this->grav['base_url'], '/') . '/' . trim($this->grav['admin']->base, '/');
|
||||
$options = [
|
||||
'hint' => Helper::isGitInitialized() ? 'Synchronize GitSync' : 'Configure GitSync',
|
||||
'class' => 'gitsync-sync',
|
||||
'location' => 'pages',
|
||||
'route' => Helper::isGitInitialized() ? 'admin' : 'admin/plugins/git-sync',
|
||||
'icon' => 'fa-' . $this->grav['plugins']->get('git-sync')->blueprints()->get('icon')
|
||||
];
|
||||
|
||||
if (Helper::isGitInstalled()) {
|
||||
if (Helper::isGitInitialized()) {
|
||||
$options['data'] = [
|
||||
'gitsync-useraction' => 'sync',
|
||||
'gitsync-uri' => $base . '/plugins/git-sync'
|
||||
];
|
||||
}
|
||||
|
||||
$this->grav['twig']->plugins_quick_tray['GitSync'] = $options;
|
||||
}
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
if ($this->isAdmin()) {
|
||||
/** @var AdminController controller */
|
||||
$this->controller = new AdminController($this);
|
||||
$this->git = &$this->controller->git;
|
||||
} else {
|
||||
$this->git = new GitSync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function synchronize()
|
||||
{
|
||||
if (!Helper::isGitInstalled() || !Helper::isGitInitialized()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->grav->fireEvent('onGitSyncBeforeSynchronize');
|
||||
|
||||
if ($this->git->hasChangesToCommit()) {
|
||||
$this->git->commit();
|
||||
}
|
||||
|
||||
// synchronize with remote
|
||||
$this->git->sync();
|
||||
|
||||
$this->grav->fireEvent('onGitSyncAfterSynchronize');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onSchedulerInitialized(Event $event)
|
||||
{
|
||||
/** @var Config $config */
|
||||
$config = Grav::instance()['config'];
|
||||
$run_at = $config->get('plugins.git-sync.sync.cron_at', '0 12,23 * * *');
|
||||
|
||||
if ($config->get('plugins.git-sync.sync.cron_enable', false)) {
|
||||
/** @var Scheduler $scheduler */
|
||||
$scheduler = $event['scheduler'];
|
||||
$job = $scheduler->addFunction('Grav\Plugin\GitSync\Helper::synchronize', [], 'GitSync');
|
||||
$job->at($run_at);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
if (!Helper::isGitInstalled() || !Helper::isGitInitialized()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->grav->fireEvent('onGitSyncBeforeReset');
|
||||
|
||||
$this->git->reset();
|
||||
|
||||
$this->grav->fireEvent('onGitSyncAfterReset');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add current directory to twig lookup paths.
|
||||
*/
|
||||
public function onTwigTemplatePaths()
|
||||
{
|
||||
$this->grav['twig']->twig_paths[] = __DIR__ . '/templates';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set needed variables to display cart.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function onTwigSiteVariables()
|
||||
{
|
||||
// workaround for admin plugin issue that doesn't properly unsubscribe events upon plugin uninstall
|
||||
if (!class_exists(Helper::class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = $this->grav['user'];
|
||||
if (!$user->authenticated) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$settings = [
|
||||
'first_time' => !Helper::isGitInitialized(),
|
||||
'git_installed' => Helper::isGitInstalled()
|
||||
];
|
||||
|
||||
$this->grav['twig']->twig_vars['git_sync'] = $settings;
|
||||
|
||||
$adminPath = trim($this->grav['admin']->base, '/');
|
||||
if ($this->grav['uri']->path() === "/$adminPath/plugins/git-sync") {
|
||||
$this->grav['assets']->addCss('plugin://git-sync/css-compiled/git-sync.css');
|
||||
} else {
|
||||
$this->grav['assets']->addInlineJs('var GitSync = ' . json_encode($settings) . ';');
|
||||
}
|
||||
|
||||
$this->grav['assets']->addJs('plugin://git-sync/js/vendor.js', ['loading' => 'defer', 'priority' => 0]);
|
||||
$this->grav['assets']->addJs('plugin://git-sync/js/app.js', ['loading' => 'defer', 'priority' => 0]);
|
||||
$this->grav['assets']->addCss('plugin://git-sync/css-compiled/git-sync-icon.css');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onPageInitialized()
|
||||
{
|
||||
if ($this->controller && $this->controller->isActive()) {
|
||||
$this->controller->execute();
|
||||
$this->controller->redirect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Event $event
|
||||
* @return Data|true
|
||||
*/
|
||||
public function onAdminSave(Event $event)
|
||||
{
|
||||
$obj = $event['object'];
|
||||
$adminPath = trim($this->grav['admin']->base, '/');
|
||||
$isPluginRoute = $this->grav['uri']->path() === "/$adminPath/plugins/" . $this->name;
|
||||
|
||||
if ($obj instanceof Data) {
|
||||
if (!$isPluginRoute || !Helper::isGitInstalled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// empty password, keep current one or encrypt if haven't already
|
||||
$password = $obj->get('password', false);
|
||||
if (!$password) { // set to !()
|
||||
$current_password = $this->git->getPassword();
|
||||
// password exists but was never encrypted
|
||||
if ($current_password && strpos($current_password, 'gitsync-') !== 0) {
|
||||
$current_password = Helper::encrypt($current_password);
|
||||
}
|
||||
} else {
|
||||
// password is getting changed
|
||||
$current_password = Helper::encrypt($password);
|
||||
}
|
||||
|
||||
$obj->set('password', $current_password);
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Event $event
|
||||
*/
|
||||
public function onAdminAfterSave(Event $event)
|
||||
{
|
||||
$obj = $event['object'];
|
||||
$adminPath = trim($this->grav['admin']->base, '/');
|
||||
$uriPath = $this->grav['uri']->path();
|
||||
$isPluginRoute = $uriPath === "/$adminPath/plugins/" . $this->name;
|
||||
|
||||
if ($obj instanceof PageInterface && !$this->grav['config']->get('plugins.git-sync.sync.on_save', true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($obj instanceof Data) {
|
||||
$folders = $this->git->getConfig('folders', $event['object']->get('folders', []));
|
||||
$data_type = preg_replace('#^/' . preg_quote($adminPath, '#') . '/#', '', $uriPath);
|
||||
$data_type = explode('/', $data_type);
|
||||
$data_type = array_shift($data_type);
|
||||
|
||||
if (null === $data_type || !Helper::isGitInstalled() || (!$isPluginRoute && !in_array($this->getFolderMapping($data_type), $folders, true))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($isPluginRoute) {
|
||||
$this->git->setConfig($obj->toArray());
|
||||
|
||||
// initialize git if not done yet
|
||||
$this->git->initializeRepository();
|
||||
|
||||
// set committer and remote data
|
||||
$this->git->setUser();
|
||||
$this->git->addRemote();
|
||||
}
|
||||
}
|
||||
|
||||
$this->synchronize();
|
||||
}
|
||||
|
||||
public function onAdminAfterSaveAs()
|
||||
{
|
||||
if ($this->grav['config']->get('plugins.git-sync.sync.on_save', true))
|
||||
{
|
||||
$this->synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
public function onAdminAfterDelete()
|
||||
{
|
||||
if ($this->grav['config']->get('plugins.git-sync.sync.on_delete', true))
|
||||
{
|
||||
$this->synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
public function onAdminAfterMedia()
|
||||
{
|
||||
if ($this->grav['config']->get('plugins.git-sync.sync.on_media', true))
|
||||
{
|
||||
$this->synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Event $event
|
||||
*/
|
||||
public function onFormProcessed(Event $event)
|
||||
{
|
||||
$action = $event['action'];
|
||||
|
||||
if ($action === 'gitsync') {
|
||||
$this->synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data_type
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFolderMapping($data_type)
|
||||
{
|
||||
switch ($data_type) {
|
||||
case 'user':
|
||||
return 'accounts';
|
||||
case 'themes':
|
||||
return 'config';
|
||||
case 'config':
|
||||
case 'data':
|
||||
case 'plugins':
|
||||
case 'pages':
|
||||
return $data_type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $len
|
||||
* @return string
|
||||
*/
|
||||
protected static function generateHash(int $len): string
|
||||
{
|
||||
$bytes = openssl_random_pseudo_bytes($len, $isStrong);
|
||||
|
||||
if ($bytes === false) {
|
||||
throw new \RuntimeException('Could not generate hash');
|
||||
}
|
||||
|
||||
if ($isStrong === false) {
|
||||
// It's ok not to be strong [EA].
|
||||
$isStrong = true;
|
||||
}
|
||||
|
||||
return bin2hex($bytes);
|
||||
}
|
||||
}
|
||||
1
plugins/git-sync/git-sync.yaml
Normal file
1
plugins/git-sync/git-sync.yaml
Normal file
|
|
@ -0,0 +1 @@
|
|||
enabled: true
|
||||
2
plugins/git-sync/gosass.sh
Normal file
2
plugins/git-sync/gosass.sh
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
gosass -input scss/ -output css/ -sourcemap -watch -style compressed
|
||||
BIN
plugins/git-sync/images/gitsync-logo.png
Normal file
BIN
plugins/git-sync/images/gitsync-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.3 KiB |
79
plugins/git-sync/images/repos/bitbucket.svg
Normal file
79
plugins/git-sync/images/repos/bitbucket.svg
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="bitbucket" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="863.566px" height="267.72px" viewBox="0 0 863.566 267.72" style="enable-background:new 0 0 863.566 267.72;"
|
||||
xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#205081;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M432.851,136.489c-9.223,0-18.545,2.275-24.859,4.641v-34.558c0-1.738-1.414-3.146-3.15-3.146h-18.628
|
||||
c-1.736,0-3.13,1.408-3.13,3.146v119.01c0,1.51,1.086,2.826,2.577,3.092c11.492,2.096,25.048,2.83,33.187,2.83
|
||||
c34.984,0,42.139-14.87,42.139-37.211v-26.049C460.984,147.162,451.519,136.489,432.851,136.489z M419.926,209.871
|
||||
c-4.717,0-8.624-0.182-11.935-0.571v-46.559c5.13-2.299,12.346-4.616,18.132-4.616c7.058,0,9.938,2.766,9.938,9.568v27.313
|
||||
C436.061,204.862,433.568,209.871,419.926,209.871z"/>
|
||||
<path class="st0" d="M546.674,138.31H528.07c-1.736,0-3.146,1.413-3.146,3.127v58.95c-6.71,3.401-16.155,6.929-21.777,6.929
|
||||
c-4.193,0-5.742-1.549-5.742-5.746v-60.133c0-1.714-1.432-3.127-3.19-3.127h-18.583c-1.762,0-3.154,1.413-3.154,3.127v62.509
|
||||
c0,18.283,7.195,27.559,21.369,27.559c9.872,0,23.308-3.392,34.652-8.726l1.372,4.645c0.409,1.344,1.617,2.265,3.028,2.265
|
||||
l13.775-0.004c1.741,0,3.153-1.412,3.153-3.147v-85.1C549.827,139.723,548.415,138.31,546.674,138.31z"/>
|
||||
<path class="st0" d="M621.62,210.423c-0.121-0.877-0.633-1.647-1.33-2.147c-0.732-0.489-1.636-0.653-2.493-0.46
|
||||
c-5.337,1.216-10.939,1.874-16.195,1.874c-11.798,0-15.213-3.005-15.213-13.394v-24.6c0-10.397,3.415-13.402,15.213-13.402
|
||||
c2.806,0,9.794,0.403,16.195,1.869c0.857,0.196,1.761,0.034,2.493-0.471c0.719-0.484,1.227-1.261,1.33-2.142l2.212-14.727
|
||||
c0.22-1.552-0.694-3.03-2.212-3.474c-7.175-2.112-15.583-2.861-20.549-2.861c-28.132,0-39.604,10.246-39.604,35.392v24.231
|
||||
c0,25.137,11.472,35.392,39.604,35.392c6.826,0,14.7-1.096,20.549-2.855c1.518-0.449,2.432-1.938,2.212-3.483L621.62,210.423z"
|
||||
/>
|
||||
<path class="st0" d="M749.865,136.489c-24.967,0-38.149,12.434-38.149,35.941v23.499c0,24.265,12.364,35.574,38.889,35.574
|
||||
c10.792,0,22.304-1.892,31.566-5.171c1.472-0.53,2.353-2.075,2.045-3.621l-2.761-13.316c-0.184-0.855-0.716-1.61-1.452-2.05
|
||||
c-0.755-0.459-1.655-0.58-2.491-0.337c-8.567,2.414-16.687,3.597-24.907,3.597c-13.556,0-15.97-4.393-15.97-13.587v-3.217
|
||||
h46.213c1.755,0,3.148-1.393,3.148-3.156v-17.13C785.995,148.248,774.524,136.489,749.865,136.489z M736.635,173.262v-3.019
|
||||
c0-8.77,4.279-12.857,13.419-12.857c10.1,0,12.117,4.928,12.117,12.857v3.019H736.635z"/>
|
||||
<path class="st0" d="M302.116,138.269H283.51c-1.739,0-3.154,1.418-3.154,3.148v85.085c0,1.745,1.415,3.152,3.154,3.152h18.605
|
||||
c1.779,0,3.168-1.407,3.168-3.152v-85.085C305.284,139.687,303.895,138.269,302.116,138.269z"/>
|
||||
<path class="st0" d="M302.116,103.416H283.51c-1.739,0-3.154,1.428-3.154,3.157v16.029c0,1.763,1.415,3.159,3.154,3.159h18.605
|
||||
c1.779,0,3.168-1.396,3.168-3.159v-16.029C305.284,104.844,303.895,103.416,302.116,103.416z"/>
|
||||
<g>
|
||||
<path class="st0" d="M255.251,164.776c7.711-4.242,11.059-10.188,11.059-19.331v-12.513c0-18.323-10.995-27.217-33.572-27.217
|
||||
h-45.939c-1.721,0-3.133,1.408-3.133,3.145v117.642c0,1.745,1.412,3.152,3.133,3.152h49.213
|
||||
c21.917,0,34.493-10.643,34.493-29.211v-12.922C270.504,176.444,264.881,168.172,255.251,164.776z M209.308,127.347h20.691
|
||||
c9.366,0,10.676,4.087,10.676,8.463v10.721c0,6.972-3.255,9.95-10.86,9.95h-4.474c-1.762,0-3.174,1.417-3.174,3.157v14.781
|
||||
c0,1.751,1.412,3.161,3.174,3.161h8.093c8.119,0,11.413,3.14,11.413,10.849v9.097c0,7.843-3.374,10.488-13.415,10.488h-22.122
|
||||
V127.347z"/>
|
||||
</g>
|
||||
<path class="st0" d="M372.022,211.568c-0.123-0.886-0.612-1.666-1.347-2.166c-0.741-0.489-1.659-0.652-2.518-0.433
|
||||
c-3.291,0.82-6.441,1.268-8.872,1.268c-4.602,0-6.646-2.003-6.646-6.476v-45.085h18.074c1.74,0,3.148-1.408,3.148-3.151v-14.069
|
||||
c0-1.734-1.408-3.148-3.148-3.148h-18.074v-21.676c0-0.917-0.41-1.779-1.083-2.372c-0.694-0.606-1.617-0.88-2.52-0.749
|
||||
l-18.605,2.59c-1.554,0.225-2.713,1.556-2.713,3.129v19.078h-10.145c-1.737,0-3.152,1.413-3.152,3.148v14.069
|
||||
c0,1.743,1.415,3.151,3.152,3.151h10.145v48.007c0,16.472,8.646,24.835,25.738,24.835c4.868,0,13.128-1.127,18.526-2.999
|
||||
c1.451-0.499,2.311-1.938,2.085-3.454L372.022,211.568z"/>
|
||||
<path class="st0" d="M847.374,211.564c-0.122-0.886-0.632-1.666-1.373-2.168c-0.733-0.487-1.657-0.652-2.493-0.427
|
||||
c-3.314,0.816-6.441,1.268-8.893,1.268c-4.582,0-6.665-2.009-6.665-6.481v-45.085h18.096c1.757,0,3.144-1.417,3.144-3.146
|
||||
v-14.069c0-1.734-1.387-3.149-3.144-3.149H827.95v-21.68c0-0.919-0.368-1.78-1.066-2.371c-0.695-0.603-1.613-0.877-2.514-0.745
|
||||
l-18.607,2.59c-1.553,0.22-2.722,1.551-2.722,3.113v19.093h-10.138c-1.722,0-3.147,1.414-3.147,3.149v14.069
|
||||
c0,1.729,1.426,3.146,3.147,3.146h10.138v48.013c0,16.466,8.671,24.829,25.746,24.829c4.887,0,13.125-1.126,18.524-2.997
|
||||
c1.433-0.501,2.326-1.934,2.104-3.454L847.374,211.564z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path class="st0" d="M708.825,224.391l-24.88-41.074l24.001-40.449c0.578-0.975,0.589-2.184,0.028-3.166
|
||||
c-0.561-0.984-1.605-1.592-2.737-1.592h-20.553c-1.126,0-2.166,0.602-2.729,1.576l-22.832,39.584v-72.678
|
||||
c0-1.741-1.411-3.15-3.15-3.15h-18.606c-1.739,0-3.15,1.409-3.15,3.15v119.911c0,1.74,1.411,3.15,3.15,3.15h18.606
|
||||
c1.739,0,3.15-1.41,3.15-3.15v-39.244l24.295,40.654c0.568,0.951,1.596,1.535,2.704,1.535h20.173c0.006,0,0.014,0,0.02,0
|
||||
c1.74,0,3.15-1.412,3.15-3.15C709.466,225.58,709.228,224.92,708.825,224.391z"/>
|
||||
<path class="st0" d="M89.219,94.963v0.002V94.963c-33.675,0-61.172,9.053-61.172,20.294c0,2.961,7.343,45.415,10.256,62.251
|
||||
c1.306,7.551,20.818,18.621,50.9,18.621l0.031-0.09v0.09c30.081,0,49.593-11.07,50.899-18.621
|
||||
c2.913-16.836,10.256-59.29,10.256-62.251C150.39,104.017,122.894,94.963,89.219,94.963z M89.219,182.49
|
||||
c-10.739,0-19.445-8.707-19.445-19.445c0-10.74,8.706-19.445,19.445-19.445c10.739,0,19.445,8.705,19.445,19.445
|
||||
C108.664,173.783,99.958,182.49,89.219,182.49z M89.208,121.53c-21.636-0.035-39.169-3.794-39.162-8.398
|
||||
c0.007-4.604,17.554-8.307,39.19-8.272c21.636,0.034,39.169,3.793,39.162,8.398C128.39,117.863,110.844,121.564,89.208,121.53z"/>
|
||||
<path class="st0" d="M133.185,194.382c-0.93,0-1.675,0.658-1.675,0.658s-15.064,11.929-42.29,11.93
|
||||
c-27.227-0.001-42.29-11.93-42.29-11.93s-0.746-0.658-1.675-0.658c-1.111,0-2.164,0.746-2.164,2.393
|
||||
c0,0.174,0.017,0.348,0.049,0.518c2.338,12.514,4.046,21.393,4.346,22.744c2.041,9.205,20.048,16.151,41.733,16.152l0,0h0.001h0.001
|
||||
l0,0c21.686-0.001,39.692-6.947,41.733-16.152c0.3-1.352,2.008-10.23,4.346-22.744c0.032-0.17,0.049-0.344,0.049-0.518
|
||||
C135.349,195.128,134.295,194.382,133.185,194.382z"/>
|
||||
<circle class="st0" cx="89.2" cy="163.039" r="9.745"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.9 KiB |
15
plugins/git-sync/images/repos/github.svg
Normal file
15
plugins/git-sync/images/repos/github.svg
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 2002 542" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
||||
<g transform="matrix(1,0,0,1,-199.492,-929.431)">
|
||||
<g id="Layer-1" transform="matrix(4.16667,0,0,4.16667,0,0)">
|
||||
<path d="M140.375,278.65L100.019,278.65C98.978,278.65 98.133,279.495 98.133,280.537L98.133,300.267C98.133,301.308 98.978,302.156 100.019,302.156L115.762,302.156L115.762,326.67C115.762,326.67 112.227,327.875 102.454,327.875C90.924,327.875 74.817,323.662 74.817,288.243C74.817,252.818 91.589,248.157 107.335,248.157C120.965,248.157 126.837,250.556 130.573,251.713C131.747,252.072 132.833,250.903 132.833,249.862L137.335,230.798C137.335,230.31 137.17,229.723 136.614,229.325C135.097,228.242 125.84,223.063 102.454,223.063C75.513,223.063 47.878,234.525 47.878,289.625C47.878,344.726 79.518,352.937 106.18,352.937C128.256,352.937 141.648,343.504 141.648,343.504C142.2,343.199 142.26,342.427 142.26,342.074L142.26,280.537C142.26,279.495 141.416,278.65 140.375,278.65" style="fill:rgb(14,13,13);fill-rule:nonzero;"/>
|
||||
<path d="M348.353,229.665C348.353,228.615 347.521,227.768 346.48,227.768L323.757,227.768C322.719,227.768 321.875,228.615 321.875,229.665C321.875,229.67 321.881,273.578 321.881,273.578L286.462,273.578L286.462,229.665C286.462,228.615 285.626,227.768 284.587,227.768L261.866,227.768C260.832,227.768 259.989,228.615 259.989,229.665L259.989,348.568C259.989,349.617 260.832,350.471 261.866,350.471L284.587,350.471C285.626,350.471 286.462,349.617 286.462,348.568L286.462,297.709L321.881,297.709C321.881,297.709 321.82,348.564 321.82,348.568C321.82,349.617 322.663,350.471 323.702,350.471L346.478,350.471C347.519,350.471 348.351,349.617 348.353,348.568L348.353,229.665Z" style="fill:rgb(14,13,13);fill-rule:nonzero;"/>
|
||||
<path d="M183.254,245.268C183.254,237.086 176.694,230.475 168.601,230.475C160.516,230.475 153.951,237.086 153.951,245.268C153.951,253.442 160.516,260.072 168.601,260.072C176.694,260.072 183.254,253.442 183.254,245.268" style="fill:rgb(14,13,13);fill-rule:nonzero;"/>
|
||||
<path d="M181.629,323.486L181.629,268.6C181.629,267.558 180.788,266.706 179.749,266.706L157.098,266.706C156.059,266.706 155.129,267.778 155.129,268.819L155.129,347.455C155.129,349.765 156.569,350.453 158.433,350.453L178.841,350.453C181.08,350.453 181.629,349.353 181.629,347.418L181.629,323.486Z" style="fill:rgb(14,13,13);fill-rule:nonzero;"/>
|
||||
<path d="M434.71,266.885L412.161,266.885C411.127,266.885 410.285,267.738 410.285,268.786L410.285,327.088C410.285,327.088 404.557,331.28 396.426,331.28C388.296,331.28 386.138,327.59 386.138,319.629L386.138,268.786C386.138,267.738 385.298,266.885 384.263,266.885L361.378,266.885C360.345,266.885 359.499,267.738 359.499,268.786L359.499,323.479C359.499,347.125 372.678,352.91 390.808,352.91C405.681,352.91 417.673,344.694 417.673,344.694C417.673,344.694 418.244,349.024 418.502,349.537C418.761,350.049 419.434,350.567 420.161,350.567L434.72,350.502C435.753,350.502 436.599,349.649 436.599,348.604L436.592,268.786C436.592,267.738 435.749,266.885 434.71,266.885" style="fill:rgb(14,13,13);fill-rule:nonzero;"/>
|
||||
<path d="M487.445,331.207C479.624,330.969 474.319,327.42 474.319,327.42L474.319,289.766C474.319,289.766 479.552,286.558 485.973,285.984C494.093,285.257 501.918,287.71 501.918,307.08C501.918,327.506 498.386,331.537 487.445,331.207M496.339,264.214C483.532,264.214 474.821,269.928 474.821,269.928L474.821,229.665C474.821,228.615 473.982,227.768 472.946,227.768L450.159,227.768C449.123,227.768 448.281,228.615 448.281,229.665L448.281,348.568C448.281,349.617 449.123,350.471 450.162,350.471L465.971,350.471C466.683,350.471 467.222,350.103 467.621,349.461C468.013,348.822 468.581,343.978 468.581,343.978C468.581,343.978 477.898,352.809 495.538,352.809C516.246,352.809 528.122,342.305 528.122,305.654C528.122,269.003 509.155,264.214 496.339,264.214" style="fill:rgb(14,13,13);fill-rule:nonzero;"/>
|
||||
<path d="M246.935,266.695L229.891,266.695C229.891,266.695 229.866,244.182 229.866,244.177C229.866,243.324 229.426,242.899 228.44,242.899L205.212,242.899C204.309,242.899 203.825,243.296 203.825,244.164L203.825,267.433C203.825,267.433 192.184,270.243 191.397,270.47C190.615,270.698 190.038,271.421 190.038,272.283L190.038,286.905C190.038,287.957 190.877,288.805 191.915,288.805L203.825,288.805L203.825,323.984C203.825,350.113 222.154,352.679 234.521,352.679C240.171,352.679 246.932,350.865 248.047,350.453C248.723,350.205 249.116,349.506 249.116,348.748L249.134,332.662C249.134,331.613 248.248,330.763 247.249,330.763C246.256,330.763 243.716,331.168 241.099,331.168C232.728,331.168 229.891,327.275 229.891,322.236C229.891,317.201 229.89,288.805 229.89,288.805L246.935,288.805C247.974,288.805 248.817,287.957 248.817,286.905L248.817,268.59C248.817,267.54 247.974,266.695 246.935,266.695" style="fill:rgb(14,13,13);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
77
plugins/git-sync/images/repos/gitlab.svg
Normal file
77
plugins/git-sync/images/repos/gitlab.svg
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="1202px" height="455px" viewBox="0 0 1202 455" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>wm_no_bg</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
<path id="path-1" d="M0,1173.3333 L1999.99995,1173.3333 L1999.99995,0 L0,0 L0,1173.3333 L0,1173.3333 Z"></path>
|
||||
</defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="gitlab_logo" sketch:type="MSLayerGroup" transform="translate(-439.000000, -360.000000)">
|
||||
<g id="g10" transform="translate(1000.000000, 587.333300) scale(1, -1) translate(-1000.000000, -587.333300) translate(0.000000, 0.333300)">
|
||||
<g id="g12" transform="translate(1316.014500, 505.244121)" fill="#8C929D" sketch:type="MSShapeGroup">
|
||||
<path d="M22.6666661,162.666663 L0.835999979,162.666663 L0.905333311,0.178666662 L89.2199978,0.178666662 L89.2199978,20.2719995 L22.7359994,20.2719995 L22.6666661,162.666663 L22.6666661,162.666663 Z" id="path14"></path>
|
||||
</g>
|
||||
<g id="g16">
|
||||
<g id="g18-Clipped">
|
||||
<mask id="mask-2" sketch:name="path22" fill="white">
|
||||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<g id="path22"></g>
|
||||
<g id="g18" mask="url(#mask-2)">
|
||||
<g transform="translate(438.666658, 358.666658)">
|
||||
<g id="g24" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(977.327440, 143.284396)">
|
||||
<path d="M73.3333315,31.9999992 C67.8759983,26.294666 58.6973319,20.5879995 46.2933322,20.5879995 C29.6719993,20.5879995 22.9746661,28.7746659 22.9746661,39.4426657 C22.9746661,55.5666653 34.1373325,63.2573318 57.9533319,63.2573318 C62.4186651,63.2573318 69.6119983,62.7613318 73.3333315,62.0173318 L73.3333315,31.9999992 L73.3333315,31.9999992 Z M50.7586654,130.48533 C33.1293325,130.48533 16.9599996,124.235997 4.34266656,113.83333 L12.0586664,100.467997 C20.9893328,105.677331 31.9053325,110.887997 47.5333321,110.887997 C65.394665,110.887997 73.3333315,101.707997 73.3333315,86.3279978 L73.3333315,78.3893314 C69.8599983,79.1333314 62.6666651,79.6306647 58.2013319,79.6306647 C19.9973328,79.6306647 0.647999984,66.234665 0.647999984,38.2013324 C0.647999984,13.1466663 16.0279996,0.494666654 39.3466657,0.494666654 C55.0546653,0.494666654 70.1079982,7.68933314 75.3173315,19.3479995 L79.2866647,3.47199991 L94.6679976,3.47199991 L94.6679976,86.5759978 C94.6679976,112.871997 83.2559979,130.48533 50.7586654,130.48533 L50.7586654,130.48533 Z" id="path26" fill="#8C929D" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g28" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(1099.766904, 143.128930)">
|
||||
<path d="M42.6666656,19.9999995 C34.4799991,19.9999995 27.2853327,20.9919995 21.8279995,23.4733327 L21.8279995,90.8253311 L21.8279995,98.6386642 C29.2706659,104.841331 38.4493324,109.306664 50.1093321,109.306664 C71.1946649,109.306664 79.3813313,94.4226643 79.3813313,70.3586649 C79.3813313,36.1253324 66.2333317,19.9999995 42.6666656,19.9999995 M51.841332,130.64133 C32.3306659,130.64133 21.8279995,117.367997 21.8279995,117.367997 L21.8279995,138.330663 L21.7586661,166.114663 L11.9159997,166.114663 L0.425333323,166.114663 L0.494666654,7.59599981 C11.1613331,3.13066659 25.7973327,0.65066665 41.6746656,0.65066665 C82.3586646,0.65066665 101.955997,26.6973327 101.955997,71.5986649 C101.955997,107.073331 83.8426646,130.64133 51.841332,130.64133" id="path30" fill="#8C929D" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g32" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(584.042117, 143.630796)">
|
||||
<path d="M78.6666647,147.999996 C98.0159975,147.999996 110.419997,141.550663 118.606664,135.099997 L127.987997,151.350663 C115.20133,162.563996 98.0026642,168.590662 79.6586647,168.590662 C33.2693325,168.590662 0.771999981,140.30933 0.771999981,83.2533313 C0.771999981,23.4666661 35.8306658,0.147999996 75.9373314,0.147999996 C96.0319976,0.147999996 113.149331,4.86133321 124.311997,9.57466643 L123.854664,73.4533315 L123.854664,80.9893313 L123.854664,93.5479977 L64.3173317,93.5479977 L64.3173317,73.4533315 L102.271997,73.4533315 L102.729331,24.9559994 C97.7679976,22.4746661 89.0853311,20.4906662 77.4266647,20.4906662 C45.1773322,20.4906662 23.5946661,40.7773323 23.5946661,83.5013312 C23.5946661,126.91333 45.9213322,147.999996 78.6666647,147.999996" id="path34" fill="#8C929D" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g36" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(793.569045, 142.577463)">
|
||||
<path d="M22.6666661,166.666662 L1.33199997,166.666662 L1.4013333,139.378663 L1.4013333,128.214663 L1.4013333,121.707997 L1.4013333,110.353331 L1.4013333,45.3586655 L1.4013333,45.1106655 C1.4013333,18.8146662 12.813333,1.2013333 45.3106655,1.2013333 C49.7999988,1.2013333 54.193332,1.60933329 58.4586652,2.38399994 L58.4586652,21.5426661 C55.3706653,21.0693328 52.0746654,20.7999995 48.5359988,20.7999995 C30.6746659,20.7999995 22.7359994,29.9786659 22.7359994,45.3586655 L22.7359994,110.353331 L58.4586652,110.353331 L58.4586652,128.214663 L22.7359994,128.214663 L22.6666661,166.666662 L22.6666661,166.666662 Z" id="path38" fill="#8C929D" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<path d="M740.766646,146.755996 L762.101312,146.755996 L762.101312,270.793327 L740.766646,270.793327 L740.766646,146.755996 L740.766646,146.755996 Z" id="path40" fill="#8C929D" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M740.766646,287.909326 L762.101312,287.909326 L762.101312,309.243992 L740.766646,309.243992 L740.766646,287.909326 L740.766646,287.909326 Z" id="path42" fill="#8C929D" sketch:type="MSShapeGroup"></path>
|
||||
<g id="g44" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(0.532000, 0.774933)">
|
||||
<path d="M491.999988,194.666662 L464.441322,279.481326 L409.82399,447.578655 C407.014656,456.226655 394.778657,456.226655 391.96799,447.578655 L337.349325,279.481326 L155.982663,279.481326 L101.362664,447.578655 C98.5533309,456.226655 86.3173312,456.226655 83.5066646,447.578655 L28.8893326,279.481326 L1.33199997,194.666662 C-1.18266664,186.930662 1.57199996,178.455996 8.1519998,173.674662 L246.665327,0.385333324 L485.179988,173.674662 C491.759988,178.455996 494.513321,186.930662 491.999988,194.666662" id="path46" fill="#FC6D26" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g48" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(155.197863, 1.160267)">
|
||||
<path d="M91.9999977,0 L91.9999977,0 L182.683995,279.095993 L1.31599997,279.095993 L91.9999977,0 L91.9999977,0 Z" id="path50" fill="#E24329" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g52" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(247.197860, 1.160267)">
|
||||
<g id="path54"></g>
|
||||
</g>
|
||||
<g id="g56" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(28.531199, 1.160800)">
|
||||
<path d="M218.666661,0 L127.982663,279.09466 L0.890666644,279.09466 L218.666661,0 L218.666661,0 Z" id="path58" fill="#FC6D26" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g60" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(247.197860, 1.160800)">
|
||||
<g id="path62"></g>
|
||||
</g>
|
||||
<g id="g64" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(0.088533, 0.255867)">
|
||||
<path d="M29.3333326,279.999993 L29.3333326,279.999993 L1.77466662,195.185328 C-0.738666648,187.449329 2.01466662,178.974662 8.59599979,174.194662 L247.109327,0.905333311 L29.3333326,279.999993 L29.3333326,279.999993 Z" id="path66" fill="#FCA326" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g68" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(247.197860, 1.160267)">
|
||||
<g id="path70"></g>
|
||||
</g>
|
||||
<g id="g72" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(29.421866, 280.255593)">
|
||||
<path d="M0,0 L127.091997,0 L72.4733315,168.097329 C69.6626649,176.746662 57.4266652,176.746662 54.617332,168.097329 L0,0 L0,0 Z" id="path74" fill="#E24329" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g76" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(247.197860, 1.160800)">
|
||||
<path d="M0,0 L90.6839977,279.09466 L217.775995,279.09466 L0,0 L0,0 Z" id="path78" fill="#FC6D26" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g80" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(246.307061, 0.255867)">
|
||||
<path d="M218.666661,279.999993 L218.666661,279.999993 L246.225327,195.185328 C248.73866,187.449329 245.985327,178.974662 239.403994,174.194662 L0.890666644,0.905333311 L218.666661,279.999993 L218.666661,279.999993 Z" id="path82" fill="#FCA326" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
<g id="g84" stroke-width="1" fill="none" sketch:type="MSLayerGroup" transform="translate(336.973725, 280.255593)">
|
||||
<path d="M127.999997,0 L0.907999977,0 L55.5266653,168.097329 C58.3373319,176.746662 70.5733316,176.746662 73.3826648,168.097329 L127.999997,0 L127.999997,0 Z" id="path86" fill="#E24329" sketch:type="MSShapeGroup"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
65
plugins/git-sync/images/repos/gitlogo.svg
Normal file
65
plugins/git-sync/images/repos/gitlogo.svg
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
viewBox="0 0 272.96 114.01"
|
||||
version="1.1"
|
||||
id="svg10"
|
||||
sodipodi:docname="gitlogo.svg"
|
||||
inkscape:version="0.92.0 r15299">
|
||||
<metadata
|
||||
id="metadata16">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs14" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1070"
|
||||
inkscape:window-height="735"
|
||||
id="namedview12"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.0807445"
|
||||
inkscape:cx="115.66102"
|
||||
inkscape:cy="55.154427"
|
||||
inkscape:window-x="2350"
|
||||
inkscape:window-y="328"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg10" />
|
||||
<path
|
||||
fill="#f05133"
|
||||
d="M111.78,51.977,62.035,2.2381c-2.8622-2.8648-7.5082-2.8648-10.374,0l-10.329,10.33,13.102,13.102c3.0459-1.0284,6.5371-0.33888,8.9639,2.0884,2.4394,2.4424,3.124,5.9634,2.0698,9.0195l12.628,12.628c3.0551-1.0528,6.58-0.37262,9.0195,2.0712,3.4106,3.4096,3.4106,8.9345,0,12.345-3.4111,3.4116-8.936,3.4116-12.349,0-2.5645-2.5665-3.1988-6.3345-1.8999-9.4942l-11.777-11.777-0.001,30.991c0.8315,0.41162,1.6162,0.961,2.3091,1.6509,3.4096,3.4092,3.4096,8.9331,0,12.348-3.4106,3.4091-8.938,3.4091-12.345,0-3.4101-3.4146-3.4101-8.9385,0-12.348,0.84275-0.84125,1.8179-1.478,2.8584-1.9048v-31.279c-1.041-0.425-2.015-1.057-2.859-1.905-2.583-2.581-3.2051-6.372-1.8804-9.5439l-12.916-12.918-34.106,34.105c-2.8657,2.867-2.8657,7.513,0,10.378l49.742,49.739c2.8638,2.8648,7.5082,2.8648,10.376,0l49.512-49.504c2.8648-2.8662,2.8648-7.5136,0-10.379"
|
||||
id="path8" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:46.82492828px;line-height:27.43648148px;font-family:'Helvetica Rounded LT Std';-inkscape-font-specification:'Helvetica Rounded LT Std';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#999999;fill-opacity:1;stroke:none;stroke-width:1.0974592px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
|
||||
x="128.30931"
|
||||
y="69.483566"
|
||||
id="text20"
|
||||
transform="scale(0.9595033,1.0422059)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan18"
|
||||
x="128.30931"
|
||||
y="69.483566"
|
||||
style="fill:#999999;stroke-width:1.0974592px;font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;font-weight: 300">Others</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
196
plugins/git-sync/js/app.js
Normal file
196
plugins/git-sync/js/app.js
Normal file
File diff suppressed because one or more lines are too long
61
plugins/git-sync/js/vendor.js
Normal file
61
plugins/git-sync/js/vendor.js
Normal file
File diff suppressed because one or more lines are too long
44
plugins/git-sync/package.json
Normal file
44
plugins/git-sync/package.json
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"name": "trilby-grav-plugin-gitsync",
|
||||
"version": "2.1.0",
|
||||
"description": "Git Sync Grav Plugin",
|
||||
"main": "app/main.js",
|
||||
"scripts": {
|
||||
"watch": "webpack --watch --progress --color --mode development --config webpack.conf.js",
|
||||
"dev": "webpack --progress --mode development --colors --config webpack.conf.js",
|
||||
"prod": "webpack --mode production --config webpack.conf.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/trilbymedia/grav-plugin-git-sync.git"
|
||||
},
|
||||
"author": "Trilby Media, LLC",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/trilbymedia/grav-plugin-git-sync/issues"
|
||||
},
|
||||
"homepage": "https://github.com/trilbymedia/grav-plugin-git-sync#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.14.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||
"@babel/plugin-proposal-json-strings": "^7.14.2",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.14.4",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.14.4",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"css-loader": "^5.2.6",
|
||||
"eslint": "^7.27.0",
|
||||
"eslint-loader": "^4.0.2",
|
||||
"exports-loader": "^3.0.0",
|
||||
"imports-loader": "^3.0.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"style-loader": "^2.0.0",
|
||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||
"webpack": "^5.38.1",
|
||||
"webpack-cli": "^4.7.0",
|
||||
"whatwg-fetch": "^3.6.2"
|
||||
}
|
||||
}
|
||||
8
plugins/git-sync/scss/configuration/_colors.scss
Normal file
8
plugins/git-sync/scss/configuration/_colors.scss
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
$page-background: #f7f7f7;
|
||||
$content-text: #666;
|
||||
$header-background: $page-background;
|
||||
$calendar-text: $content-text;
|
||||
$calendar-details-background: #dcdcdc;
|
||||
$calendar-details-background-alt: #cecece;
|
||||
$calendar-day-background: #ffffff;
|
||||
$toast-danger-background: #C62828;
|
||||
7
plugins/git-sync/scss/git-sync.scss
Normal file
7
plugins/git-sync/scss/git-sync.scss
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// Vendors
|
||||
@import "vendor/bourbon/bourbon";
|
||||
|
||||
// Load Template Configuration
|
||||
@import "configuration/colors";
|
||||
@import "plugin/wizard";
|
||||
|
||||
191
plugins/git-sync/scss/plugin/_wizard.scss
Normal file
191
plugins/git-sync/scss/plugin/_wizard.scss
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
[data-remodal-id="wizard"], [data-remodal-id="reset-local"] {
|
||||
.button[disabled] {
|
||||
&, &:hover {
|
||||
background: #ccc;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&:active {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
form [class^="step-"] a:not(.button):not([target]) {
|
||||
vertical-align: middle;
|
||||
color: #5591c7;
|
||||
|
||||
&:hover {
|
||||
color: #366188;
|
||||
}
|
||||
}
|
||||
|
||||
.step-1 a {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.access-tokens {
|
||||
h3 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
a {
|
||||
vertical-align: inherit !important;
|
||||
}
|
||||
}
|
||||
|
||||
.access-tokens-details {
|
||||
> p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
> div > ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 0;
|
||||
padding-top: 0.5rem;
|
||||
border-top: 3px solid transparent;
|
||||
}
|
||||
|
||||
.wizard-padding {
|
||||
padding: 0 3rem;
|
||||
|
||||
p {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
input[disabled] {
|
||||
background: #efefef;
|
||||
border-color: #ddd;
|
||||
}
|
||||
|
||||
input.invalid {
|
||||
border-color: #f4516d;
|
||||
color: #f4516d;
|
||||
}
|
||||
|
||||
label {
|
||||
&.disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.columns {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.column {
|
||||
flex: 1;
|
||||
|
||||
&:first-child {
|
||||
width: 35%;
|
||||
flex: none;
|
||||
border-right: 1px solid #ddd;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-1 {
|
||||
div.column:nth-child(1) {
|
||||
flex-grow: 1.5;
|
||||
width: 15%;
|
||||
|
||||
> label:nth-child(4) {
|
||||
width: 110%;
|
||||
}
|
||||
}
|
||||
|
||||
div.column:nth-child(2) {
|
||||
margin-left: 25px;
|
||||
}
|
||||
div.column:nth-child(2) > label:nth-child(1) > input:nth-child(1), div.column:nth-child(2) > label:nth-child(2) > input:nth-child(1) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.no_user {
|
||||
float: right;
|
||||
font-size: .8rem;
|
||||
padding: 0;
|
||||
|
||||
input {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step-2 {
|
||||
.info {
|
||||
margin: 0.2rem 0;
|
||||
padding: 0.5rem 1.5rem;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.step-4 {
|
||||
.info {
|
||||
font-size: 100%;
|
||||
margin: 0.2rem 0;
|
||||
}
|
||||
|
||||
.alert, .warning {
|
||||
padding: 0.5rem 1.5rem;
|
||||
}
|
||||
|
||||
.fa.fa-warning {
|
||||
color: #ff7d3b;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.wizard-padding label > * {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.info-desc {
|
||||
color: #0091ff;
|
||||
float: right;
|
||||
margin-right: .5rem;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: .5rem 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#admin-main [data-grav-field="git-wizard"] {
|
||||
margin: 0 1rem;
|
||||
.danger.button-bar {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.button {
|
||||
top: 0 !important;
|
||||
@include transform(translateY(0) !important);
|
||||
}
|
||||
}
|
||||
411
plugins/git-sync/scss/vendor/bourbon/_bourbon-deprecated-upcoming.scss
vendored
Normal file
411
plugins/git-sync/scss/vendor/bourbon/_bourbon-deprecated-upcoming.scss
vendored
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
// The following features have been deprecated and will be removed in the next MAJOR version release
|
||||
|
||||
@mixin inline-block {
|
||||
display: inline-block;
|
||||
|
||||
@warn "The inline-block mixin is deprecated and will be removed in the next major version release";
|
||||
}
|
||||
|
||||
@mixin button ($style: simple, $base-color: #4294f0, $text-size: inherit, $padding: 7px 18px) {
|
||||
|
||||
@if type-of($style) == string and type-of($base-color) == color {
|
||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
||||
}
|
||||
|
||||
@if type-of($style) == string and type-of($base-color) == number {
|
||||
$padding: $text-size;
|
||||
$text-size: $base-color;
|
||||
$base-color: #4294f0;
|
||||
|
||||
@if $padding == inherit {
|
||||
$padding: 7px 18px;
|
||||
}
|
||||
|
||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
||||
}
|
||||
|
||||
@if type-of($style) == color and type-of($base-color) == color {
|
||||
$base-color: $style;
|
||||
$style: simple;
|
||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
||||
}
|
||||
|
||||
@if type-of($style) == color and type-of($base-color) == number {
|
||||
$padding: $text-size;
|
||||
$text-size: $base-color;
|
||||
$base-color: $style;
|
||||
$style: simple;
|
||||
|
||||
@if $padding == inherit {
|
||||
$padding: 7px 18px;
|
||||
}
|
||||
|
||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
||||
}
|
||||
|
||||
@if type-of($style) == number {
|
||||
$padding: $base-color;
|
||||
$text-size: $style;
|
||||
$base-color: #4294f0;
|
||||
$style: simple;
|
||||
|
||||
@if $padding == #4294f0 {
|
||||
$padding: 7px 18px;
|
||||
}
|
||||
|
||||
@include buttonstyle($style, $base-color, $text-size, $padding);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@warn "The button mixin is deprecated and will be removed in the next major version release";
|
||||
}
|
||||
|
||||
// Selector Style Button
|
||||
@mixin buttonstyle($type, $b-color, $t-size, $pad) {
|
||||
// Grayscale button
|
||||
@if $type == simple and $b-color == grayscale($b-color) {
|
||||
@include simple($b-color, true, $t-size, $pad);
|
||||
}
|
||||
|
||||
@if $type == shiny and $b-color == grayscale($b-color) {
|
||||
@include shiny($b-color, true, $t-size, $pad);
|
||||
}
|
||||
|
||||
@if $type == pill and $b-color == grayscale($b-color) {
|
||||
@include pill($b-color, true, $t-size, $pad);
|
||||
}
|
||||
|
||||
@if $type == flat and $b-color == grayscale($b-color) {
|
||||
@include flat($b-color, true, $t-size, $pad);
|
||||
}
|
||||
|
||||
// Colored button
|
||||
@if $type == simple {
|
||||
@include simple($b-color, false, $t-size, $pad);
|
||||
}
|
||||
|
||||
@else if $type == shiny {
|
||||
@include shiny($b-color, false, $t-size, $pad);
|
||||
}
|
||||
|
||||
@else if $type == pill {
|
||||
@include pill($b-color, false, $t-size, $pad);
|
||||
}
|
||||
|
||||
@else if $type == flat {
|
||||
@include flat($b-color, false, $t-size, $pad);
|
||||
}
|
||||
}
|
||||
|
||||
// Simple Button
|
||||
@mixin simple($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) {
|
||||
$color: hsl(0, 0, 100%);
|
||||
$border: adjust-color($base-color, $saturation: 9%, $lightness: -14%);
|
||||
$inset-shadow: adjust-color($base-color, $saturation: -8%, $lightness: 15%);
|
||||
$stop-gradient: adjust-color($base-color, $saturation: 9%, $lightness: -11%);
|
||||
$text-shadow: adjust-color($base-color, $saturation: 15%, $lightness: -18%);
|
||||
|
||||
@if is-light($base-color) {
|
||||
$color: hsl(0, 0, 20%);
|
||||
$text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%);
|
||||
}
|
||||
|
||||
@if $grayscale == true {
|
||||
$border: grayscale($border);
|
||||
$inset-shadow: grayscale($inset-shadow);
|
||||
$stop-gradient: grayscale($stop-gradient);
|
||||
$text-shadow: grayscale($text-shadow);
|
||||
}
|
||||
|
||||
border: 1px solid $border;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow;
|
||||
color: $color;
|
||||
display: inline-block;
|
||||
font-size: $textsize;
|
||||
font-weight: bold;
|
||||
@include linear-gradient ($base-color, $stop-gradient);
|
||||
padding: $padding;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 0 $text-shadow;
|
||||
background-clip: padding-box;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
$base-color-hover: adjust-color($base-color, $saturation: -4%, $lightness: -5%);
|
||||
$inset-shadow-hover: adjust-color($base-color, $saturation: -7%, $lightness: 5%);
|
||||
$stop-gradient-hover: adjust-color($base-color, $saturation: 8%, $lightness: -14%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$base-color-hover: grayscale($base-color-hover);
|
||||
$inset-shadow-hover: grayscale($inset-shadow-hover);
|
||||
$stop-gradient-hover: grayscale($stop-gradient-hover);
|
||||
}
|
||||
|
||||
@include linear-gradient ($base-color-hover, $stop-gradient-hover);
|
||||
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow-hover;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:active:not(:disabled),
|
||||
&:focus:not(:disabled) {
|
||||
$border-active: adjust-color($base-color, $saturation: 9%, $lightness: -14%);
|
||||
$inset-shadow-active: adjust-color($base-color, $saturation: 7%, $lightness: -17%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$border-active: grayscale($border-active);
|
||||
$inset-shadow-active: grayscale($inset-shadow-active);
|
||||
}
|
||||
|
||||
border: 1px solid $border-active;
|
||||
box-shadow: inset 0 0 8px 4px $inset-shadow-active, inset 0 0 8px 4px $inset-shadow-active;
|
||||
}
|
||||
}
|
||||
|
||||
// Shiny Button
|
||||
@mixin shiny($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) {
|
||||
$color: hsl(0, 0, 100%);
|
||||
$border: adjust-color($base-color, $red: -117, $green: -111, $blue: -81);
|
||||
$border-bottom: adjust-color($base-color, $red: -126, $green: -127, $blue: -122);
|
||||
$fourth-stop: adjust-color($base-color, $red: -79, $green: -70, $blue: -46);
|
||||
$inset-shadow: adjust-color($base-color, $red: 37, $green: 29, $blue: 12);
|
||||
$second-stop: adjust-color($base-color, $red: -56, $green: -50, $blue: -33);
|
||||
$text-shadow: adjust-color($base-color, $red: -140, $green: -141, $blue: -114);
|
||||
$third-stop: adjust-color($base-color, $red: -86, $green: -75, $blue: -48);
|
||||
|
||||
@if is-light($base-color) {
|
||||
$color: hsl(0, 0, 20%);
|
||||
$text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%);
|
||||
}
|
||||
|
||||
@if $grayscale == true {
|
||||
$border: grayscale($border);
|
||||
$border-bottom: grayscale($border-bottom);
|
||||
$fourth-stop: grayscale($fourth-stop);
|
||||
$inset-shadow: grayscale($inset-shadow);
|
||||
$second-stop: grayscale($second-stop);
|
||||
$text-shadow: grayscale($text-shadow);
|
||||
$third-stop: grayscale($third-stop);
|
||||
}
|
||||
|
||||
@include linear-gradient(top, $base-color 0%, $second-stop 50%, $third-stop 50%, $fourth-stop 100%);
|
||||
|
||||
border: 1px solid $border;
|
||||
border-bottom: 1px solid $border-bottom;
|
||||
border-radius: 5px;
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow;
|
||||
color: $color;
|
||||
display: inline-block;
|
||||
font-size: $textsize;
|
||||
font-weight: bold;
|
||||
padding: $padding;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 -1px 1px $text-shadow;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
$first-stop-hover: adjust-color($base-color, $red: -13, $green: -15, $blue: -18);
|
||||
$second-stop-hover: adjust-color($base-color, $red: -66, $green: -62, $blue: -51);
|
||||
$third-stop-hover: adjust-color($base-color, $red: -93, $green: -85, $blue: -66);
|
||||
$fourth-stop-hover: adjust-color($base-color, $red: -86, $green: -80, $blue: -63);
|
||||
|
||||
@if $grayscale == true {
|
||||
$first-stop-hover: grayscale($first-stop-hover);
|
||||
$second-stop-hover: grayscale($second-stop-hover);
|
||||
$third-stop-hover: grayscale($third-stop-hover);
|
||||
$fourth-stop-hover: grayscale($fourth-stop-hover);
|
||||
}
|
||||
|
||||
@include linear-gradient(top, $first-stop-hover 0%,
|
||||
$second-stop-hover 50%,
|
||||
$third-stop-hover 50%,
|
||||
$fourth-stop-hover 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:active:not(:disabled),
|
||||
&:focus:not(:disabled) {
|
||||
$inset-shadow-active: adjust-color($base-color, $red: -111, $green: -116, $blue: -122);
|
||||
|
||||
@if $grayscale == true {
|
||||
$inset-shadow-active: grayscale($inset-shadow-active);
|
||||
}
|
||||
|
||||
box-shadow: inset 0 0 20px 0 $inset-shadow-active;
|
||||
}
|
||||
}
|
||||
|
||||
// Pill Button
|
||||
@mixin pill($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) {
|
||||
$color: hsl(0, 0, 100%);
|
||||
$border-bottom: adjust-color($base-color, $hue: 8, $saturation: -11%, $lightness: -26%);
|
||||
$border-sides: adjust-color($base-color, $hue: 4, $saturation: -21%, $lightness: -21%);
|
||||
$border-top: adjust-color($base-color, $hue: -1, $saturation: -30%, $lightness: -15%);
|
||||
$inset-shadow: adjust-color($base-color, $hue: -1, $saturation: -1%, $lightness: 7%);
|
||||
$stop-gradient: adjust-color($base-color, $hue: 8, $saturation: 14%, $lightness: -10%);
|
||||
$text-shadow: adjust-color($base-color, $hue: 5, $saturation: -19%, $lightness: -15%);
|
||||
|
||||
@if is-light($base-color) {
|
||||
$color: hsl(0, 0, 20%);
|
||||
$text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%);
|
||||
}
|
||||
|
||||
@if $grayscale == true {
|
||||
$border-bottom: grayscale($border-bottom);
|
||||
$border-sides: grayscale($border-sides);
|
||||
$border-top: grayscale($border-top);
|
||||
$inset-shadow: grayscale($inset-shadow);
|
||||
$stop-gradient: grayscale($stop-gradient);
|
||||
$text-shadow: grayscale($text-shadow);
|
||||
}
|
||||
|
||||
border: 1px solid $border-top;
|
||||
border-color: $border-top $border-sides $border-bottom;
|
||||
border-radius: 16px;
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow;
|
||||
color: $color;
|
||||
display: inline-block;
|
||||
font-size: $textsize;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
@include linear-gradient ($base-color, $stop-gradient);
|
||||
padding: $padding;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 -1px 1px $text-shadow;
|
||||
background-clip: padding-box;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
$base-color-hover: adjust-color($base-color, $lightness: -4.5%);
|
||||
$border-bottom: adjust-color($base-color, $hue: 8, $saturation: 13.5%, $lightness: -32%);
|
||||
$border-sides: adjust-color($base-color, $hue: 4, $saturation: -2%, $lightness: -27%);
|
||||
$border-top: adjust-color($base-color, $hue: -1, $saturation: -17%, $lightness: -21%);
|
||||
$inset-shadow-hover: adjust-color($base-color, $saturation: -1%, $lightness: 3%);
|
||||
$stop-gradient-hover: adjust-color($base-color, $hue: 8, $saturation: -4%, $lightness: -15.5%);
|
||||
$text-shadow-hover: adjust-color($base-color, $hue: 5, $saturation: -5%, $lightness: -22%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$base-color-hover: grayscale($base-color-hover);
|
||||
$border-bottom: grayscale($border-bottom);
|
||||
$border-sides: grayscale($border-sides);
|
||||
$border-top: grayscale($border-top);
|
||||
$inset-shadow-hover: grayscale($inset-shadow-hover);
|
||||
$stop-gradient-hover: grayscale($stop-gradient-hover);
|
||||
$text-shadow-hover: grayscale($text-shadow-hover);
|
||||
}
|
||||
|
||||
@include linear-gradient ($base-color-hover, $stop-gradient-hover);
|
||||
|
||||
background-clip: padding-box;
|
||||
border: 1px solid $border-top;
|
||||
border-color: $border-top $border-sides $border-bottom;
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow-hover;
|
||||
cursor: pointer;
|
||||
text-shadow: 0 -1px 1px $text-shadow-hover;
|
||||
}
|
||||
|
||||
&:active:not(:disabled),
|
||||
&:focus:not(:disabled) {
|
||||
$active-color: adjust-color($base-color, $hue: 4, $saturation: -12%, $lightness: -10%);
|
||||
$border-active: adjust-color($base-color, $hue: 6, $saturation: -2.5%, $lightness: -30%);
|
||||
$border-bottom-active: adjust-color($base-color, $hue: 11, $saturation: 6%, $lightness: -31%);
|
||||
$inset-shadow-active: adjust-color($base-color, $hue: 9, $saturation: 2%, $lightness: -21.5%);
|
||||
$text-shadow-active: adjust-color($base-color, $hue: 5, $saturation: -12%, $lightness: -21.5%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$active-color: grayscale($active-color);
|
||||
$border-active: grayscale($border-active);
|
||||
$border-bottom-active: grayscale($border-bottom-active);
|
||||
$inset-shadow-active: grayscale($inset-shadow-active);
|
||||
$text-shadow-active: grayscale($text-shadow-active);
|
||||
}
|
||||
|
||||
background: $active-color;
|
||||
border: 1px solid $border-active;
|
||||
border-bottom: 1px solid $border-bottom-active;
|
||||
box-shadow: inset 0 0 6px 3px $inset-shadow-active;
|
||||
text-shadow: 0 -1px 1px $text-shadow-active;
|
||||
}
|
||||
}
|
||||
|
||||
// Flat Button
|
||||
@mixin flat($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) {
|
||||
$color: hsl(0, 0, 100%);
|
||||
|
||||
@if is-light($base-color) {
|
||||
$color: hsl(0, 0, 20%);
|
||||
}
|
||||
|
||||
background-color: $base-color;
|
||||
border-radius: 3px;
|
||||
border: 0;
|
||||
color: $color;
|
||||
display: inline-block;
|
||||
font-size: $textsize;
|
||||
font-weight: bold;
|
||||
padding: $padding;
|
||||
text-decoration: none;
|
||||
background-clip: padding-box;
|
||||
|
||||
&:hover:not(:disabled){
|
||||
$base-color-hover: adjust-color($base-color, $saturation: 4%, $lightness: 5%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$base-color-hover: grayscale($base-color-hover);
|
||||
}
|
||||
|
||||
background-color: $base-color-hover;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:active:not(:disabled),
|
||||
&:focus:not(:disabled) {
|
||||
$base-color-active: adjust-color($base-color, $saturation: -4%, $lightness: -5%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$base-color-active: grayscale($base-color-active);
|
||||
}
|
||||
|
||||
background-color: $base-color-active;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// Flexible grid
|
||||
@function flex-grid($columns, $container-columns: $fg-max-columns) {
|
||||
$width: $columns * $fg-column + ($columns - 1) * $fg-gutter;
|
||||
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
|
||||
@return percentage($width / $container-width);
|
||||
|
||||
@warn "The flex-grid function is deprecated and will be removed in the next major version release";
|
||||
}
|
||||
|
||||
// Flexible gutter
|
||||
@function flex-gutter($container-columns: $fg-max-columns, $gutter: $fg-gutter) {
|
||||
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
|
||||
@return percentage($gutter / $container-width);
|
||||
|
||||
@warn "The flex-gutter function is deprecated and will be removed in the next major version release";
|
||||
}
|
||||
|
||||
@function grid-width($n) {
|
||||
@return $n * $gw-column + ($n - 1) * $gw-gutter;
|
||||
|
||||
@warn "The grid-width function is deprecated and will be removed in the next major version release";
|
||||
}
|
||||
|
||||
@function golden-ratio($value, $increment) {
|
||||
@return modular-scale($increment, $value, $ratio: $golden);
|
||||
|
||||
@warn "The golden-ratio function is deprecated and will be removed in the next major version release. Please use the modular-scale function, instead.";
|
||||
}
|
||||
|
||||
@mixin box-sizing($box) {
|
||||
@include prefixer(box-sizing, $box, webkit moz spec);
|
||||
|
||||
@warn "The box-sizing mixin is deprecated and will be removed in the next major version release. This property can now be used un-prefixed.";
|
||||
}
|
||||
87
plugins/git-sync/scss/vendor/bourbon/_bourbon.scss
vendored
Normal file
87
plugins/git-sync/scss/vendor/bourbon/_bourbon.scss
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
// Bourbon 4.2.7
|
||||
// http://bourbon.io
|
||||
// Copyright 2011-2015 thoughtbot, inc.
|
||||
// MIT License
|
||||
|
||||
@import "settings/prefixer";
|
||||
@import "settings/px-to-em";
|
||||
@import "settings/asset-pipeline";
|
||||
|
||||
@import "functions/assign-inputs";
|
||||
@import "functions/contains";
|
||||
@import "functions/contains-falsy";
|
||||
@import "functions/is-length";
|
||||
@import "functions/is-light";
|
||||
@import "functions/is-number";
|
||||
@import "functions/is-size";
|
||||
@import "functions/px-to-em";
|
||||
@import "functions/px-to-rem";
|
||||
@import "functions/shade";
|
||||
@import "functions/strip-units";
|
||||
@import "functions/tint";
|
||||
@import "functions/transition-property-name";
|
||||
@import "functions/unpack";
|
||||
@import "functions/modular-scale";
|
||||
|
||||
@import "helpers/convert-units";
|
||||
@import "helpers/directional-values";
|
||||
@import "helpers/font-source-declaration";
|
||||
@import "helpers/gradient-positions-parser";
|
||||
@import "helpers/linear-angle-parser";
|
||||
@import "helpers/linear-gradient-parser";
|
||||
@import "helpers/linear-positions-parser";
|
||||
@import "helpers/linear-side-corner-parser";
|
||||
@import "helpers/radial-arg-parser";
|
||||
@import "helpers/radial-positions-parser";
|
||||
@import "helpers/radial-gradient-parser";
|
||||
@import "helpers/render-gradients";
|
||||
@import "helpers/shape-size-stripper";
|
||||
@import "helpers/str-to-num";
|
||||
|
||||
@import "css3/animation";
|
||||
@import "css3/appearance";
|
||||
@import "css3/backface-visibility";
|
||||
@import "css3/background";
|
||||
@import "css3/background-image";
|
||||
@import "css3/border-image";
|
||||
@import "css3/calc";
|
||||
@import "css3/columns";
|
||||
@import "css3/filter";
|
||||
@import "css3/flex-box";
|
||||
@import "css3/font-face";
|
||||
@import "css3/font-feature-settings";
|
||||
@import "css3/hidpi-media-query";
|
||||
@import "css3/hyphens";
|
||||
@import "css3/image-rendering";
|
||||
@import "css3/keyframes";
|
||||
@import "css3/linear-gradient";
|
||||
@import "css3/perspective";
|
||||
@import "css3/placeholder";
|
||||
@import "css3/radial-gradient";
|
||||
@import "css3/selection";
|
||||
@import "css3/text-decoration";
|
||||
@import "css3/transform";
|
||||
@import "css3/transition";
|
||||
@import "css3/user-select";
|
||||
|
||||
@import "addons/border-color";
|
||||
@import "addons/border-radius";
|
||||
@import "addons/border-style";
|
||||
@import "addons/border-width";
|
||||
@import "addons/buttons";
|
||||
@import "addons/clearfix";
|
||||
@import "addons/ellipsis";
|
||||
@import "addons/font-stacks";
|
||||
@import "addons/hide-text";
|
||||
@import "addons/margin";
|
||||
@import "addons/padding";
|
||||
@import "addons/position";
|
||||
@import "addons/prefixer";
|
||||
@import "addons/retina-image";
|
||||
@import "addons/size";
|
||||
@import "addons/text-inputs";
|
||||
@import "addons/timing-functions";
|
||||
@import "addons/triangle";
|
||||
@import "addons/word-wrap";
|
||||
|
||||
@import "bourbon-deprecated-upcoming";
|
||||
26
plugins/git-sync/scss/vendor/bourbon/addons/_border-color.scss
vendored
Normal file
26
plugins/git-sync/scss/vendor/bourbon/addons/_border-color.scss
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Provides a quick method for targeting `border-color` on specific sides of a box. Use a `null` value to “skip” a side.
|
||||
///
|
||||
/// @param {Arglist} $vals
|
||||
/// List of arguments
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include border-color(#a60b55 #76cd9c null #e8ae1a);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// border-left-color: #e8ae1a;
|
||||
/// border-right-color: #76cd9c;
|
||||
/// border-top-color: #a60b55;
|
||||
/// }
|
||||
///
|
||||
/// @require {mixin} directional-property
|
||||
///
|
||||
/// @output `border-color`
|
||||
|
||||
@mixin border-color($vals...) {
|
||||
@include directional-property(border, color, $vals...);
|
||||
}
|
||||
48
plugins/git-sync/scss/vendor/bourbon/addons/_border-radius.scss
vendored
Normal file
48
plugins/git-sync/scss/vendor/bourbon/addons/_border-radius.scss
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Provides a quick method for targeting `border-radius` on both corners on the side of a box.
|
||||
///
|
||||
/// @param {Number} $radii
|
||||
/// List of arguments
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element-one {
|
||||
/// @include border-top-radius(5px);
|
||||
/// }
|
||||
///
|
||||
/// .element-two {
|
||||
/// @include border-left-radius(3px);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element-one {
|
||||
/// border-top-left-radius: 5px;
|
||||
/// border-top-right-radius: 5px;
|
||||
/// }
|
||||
///
|
||||
/// .element-two {
|
||||
/// border-bottom-left-radius: 3px;
|
||||
/// border-top-left-radius: 3px;
|
||||
/// }
|
||||
///
|
||||
/// @output `border-radius`
|
||||
|
||||
@mixin border-top-radius($radii) {
|
||||
border-top-left-radius: $radii;
|
||||
border-top-right-radius: $radii;
|
||||
}
|
||||
|
||||
@mixin border-right-radius($radii) {
|
||||
border-bottom-right-radius: $radii;
|
||||
border-top-right-radius: $radii;
|
||||
}
|
||||
|
||||
@mixin border-bottom-radius($radii) {
|
||||
border-bottom-left-radius: $radii;
|
||||
border-bottom-right-radius: $radii;
|
||||
}
|
||||
|
||||
@mixin border-left-radius($radii) {
|
||||
border-bottom-left-radius: $radii;
|
||||
border-top-left-radius: $radii;
|
||||
}
|
||||
25
plugins/git-sync/scss/vendor/bourbon/addons/_border-style.scss
vendored
Normal file
25
plugins/git-sync/scss/vendor/bourbon/addons/_border-style.scss
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Provides a quick method for targeting `border-style` on specific sides of a box. Use a `null` value to “skip” a side.
|
||||
///
|
||||
/// @param {Arglist} $vals
|
||||
/// List of arguments
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include border-style(dashed null solid);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// border-bottom-style: solid;
|
||||
/// border-top-style: dashed;
|
||||
/// }
|
||||
///
|
||||
/// @require {mixin} directional-property
|
||||
///
|
||||
/// @output `border-style`
|
||||
|
||||
@mixin border-style($vals...) {
|
||||
@include directional-property(border, style, $vals...);
|
||||
}
|
||||
25
plugins/git-sync/scss/vendor/bourbon/addons/_border-width.scss
vendored
Normal file
25
plugins/git-sync/scss/vendor/bourbon/addons/_border-width.scss
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Provides a quick method for targeting `border-width` on specific sides of a box. Use a `null` value to “skip” a side.
|
||||
///
|
||||
/// @param {Arglist} $vals
|
||||
/// List of arguments
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include border-width(1em null 20px);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// border-bottom-width: 20px;
|
||||
/// border-top-width: 1em;
|
||||
/// }
|
||||
///
|
||||
/// @require {mixin} directional-property
|
||||
///
|
||||
/// @output `border-width`
|
||||
|
||||
@mixin border-width($vals...) {
|
||||
@include directional-property(border, width, $vals...);
|
||||
}
|
||||
64
plugins/git-sync/scss/vendor/bourbon/addons/_buttons.scss
vendored
Normal file
64
plugins/git-sync/scss/vendor/bourbon/addons/_buttons.scss
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Generates variables for all buttons. Please note that you must use interpolation on the variable: `#{$all-buttons}`.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// #{$all-buttons} {
|
||||
/// background-color: #f00;
|
||||
/// }
|
||||
///
|
||||
/// #{$all-buttons-focus},
|
||||
/// #{$all-buttons-hover} {
|
||||
/// background-color: #0f0;
|
||||
/// }
|
||||
///
|
||||
/// #{$all-buttons-active} {
|
||||
/// background-color: #00f;
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// button,
|
||||
/// input[type="button"],
|
||||
/// input[type="reset"],
|
||||
/// input[type="submit"] {
|
||||
/// background-color: #f00;
|
||||
/// }
|
||||
///
|
||||
/// button:focus,
|
||||
/// input[type="button"]:focus,
|
||||
/// input[type="reset"]:focus,
|
||||
/// input[type="submit"]:focus,
|
||||
/// button:hover,
|
||||
/// input[type="button"]:hover,
|
||||
/// input[type="reset"]:hover,
|
||||
/// input[type="submit"]:hover {
|
||||
/// background-color: #0f0;
|
||||
/// }
|
||||
///
|
||||
/// button:active,
|
||||
/// input[type="button"]:active,
|
||||
/// input[type="reset"]:active,
|
||||
/// input[type="submit"]:active {
|
||||
/// background-color: #00f;
|
||||
/// }
|
||||
///
|
||||
/// @require assign-inputs
|
||||
///
|
||||
/// @type List
|
||||
///
|
||||
/// @todo Remove double assigned variables (Lines 59–62) in v5.0.0
|
||||
|
||||
$buttons-list: 'button',
|
||||
'input[type="button"]',
|
||||
'input[type="reset"]',
|
||||
'input[type="submit"]';
|
||||
|
||||
$all-buttons: assign-inputs($buttons-list);
|
||||
$all-buttons-active: assign-inputs($buttons-list, active);
|
||||
$all-buttons-focus: assign-inputs($buttons-list, focus);
|
||||
$all-buttons-hover: assign-inputs($buttons-list, hover);
|
||||
|
||||
$all-button-inputs: $all-buttons;
|
||||
$all-button-inputs-active: $all-buttons-active;
|
||||
$all-button-inputs-focus: $all-buttons-focus;
|
||||
$all-button-inputs-hover: $all-buttons-hover;
|
||||
25
plugins/git-sync/scss/vendor/bourbon/addons/_clearfix.scss
vendored
Normal file
25
plugins/git-sync/scss/vendor/bourbon/addons/_clearfix.scss
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Provides an easy way to include a clearfix for containing floats.
|
||||
///
|
||||
/// @link http://cssmojo.com/latest_new_clearfix_so_far/
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include clearfix;
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element::after {
|
||||
/// clear: both;
|
||||
/// content: "";
|
||||
/// display: table;
|
||||
/// }
|
||||
|
||||
@mixin clearfix {
|
||||
&::after {
|
||||
clear: both;
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
}
|
||||
30
plugins/git-sync/scss/vendor/bourbon/addons/_ellipsis.scss
vendored
Normal file
30
plugins/git-sync/scss/vendor/bourbon/addons/_ellipsis.scss
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Truncates text and adds an ellipsis to represent overflow.
|
||||
///
|
||||
/// @param {Number} $width [100%]
|
||||
/// Max-width for the string to respect before being truncated
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include ellipsis;
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// display: inline-block;
|
||||
/// max-width: 100%;
|
||||
/// overflow: hidden;
|
||||
/// text-overflow: ellipsis;
|
||||
/// white-space: nowrap;
|
||||
/// word-wrap: normal;
|
||||
/// }
|
||||
|
||||
@mixin ellipsis($width: 100%) {
|
||||
display: inline-block;
|
||||
max-width: $width;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
}
|
||||
31
plugins/git-sync/scss/vendor/bourbon/addons/_font-stacks.scss
vendored
Normal file
31
plugins/git-sync/scss/vendor/bourbon/addons/_font-stacks.scss
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Georgia font stack.
|
||||
///
|
||||
/// @type List
|
||||
|
||||
$georgia: "Georgia", "Cambria", "Times New Roman", "Times", serif;
|
||||
|
||||
/// Helvetica font stack.
|
||||
///
|
||||
/// @type List
|
||||
|
||||
$helvetica: "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif;
|
||||
|
||||
/// Lucida Grande font stack.
|
||||
///
|
||||
/// @type List
|
||||
|
||||
$lucida-grande: "Lucida Grande", "Tahoma", "Verdana", "Arial", sans-serif;
|
||||
|
||||
/// Monospace font stack.
|
||||
///
|
||||
/// @type List
|
||||
|
||||
$monospace: "Bitstream Vera Sans Mono", "Consolas", "Courier", monospace;
|
||||
|
||||
/// Verdana font stack.
|
||||
///
|
||||
/// @type List
|
||||
|
||||
$verdana: "Verdana", "Geneva", sans-serif;
|
||||
27
plugins/git-sync/scss/vendor/bourbon/addons/_hide-text.scss
vendored
Normal file
27
plugins/git-sync/scss/vendor/bourbon/addons/_hide-text.scss
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/// Hides the text in an element, commonly used to show an image. Some elements will need block-level styles applied.
|
||||
///
|
||||
/// @link http://zeldman.com/2012/03/01/replacing-the-9999px-hack-new-image-replacement
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include hide-text;
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// overflow: hidden;
|
||||
/// text-indent: 101%;
|
||||
/// white-space: nowrap;
|
||||
/// }
|
||||
///
|
||||
/// @todo Remove height argument in v5.0.0
|
||||
|
||||
@mixin hide-text($height: null) {
|
||||
overflow: hidden;
|
||||
text-indent: 101%;
|
||||
white-space: nowrap;
|
||||
|
||||
@if $height {
|
||||
@warn "The `hide-text` mixin has changed and no longer requires a height. The height argument will no longer be accepted in v5.0.0";
|
||||
}
|
||||
}
|
||||
26
plugins/git-sync/scss/vendor/bourbon/addons/_margin.scss
vendored
Normal file
26
plugins/git-sync/scss/vendor/bourbon/addons/_margin.scss
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Provides a quick method for targeting `margin` on specific sides of a box. Use a `null` value to “skip” a side.
|
||||
///
|
||||
/// @param {Arglist} $vals
|
||||
/// List of arguments
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include margin(null 10px 3em 20vh);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// margin-bottom: 3em;
|
||||
/// margin-left: 20vh;
|
||||
/// margin-right: 10px;
|
||||
/// }
|
||||
///
|
||||
/// @require {mixin} directional-property
|
||||
///
|
||||
/// @output `margin`
|
||||
|
||||
@mixin margin($vals...) {
|
||||
@include directional-property(margin, false, $vals...);
|
||||
}
|
||||
26
plugins/git-sync/scss/vendor/bourbon/addons/_padding.scss
vendored
Normal file
26
plugins/git-sync/scss/vendor/bourbon/addons/_padding.scss
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Provides a quick method for targeting `padding` on specific sides of a box. Use a `null` value to “skip” a side.
|
||||
///
|
||||
/// @param {Arglist} $vals
|
||||
/// List of arguments
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include padding(12vh null 10px 5%);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// padding-bottom: 10px;
|
||||
/// padding-left: 5%;
|
||||
/// padding-top: 12vh;
|
||||
/// }
|
||||
///
|
||||
/// @require {mixin} directional-property
|
||||
///
|
||||
/// @output `padding`
|
||||
|
||||
@mixin padding($vals...) {
|
||||
@include directional-property(padding, false, $vals...);
|
||||
}
|
||||
48
plugins/git-sync/scss/vendor/bourbon/addons/_position.scss
vendored
Normal file
48
plugins/git-sync/scss/vendor/bourbon/addons/_position.scss
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Provides a quick method for setting an element’s position. Use a `null` value to “skip” a side.
|
||||
///
|
||||
/// @param {Position} $position [relative]
|
||||
/// A CSS position value
|
||||
///
|
||||
/// @param {Arglist} $coordinates [null null null null]
|
||||
/// List of values that correspond to the 4-value syntax for the edges of a box
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include position(absolute, 0 null null 10em);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// left: 10em;
|
||||
/// position: absolute;
|
||||
/// top: 0;
|
||||
/// }
|
||||
///
|
||||
/// @require {function} is-length
|
||||
/// @require {function} unpack
|
||||
|
||||
@mixin position($position: relative, $coordinates: null null null null) {
|
||||
@if type-of($position) == list {
|
||||
$coordinates: $position;
|
||||
$position: relative;
|
||||
}
|
||||
|
||||
$coordinates: unpack($coordinates);
|
||||
|
||||
$offsets: (
|
||||
top: nth($coordinates, 1),
|
||||
right: nth($coordinates, 2),
|
||||
bottom: nth($coordinates, 3),
|
||||
left: nth($coordinates, 4)
|
||||
);
|
||||
|
||||
position: $position;
|
||||
|
||||
@each $offset, $value in $offsets {
|
||||
@if is-length($value) {
|
||||
#{$offset}: $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
66
plugins/git-sync/scss/vendor/bourbon/addons/_prefixer.scss
vendored
Normal file
66
plugins/git-sync/scss/vendor/bourbon/addons/_prefixer.scss
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// A mixin for generating vendor prefixes on non-standardized properties.
|
||||
///
|
||||
/// @param {String} $property
|
||||
/// Property to prefix
|
||||
///
|
||||
/// @param {*} $value
|
||||
/// Value to use
|
||||
///
|
||||
/// @param {List} $prefixes
|
||||
/// Prefixes to define
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include prefixer(border-radius, 10px, webkit ms spec);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// -webkit-border-radius: 10px;
|
||||
/// -moz-border-radius: 10px;
|
||||
/// border-radius: 10px;
|
||||
/// }
|
||||
///
|
||||
/// @require {variable} $prefix-for-webkit
|
||||
/// @require {variable} $prefix-for-mozilla
|
||||
/// @require {variable} $prefix-for-microsoft
|
||||
/// @require {variable} $prefix-for-opera
|
||||
/// @require {variable} $prefix-for-spec
|
||||
|
||||
@mixin prefixer($property, $value, $prefixes) {
|
||||
@each $prefix in $prefixes {
|
||||
@if $prefix == webkit {
|
||||
@if $prefix-for-webkit {
|
||||
-webkit-#{$property}: $value;
|
||||
}
|
||||
} @else if $prefix == moz {
|
||||
@if $prefix-for-mozilla {
|
||||
-moz-#{$property}: $value;
|
||||
}
|
||||
} @else if $prefix == ms {
|
||||
@if $prefix-for-microsoft {
|
||||
-ms-#{$property}: $value;
|
||||
}
|
||||
} @else if $prefix == o {
|
||||
@if $prefix-for-opera {
|
||||
-o-#{$property}: $value;
|
||||
}
|
||||
} @else if $prefix == spec {
|
||||
@if $prefix-for-spec {
|
||||
#{$property}: $value;
|
||||
}
|
||||
} @else {
|
||||
@warn "Unrecognized prefix: #{$prefix}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin disable-prefix-for-all() {
|
||||
$prefix-for-webkit: false !global;
|
||||
$prefix-for-mozilla: false !global;
|
||||
$prefix-for-microsoft: false !global;
|
||||
$prefix-for-opera: false !global;
|
||||
$prefix-for-spec: false !global;
|
||||
}
|
||||
25
plugins/git-sync/scss/vendor/bourbon/addons/_retina-image.scss
vendored
Normal file
25
plugins/git-sync/scss/vendor/bourbon/addons/_retina-image.scss
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
@mixin retina-image($filename, $background-size, $extension: png, $retina-filename: null, $retina-suffix: _2x, $asset-pipeline: $asset-pipeline) {
|
||||
@if $asset-pipeline {
|
||||
background-image: image-url("#{$filename}.#{$extension}");
|
||||
} @else {
|
||||
background-image: url("#{$filename}.#{$extension}");
|
||||
}
|
||||
|
||||
@include hidpi {
|
||||
@if $asset-pipeline {
|
||||
@if $retina-filename {
|
||||
background-image: image-url("#{$retina-filename}.#{$extension}");
|
||||
} @else {
|
||||
background-image: image-url("#{$filename}#{$retina-suffix}.#{$extension}");
|
||||
}
|
||||
} @else {
|
||||
@if $retina-filename {
|
||||
background-image: url("#{$retina-filename}.#{$extension}");
|
||||
} @else {
|
||||
background-image: url("#{$filename}#{$retina-suffix}.#{$extension}");
|
||||
}
|
||||
}
|
||||
|
||||
background-size: $background-size;
|
||||
}
|
||||
}
|
||||
51
plugins/git-sync/scss/vendor/bourbon/addons/_size.scss
vendored
Normal file
51
plugins/git-sync/scss/vendor/bourbon/addons/_size.scss
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Sets the `width` and `height` of the element.
|
||||
///
|
||||
/// @param {List} $size
|
||||
/// A list of at most 2 size values.
|
||||
///
|
||||
/// If there is only a single value in `$size` it is used for both width and height. All units are supported.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .first-element {
|
||||
/// @include size(2em);
|
||||
/// }
|
||||
///
|
||||
/// .second-element {
|
||||
/// @include size(auto 10em);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .first-element {
|
||||
/// width: 2em;
|
||||
/// height: 2em;
|
||||
/// }
|
||||
///
|
||||
/// .second-element {
|
||||
/// width: auto;
|
||||
/// height: 10em;
|
||||
/// }
|
||||
///
|
||||
/// @todo Refactor in 5.0.0 to use a comma-separated argument
|
||||
|
||||
@mixin size($value) {
|
||||
$width: nth($value, 1);
|
||||
$height: $width;
|
||||
|
||||
@if length($value) > 1 {
|
||||
$height: nth($value, 2);
|
||||
}
|
||||
|
||||
@if is-size($height) {
|
||||
height: $height;
|
||||
} @else {
|
||||
@warn "`#{$height}` is not a valid length for the `$height` parameter in the `size` mixin.";
|
||||
}
|
||||
|
||||
@if is-size($width) {
|
||||
width: $width;
|
||||
} @else {
|
||||
@warn "`#{$width}` is not a valid length for the `$width` parameter in the `size` mixin.";
|
||||
}
|
||||
}
|
||||
113
plugins/git-sync/scss/vendor/bourbon/addons/_text-inputs.scss
vendored
Normal file
113
plugins/git-sync/scss/vendor/bourbon/addons/_text-inputs.scss
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Generates variables for all text-based inputs. Please note that you must use interpolation on the variable: `#{$all-text-inputs}`.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// #{$all-text-inputs} {
|
||||
/// border: 1px solid #f00;
|
||||
/// }
|
||||
///
|
||||
/// #{$all-text-inputs-focus},
|
||||
/// #{$all-text-inputs-hover} {
|
||||
/// border: 1px solid #0f0;
|
||||
/// }
|
||||
///
|
||||
/// #{$all-text-inputs-active} {
|
||||
/// border: 1px solid #00f;
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// input[type="color"],
|
||||
/// input[type="date"],
|
||||
/// input[type="datetime"],
|
||||
/// input[type="datetime-local"],
|
||||
/// input[type="email"],
|
||||
/// input[type="month"],
|
||||
/// input[type="number"],
|
||||
/// input[type="password"],
|
||||
/// input[type="search"],
|
||||
/// input[type="tel"],
|
||||
/// input[type="text"],
|
||||
/// input[type="time"],
|
||||
/// input[type="url"],
|
||||
/// input[type="week"],
|
||||
/// textarea {
|
||||
/// border: 1px solid #f00;
|
||||
/// }
|
||||
///
|
||||
/// input[type="color"]:focus,
|
||||
/// input[type="date"]:focus,
|
||||
/// input[type="datetime"]:focus,
|
||||
/// input[type="datetime-local"]:focus,
|
||||
/// input[type="email"]:focus,
|
||||
/// input[type="month"]:focus,
|
||||
/// input[type="number"]:focus,
|
||||
/// input[type="password"]:focus,
|
||||
/// input[type="search"]:focus,
|
||||
/// input[type="tel"]:focus,
|
||||
/// input[type="text"]:focus,
|
||||
/// input[type="time"]:focus,
|
||||
/// input[type="url"]:focus,
|
||||
/// input[type="week"]:focus,
|
||||
/// textarea:focus,
|
||||
/// input[type="color"]:hover,
|
||||
/// input[type="date"]:hover,
|
||||
/// input[type="datetime"]:hover,
|
||||
/// input[type="datetime-local"]:hover,
|
||||
/// input[type="email"]:hover,
|
||||
/// input[type="month"]:hover,
|
||||
/// input[type="number"]:hover,
|
||||
/// input[type="password"]:hover,
|
||||
/// input[type="search"]:hover,
|
||||
/// input[type="tel"]:hover,
|
||||
/// input[type="text"]:hover,
|
||||
/// input[type="time"]:hover,
|
||||
/// input[type="url"]:hover,
|
||||
/// input[type="week"]:hover,
|
||||
/// textarea:hover {
|
||||
/// border: 1px solid #0f0;
|
||||
/// }
|
||||
///
|
||||
/// input[type="color"]:active,
|
||||
/// input[type="date"]:active,
|
||||
/// input[type="datetime"]:active,
|
||||
/// input[type="datetime-local"]:active,
|
||||
/// input[type="email"]:active,
|
||||
/// input[type="month"]:active,
|
||||
/// input[type="number"]:active,
|
||||
/// input[type="password"]:active,
|
||||
/// input[type="search"]:active,
|
||||
/// input[type="tel"]:active,
|
||||
/// input[type="text"]:active,
|
||||
/// input[type="time"]:active,
|
||||
/// input[type="url"]:active,
|
||||
/// input[type="week"]:active,
|
||||
/// textarea:active {
|
||||
/// border: 1px solid #00f;
|
||||
/// }
|
||||
///
|
||||
/// @require assign-inputs
|
||||
///
|
||||
/// @type List
|
||||
|
||||
$text-inputs-list: 'input[type="color"]',
|
||||
'input[type="date"]',
|
||||
'input[type="datetime"]',
|
||||
'input[type="datetime-local"]',
|
||||
'input[type="email"]',
|
||||
'input[type="month"]',
|
||||
'input[type="number"]',
|
||||
'input[type="password"]',
|
||||
'input[type="search"]',
|
||||
'input[type="tel"]',
|
||||
'input[type="text"]',
|
||||
'input[type="time"]',
|
||||
'input[type="url"]',
|
||||
'input[type="week"]',
|
||||
'input:not([type])',
|
||||
'textarea';
|
||||
|
||||
$all-text-inputs: assign-inputs($text-inputs-list);
|
||||
$all-text-inputs-active: assign-inputs($text-inputs-list, active);
|
||||
$all-text-inputs-focus: assign-inputs($text-inputs-list, focus);
|
||||
$all-text-inputs-hover: assign-inputs($text-inputs-list, hover);
|
||||
34
plugins/git-sync/scss/vendor/bourbon/addons/_timing-functions.scss
vendored
Normal file
34
plugins/git-sync/scss/vendor/bourbon/addons/_timing-functions.scss
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// CSS cubic-bezier timing functions. Timing functions courtesy of jquery.easie (github.com/jaukia/easie)
|
||||
///
|
||||
/// Timing functions are the same as demoed here: http://jqueryui.com/resources/demos/effect/easing.html
|
||||
///
|
||||
/// @type cubic-bezier
|
||||
|
||||
$ease-in-quad: cubic-bezier(0.550, 0.085, 0.680, 0.530);
|
||||
$ease-in-cubic: cubic-bezier(0.550, 0.055, 0.675, 0.190);
|
||||
$ease-in-quart: cubic-bezier(0.895, 0.030, 0.685, 0.220);
|
||||
$ease-in-quint: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
$ease-in-sine: cubic-bezier(0.470, 0.000, 0.745, 0.715);
|
||||
$ease-in-expo: cubic-bezier(0.950, 0.050, 0.795, 0.035);
|
||||
$ease-in-circ: cubic-bezier(0.600, 0.040, 0.980, 0.335);
|
||||
$ease-in-back: cubic-bezier(0.600, -0.280, 0.735, 0.045);
|
||||
|
||||
$ease-out-quad: cubic-bezier(0.250, 0.460, 0.450, 0.940);
|
||||
$ease-out-cubic: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
$ease-out-quart: cubic-bezier(0.165, 0.840, 0.440, 1.000);
|
||||
$ease-out-quint: cubic-bezier(0.230, 1.000, 0.320, 1.000);
|
||||
$ease-out-sine: cubic-bezier(0.390, 0.575, 0.565, 1.000);
|
||||
$ease-out-expo: cubic-bezier(0.190, 1.000, 0.220, 1.000);
|
||||
$ease-out-circ: cubic-bezier(0.075, 0.820, 0.165, 1.000);
|
||||
$ease-out-back: cubic-bezier(0.175, 0.885, 0.320, 1.275);
|
||||
|
||||
$ease-in-out-quad: cubic-bezier(0.455, 0.030, 0.515, 0.955);
|
||||
$ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
$ease-in-out-quart: cubic-bezier(0.770, 0.000, 0.175, 1.000);
|
||||
$ease-in-out-quint: cubic-bezier(0.860, 0.000, 0.070, 1.000);
|
||||
$ease-in-out-sine: cubic-bezier(0.445, 0.050, 0.550, 0.950);
|
||||
$ease-in-out-expo: cubic-bezier(1.000, 0.000, 0.000, 1.000);
|
||||
$ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.150, 0.860);
|
||||
$ease-in-out-back: cubic-bezier(0.680, -0.550, 0.265, 1.550);
|
||||
63
plugins/git-sync/scss/vendor/bourbon/addons/_triangle.scss
vendored
Normal file
63
plugins/git-sync/scss/vendor/bourbon/addons/_triangle.scss
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
@mixin triangle($size, $color, $direction) {
|
||||
$width: nth($size, 1);
|
||||
$height: nth($size, length($size));
|
||||
$foreground-color: nth($color, 1);
|
||||
$background-color: if(length($color) == 2, nth($color, 2), transparent);
|
||||
height: 0;
|
||||
width: 0;
|
||||
|
||||
@if ($direction == up) or ($direction == down) or ($direction == right) or ($direction == left) {
|
||||
$width: $width / 2;
|
||||
$height: if(length($size) > 1, $height, $height/2);
|
||||
|
||||
@if $direction == up {
|
||||
border-bottom: $height solid $foreground-color;
|
||||
border-left: $width solid $background-color;
|
||||
border-right: $width solid $background-color;
|
||||
} @else if $direction == right {
|
||||
border-bottom: $width solid $background-color;
|
||||
border-left: $height solid $foreground-color;
|
||||
border-top: $width solid $background-color;
|
||||
} @else if $direction == down {
|
||||
border-left: $width solid $background-color;
|
||||
border-right: $width solid $background-color;
|
||||
border-top: $height solid $foreground-color;
|
||||
} @else if $direction == left {
|
||||
border-bottom: $width solid $background-color;
|
||||
border-right: $height solid $foreground-color;
|
||||
border-top: $width solid $background-color;
|
||||
}
|
||||
} @else if ($direction == up-right) or ($direction == up-left) {
|
||||
border-top: $height solid $foreground-color;
|
||||
|
||||
@if $direction == up-right {
|
||||
border-left: $width solid $background-color;
|
||||
} @else if $direction == up-left {
|
||||
border-right: $width solid $background-color;
|
||||
}
|
||||
} @else if ($direction == down-right) or ($direction == down-left) {
|
||||
border-bottom: $height solid $foreground-color;
|
||||
|
||||
@if $direction == down-right {
|
||||
border-left: $width solid $background-color;
|
||||
} @else if $direction == down-left {
|
||||
border-right: $width solid $background-color;
|
||||
}
|
||||
} @else if ($direction == inset-up) {
|
||||
border-color: $background-color $background-color $foreground-color;
|
||||
border-style: solid;
|
||||
border-width: $height $width;
|
||||
} @else if ($direction == inset-down) {
|
||||
border-color: $foreground-color $background-color $background-color;
|
||||
border-style: solid;
|
||||
border-width: $height $width;
|
||||
} @else if ($direction == inset-right) {
|
||||
border-color: $background-color $background-color $background-color $foreground-color;
|
||||
border-style: solid;
|
||||
border-width: $width $height;
|
||||
} @else if ($direction == inset-left) {
|
||||
border-color: $background-color $foreground-color $background-color $background-color;
|
||||
border-style: solid;
|
||||
border-width: $width $height;
|
||||
}
|
||||
}
|
||||
29
plugins/git-sync/scss/vendor/bourbon/addons/_word-wrap.scss
vendored
Normal file
29
plugins/git-sync/scss/vendor/bourbon/addons/_word-wrap.scss
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Provides an easy way to change the `word-wrap` property.
|
||||
///
|
||||
/// @param {String} $wrap [break-word]
|
||||
/// Value for the `word-break` property.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .wrapper {
|
||||
/// @include word-wrap(break-word);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .wrapper {
|
||||
/// overflow-wrap: break-word;
|
||||
/// word-break: break-all;
|
||||
/// word-wrap: break-word;
|
||||
/// }
|
||||
|
||||
@mixin word-wrap($wrap: break-word) {
|
||||
overflow-wrap: $wrap;
|
||||
word-wrap: $wrap;
|
||||
|
||||
@if $wrap == break-word {
|
||||
word-break: break-all;
|
||||
} @else {
|
||||
word-break: $wrap;
|
||||
}
|
||||
}
|
||||
43
plugins/git-sync/scss/vendor/bourbon/css3/_animation.scss
vendored
Normal file
43
plugins/git-sync/scss/vendor/bourbon/css3/_animation.scss
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// http://www.w3.org/TR/css3-animations/#the-animation-name-property-
|
||||
// Each of these mixins support comma separated lists of values, which allows different transitions for individual properties to be described in a single style rule. Each value in the list corresponds to the value at that same position in the other properties.
|
||||
|
||||
@mixin animation($animations...) {
|
||||
@include prefixer(animation, $animations, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-name($names...) {
|
||||
@include prefixer(animation-name, $names, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-duration($times...) {
|
||||
@include prefixer(animation-duration, $times, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-timing-function($motions...) {
|
||||
// ease | linear | ease-in | ease-out | ease-in-out
|
||||
@include prefixer(animation-timing-function, $motions, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-iteration-count($values...) {
|
||||
// infinite | <number>
|
||||
@include prefixer(animation-iteration-count, $values, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-direction($directions...) {
|
||||
// normal | alternate
|
||||
@include prefixer(animation-direction, $directions, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-play-state($states...) {
|
||||
// running | paused
|
||||
@include prefixer(animation-play-state, $states, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-delay($times...) {
|
||||
@include prefixer(animation-delay, $times, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin animation-fill-mode($modes...) {
|
||||
// none | forwards | backwards | both
|
||||
@include prefixer(animation-fill-mode, $modes, webkit moz spec);
|
||||
}
|
||||
3
plugins/git-sync/scss/vendor/bourbon/css3/_appearance.scss
vendored
Normal file
3
plugins/git-sync/scss/vendor/bourbon/css3/_appearance.scss
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@mixin appearance($value) {
|
||||
@include prefixer(appearance, $value, webkit moz ms o spec);
|
||||
}
|
||||
3
plugins/git-sync/scss/vendor/bourbon/css3/_backface-visibility.scss
vendored
Normal file
3
plugins/git-sync/scss/vendor/bourbon/css3/_backface-visibility.scss
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@mixin backface-visibility($visibility) {
|
||||
@include prefixer(backface-visibility, $visibility, webkit spec);
|
||||
}
|
||||
42
plugins/git-sync/scss/vendor/bourbon/css3/_background-image.scss
vendored
Normal file
42
plugins/git-sync/scss/vendor/bourbon/css3/_background-image.scss
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//************************************************************************//
|
||||
// Background-image property for adding multiple background images with
|
||||
// gradients, or for stringing multiple gradients together.
|
||||
//************************************************************************//
|
||||
|
||||
@mixin background-image($images...) {
|
||||
$webkit-images: ();
|
||||
$spec-images: ();
|
||||
|
||||
@each $image in $images {
|
||||
$webkit-image: ();
|
||||
$spec-image: ();
|
||||
|
||||
@if (type-of($image) == string) {
|
||||
$url-str: str-slice($image, 1, 3);
|
||||
$gradient-type: str-slice($image, 1, 6);
|
||||
|
||||
@if $url-str == "url" {
|
||||
$webkit-image: $image;
|
||||
$spec-image: $image;
|
||||
}
|
||||
|
||||
@else if $gradient-type == "linear" {
|
||||
$gradients: _linear-gradient-parser($image);
|
||||
$webkit-image: map-get($gradients, webkit-image);
|
||||
$spec-image: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else if $gradient-type == "radial" {
|
||||
$gradients: _radial-gradient-parser($image);
|
||||
$webkit-image: map-get($gradients, webkit-image);
|
||||
$spec-image: map-get($gradients, spec-image);
|
||||
}
|
||||
}
|
||||
|
||||
$webkit-images: append($webkit-images, $webkit-image, comma);
|
||||
$spec-images: append($spec-images, $spec-image, comma);
|
||||
}
|
||||
|
||||
background-image: $webkit-images;
|
||||
background-image: $spec-images;
|
||||
}
|
||||
55
plugins/git-sync/scss/vendor/bourbon/css3/_background.scss
vendored
Normal file
55
plugins/git-sync/scss/vendor/bourbon/css3/_background.scss
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
//************************************************************************//
|
||||
// Background property for adding multiple backgrounds using shorthand
|
||||
// notation.
|
||||
//************************************************************************//
|
||||
|
||||
@mixin background($backgrounds...) {
|
||||
$webkit-backgrounds: ();
|
||||
$spec-backgrounds: ();
|
||||
|
||||
@each $background in $backgrounds {
|
||||
$webkit-background: ();
|
||||
$spec-background: ();
|
||||
$background-type: type-of($background);
|
||||
|
||||
@if $background-type == string or $background-type == list {
|
||||
$background-str: if($background-type == list, nth($background, 1), $background);
|
||||
|
||||
$url-str: str-slice($background-str, 1, 3);
|
||||
$gradient-type: str-slice($background-str, 1, 6);
|
||||
|
||||
@if $url-str == "url" {
|
||||
$webkit-background: $background;
|
||||
$spec-background: $background;
|
||||
}
|
||||
|
||||
@else if $gradient-type == "linear" {
|
||||
$gradients: _linear-gradient-parser("#{$background}");
|
||||
$webkit-background: map-get($gradients, webkit-image);
|
||||
$spec-background: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else if $gradient-type == "radial" {
|
||||
$gradients: _radial-gradient-parser("#{$background}");
|
||||
$webkit-background: map-get($gradients, webkit-image);
|
||||
$spec-background: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else {
|
||||
$webkit-background: $background;
|
||||
$spec-background: $background;
|
||||
}
|
||||
}
|
||||
|
||||
@else {
|
||||
$webkit-background: $background;
|
||||
$spec-background: $background;
|
||||
}
|
||||
|
||||
$webkit-backgrounds: append($webkit-backgrounds, $webkit-background, comma);
|
||||
$spec-backgrounds: append($spec-backgrounds, $spec-background, comma);
|
||||
}
|
||||
|
||||
background: $webkit-backgrounds;
|
||||
background: $spec-backgrounds;
|
||||
}
|
||||
59
plugins/git-sync/scss/vendor/bourbon/css3/_border-image.scss
vendored
Normal file
59
plugins/git-sync/scss/vendor/bourbon/css3/_border-image.scss
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
@mixin border-image($borders...) {
|
||||
$webkit-borders: ();
|
||||
$spec-borders: ();
|
||||
|
||||
@each $border in $borders {
|
||||
$webkit-border: ();
|
||||
$spec-border: ();
|
||||
$border-type: type-of($border);
|
||||
|
||||
@if $border-type == string or list {
|
||||
$border-str: if($border-type == list, nth($border, 1), $border);
|
||||
|
||||
$url-str: str-slice($border-str, 1, 3);
|
||||
$gradient-type: str-slice($border-str, 1, 6);
|
||||
|
||||
@if $url-str == "url" {
|
||||
$webkit-border: $border;
|
||||
$spec-border: $border;
|
||||
}
|
||||
|
||||
@else if $gradient-type == "linear" {
|
||||
$gradients: _linear-gradient-parser("#{$border}");
|
||||
$webkit-border: map-get($gradients, webkit-image);
|
||||
$spec-border: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else if $gradient-type == "radial" {
|
||||
$gradients: _radial-gradient-parser("#{$border}");
|
||||
$webkit-border: map-get($gradients, webkit-image);
|
||||
$spec-border: map-get($gradients, spec-image);
|
||||
}
|
||||
|
||||
@else {
|
||||
$webkit-border: $border;
|
||||
$spec-border: $border;
|
||||
}
|
||||
}
|
||||
|
||||
@else {
|
||||
$webkit-border: $border;
|
||||
$spec-border: $border;
|
||||
}
|
||||
|
||||
$webkit-borders: append($webkit-borders, $webkit-border, comma);
|
||||
$spec-borders: append($spec-borders, $spec-border, comma);
|
||||
}
|
||||
|
||||
-webkit-border-image: $webkit-borders;
|
||||
border-image: $spec-borders;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
//Examples:
|
||||
// @include border-image(url("image.png"));
|
||||
// @include border-image(url("image.png") 20 stretch);
|
||||
// @include border-image(linear-gradient(45deg, orange, yellow));
|
||||
// @include border-image(linear-gradient(45deg, orange, yellow) stretch);
|
||||
// @include border-image(linear-gradient(45deg, orange, yellow) 20 30 40 50 stretch round);
|
||||
// @include border-image(radial-gradient(top, cover, orange, yellow, orange));
|
||||
4
plugins/git-sync/scss/vendor/bourbon/css3/_calc.scss
vendored
Normal file
4
plugins/git-sync/scss/vendor/bourbon/css3/_calc.scss
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
@mixin calc($property, $value) {
|
||||
#{$property}: -webkit-calc(#{$value});
|
||||
#{$property}: calc(#{$value});
|
||||
}
|
||||
47
plugins/git-sync/scss/vendor/bourbon/css3/_columns.scss
vendored
Normal file
47
plugins/git-sync/scss/vendor/bourbon/css3/_columns.scss
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
@mixin columns($arg: auto) {
|
||||
// <column-count> || <column-width>
|
||||
@include prefixer(columns, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-count($int: auto) {
|
||||
// auto || integer
|
||||
@include prefixer(column-count, $int, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-gap($length: normal) {
|
||||
// normal || length
|
||||
@include prefixer(column-gap, $length, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-fill($arg: auto) {
|
||||
// auto || length
|
||||
@include prefixer(column-fill, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule($arg) {
|
||||
// <border-width> || <border-style> || <color>
|
||||
@include prefixer(column-rule, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule-color($color) {
|
||||
@include prefixer(column-rule-color, $color, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule-style($style: none) {
|
||||
// none | hidden | dashed | dotted | double | groove | inset | inset | outset | ridge | solid
|
||||
@include prefixer(column-rule-style, $style, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule-width ($width: none) {
|
||||
@include prefixer(column-rule-width, $width, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-span($arg: none) {
|
||||
// none || all
|
||||
@include prefixer(column-span, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-width($length: auto) {
|
||||
// auto || length
|
||||
@include prefixer(column-width, $length, webkit moz spec);
|
||||
}
|
||||
4
plugins/git-sync/scss/vendor/bourbon/css3/_filter.scss
vendored
Normal file
4
plugins/git-sync/scss/vendor/bourbon/css3/_filter.scss
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
@mixin filter($function: none) {
|
||||
// <filter-function> [<filter-function]* | none
|
||||
@include prefixer(filter, $function, webkit spec);
|
||||
}
|
||||
287
plugins/git-sync/scss/vendor/bourbon/css3/_flex-box.scss
vendored
Normal file
287
plugins/git-sync/scss/vendor/bourbon/css3/_flex-box.scss
vendored
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
// CSS3 Flexible Box Model and property defaults
|
||||
|
||||
// Custom shorthand notation for flexbox
|
||||
@mixin box($orient: inline-axis, $pack: start, $align: stretch) {
|
||||
@include display-box;
|
||||
@include box-orient($orient);
|
||||
@include box-pack($pack);
|
||||
@include box-align($align);
|
||||
}
|
||||
|
||||
@mixin display-box {
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox; // IE 10
|
||||
display: box;
|
||||
}
|
||||
|
||||
@mixin box-orient($orient: inline-axis) {
|
||||
// horizontal|vertical|inline-axis|block-axis|inherit
|
||||
@include prefixer(box-orient, $orient, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-pack($pack: start) {
|
||||
// start|end|center|justify
|
||||
@include prefixer(box-pack, $pack, webkit moz spec);
|
||||
-ms-flex-pack: $pack; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-align($align: stretch) {
|
||||
// start|end|center|baseline|stretch
|
||||
@include prefixer(box-align, $align, webkit moz spec);
|
||||
-ms-flex-align: $align; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-direction($direction: normal) {
|
||||
// normal|reverse|inherit
|
||||
@include prefixer(box-direction, $direction, webkit moz spec);
|
||||
-ms-flex-direction: $direction; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-lines($lines: single) {
|
||||
// single|multiple
|
||||
@include prefixer(box-lines, $lines, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-ordinal-group($int: 1) {
|
||||
@include prefixer(box-ordinal-group, $int, webkit moz spec);
|
||||
-ms-flex-order: $int; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-flex($value: 0) {
|
||||
@include prefixer(box-flex, $value, webkit moz spec);
|
||||
-ms-flex: $value; // IE 10
|
||||
}
|
||||
|
||||
@mixin box-flex-group($int: 1) {
|
||||
@include prefixer(box-flex-group, $int, webkit moz spec);
|
||||
}
|
||||
|
||||
// CSS3 Flexible Box Model and property defaults
|
||||
// Unified attributes for 2009, 2011, and 2012 flavours.
|
||||
|
||||
// 2009 - display (box | inline-box)
|
||||
// 2011 - display (flexbox | inline-flexbox)
|
||||
// 2012 - display (flex | inline-flex)
|
||||
@mixin display($value) {
|
||||
// flex | inline-flex
|
||||
@if $value == "flex" {
|
||||
// 2009
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: box;
|
||||
|
||||
// 2012
|
||||
display: -webkit-flex;
|
||||
display: -moz-flex;
|
||||
display: -ms-flexbox; // 2011 (IE 10)
|
||||
display: flex;
|
||||
} @else if $value == "inline-flex" {
|
||||
display: -webkit-inline-box;
|
||||
display: -moz-inline-box;
|
||||
display: inline-box;
|
||||
|
||||
display: -webkit-inline-flex;
|
||||
display: -moz-inline-flex;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
} @else {
|
||||
display: $value;
|
||||
}
|
||||
}
|
||||
|
||||
// 2009 - box-flex (integer)
|
||||
// 2011 - flex (decimal | width decimal)
|
||||
// 2012 - flex (integer integer width)
|
||||
@mixin flex($value) {
|
||||
|
||||
// Grab flex-grow for older browsers.
|
||||
$flex-grow: nth($value, 1);
|
||||
|
||||
// 2009
|
||||
@include prefixer(box-flex, $flex-grow, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10), 2012
|
||||
@include prefixer(flex, $value, webkit moz ms spec);
|
||||
}
|
||||
|
||||
// 2009 - box-orient ( horizontal | vertical | inline-axis | block-axis)
|
||||
// - box-direction (normal | reverse)
|
||||
// 2011 - flex-direction (row | row-reverse | column | column-reverse)
|
||||
// 2012 - flex-direction (row | row-reverse | column | column-reverse)
|
||||
@mixin flex-direction($value: row) {
|
||||
|
||||
// Alt values.
|
||||
$value-2009: $value;
|
||||
$value-2011: $value;
|
||||
$direction: normal;
|
||||
|
||||
@if $value == row {
|
||||
$value-2009: horizontal;
|
||||
} @else if $value == "row-reverse" {
|
||||
$value-2009: horizontal;
|
||||
$direction: reverse;
|
||||
} @else if $value == column {
|
||||
$value-2009: vertical;
|
||||
} @else if $value == "column-reverse" {
|
||||
$value-2009: vertical;
|
||||
$direction: reverse;
|
||||
}
|
||||
|
||||
// 2009
|
||||
@include prefixer(box-orient, $value-2009, webkit moz spec);
|
||||
@include prefixer(box-direction, $direction, webkit moz spec);
|
||||
|
||||
// 2012
|
||||
@include prefixer(flex-direction, $value, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-direction: $value;
|
||||
}
|
||||
|
||||
// 2009 - box-lines (single | multiple)
|
||||
// 2011 - flex-wrap (nowrap | wrap | wrap-reverse)
|
||||
// 2012 - flex-wrap (nowrap | wrap | wrap-reverse)
|
||||
@mixin flex-wrap($value: nowrap) {
|
||||
// Alt values
|
||||
$alt-value: $value;
|
||||
@if $value == nowrap {
|
||||
$alt-value: single;
|
||||
} @else if $value == wrap {
|
||||
$alt-value: multiple;
|
||||
} @else if $value == "wrap-reverse" {
|
||||
$alt-value: multiple;
|
||||
}
|
||||
|
||||
@include prefixer(box-lines, $alt-value, webkit moz spec);
|
||||
@include prefixer(flex-wrap, $value, webkit moz ms spec);
|
||||
}
|
||||
|
||||
// 2009 - TODO: parse values into flex-direction/flex-wrap
|
||||
// 2011 - TODO: parse values into flex-direction/flex-wrap
|
||||
// 2012 - flex-flow (flex-direction || flex-wrap)
|
||||
@mixin flex-flow($value) {
|
||||
@include prefixer(flex-flow, $value, webkit moz spec);
|
||||
}
|
||||
|
||||
// 2009 - box-ordinal-group (integer)
|
||||
// 2011 - flex-order (integer)
|
||||
// 2012 - order (integer)
|
||||
@mixin order($int: 0) {
|
||||
// 2009
|
||||
@include prefixer(box-ordinal-group, $int, webkit moz spec);
|
||||
|
||||
// 2012
|
||||
@include prefixer(order, $int, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-order: $int;
|
||||
}
|
||||
|
||||
// 2012 - flex-grow (number)
|
||||
@mixin flex-grow($number: 0) {
|
||||
@include prefixer(flex-grow, $number, webkit moz spec);
|
||||
-ms-flex-positive: $number;
|
||||
}
|
||||
|
||||
// 2012 - flex-shrink (number)
|
||||
@mixin flex-shrink($number: 1) {
|
||||
@include prefixer(flex-shrink, $number, webkit moz spec);
|
||||
-ms-flex-negative: $number;
|
||||
}
|
||||
|
||||
// 2012 - flex-basis (number)
|
||||
@mixin flex-basis($width: auto) {
|
||||
@include prefixer(flex-basis, $width, webkit moz spec);
|
||||
-ms-flex-preferred-size: $width;
|
||||
}
|
||||
|
||||
// 2009 - box-pack (start | end | center | justify)
|
||||
// 2011 - flex-pack (start | end | center | justify)
|
||||
// 2012 - justify-content (flex-start | flex-end | center | space-between | space-around)
|
||||
@mixin justify-content($value: flex-start) {
|
||||
|
||||
// Alt values.
|
||||
$alt-value: $value;
|
||||
@if $value == "flex-start" {
|
||||
$alt-value: start;
|
||||
} @else if $value == "flex-end" {
|
||||
$alt-value: end;
|
||||
} @else if $value == "space-between" {
|
||||
$alt-value: justify;
|
||||
} @else if $value == "space-around" {
|
||||
$alt-value: distribute;
|
||||
}
|
||||
|
||||
// 2009
|
||||
@include prefixer(box-pack, $alt-value, webkit moz spec);
|
||||
|
||||
// 2012
|
||||
@include prefixer(justify-content, $value, webkit moz ms o spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-pack: $alt-value;
|
||||
}
|
||||
|
||||
// 2009 - box-align (start | end | center | baseline | stretch)
|
||||
// 2011 - flex-align (start | end | center | baseline | stretch)
|
||||
// 2012 - align-items (flex-start | flex-end | center | baseline | stretch)
|
||||
@mixin align-items($value: stretch) {
|
||||
|
||||
$alt-value: $value;
|
||||
|
||||
@if $value == "flex-start" {
|
||||
$alt-value: start;
|
||||
} @else if $value == "flex-end" {
|
||||
$alt-value: end;
|
||||
}
|
||||
|
||||
// 2009
|
||||
@include prefixer(box-align, $alt-value, webkit moz spec);
|
||||
|
||||
// 2012
|
||||
@include prefixer(align-items, $value, webkit moz ms o spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-align: $alt-value;
|
||||
}
|
||||
|
||||
// 2011 - flex-item-align (auto | start | end | center | baseline | stretch)
|
||||
// 2012 - align-self (auto | flex-start | flex-end | center | baseline | stretch)
|
||||
@mixin align-self($value: auto) {
|
||||
|
||||
$value-2011: $value;
|
||||
@if $value == "flex-start" {
|
||||
$value-2011: start;
|
||||
} @else if $value == "flex-end" {
|
||||
$value-2011: end;
|
||||
}
|
||||
|
||||
// 2012
|
||||
@include prefixer(align-self, $value, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-item-align: $value-2011;
|
||||
}
|
||||
|
||||
// 2011 - flex-line-pack (start | end | center | justify | distribute | stretch)
|
||||
// 2012 - align-content (flex-start | flex-end | center | space-between | space-around | stretch)
|
||||
@mixin align-content($value: stretch) {
|
||||
|
||||
$value-2011: $value;
|
||||
@if $value == "flex-start" {
|
||||
$value-2011: start;
|
||||
} @else if $value == "flex-end" {
|
||||
$value-2011: end;
|
||||
} @else if $value == "space-between" {
|
||||
$value-2011: justify;
|
||||
} @else if $value == "space-around" {
|
||||
$value-2011: distribute;
|
||||
}
|
||||
|
||||
// 2012
|
||||
@include prefixer(align-content, $value, webkit moz spec);
|
||||
|
||||
// 2011 (IE 10)
|
||||
-ms-flex-line-pack: $value-2011;
|
||||
}
|
||||
24
plugins/git-sync/scss/vendor/bourbon/css3/_font-face.scss
vendored
Normal file
24
plugins/git-sync/scss/vendor/bourbon/css3/_font-face.scss
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
@mixin font-face(
|
||||
$font-family,
|
||||
$file-path,
|
||||
$weight: normal,
|
||||
$style: normal,
|
||||
$asset-pipeline: $asset-pipeline,
|
||||
$file-formats: eot woff2 woff ttf svg) {
|
||||
|
||||
$font-url-prefix: font-url-prefixer($asset-pipeline);
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family;
|
||||
font-style: $style;
|
||||
font-weight: $weight;
|
||||
|
||||
src: font-source-declaration(
|
||||
$font-family,
|
||||
$file-path,
|
||||
$asset-pipeline,
|
||||
$file-formats,
|
||||
$font-url-prefix
|
||||
);
|
||||
}
|
||||
}
|
||||
4
plugins/git-sync/scss/vendor/bourbon/css3/_font-feature-settings.scss
vendored
Normal file
4
plugins/git-sync/scss/vendor/bourbon/css3/_font-feature-settings.scss
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
@mixin font-feature-settings($settings...) {
|
||||
@if length($settings) == 0 { $settings: none; }
|
||||
@include prefixer(font-feature-settings, $settings, webkit moz ms spec);
|
||||
}
|
||||
10
plugins/git-sync/scss/vendor/bourbon/css3/_hidpi-media-query.scss
vendored
Normal file
10
plugins/git-sync/scss/vendor/bourbon/css3/_hidpi-media-query.scss
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// HiDPI mixin. Default value set to 1.3 to target Google Nexus 7 (http://bjango.com/articles/min-device-pixel-ratio/)
|
||||
@mixin hidpi($ratio: 1.3) {
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: $ratio),
|
||||
only screen and (min--moz-device-pixel-ratio: $ratio),
|
||||
only screen and (-o-min-device-pixel-ratio: #{$ratio}/1),
|
||||
only screen and (min-resolution: round($ratio * 96dpi)),
|
||||
only screen and (min-resolution: $ratio * 1dppx) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
4
plugins/git-sync/scss/vendor/bourbon/css3/_hyphens.scss
vendored
Normal file
4
plugins/git-sync/scss/vendor/bourbon/css3/_hyphens.scss
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
@mixin hyphens($hyphenation: none) {
|
||||
// none | manual | auto
|
||||
@include prefixer(hyphens, $hyphenation, webkit moz ms spec);
|
||||
}
|
||||
14
plugins/git-sync/scss/vendor/bourbon/css3/_image-rendering.scss
vendored
Normal file
14
plugins/git-sync/scss/vendor/bourbon/css3/_image-rendering.scss
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
@mixin image-rendering ($mode:auto) {
|
||||
|
||||
@if ($mode == crisp-edges) {
|
||||
-ms-interpolation-mode: nearest-neighbor; // IE8+
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
|
||||
@else {
|
||||
image-rendering: $mode;
|
||||
}
|
||||
}
|
||||
36
plugins/git-sync/scss/vendor/bourbon/css3/_keyframes.scss
vendored
Normal file
36
plugins/git-sync/scss/vendor/bourbon/css3/_keyframes.scss
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Adds keyframes blocks for supported prefixes, removing redundant prefixes in the block's content
|
||||
@mixin keyframes($name) {
|
||||
$original-prefix-for-webkit: $prefix-for-webkit;
|
||||
$original-prefix-for-mozilla: $prefix-for-mozilla;
|
||||
$original-prefix-for-microsoft: $prefix-for-microsoft;
|
||||
$original-prefix-for-opera: $prefix-for-opera;
|
||||
$original-prefix-for-spec: $prefix-for-spec;
|
||||
|
||||
@if $original-prefix-for-webkit {
|
||||
@include disable-prefix-for-all();
|
||||
$prefix-for-webkit: true !global;
|
||||
@-webkit-keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@if $original-prefix-for-mozilla {
|
||||
@include disable-prefix-for-all();
|
||||
$prefix-for-mozilla: true !global;
|
||||
@-moz-keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
$prefix-for-webkit: $original-prefix-for-webkit !global;
|
||||
$prefix-for-mozilla: $original-prefix-for-mozilla !global;
|
||||
$prefix-for-microsoft: $original-prefix-for-microsoft !global;
|
||||
$prefix-for-opera: $original-prefix-for-opera !global;
|
||||
$prefix-for-spec: $original-prefix-for-spec !global;
|
||||
|
||||
@if $original-prefix-for-spec {
|
||||
@keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
plugins/git-sync/scss/vendor/bourbon/css3/_linear-gradient.scss
vendored
Normal file
38
plugins/git-sync/scss/vendor/bourbon/css3/_linear-gradient.scss
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
@mixin linear-gradient($pos, $g1, $g2: null,
|
||||
$g3: null, $g4: null,
|
||||
$g5: null, $g6: null,
|
||||
$g7: null, $g8: null,
|
||||
$g9: null, $g10: null,
|
||||
$fallback: null) {
|
||||
// Detect what type of value exists in $pos
|
||||
$pos-type: type-of(nth($pos, 1));
|
||||
$pos-spec: null;
|
||||
$pos-degree: null;
|
||||
|
||||
// If $pos is missing from mixin, reassign vars and add default position
|
||||
@if ($pos-type == color) or (nth($pos, 1) == "transparent") {
|
||||
$g10: $g9; $g9: $g8; $g8: $g7; $g7: $g6; $g6: $g5;
|
||||
$g5: $g4; $g4: $g3; $g3: $g2; $g2: $g1; $g1: $pos;
|
||||
$pos: null;
|
||||
}
|
||||
|
||||
@if $pos {
|
||||
$positions: _linear-positions-parser($pos);
|
||||
$pos-degree: nth($positions, 1);
|
||||
$pos-spec: nth($positions, 2);
|
||||
}
|
||||
|
||||
$full: $g1, $g2, $g3, $g4, $g5, $g6, $g7, $g8, $g9, $g10;
|
||||
|
||||
// Set $g1 as the default fallback color
|
||||
$fallback-color: nth($g1, 1);
|
||||
|
||||
// If $fallback is a color use that color as the fallback color
|
||||
@if (type-of($fallback) == color) or ($fallback == "transparent") {
|
||||
$fallback-color: $fallback;
|
||||
}
|
||||
|
||||
background-color: $fallback-color;
|
||||
background-image: -webkit-linear-gradient($pos-degree $full); // Safari 5.1+, Chrome
|
||||
background-image: unquote("linear-gradient(#{$pos-spec}#{$full})");
|
||||
}
|
||||
8
plugins/git-sync/scss/vendor/bourbon/css3/_perspective.scss
vendored
Normal file
8
plugins/git-sync/scss/vendor/bourbon/css3/_perspective.scss
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
@mixin perspective($depth: none) {
|
||||
// none | <length>
|
||||
@include prefixer(perspective, $depth, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin perspective-origin($value: 50% 50%) {
|
||||
@include prefixer(perspective-origin, $value, webkit moz spec);
|
||||
}
|
||||
8
plugins/git-sync/scss/vendor/bourbon/css3/_placeholder.scss
vendored
Normal file
8
plugins/git-sync/scss/vendor/bourbon/css3/_placeholder.scss
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
@mixin placeholder {
|
||||
$placeholders: ":-webkit-input" ":-moz" "-moz" "-ms-input";
|
||||
@each $placeholder in $placeholders {
|
||||
&:#{$placeholder}-placeholder {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
39
plugins/git-sync/scss/vendor/bourbon/css3/_radial-gradient.scss
vendored
Normal file
39
plugins/git-sync/scss/vendor/bourbon/css3/_radial-gradient.scss
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// Requires Sass 3.1+
|
||||
@mixin radial-gradient($g1, $g2,
|
||||
$g3: null, $g4: null,
|
||||
$g5: null, $g6: null,
|
||||
$g7: null, $g8: null,
|
||||
$g9: null, $g10: null,
|
||||
$pos: null,
|
||||
$shape-size: null,
|
||||
$fallback: null) {
|
||||
|
||||
$data: _radial-arg-parser($g1, $g2, $pos, $shape-size);
|
||||
$g1: nth($data, 1);
|
||||
$g2: nth($data, 2);
|
||||
$pos: nth($data, 3);
|
||||
$shape-size: nth($data, 4);
|
||||
|
||||
$full: $g1, $g2, $g3, $g4, $g5, $g6, $g7, $g8, $g9, $g10;
|
||||
|
||||
// Strip deprecated cover/contain for spec
|
||||
$shape-size-spec: _shape-size-stripper($shape-size);
|
||||
|
||||
// Set $g1 as the default fallback color
|
||||
$first-color: nth($full, 1);
|
||||
$fallback-color: nth($first-color, 1);
|
||||
|
||||
@if (type-of($fallback) == color) or ($fallback == "transparent") {
|
||||
$fallback-color: $fallback;
|
||||
}
|
||||
|
||||
// Add Commas and spaces
|
||||
$shape-size: if($shape-size, "#{$shape-size}, ", null);
|
||||
$pos: if($pos, "#{$pos}, ", null);
|
||||
$pos-spec: if($pos, "at #{$pos}", null);
|
||||
$shape-size-spec: if(($shape-size-spec != " ") and ($pos == null), "#{$shape-size-spec}, ", "#{$shape-size-spec} ");
|
||||
|
||||
background-color: $fallback-color;
|
||||
background-image: -webkit-radial-gradient(#{$pos}#{$shape-size}#{$full});
|
||||
background-image: radial-gradient(#{$shape-size-spec}#{$pos-spec}#{$full});
|
||||
}
|
||||
42
plugins/git-sync/scss/vendor/bourbon/css3/_selection.scss
vendored
Normal file
42
plugins/git-sync/scss/vendor/bourbon/css3/_selection.scss
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Outputs the spec and prefixed versions of the `::selection` pseudo-element.
|
||||
///
|
||||
/// @param {Bool} $current-selector [false]
|
||||
/// If set to `true`, it takes the current element into consideration.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include selection(true) {
|
||||
/// background-color: #ffbb52;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element::-moz-selection {
|
||||
/// background-color: #ffbb52;
|
||||
/// }
|
||||
///
|
||||
/// .element::selection {
|
||||
/// background-color: #ffbb52;
|
||||
/// }
|
||||
|
||||
@mixin selection($current-selector: false) {
|
||||
@if $current-selector {
|
||||
&::-moz-selection {
|
||||
@content;
|
||||
}
|
||||
|
||||
&::selection {
|
||||
@content;
|
||||
}
|
||||
} @else {
|
||||
::-moz-selection {
|
||||
@content;
|
||||
}
|
||||
|
||||
::selection {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
plugins/git-sync/scss/vendor/bourbon/css3/_text-decoration.scss
vendored
Normal file
19
plugins/git-sync/scss/vendor/bourbon/css3/_text-decoration.scss
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
@mixin text-decoration($value) {
|
||||
// <text-decoration-line> || <text-decoration-style> || <text-decoration-color>
|
||||
@include prefixer(text-decoration, $value, moz);
|
||||
}
|
||||
|
||||
@mixin text-decoration-line($line: none) {
|
||||
// none || underline || overline || line-through
|
||||
@include prefixer(text-decoration-line, $line, moz);
|
||||
}
|
||||
|
||||
@mixin text-decoration-style($style: solid) {
|
||||
// solid || double || dotted || dashed || wavy
|
||||
@include prefixer(text-decoration-style, $style, moz webkit);
|
||||
}
|
||||
|
||||
@mixin text-decoration-color($color: currentColor) {
|
||||
// currentColor || <color>
|
||||
@include prefixer(text-decoration-color, $color, moz);
|
||||
}
|
||||
15
plugins/git-sync/scss/vendor/bourbon/css3/_transform.scss
vendored
Normal file
15
plugins/git-sync/scss/vendor/bourbon/css3/_transform.scss
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
@mixin transform($property: none) {
|
||||
// none | <transform-function>
|
||||
@include prefixer(transform, $property, webkit moz ms o spec);
|
||||
}
|
||||
|
||||
@mixin transform-origin($axes: 50%) {
|
||||
// x-axis - left | center | right | length | %
|
||||
// y-axis - top | center | bottom | length | %
|
||||
// z-axis - length
|
||||
@include prefixer(transform-origin, $axes, webkit moz ms o spec);
|
||||
}
|
||||
|
||||
@mixin transform-style($style: flat) {
|
||||
@include prefixer(transform-style, $style, webkit moz ms o spec);
|
||||
}
|
||||
71
plugins/git-sync/scss/vendor/bourbon/css3/_transition.scss
vendored
Normal file
71
plugins/git-sync/scss/vendor/bourbon/css3/_transition.scss
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// Shorthand mixin. Supports multiple parentheses-deliminated values for each variable.
|
||||
// Example: @include transition (all 2s ease-in-out);
|
||||
// @include transition (opacity 1s ease-in 2s, width 2s ease-out);
|
||||
// @include transition-property (transform, opacity);
|
||||
|
||||
@mixin transition($properties...) {
|
||||
// Fix for vendor-prefix transform property
|
||||
$needs-prefixes: false;
|
||||
$webkit: ();
|
||||
$moz: ();
|
||||
$spec: ();
|
||||
|
||||
// Create lists for vendor-prefixed transform
|
||||
@each $list in $properties {
|
||||
@if nth($list, 1) == "transform" {
|
||||
$needs-prefixes: true;
|
||||
$list1: -webkit-transform;
|
||||
$list2: -moz-transform;
|
||||
$list3: ();
|
||||
|
||||
@each $var in $list {
|
||||
$list3: join($list3, $var);
|
||||
|
||||
@if $var != "transform" {
|
||||
$list1: join($list1, $var);
|
||||
$list2: join($list2, $var);
|
||||
}
|
||||
}
|
||||
|
||||
$webkit: append($webkit, $list1);
|
||||
$moz: append($moz, $list2);
|
||||
$spec: append($spec, $list3);
|
||||
} @else {
|
||||
$webkit: append($webkit, $list, comma);
|
||||
$moz: append($moz, $list, comma);
|
||||
$spec: append($spec, $list, comma);
|
||||
}
|
||||
}
|
||||
|
||||
@if $needs-prefixes {
|
||||
-webkit-transition: $webkit;
|
||||
-moz-transition: $moz;
|
||||
transition: $spec;
|
||||
} @else {
|
||||
@if length($properties) >= 1 {
|
||||
@include prefixer(transition, $properties, webkit moz spec);
|
||||
} @else {
|
||||
$properties: all 0.15s ease-out 0s;
|
||||
@include prefixer(transition, $properties, webkit moz spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin transition-property($properties...) {
|
||||
-webkit-transition-property: transition-property-names($properties, "webkit");
|
||||
-moz-transition-property: transition-property-names($properties, "moz");
|
||||
transition-property: transition-property-names($properties, false);
|
||||
}
|
||||
|
||||
@mixin transition-duration($times...) {
|
||||
@include prefixer(transition-duration, $times, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin transition-timing-function($motions...) {
|
||||
// ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier()
|
||||
@include prefixer(transition-timing-function, $motions, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin transition-delay($times...) {
|
||||
@include prefixer(transition-delay, $times, webkit moz spec);
|
||||
}
|
||||
3
plugins/git-sync/scss/vendor/bourbon/css3/_user-select.scss
vendored
Normal file
3
plugins/git-sync/scss/vendor/bourbon/css3/_user-select.scss
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@mixin user-select($value: none) {
|
||||
@include prefixer(user-select, $value, webkit moz ms spec);
|
||||
}
|
||||
11
plugins/git-sync/scss/vendor/bourbon/functions/_assign-inputs.scss
vendored
Normal file
11
plugins/git-sync/scss/vendor/bourbon/functions/_assign-inputs.scss
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
@function assign-inputs($inputs, $pseudo: null) {
|
||||
$list: ();
|
||||
|
||||
@each $input in $inputs {
|
||||
$input: unquote($input);
|
||||
$input: if($pseudo, $input + ":" + $pseudo, $input);
|
||||
$list: append($list, $input, comma);
|
||||
}
|
||||
|
||||
@return $list;
|
||||
}
|
||||
20
plugins/git-sync/scss/vendor/bourbon/functions/_contains-falsy.scss
vendored
Normal file
20
plugins/git-sync/scss/vendor/bourbon/functions/_contains-falsy.scss
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Checks if a list does not contains a value.
|
||||
///
|
||||
/// @access private
|
||||
///
|
||||
/// @param {List} $list
|
||||
/// The list to check against.
|
||||
///
|
||||
/// @return {Bool}
|
||||
|
||||
@function contains-falsy($list) {
|
||||
@each $item in $list {
|
||||
@if not $item {
|
||||
@return true;
|
||||
}
|
||||
}
|
||||
|
||||
@return false;
|
||||
}
|
||||
26
plugins/git-sync/scss/vendor/bourbon/functions/_contains.scss
vendored
Normal file
26
plugins/git-sync/scss/vendor/bourbon/functions/_contains.scss
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Checks if a list contains a value(s).
|
||||
///
|
||||
/// @access private
|
||||
///
|
||||
/// @param {List} $list
|
||||
/// The list to check against.
|
||||
///
|
||||
/// @param {List} $values
|
||||
/// A single value or list of values to check for.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// contains($list, $value)
|
||||
///
|
||||
/// @return {Bool}
|
||||
|
||||
@function contains($list, $values...) {
|
||||
@each $value in $values {
|
||||
@if type-of(index($list, $value)) != "number" {
|
||||
@return false;
|
||||
}
|
||||
}
|
||||
|
||||
@return true;
|
||||
}
|
||||
11
plugins/git-sync/scss/vendor/bourbon/functions/_is-length.scss
vendored
Normal file
11
plugins/git-sync/scss/vendor/bourbon/functions/_is-length.scss
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Checks for a valid CSS length.
|
||||
///
|
||||
/// @param {String} $value
|
||||
|
||||
@function is-length($value) {
|
||||
@return type-of($value) != "null" and (str-slice($value + "", 1, 4) == "calc"
|
||||
or index(auto inherit initial 0, $value)
|
||||
or (type-of($value) == "number" and not(unitless($value))));
|
||||
}
|
||||
21
plugins/git-sync/scss/vendor/bourbon/functions/_is-light.scss
vendored
Normal file
21
plugins/git-sync/scss/vendor/bourbon/functions/_is-light.scss
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Programatically determines whether a color is light or dark.
|
||||
///
|
||||
/// @link http://robots.thoughtbot.com/closer-look-color-lightness
|
||||
///
|
||||
/// @param {Color (Hex)} $color
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// is-light($color)
|
||||
///
|
||||
/// @return {Bool}
|
||||
|
||||
@function is-light($hex-color) {
|
||||
$-local-red: red(rgba($hex-color, 1));
|
||||
$-local-green: green(rgba($hex-color, 1));
|
||||
$-local-blue: blue(rgba($hex-color, 1));
|
||||
$-local-lightness: ($-local-red * 0.2126 + $-local-green * 0.7152 + $-local-blue * 0.0722) / 255;
|
||||
|
||||
@return $-local-lightness > 0.6;
|
||||
}
|
||||
11
plugins/git-sync/scss/vendor/bourbon/functions/_is-number.scss
vendored
Normal file
11
plugins/git-sync/scss/vendor/bourbon/functions/_is-number.scss
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Checks for a valid number.
|
||||
///
|
||||
/// @param {Number} $value
|
||||
///
|
||||
/// @require {function} contains
|
||||
|
||||
@function is-number($value) {
|
||||
@return contains("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" 0 1 2 3 4 5 6 7 8 9, $value);
|
||||
}
|
||||
13
plugins/git-sync/scss/vendor/bourbon/functions/_is-size.scss
vendored
Normal file
13
plugins/git-sync/scss/vendor/bourbon/functions/_is-size.scss
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Checks for a valid CSS size.
|
||||
///
|
||||
/// @param {String} $value
|
||||
///
|
||||
/// @require {function} contains
|
||||
/// @require {function} is-length
|
||||
|
||||
@function is-size($value) {
|
||||
@return is-length($value)
|
||||
or contains("fill" "fit-content" "min-content" "max-content", $value);
|
||||
}
|
||||
69
plugins/git-sync/scss/vendor/bourbon/functions/_modular-scale.scss
vendored
Normal file
69
plugins/git-sync/scss/vendor/bourbon/functions/_modular-scale.scss
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// Scaling Variables
|
||||
$golden: 1.618;
|
||||
$minor-second: 1.067;
|
||||
$major-second: 1.125;
|
||||
$minor-third: 1.2;
|
||||
$major-third: 1.25;
|
||||
$perfect-fourth: 1.333;
|
||||
$augmented-fourth: 1.414;
|
||||
$perfect-fifth: 1.5;
|
||||
$minor-sixth: 1.6;
|
||||
$major-sixth: 1.667;
|
||||
$minor-seventh: 1.778;
|
||||
$major-seventh: 1.875;
|
||||
$octave: 2;
|
||||
$major-tenth: 2.5;
|
||||
$major-eleventh: 2.667;
|
||||
$major-twelfth: 3;
|
||||
$double-octave: 4;
|
||||
|
||||
$modular-scale-ratio: $perfect-fourth !default;
|
||||
$modular-scale-base: em($em-base) !default;
|
||||
|
||||
@function modular-scale($increment, $value: $modular-scale-base, $ratio: $modular-scale-ratio) {
|
||||
$v1: nth($value, 1);
|
||||
$v2: nth($value, length($value));
|
||||
$value: $v1;
|
||||
|
||||
// scale $v2 to just above $v1
|
||||
@while $v2 > $v1 {
|
||||
$v2: ($v2 / $ratio); // will be off-by-1
|
||||
}
|
||||
@while $v2 < $v1 {
|
||||
$v2: ($v2 * $ratio); // will fix off-by-1
|
||||
}
|
||||
|
||||
// check AFTER scaling $v2 to prevent double-counting corner-case
|
||||
$double-stranded: $v2 > $v1;
|
||||
|
||||
@if $increment > 0 {
|
||||
@for $i from 1 through $increment {
|
||||
@if $double-stranded and ($v1 * $ratio) > $v2 {
|
||||
$value: $v2;
|
||||
$v2: ($v2 * $ratio);
|
||||
} @else {
|
||||
$v1: ($v1 * $ratio);
|
||||
$value: $v1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@if $increment < 0 {
|
||||
// adjust $v2 to just below $v1
|
||||
@if $double-stranded {
|
||||
$v2: ($v2 / $ratio);
|
||||
}
|
||||
|
||||
@for $i from $increment through -1 {
|
||||
@if $double-stranded and ($v1 / $ratio) < $v2 {
|
||||
$value: $v2;
|
||||
$v2: ($v2 / $ratio);
|
||||
} @else {
|
||||
$v1: ($v1 / $ratio);
|
||||
$value: $v1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@return $value;
|
||||
}
|
||||
13
plugins/git-sync/scss/vendor/bourbon/functions/_px-to-em.scss
vendored
Normal file
13
plugins/git-sync/scss/vendor/bourbon/functions/_px-to-em.scss
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Convert pixels to ems
|
||||
// eg. for a relational value of 12px write em(12) when the parent is 16px
|
||||
// if the parent is another value say 24px write em(12, 24)
|
||||
|
||||
@function em($pxval, $base: $em-base) {
|
||||
@if not unitless($pxval) {
|
||||
$pxval: strip-units($pxval);
|
||||
}
|
||||
@if not unitless($base) {
|
||||
$base: strip-units($base);
|
||||
}
|
||||
@return ($pxval / $base) * 1em;
|
||||
}
|
||||
15
plugins/git-sync/scss/vendor/bourbon/functions/_px-to-rem.scss
vendored
Normal file
15
plugins/git-sync/scss/vendor/bourbon/functions/_px-to-rem.scss
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Convert pixels to rems
|
||||
// eg. for a relational value of 12px write rem(12)
|
||||
// Assumes $em-base is the font-size of <html>
|
||||
|
||||
@function rem($pxval) {
|
||||
@if not unitless($pxval) {
|
||||
$pxval: strip-units($pxval);
|
||||
}
|
||||
|
||||
$base: $em-base;
|
||||
@if not unitless($base) {
|
||||
$base: strip-units($base);
|
||||
}
|
||||
@return ($pxval / $base) * 1rem;
|
||||
}
|
||||
24
plugins/git-sync/scss/vendor/bourbon/functions/_shade.scss
vendored
Normal file
24
plugins/git-sync/scss/vendor/bourbon/functions/_shade.scss
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Mixes a color with black.
|
||||
///
|
||||
/// @param {Color} $color
|
||||
///
|
||||
/// @param {Number (Percentage)} $percent
|
||||
/// The amount of black to be mixed in.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// background-color: shade(#ffbb52, 60%);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// background-color: #664a20;
|
||||
/// }
|
||||
///
|
||||
/// @return {Color}
|
||||
|
||||
@function shade($color, $percent) {
|
||||
@return mix(#000, $color, $percent);
|
||||
}
|
||||
17
plugins/git-sync/scss/vendor/bourbon/functions/_strip-units.scss
vendored
Normal file
17
plugins/git-sync/scss/vendor/bourbon/functions/_strip-units.scss
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Strips the unit from a number.
|
||||
///
|
||||
/// @param {Number (With Unit)} $value
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// $dimension: strip-units(10em);
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// $dimension: 10;
|
||||
///
|
||||
/// @return {Number (Unitless)}
|
||||
|
||||
@function strip-units($value) {
|
||||
@return ($value / ($value * 0 + 1));
|
||||
}
|
||||
24
plugins/git-sync/scss/vendor/bourbon/functions/_tint.scss
vendored
Normal file
24
plugins/git-sync/scss/vendor/bourbon/functions/_tint.scss
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Mixes a color with white.
|
||||
///
|
||||
/// @param {Color} $color
|
||||
///
|
||||
/// @param {Number (Percentage)} $percent
|
||||
/// The amount of white to be mixed in.
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// background-color: tint(#6ecaa6, 40%);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// background-color: #a8dfc9;
|
||||
/// }
|
||||
///
|
||||
/// @return {Color}
|
||||
|
||||
@function tint($color, $percent) {
|
||||
@return mix(#fff, $color, $percent);
|
||||
}
|
||||
22
plugins/git-sync/scss/vendor/bourbon/functions/_transition-property-name.scss
vendored
Normal file
22
plugins/git-sync/scss/vendor/bourbon/functions/_transition-property-name.scss
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Return vendor-prefixed property names if appropriate
|
||||
// Example: transition-property-names((transform, color, background), moz) -> -moz-transform, color, background
|
||||
//************************************************************************//
|
||||
@function transition-property-names($props, $vendor: false) {
|
||||
$new-props: ();
|
||||
|
||||
@each $prop in $props {
|
||||
$new-props: append($new-props, transition-property-name($prop, $vendor), comma);
|
||||
}
|
||||
|
||||
@return $new-props;
|
||||
}
|
||||
|
||||
@function transition-property-name($prop, $vendor: false) {
|
||||
// put other properties that need to be prefixed here aswell
|
||||
@if $vendor and $prop == transform {
|
||||
@return unquote('-'+$vendor+'-'+$prop);
|
||||
}
|
||||
@else {
|
||||
@return $prop;
|
||||
}
|
||||
}
|
||||
27
plugins/git-sync/scss/vendor/bourbon/functions/_unpack.scss
vendored
Normal file
27
plugins/git-sync/scss/vendor/bourbon/functions/_unpack.scss
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Converts shorthand to the 4-value syntax.
|
||||
///
|
||||
/// @param {List} $shorthand
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// margin: unpack(1em 2em);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// margin: 1em 2em 1em 2em;
|
||||
/// }
|
||||
|
||||
@function unpack($shorthand) {
|
||||
@if length($shorthand) == 1 {
|
||||
@return nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1);
|
||||
} @else if length($shorthand) == 2 {
|
||||
@return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 1) nth($shorthand, 2);
|
||||
} @else if length($shorthand) == 3 {
|
||||
@return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 3) nth($shorthand, 2);
|
||||
} @else {
|
||||
@return $shorthand;
|
||||
}
|
||||
}
|
||||
21
plugins/git-sync/scss/vendor/bourbon/helpers/_convert-units.scss
vendored
Normal file
21
plugins/git-sync/scss/vendor/bourbon/helpers/_convert-units.scss
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//************************************************************************//
|
||||
// Helper function for str-to-num fn.
|
||||
// Source: http://sassmeister.com/gist/9647408
|
||||
//************************************************************************//
|
||||
@function _convert-units($number, $unit) {
|
||||
$strings: "px", "cm", "mm", "%", "ch", "pica", "in", "em", "rem", "pt", "pc", "ex", "vw", "vh", "vmin", "vmax", "deg", "rad", "grad", "turn";
|
||||
$units: 1px, 1cm, 1mm, 1%, 1ch, 1pica, 1in, 1em, 1rem, 1pt, 1pc, 1ex, 1vw, 1vh, 1vmin, 1vmax, 1deg, 1rad, 1grad, 1turn;
|
||||
$index: index($strings, $unit);
|
||||
|
||||
@if not $index {
|
||||
@warn "Unknown unit `#{$unit}`.";
|
||||
@return false;
|
||||
}
|
||||
|
||||
@if type-of($number) != "number" {
|
||||
@warn "`#{$number} is not a number`";
|
||||
@return false;
|
||||
}
|
||||
|
||||
@return $number * nth($units, $index);
|
||||
}
|
||||
96
plugins/git-sync/scss/vendor/bourbon/helpers/_directional-values.scss
vendored
Normal file
96
plugins/git-sync/scss/vendor/bourbon/helpers/_directional-values.scss
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
@charset "UTF-8";
|
||||
|
||||
/// Directional-property mixins are shorthands for writing properties like the following
|
||||
///
|
||||
/// @ignore You can also use `false` instead of `null`.
|
||||
///
|
||||
/// @param {List} $vals
|
||||
/// List of directional values
|
||||
///
|
||||
/// @example scss - Usage
|
||||
/// .element {
|
||||
/// @include border-style(dotted null);
|
||||
/// @include margin(null 0 10px);
|
||||
/// }
|
||||
///
|
||||
/// @example css - CSS Output
|
||||
/// .element {
|
||||
/// border-bottom-style: dotted;
|
||||
/// border-top-style: dotted;
|
||||
/// margin-bottom: 10px;
|
||||
/// margin-left: 0;
|
||||
/// margin-right: 0;
|
||||
/// }
|
||||
///
|
||||
/// @require {function} contains-falsy
|
||||
///
|
||||
/// @return {List}
|
||||
|
||||
@function collapse-directionals($vals) {
|
||||
$output: null;
|
||||
|
||||
$a: nth($vals, 1);
|
||||
$b: if(length($vals) < 2, $a, nth($vals, 2));
|
||||
$c: if(length($vals) < 3, $a, nth($vals, 3));
|
||||
$d: if(length($vals) < 2, $a, nth($vals, if(length($vals) < 4, 2, 4)));
|
||||
|
||||
@if $a == 0 { $a: 0; }
|
||||
@if $b == 0 { $b: 0; }
|
||||
@if $c == 0 { $c: 0; }
|
||||
@if $d == 0 { $d: 0; }
|
||||
|
||||
@if $a == $b and $a == $c and $a == $d { $output: $a; }
|
||||
@else if $a == $c and $b == $d { $output: $a $b; }
|
||||
@else if $b == $d { $output: $a $b $c; }
|
||||
@else { $output: $a $b $c $d; }
|
||||
|
||||
@return $output;
|
||||
}
|
||||
|
||||
/// Output directional properties, for instance `margin`.
|
||||
///
|
||||
/// @access private
|
||||
///
|
||||
/// @param {String} $pre
|
||||
/// Prefix to use
|
||||
/// @param {String} $suf
|
||||
/// Suffix to use
|
||||
/// @param {List} $vals
|
||||
/// List of values
|
||||
///
|
||||
/// @require {function} collapse-directionals
|
||||
/// @require {function} contains-falsy
|
||||
|
||||
@mixin directional-property($pre, $suf, $vals) {
|
||||
// Property Names
|
||||
$top: $pre + "-top" + if($suf, "-#{$suf}", "");
|
||||
$bottom: $pre + "-bottom" + if($suf, "-#{$suf}", "");
|
||||
$left: $pre + "-left" + if($suf, "-#{$suf}", "");
|
||||
$right: $pre + "-right" + if($suf, "-#{$suf}", "");
|
||||
$all: $pre + if($suf, "-#{$suf}", "");
|
||||
|
||||
$vals: collapse-directionals($vals);
|
||||
|
||||
@if contains-falsy($vals) {
|
||||
@if nth($vals, 1) { #{$top}: nth($vals, 1); }
|
||||
|
||||
@if length($vals) == 1 {
|
||||
@if nth($vals, 1) { #{$right}: nth($vals, 1); }
|
||||
} @else {
|
||||
@if nth($vals, 2) { #{$right}: nth($vals, 2); }
|
||||
}
|
||||
|
||||
@if length($vals) == 2 {
|
||||
@if nth($vals, 1) { #{$bottom}: nth($vals, 1); }
|
||||
@if nth($vals, 2) { #{$left}: nth($vals, 2); }
|
||||
} @else if length($vals) == 3 {
|
||||
@if nth($vals, 3) { #{$bottom}: nth($vals, 3); }
|
||||
@if nth($vals, 2) { #{$left}: nth($vals, 2); }
|
||||
} @else if length($vals) == 4 {
|
||||
@if nth($vals, 3) { #{$bottom}: nth($vals, 3); }
|
||||
@if nth($vals, 4) { #{$left}: nth($vals, 4); }
|
||||
}
|
||||
} @else {
|
||||
#{$all}: $vals;
|
||||
}
|
||||
}
|
||||
43
plugins/git-sync/scss/vendor/bourbon/helpers/_font-source-declaration.scss
vendored
Normal file
43
plugins/git-sync/scss/vendor/bourbon/helpers/_font-source-declaration.scss
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Used for creating the source string for fonts using @font-face
|
||||
// Reference: http://goo.gl/Ru1bKP
|
||||
|
||||
@function font-url-prefixer($asset-pipeline) {
|
||||
@if $asset-pipeline == true {
|
||||
@return font-url;
|
||||
} @else {
|
||||
@return url;
|
||||
}
|
||||
}
|
||||
|
||||
@function font-source-declaration(
|
||||
$font-family,
|
||||
$file-path,
|
||||
$asset-pipeline,
|
||||
$file-formats,
|
||||
$font-url) {
|
||||
|
||||
$src: ();
|
||||
|
||||
$formats-map: (
|
||||
eot: "#{$file-path}.eot?#iefix" format("embedded-opentype"),
|
||||
woff2: "#{$file-path}.woff2" format("woff2"),
|
||||
woff: "#{$file-path}.woff" format("woff"),
|
||||
ttf: "#{$file-path}.ttf" format("truetype"),
|
||||
svg: "#{$file-path}.svg##{$font-family}" format("svg")
|
||||
);
|
||||
|
||||
@each $key, $values in $formats-map {
|
||||
@if contains($file-formats, $key) {
|
||||
$file-path: nth($values, 1);
|
||||
$font-format: nth($values, 2);
|
||||
|
||||
@if $asset-pipeline == true {
|
||||
$src: append($src, font-url($file-path) $font-format, comma);
|
||||
} @else {
|
||||
$src: append($src, url($file-path) $font-format, comma);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@return $src;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue