From 6eb6a79bbc547be85fa3e59df8f307af861e2b42 Mon Sep 17 00:00:00 2001 From: Sommerregen Date: Tue, 23 Jun 2015 21:31:24 +0200 Subject: [PATCH] :package: Initial commit of new "Shortcodes" plugin --- CHANGELOG.md | 5 + LICENSE | 702 ++++++++++++++++++++++++++ README.md | 217 ++++++++ assets/logo.png | Bin 0 -> 21300 bytes assets/screenshot.png | Bin 0 -> 28166 bytes blueprints.yaml | 26 + classes/Autoloader.php | 103 ++++ classes/Shortcode.php | 35 ++ classes/ShortcodeInterface.php | 36 ++ classes/Shortcodes.php | 160 ++++++ classes/Shortcodes/Assets.php | 114 +++++ classes/Shortcodes/Embed.php | 66 +++ classes/Shortcodes/Summary.php | 81 +++ classes/Twig/ShortcodeNode.php | 73 +++ classes/Twig/ShortcodeTokenParser.php | 188 +++++++ docs/CONTRIBUTING.md | 125 +++++ docs/INSTALL.md | 47 ++ docs/assets.md | 30 ++ docs/embed.md | 23 + docs/summary.md | 24 + hebe.json | 15 + shortcodes.php | 140 +++++ shortcodes.yaml | 19 + 23 files changed, 2229 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 assets/logo.png create mode 100644 assets/screenshot.png create mode 100644 blueprints.yaml create mode 100644 classes/Autoloader.php create mode 100644 classes/Shortcode.php create mode 100644 classes/ShortcodeInterface.php create mode 100644 classes/Shortcodes.php create mode 100644 classes/Shortcodes/Assets.php create mode 100644 classes/Shortcodes/Embed.php create mode 100644 classes/Shortcodes/Summary.php create mode 100644 classes/Twig/ShortcodeNode.php create mode 100644 classes/Twig/ShortcodeTokenParser.php create mode 100644 docs/CONTRIBUTING.md create mode 100644 docs/INSTALL.md create mode 100644 docs/assets.md create mode 100644 docs/embed.md create mode 100644 docs/summary.md create mode 100644 hebe.json create mode 100644 shortcodes.php create mode 100644 shortcodes.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d20c862 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# v1.0.0 +## 06/23/2015 + +1. [](#new) + * ChangeLog started... diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2166e80 --- /dev/null +++ b/LICENSE @@ -0,0 +1,702 @@ +For ease of distribution, Grav Shortcodes Plugin is under a dual license. You are free to pick which one suits your needs, but please keep in mind that dual licensing is based on the principle of Give-and-Take. Choose wisely. + +MIT LICENSE +----------- + +Copyright (c) 2015 Benjamin Regler, https://github.com/sommerregen/grav-plugin-shortcodes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +GPL VERSION 3 +------------- + +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d114ee8 --- /dev/null +++ b/README.md @@ -0,0 +1,217 @@ +# [![Grav Shortcodes Plugin](assets/logo.png)][project] + +[![Release](https://img.shields.io/github/release/sommerregen/grav-plugin-shortcodes.svg)][project] [![Issues](https://img.shields.io/github/issues/sommerregen/grav-plugin-shortcodes.svg)][issues] [![Dual license](https://img.shields.io/badge/dual%20license-MIT%2FGPL-blue.svg)](LICENSE "License") [![Flattr](https://api.flattr.com/button/flattr-badge-large.png)][flattr] [![PayPal](https://www.paypal.com/en_US/i/btn/btn_donate_SM.gif)][paypal] + +> This plugin introduces shortcodes to be used as simple snippets inside a document to be rendered by Grav. + +##### Table of Contents: + +* [About](#about) +* [Installation and Updates](#installation-and-updates) +* [Usage](#usage) + * [For end-users](#for-end-users) + * [For developers](#for-developers) + * [Available shortcodes](#available-shortcodes) +* [Contributing](#contributing) +* [Licencse](#license) + +## About + +`Shortcodes` is a plugin for [**Grav**](http://getgrav.org) used to extend Markdown's ability to do nifty things with very little effort. + +*Shortcodes are shortcuts*. Using a simple content format [shortcodes](#available-shortcodes) can embed files or create objects that would normally require lots of complicated, ugly code in just one line. + +![Screenshot Shortcodes Plugin](assets/screenshot.png "Shortcodes Preview") + +## Installation and Updates + +Installing or updating the `Shortcodes` plugin can be done in one of two ways. Using the GPM (Grav Package Manager) installation update method or manual install by downloading [this plugin](https://github.com/sommerregen/grav-plugin-shortcodes) and extracting all plugin files to + + /your/site/grav/user/plugins/shortcodes + +For more informations, please check the [Installation and update guide](docs/INSTALL.md). + +## Usage + +The `Shortcodes` plugin comes with some sensible default configuration, that are pretty self explanatory: + +### Config Defaults + +```yaml +# Global plugin configurations + +enabled: true # Set to false to disable this plugin completely + +# Default configurations for special shortcodes + +shortcodes: + summary: + render: "html" # Render content as HTML + + embed: + template: "" # Default template to render a page + + assets: + type: "css" # Assets type (either "css" or "js") + inline: false # Include assets as block or inline argument + priority: 10 # Priority to add CSS or JS to Grav pipeline, bigger comes first + pipeline: false # Pipeline assets or not + load: "" # Load asset either asynchronously "async" or deferred "defer" +``` + +If you need to change any value, then the best process is to copy the [shortcodes.yaml](shortcodes.yaml) file into your `users/config/plugins/` folder (create it if it doesn't exist), and then modify there. This will override the default settings. + +If you want to alter the settings for one or a few pages only, you can do so by adding page specific configurations into your page headers, e.g. + +```yaml +shortcodes: false +``` + +to disable the `Shortcodes` plugin just for this page. + +### For end-users + +In your content files, a shortcode can be called by using `{{% myshortcode %}}` +respectively. Shortcodes are space delimited (parameters with spaces can be quoted). + +The first word is always the name of the shortcode. Parameters follow the name.The format for named parameters models that of HTML with the format `name="value"`. + +Some shortcodes use or require closing shortcodes. Closing shortcodes either match the name of the shortcode with prepended `end` like `{{% endmyshortcode %}}` or just `{{% end %}}` e.g., + +```twig +{{% summary %}} + My summary +{{% end %}} +``` + +Shortcodes can be nested and may require parameters to work. Parameters to shortcodes can either be passed in two ways + +```twig +{{% myshortcode param1 name="value" %}} +OR +{{% myshortcode(param1, name="value") %}} +``` + +Sometimes you may want to print the shortcode without processing it. To archive this you have two options. Either you disable `Shortcodes` plugin per page using `shortcodes: false` or enclose the (whole) shortcode with the special `{{% raw %}}...{{% endraw %}}` shortcode like this: + +``` +{{% raw %}} + {{% My ignored tag %}} +{{% endraw %}} +``` + +### Twig Function + +`Shortcodes` provides a Twig function to render shortcodes for any text. To use it, place the following line of code in the theme file: + +```twig +{{ shortcodes("A text and shortcodes") }} +``` + +### Available shortcodes + +The `Shortcode` plugin offers some of the shortcodes by default and plugins can add their own as well via the [Shortcode API](#for-developers). The default supported shortcodes are listed in the following: + +##### System + +- `{{% embed %}}` embeds a page or the contents of a page. [» Full instructions](docs/embed.md) +- `{{% assets %}}` adds CSS and JS assets directly to the site. [» Full instructions](docs/assets.md) + +##### Images and Documents + +- `{{% summary %}}` sets the summary of page. [» Full instructions](docs/summary.md) + +##### Audio + +##### Video + +##### Miscellaneous + +Useful shortcodes for adding a blog archive index, contact form, polls, and more. + +## For developers + +The `Shortcodes` plugin offers developers to register their own shortcodes (here: `myshortcode`). To do this `Shortcodes` provides an event `onShortcodesEvent`, which could be used to register new shortcodes via + +```php +class MyShortcode extends Plugin +{ + public static function getSubscribedEvents() + { + return [ + 'onShortcodesEvent' => ['onShortcodesEvent', 0] + ]; + } + + ... + + public function onShortcodesEvent(Event, $event) + { + // Initialize custom shortcode + $shortcode = new MyShortCode(); + + // Register shortcode + $event['shortcodes']->register($shortcode); + } +} +``` + +Here `MyShortCode` is a class, which basically has the form + +```php +use RocketTheme\Toolbox\Event\Event; +use Grav\Plugin\Shortcodes\Shortcode; + +class MyShortCode extends Shortcode +{ + public function getShortcode() + { + return ['name' => 'myshortcode', 'type' => 'block']; + } + + public function execute(Event $event) + { + // do something and return string + } +} +``` +where you can put your code inside the `execute` method. Here the `getShortcode` returns some informations bout your shortcode i.e, that the name should be "myshortcode" and that it is a block element. That's it. + +For further examples please study the already available shortcodes in the [provided shortcodes classes](classes/Shortcodes). + +## Contributing + +You can contribute at any time! Before opening any issue, please search for existing issues and review the [guidelines for contributing](docs/CONTRIBUTING.md). + +After that please note: + +* If you find a bug or would like to make a feature request or suggest an improvement, [please open a new issue][issues]. If you have any interesting ideas for additions to the syntax please do suggest them as well! +* Feature requests are more likely to get attention if you include a clearly described use case. +* If you wish to submit a pull request, please make again sure that your request match the [guidelines for contributing](docs/CONTRIBUTING.md) and that you keep track of adding unit tests for any new or changed functionality. + +### Support and donations + +If you like my project, feel free to support me via [![Flattr](https://api.flattr.com/button/flattr-badge-large.png)][flattr] or by sending me some bitcoins to [**1HQdy5aBzNKNvqspiLvcmzigCq7doGfLM4**][bitcoin]. + +Thanks! + +## License + +Copyright (c) 2015 [Benjamin Regler][github]. See also the list of [contributors] who participated in this project. + +[Dual-licensed](LICENSE) for use under the terms of the [MIT][mit-license] or [GPLv3][gpl-license] licenses. + +![GNU license - Some rights reserved][gnu] + +[github]: https://github.com/sommerregen/ "GitHub account from Benjamin Regler" +[gpl-license]: http://opensource.org/licenses/GPL-3.0 "GPLv3 license" +[mit-license]: http://www.opensource.org/licenses/mit-license.php "MIT license" + +[flattr]: https://flattr.com/submit/auto?user_id=Sommerregen&url=https://github.com/sommerregen/grav-plugin-shortcodes "Flatter my GitHub project" +[paypal]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SYFNP82USG3RN "Donate for my GitHub project using PayPal" +[bitcoin]: bitcoin:1HQdy5aBzNKNvqspiLvcmzigCq7doGfLM4?label=GitHub%20project "Donate for my GitHub project using BitCoin" +[gnu]: https://upload.wikimedia.org/wikipedia/commons/thumb/3/33/License_icon-gpl-88x31.svg/88px-License_icon-gpl-88x31.svg.png "GNU license - Some rights reserved" + +[project]: https://github.com/sommerregen/grav-plugin-shortcodes +[issues]: https://github.com/sommerregen/grav-plugin-shortcodes/issues "GitHub Issues for Grav Shortcodes Plugin" +[contributors]: https://github.com/sommerregen/grav-plugin-shortcodes/graphs/contributors "List of contributors of the project" diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..05a35790be2ea68cafb420a14b661a368869a46c GIT binary patch literal 21300 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 Oqphj0QKI%N literal 0 HcmV?d00001 diff --git a/blueprints.yaml b/blueprints.yaml new file mode 100644 index 0000000..e77b650 --- /dev/null +++ b/blueprints.yaml @@ -0,0 +1,26 @@ +name: "Shortcodes" +version: 1.0.0 +description: "This plugin enables to use shortcodes (simple snippets) inside a document to be rendered by Grav." +icon: puzzle-piece +author: + name: Sommerregen + email: sommerregen@benjamin-regler.de +homepage: https://github.com/sommerregen/grav-plugin-shortcodes +keywords: [shortcodes, twig, grav, extension, plugin] +docs: https://github.com/sommerregen/grav-plugin-shortcodes/blob/master/README.md +bugs: https://github.com/sommerregen/grav-plugin-shortcodes/issues +license: MIT/GPL + +form: + validation: strict + fields: + enabled: + type: toggle + label: "Plugin Status" + highlight: 1 + default: 0 + options: + 1: Enabled + 0: Disabled + validate: + type: bool diff --git a/classes/Autoloader.php b/classes/Autoloader.php new file mode 100644 index 0000000..68e8b49 --- /dev/null +++ b/classes/Autoloader.php @@ -0,0 +1,103 @@ + __DIR__]; + } + + $this->route($routes); + } + + public function route($var = null, $reset = true) + { + if ($var !== null && is_array($var)) { + if ($reset) { + $this->routes = []; + } + + // Setup routes + foreach ($var as $prefix => $path) { + if (false !== strrpos($prefix, '\\')) { + // Prefix is a namespaced path + $prefix = rtrim($prefix, '_\\') . '\\'; + } else { + // Prefix contain underscores + $prefix = rtrim($prefix, '_') . '_'; + } + + $this->routes[$prefix] = rtrim($path, '/\\') . '/'; + } + } + + return $this->routes; + } + + /** + * Autoload classes + * + * @param string $class Class name + * + * @return mixed false FALSE if unable to load $class; Class name if + * $class is successfully loaded + */ + public function autoload($class) + { + foreach ($this->routes as $prefix => $path) { + // Only load classes of MediaEmbed plugin + if (false !== strpos($class, $prefix)) { + // Remove prefix from class + $class = substr($class, strlen($prefix)); + + // Replace namespace tokens to directory separators + $file = $path . preg_replace('#\\\|_(?!.+\\\)#', '/', $class) . '.php'; + + // Load class + if (stream_resolve_include_path($file)) { + return include_once($file); + } + + return false; + } + } + + return false; + } + + /** + * Registers this instance as an autoloader + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'autoload'), false, $prepend); + } + + /** + * Unregisters this instance as an autoloader + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'autoload')); + } +} diff --git a/classes/Shortcode.php b/classes/Shortcode.php new file mode 100644 index 0000000..f36c552 --- /dev/null +++ b/classes/Shortcode.php @@ -0,0 +1,35 @@ +defaults = $defaults; + } +} diff --git a/classes/ShortcodeInterface.php b/classes/ShortcodeInterface.php new file mode 100644 index 0000000..67b2829 --- /dev/null +++ b/classes/ShortcodeInterface.php @@ -0,0 +1,36 @@ +config = $config; + + // Set up Twig environment + $this->twig = new \Twig_Environment(new \Twig_Loader_String(), [ + 'use_strictr_variables' => false, + ]); + + // Set up sandbox for parsing shortcodes + $policy = new \Twig_Sandbox_SecurityPolicy($this->loadShortcodes()); + $this->twig->addExtension(new \Twig_Extension_Sandbox($policy, true)); + + // Modify lexer to match special shortcode syntax + $lexer = new \Twig_Lexer($this->twig, array( + 'tag_comment' => ['{#', '#}'], + 'tag_block' => ['{{%', '%}}'], + 'tag_variable' => ['{#', '#}'], + 'interpolation' => ['#{', '}'] + )); + $this->twig->setLexer($lexer); + } + + /** + * Render shortcodes. + * + * @param string $content The content to render. + * @param array $options Options to be passed to the renderer. + * @param null|Page $page Null or an instance of \Grav\Common\Page. + * + * @return string The modified contents. + */ + public function render($content, $options = [], $page = null) + { + // Build an anonymous function to pass to twig `render` method + $function = function($tag, $body, $params) use ($options, $page) { + if (isset($this->shortcodes[$tag])) { + $options = isset($options[$tag]) ? $options[$tag] : []; + $event = new Event([ + 'body' => $body, + 'options' => new Data(array_replace_recursive($options, $params)), + 'grav' => self::getGrav(), + 'shortcodes' => $this, + 'page' => $page + ]); + + return $this->shortcodes[$tag]->execute($event); + } + }; + + return $this->twig->render($content, ['__shortcodes' => $function]); + } + + /** + * Register a shortcode. + * + * @param Shortcode $shortcode An instance of ShortcodeInterface. + * @param array $options An array of defaults options for the + * shortcode. + * + * @return bool Return status code (true on success). + */ + public function register($shortcode, $options = []) + { + if ($shortcode instanceof ShortcodeInterface) { + $options += $shortcode->getShortcode(); + $inline = ($options['type'] === 'inline') ? true : false; + $this->shortcodes[$options['name']] = $shortcode; + + $this->twig->addTokenParser( + new ShortcodeTokenParser($options['name'], $inline) + ); + + return true; + } + + return false; + } + + /** + * Load shortcodes already provided by this plugin. + */ + protected function loadShortcodes() + { + $iterator = new \FilesystemIterator(__DIR__.'/shortcodes'); + foreach ($iterator as $fileinfo) { + $name = $fileinfo->getBasename('.php'); + + // Load shortcodes in directory "Shortcodes" + $class = __NAMESPACE__."\\Shortcodes\\$name"; + $defaults = $this->config->get('plugins.shortcodes.shortcodes.'.strtolower($name), []); + $shortcode = new $class($defaults); + $this->register($shortcode); + } + + // Fire event + self::getGrav()->fireEvent('onShortcodesEvent', new Event(['shortcodes' => $this])); + + return array_keys($this->shortcodes); + } +} diff --git a/classes/Shortcodes/Assets.php b/classes/Shortcodes/Assets.php new file mode 100644 index 0000000..689be16 --- /dev/null +++ b/classes/Shortcodes/Assets.php @@ -0,0 +1,114 @@ + 'assets', 'type' => 'block']; + } + + + /** + * Execute shortcode. + * + * @param Event $event An event object. + * @return string|null Return modified contents. + */ + public function execute(Event $event) + { + /* @var \Grav\Common\Grav $grav */ + $grav = $event['grav']; + + /* @var \Grav\Common\Data\Data $options */ + $options = $event['options']; + $options->setDefaults($this->defaults); + + $type = strtolower($options->get('type')); + $body = trim(strip_tags($event['body'], '