PaxHeader/Mason-2.21000775 777777 777777 00000000213 12266570730 014502 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365355 19 SCHILY.nlink=14 Mason-2.21/000775 €ˆž«€q{Ì00000000000 12266570730 013535 5ustar00jonswart000000 000000 Mason-2.21/PaxHeader/bin000775 777777 777777 00000000212 12266570730 015251 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365357 18 SCHILY.nlink=3 Mason-2.21/bin/000775 €ˆž«€q{Ì00000000000 12266570730 014305 5ustar00jonswart000000 000000 Mason-2.21/PaxHeader/Changes000644 777777 777777 00000000212 12266570730 016044 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365356 18 SCHILY.nlink=1 Mason-2.21/Changes000644 €ˆž«€q{Ì00000013536 12266570730 015036 0ustar00jonswart000000 000000 Revision history for Mason ** marks an incompatible change 2.21 Jan 18, 2014 * Fixes - Replace deprecated Class::MOP methods with Class::Load - perl-mason/pull/21 (Leeft) * Improvements - Add class_header shortcut to add to each component class header - perl-mason/pull/14 (jomo666) 2.20 Jul 12, 2012 * Improvements - Implement and document trailing slash policy - perl-mason/pull/11 (Pedro Melo) * Fixes - Coerce undefined filter argument to the empty string (Tomohiro Hosaka) - Eliminate "=for html" POD entries, which were mangling metacpan.org output (Pedro Melo) - Fix some tests for Windows - perl-mason/pull/9 (Tomasz Konojacki) * Documentation - Moved eg/blog to Poet 2.19 May 2, 2012 * Improvements - Add $.Tee standard filter, like $.Capture but outputs at same time * Fixes - Fix for Moose 2.06 - RT #76793 (doy) * Documentation - Mention Mason::Plugin::DefaultFilter more prominently 2.18 Apr 22, 2012 * Documentation - Add references to Poet, Mason's new companion web framework - Move Admin.pod to Setup.pod - Fix lots of broken links 2.17 Mar 27, 2012 * Documentation - Move FAQ pod sections up one level * Fixes - Use make_immutable on generated Mason subclasses (Tomohiro Hosaka) - Properly quote paths when generating component class (Peter Franke) 2.16 Feb 24, 2012 * Documentation - Add Mason::Manual::FAQ, and various documentation improvements/fixes * Fixes - Add prereq Exception::Class - Use Data::Dumper in Mason::Util 2.15 Nov 27, 2011 ** Incompatible changes - Rename bin/mason to bin/mason.pl, to avoid conflict with the Mason firewall tool - RT #72497 (Florian) * Fixes - Fix parser bug with filters and comment characters (Tomohiro Hosaka) 2.14 Sep 6, 2011 ** Incompatible changes - Deprecate %%-lines, <%args> section and <%shared> section, which IMO add unnecessary TMTOWTDI. Standardize on the <%class> section and Moose 'has' declarations. These alternate syntaxes may make it into a plugin. * Improvements - Allow applications to specify Mason subclasses by naming convention. - Document use of Mason subclasses in Mason::Manual::Subclasses. * Fixes - Respect Mason::CodeCache plugins (bokutin) - Allow comments after filter markers {{ and }} 2.13 Jul 26, 2011 * Improvements - Add process_output, an easy way to modify all Mason output in a plugin or subclass 2.12 Jul 3, 2011 * Fixes - Fix $m->visit under PSGIHandler (Jozef Mojzis) - Fix $m->visit when initial out_method passed 2.11 Jun 29, 2011 * Fixes - Fix memory leaks between Interp, Request and Component; add test for leaks (StephenClouse) 2.10 Jun 23, 2011 * Fixes - Fix filter pipe syntax, broken in 2.09 - RT #69038 (MDIETRICH) - Specify and test execution order of multiple filters in pipe syntax - Go back to generating version numbers for all sub-modules again 2.09 Jun 20, 2011 * Fixes - Properly rename Mason::t::Defer test 2.08 Jun 18, 2011 ** Incompatible changes - Change apply filter syntax to % $.Filter {{ ... % }} as it reduces tag soup and better matches the typical use of filtering a block of content * Improvements - Add $m->filter to manually apply filters - Add CLASS->no_wrap() as a convenient way to skip parent wrapping - Set $_ as well as $_[0] to content for filtering, to make s// based filters easier * Fixes - Define $CLASS as well as CLASS in components, ala CLASS module - Fix $. notation inside <& &> - Re-fix compatibility with JSON version 1.x - Untaint component source when in taint mode (e.g. mod_perl) as in Mason 1, otherwise compiler regexes may fail 2.07 Apr 21, 2011 * Improvements - Allow arguments to be passed to the content sub from a dynamic filter (e.g. CompCall) - Throw error on unmatched %> or &> - Fix error line numbers after method sections and multiple text sections * Fixes - Prevent false inheritance loops when component overrides its default parent (Jozef Mojzis) - Fix compatibility with JSON version 1.x * Other - Only generate version numbers for .pm files with documentation, to reduce inter-version churn 2.06 Mar 14, 2011 * Fixes - Use new file extensions in eg/blog (Jozef Mojzis) 2.05 Mar 6, 2011 ** Incompatible changes - Change default component file extensions due to conflict with Objective C's .m (suggested by jomo). New extensions: .mc - top-level component .mi - internal component .mp - pure-perl component * Fixes - Require comp_root parameter to Mason->new (cxreg) - Require that request path is absolute - Ignore whitespace at beginning of a <%args> and <%shared> line (cxreg) * Improvements - Forbid reserved names such as 'cmeta' in new method and attribute declarations - Improve error message when request path not found - list all component paths searched * Testing - Stop using test counts - see http://bit.ly/eISu3R * Documentation - Add Mason/Manual/Intro.pod 2.04 Feb 26, 2011 * Fixes - Fix broken $m->scomp (Tomohiro Hosaka) * Testing - Add a pile of tests to fill in coverage gaps 2.03 Feb 24, 2011 * Improvements - Add -e option to bin/mason * Fixes - Depend on Log::Any 0.08, for Log::Any::Test (David Wheeler) 2.02 Feb 24, 2011 * Fixes - Allow index file (index.m, index.pm) to be accessed directly with /index path (Matthias Dietrich) - Fix error line # for invalid attribute - Include HTMLFilters in eg/blog/install.sh (qiuhw) - Fix t/mason-app.t to be perl-location-agnostic (qiuhw) - Prevent CPAN from indexing built-in plugin implementation files * Backend - Remove InstanceMeta object, make args() a direct method of component - Add pluggable Mason::Component::Import for importing non-Moose things into components 2.01 Feb 20, 2011 * Fixes - Declare Devel::GlobalDestruction dependency; get rid of List::MoreUtils dependency 2.00 Feb 16, 2011 - Initial Mason 2 version - see HTML::Mason for previous versions Mason-2.21/PaxHeader/eg000775 777777 777777 00000000212 12266570730 015074 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365359 18 SCHILY.nlink=3 Mason-2.21/eg/000775 €ˆž«€q{Ì00000000000 12266570730 014130 5ustar00jonswart000000 000000 Mason-2.21/PaxHeader/INSTALL000644 777777 777777 00000000212 12266570730 015602 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365490 18 SCHILY.nlink=1 Mason-2.21/INSTALL000644 €ˆž«€q{Ì00000001605 12266570730 014566 0ustar00jonswart000000 000000 This is the Perl distribution Mason. Installing Mason is straightforward. ## Installation with cpanm If you have cpanm, you only need one line: % cpanm Mason If you are installing into a system-wide directory, you may need to pass the "-S" flag to cpanm, which uses sudo to install the module: % cpanm -S Mason ## Installing with the CPAN shell Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan Mason ## Manual installation As a last resort, you can manually install it. Download the tarball, untar it, then build it: % perl Makefile.PL % make && make test Then install it: % make install If you are installing into a system-wide directory, you may need to run: % sudo make install ## Documentation Mason documentation is available as POD. You can run perldoc from a shell to read the documentation: % perldoc Mason Mason-2.21/PaxHeader/lib000775 777777 777777 00000000212 12266570730 015247 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365362 18 SCHILY.nlink=4 Mason-2.21/lib/000775 €ˆž«€q{Ì00000000000 12266570730 014303 5ustar00jonswart000000 000000 Mason-2.21/PaxHeader/LICENSE000644 777777 777777 00000000212 12266570730 015556 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365485 18 SCHILY.nlink=1 Mason-2.21/LICENSE000644 €ˆž«€q{Ì00000043664 12266570730 014555 0ustar00jonswart000000 000000 This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2012 by Jonathan Swartz. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: 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 humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2012 by Jonathan Swartz. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End Mason-2.21/PaxHeader/Makefile.PL000644 777777 777777 00000000212 12266570730 016523 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365489 18 SCHILY.nlink=1 Mason-2.21/Makefile.PL000644 €ˆž«€q{Ì00000003610 12266570730 015505 0ustar00jonswart000000 000000 use strict; use warnings; use ExtUtils::MakeMaker 6.30; my %WriteMakefileArgs = ( "ABSTRACT" => "Powerful, high-performance templating for the web and beyond", "AUTHOR" => "Jonathan Swartz ", "BUILD_REQUIRES" => {}, "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => "6.30" }, "DISTNAME" => "Mason", "EXE_FILES" => [ "bin/mason.pl" ], "LICENSE" => "perl", "NAME" => "Mason", "PREREQ_PM" => { "Capture::Tiny" => 0, "Class::Load" => 0, "Class::Unload" => 0, "Devel::GlobalDestruction" => 0, "Exception::Class" => 0, "File::Spec" => 0, "File::Temp" => 0, "Guard" => 0, "IPC::System::Simple" => 0, "JSON" => 0, "Log::Any" => "0.08", "Memoize" => 0, "Method::Signatures::Simple" => 0, "Moose" => "1.15", "MooseX::HasDefaults" => "0.03", "MooseX::StrictConstructor" => "0.13", "Scalar::Util" => "1.01", "Try::Tiny" => 0 }, "TEST_REQUIRES" => { "Test::Class::Most" => 0, "Test::LongString" => 0 }, "VERSION" => "2.21", "test" => { "TESTS" => "t/*.t" } ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { my $tr = delete $WriteMakefileArgs{TEST_REQUIRES}; my $br = $WriteMakefileArgs{BUILD_REQUIRES}; for my $mod ( keys %$tr ) { if ( exists $br->{$mod} ) { $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod}; } else { $br->{$mod} = $tr->{$mod}; } } } unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) { my $br = delete $WriteMakefileArgs{BUILD_REQUIRES}; my $pp = $WriteMakefileArgs{PREREQ_PM}; for my $mod ( keys %$br ) { if ( exists $pp->{$mod} ) { $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod}; } else { $pp->{$mod} = $br->{$mod}; } } } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); Mason-2.21/PaxHeader/MANIFEST000644 777777 777777 00000000212 12266570730 015702 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365486 18 SCHILY.nlink=1 Mason-2.21/MANIFEST000644 €ˆž«€q{Ì00000005161 12266570730 014667 0ustar00jonswart000000 000000 Changes INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL bin/mason.pl eg/blog/README lib/Mason.pm lib/Mason/App.pm lib/Mason/CodeCache.pm lib/Mason/Compilation.pm lib/Mason/Component.pm lib/Mason/Component/ClassMeta.pm lib/Mason/Component/Import.pm lib/Mason/Component/Moose.pm lib/Mason/DynamicFilter.pm lib/Mason/Exceptions.pm lib/Mason/Filters/Standard.pm lib/Mason/Interp.pm lib/Mason/Manual.pod lib/Mason/Manual/Components.pod lib/Mason/Manual/Cookbook.pod lib/Mason/Manual/FAQ.pod lib/Mason/Manual/Filters.pod lib/Mason/Manual/Intro.pod lib/Mason/Manual/Plugins.pod lib/Mason/Manual/RequestDispatch.pod lib/Mason/Manual/Setup.pod lib/Mason/Manual/Subclasses.pod lib/Mason/Manual/Syntax.pod lib/Mason/Manual/Tutorial.pod lib/Mason/Manual/UpgradingFromMason1.pod lib/Mason/Moose.pm lib/Mason/Moose/Role.pm lib/Mason/Plugin.pm lib/Mason/Plugin/Defer.pm lib/Mason/Plugin/Defer/Filters.pm lib/Mason/Plugin/Defer/Request.pm lib/Mason/Plugin/DollarDot.pm lib/Mason/Plugin/DollarDot/Compilation.pm lib/Mason/Plugin/LvalueAttributes.pm lib/Mason/Plugin/LvalueAttributes/Interp.pm lib/Mason/Plugin/TidyObjectFiles.pm lib/Mason/Plugin/TidyObjectFiles/Interp.pm lib/Mason/PluginBundle.pm lib/Mason/PluginBundle/Default.pm lib/Mason/PluginManager.pm lib/Mason/PluginRole.pm lib/Mason/Request.pm lib/Mason/Result.pm lib/Mason/Test/Class.pm lib/Mason/Test/Overrides/Component/StrictMoose.pm lib/Mason/Test/Plugins/Notify.pm lib/Mason/Test/Plugins/Notify/Compilation.pm lib/Mason/Test/Plugins/Notify/Component.pm lib/Mason/Test/Plugins/Notify/Interp.pm lib/Mason/Test/Plugins/Notify/Request.pm lib/Mason/Test/RootClass.pm lib/Mason/Test/RootClass/Compilation.pm lib/Mason/Test/RootClass/Component.pm lib/Mason/Test/RootClass/Interp.pm lib/Mason/Test/RootClass/Request.pm lib/Mason/TieHandle.pm lib/Mason/Types.pm lib/Mason/Util.pm lib/Mason/t/Autobase.pm lib/Mason/t/Cache.pm lib/Mason/t/CompCalls.pm lib/Mason/t/Compilation.pm lib/Mason/t/ComponentMeta.pm lib/Mason/t/Defer.pm lib/Mason/t/DollarDot.pm lib/Mason/t/Errors.pm lib/Mason/t/Filters.pm lib/Mason/t/Globals.pm lib/Mason/t/HTMLFilters.pm lib/Mason/t/Interp.pm lib/Mason/t/LvalueAttributes.pm lib/Mason/t/Plugins.pm lib/Mason/t/Reload.pm lib/Mason/t/Request.pm lib/Mason/t/ResolveURI.pm lib/Mason/t/Sanity.pm lib/Mason/t/Sections.pm lib/Mason/t/Skel.pm lib/Mason/t/StaticSource.pm lib/Mason/t/Syntax.pm lib/Mason/t/Util.pm t/Autobase.t t/CompCalls.t t/Compilation.t t/ComponentMeta.t t/Defer.t t/DollarDot.t t/Errors.t t/Filters.t t/Globals.t t/Interp.t t/LvalueAttributes.t t/Plugins.t t/Reload.t t/Request.t t/ResolveURI.t t/Sanity.t t/Sections.t t/StaticSource.t t/Syntax.t t/Util.t t/author-leaks.t t/mason-app.t Mason-2.21/PaxHeader/META.json000644 777777 777777 00000000212 12266570730 016172 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365487 18 SCHILY.nlink=1 Mason-2.21/META.json000644 €ˆž«€q{Ì00000004146 12266570730 015161 0ustar00jonswart000000 000000 { "abstract" : "Powerful, high-performance templating for the web and beyond", "author" : [ "Jonathan Swartz " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 4.300034, CPAN::Meta::Converter version 2.131560", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Mason", "no_index" : { "directory" : [ "eg", "lib/Mason/t", "lib/Mason/Test", "lib/Mason/Plugin/Defer", "lib/Mason/Plugin/DollarDot", "lib/Mason/Plugin/LvalueAttributes", "lib/Mason/Plugin/TidyObjectFiles" ], "file" : [ "lib/Mason/Util.pm" ] }, "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "6.30" } }, "runtime" : { "requires" : { "Capture::Tiny" : "0", "Class::Load" : "0", "Class::Unload" : "0", "Devel::GlobalDestruction" : "0", "Exception::Class" : "0", "File::Spec" : "0", "File::Temp" : "0", "Guard" : "0", "IPC::System::Simple" : "0", "JSON" : "0", "Log::Any" : "0.08", "Memoize" : "0", "Method::Signatures::Simple" : "0", "Moose" : "1.15", "MooseX::HasDefaults" : "0.03", "MooseX::StrictConstructor" : "0.13", "Scalar::Util" : "1.01", "Try::Tiny" : "0" } }, "test" : { "requires" : { "Test::Class::Most" : "0", "Test::LongString" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-mason@rt.cpan.org", "web" : "http://rt.cpan.org/NoAuth/Bugs.html?Dist=Mason" }, "repository" : { "type" : "git", "url" : "git://github.com/jonswar/perl-mason.git", "web" : "https://github.com/jonswar/perl-mason" } }, "version" : "2.21" } Mason-2.21/PaxHeader/META.yml000644 777777 777777 00000000212 12266570730 016022 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365488 18 SCHILY.nlink=1 Mason-2.21/META.yml000644 €ˆž«€q{Ì00000002266 12266570730 015012 0ustar00jonswart000000 000000 --- abstract: 'Powerful, high-performance templating for the web and beyond' author: - 'Jonathan Swartz ' build_requires: Test::Class::Most: 0 Test::LongString: 0 configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 generated_by: 'Dist::Zilla version 4.300034, CPAN::Meta::Converter version 2.131560' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Mason no_index: directory: - eg - lib/Mason/t - lib/Mason/Test - lib/Mason/Plugin/Defer - lib/Mason/Plugin/DollarDot - lib/Mason/Plugin/LvalueAttributes - lib/Mason/Plugin/TidyObjectFiles file: - lib/Mason/Util.pm requires: Capture::Tiny: 0 Class::Load: 0 Class::Unload: 0 Devel::GlobalDestruction: 0 Exception::Class: 0 File::Spec: 0 File::Temp: 0 Guard: 0 IPC::System::Simple: 0 JSON: 0 Log::Any: 0.08 Memoize: 0 Method::Signatures::Simple: 0 Moose: 1.15 MooseX::HasDefaults: 0.03 MooseX::StrictConstructor: 0.13 Scalar::Util: 1.01 Try::Tiny: 0 resources: bugtracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Mason repository: git://github.com/jonswar/perl-mason.git version: 2.21 Mason-2.21/PaxHeader/README000664 777777 777777 00000000212 12266570730 015433 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365492 18 SCHILY.nlink=1 Mason-2.21/README000664 €ˆž«€q{Ì00000004666 12266570730 014431 0ustar00jonswart000000 000000 NAME Mason - Powerful, high-performance templating for the web and beyond SYNOPSIS foo.mc: % my $name = "Mason"; Hello world! Welcome to <% $name %>. #!/usr/local/bin/perl use Mason; my $mason = Mason->new(comp_root => '...'); print $mason->run('/foo')->output; DESCRIPTION Mason is a powerful Perl-based templating system, designed to generate dynamic content of all kinds. Unlike many templating systems, Mason does not attempt to invent an alternate, "easier" syntax for templates. It provides a set of syntax and features specific to template creation, but underneath it is still clearly and proudly recognizable as Perl. Mason is most often used for generating web pages. It has a companion web framework, Poet, designed to take maximum advantage of its routing and content generation features. It can also be used as the templating layer for web frameworks such as Catalyst and Dancer. All documentation is indexed at Mason::Manual. The previous major version of Mason (1.x) is available under the name HTML::Mason. SUPPORT The mailing list is `mason-users@lists.sourceforge.net'. You must be subscribed to send a message. To subscribe, visit https://lists.sourceforge.net/lists/listinfo/mason-users. You can also visit us at `#mason' on irc:. Bugs and feature requests will be tracked at RT: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Mason bug-mason@rt.cpan.org The latest source code can be browsed and fetched at: http://github.com/jonswar/perl-mason git clone git://github.com/jonswar/perl-mason.git The official Mason website is http://www.masonhq.com/, however it contains mostly information about Mason 1. We're not sure what the future of the website will be wrt Mason 2. ACKNOWLEDGEMENTS Thanks to Stevan Little and the Moose team for the awesomeness of Moose, which motivated me to create a second version of Mason years after I thought I was done. Thanks to Tatsuhiko Miyagawa and the PSGI/Plack team, who freed me from ever worrying about server backends again. SEE ALSO HTML::Mason AUTHOR Jonathan Swartz COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Mason-2.21/PaxHeader/t000775 777777 777777 00000000213 12266570730 014745 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365462 19 SCHILY.nlink=24 Mason-2.21/t/000775 €ˆž«€q{Ì00000000000 12266570730 014000 5ustar00jonswart000000 000000 Mason-2.21/t/PaxHeader/author-leaks.t000644 777777 777777 00000000212 12266570730 017600 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365484 18 SCHILY.nlink=1 Mason-2.21/t/author-leaks.t000644 €ˆž«€q{Ì00000002221 12266570730 016557 0ustar00jonswart000000 000000 #!perl -w BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use Devel::LeakGuard::Object qw(leakguard); use File::Path qw(mkpath); use File::Temp qw(tempdir); use Test::Most; use Mason::Util qw(write_file); use Mason; sub testleaks { my $code = shift; my $report; $code->(); leakguard( sub { $code->() }, only => 'Mason*', on_leak => sub { $report = shift; } ); if ($report) { my $desc = join("\n", map { sprintf("%s %d %d", $_, @{ $report->{$_} }) } keys(%$report)); ok( 0, "leaks found:\n$desc" ); } else { ok( 1, "no leaks found" ); } } my $root = tempdir('name-XXXX', TMPDIR => 1, CLEANUP => 1); my $comp_root = "$root/comps"; my $data_dir = "$root/data"; mkpath( [ $comp_root, $data_dir ], 0, 0775 ); testleaks( sub { my $interp = Mason->new( comp_root => $comp_root, data_dir => $data_dir ); foreach my $comp (qw(foo bar)) { write_file("$comp_root/$comp.mc", "Hi"); $interp->run("/$comp"); } } ); done_testing(); Mason-2.21/t/PaxHeader/Autobase.t000644 777777 777777 00000000212 12266570730 016744 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365463 18 SCHILY.nlink=1 Mason-2.21/t/Autobase.t000644 €ˆž«€q{Ì00000000100 12266570730 015715 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Autobase; Mason::t::Autobase->runtests; Mason-2.21/t/PaxHeader/CompCalls.t000644 777777 777777 00000000212 12266570730 017056 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365464 18 SCHILY.nlink=1 Mason-2.21/t/CompCalls.t000644 €ˆž«€q{Ì00000000102 12266570730 016031 0ustar00jonswart000000 000000 #!perl -w use Mason::t::CompCalls; Mason::t::CompCalls->runtests; Mason-2.21/t/PaxHeader/Compilation.t000644 777777 777777 00000000212 12266570730 017457 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365465 18 SCHILY.nlink=1 Mason-2.21/t/Compilation.t000644 €ˆž«€q{Ì00000000106 12266570730 016436 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Compilation; Mason::t::Compilation->runtests; Mason-2.21/t/PaxHeader/ComponentMeta.t000644 777777 777777 00000000212 12266570730 017752 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365466 18 SCHILY.nlink=1 Mason-2.21/t/ComponentMeta.t000644 €ˆž«€q{Ì00000000112 12266570730 016726 0ustar00jonswart000000 000000 #!perl -w use Mason::t::ComponentMeta; Mason::t::ComponentMeta->runtests; Mason-2.21/t/PaxHeader/Defer.t000644 777777 777777 00000000212 12266570730 016226 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365467 18 SCHILY.nlink=1 Mason-2.21/t/Defer.t000644 €ˆž«€q{Ì00000000072 12266570730 015207 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Defer; Mason::t::Defer->runtests; Mason-2.21/t/PaxHeader/DollarDot.t000644 777777 777777 00000000212 12266570730 017065 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365468 18 SCHILY.nlink=1 Mason-2.21/t/DollarDot.t000644 €ˆž«€q{Ì00000000102 12266570730 016040 0ustar00jonswart000000 000000 #!perl -w use Mason::t::DollarDot; Mason::t::DollarDot->runtests; Mason-2.21/t/PaxHeader/Errors.t000644 777777 777777 00000000212 12266570730 016455 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365469 18 SCHILY.nlink=1 Mason-2.21/t/Errors.t000644 €ˆž«€q{Ì00000000076 12266570730 015442 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Errors; Mason::t::Errors->runtests(); Mason-2.21/t/PaxHeader/Filters.t000644 777777 777777 00000000212 12266570730 016611 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365470 18 SCHILY.nlink=1 Mason-2.21/t/Filters.t000644 €ˆž«€q{Ì00000000076 12266570730 015576 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Filters; Mason::t::Filters->runtests; Mason-2.21/t/PaxHeader/Globals.t000644 777777 777777 00000000212 12266570730 016564 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365471 18 SCHILY.nlink=1 Mason-2.21/t/Globals.t000644 €ˆž«€q{Ì00000000076 12266570730 015551 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Globals; Mason::t::Globals->runtests; Mason-2.21/t/PaxHeader/Interp.t000644 777777 777777 00000000212 12266570730 016442 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365472 18 SCHILY.nlink=1 Mason-2.21/t/Interp.t000644 €ˆž«€q{Ì00000000076 12266570730 015427 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Interp; Mason::t::Interp->runtests(); Mason-2.21/t/PaxHeader/LvalueAttributes.t000644 777777 777777 00000000212 12266570730 020500 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365473 18 SCHILY.nlink=1 Mason-2.21/t/LvalueAttributes.t000644 €ˆž«€q{Ì00000000120 12266570730 017453 0ustar00jonswart000000 000000 #!perl -w use Mason::t::LvalueAttributes; Mason::t::LvalueAttributes->runtests; Mason-2.21/t/PaxHeader/mason-app.t000644 777777 777777 00000000212 12266570730 017074 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365474 18 SCHILY.nlink=1 Mason-2.21/t/mason-app.t000644 €ˆž«€q{Ì00000001171 12266570730 016056 0ustar00jonswart000000 000000 #!/usr/bin/perl use File::Temp qw(tempdir); use Mason::Util qw(write_file); use Test::More tests => 3; use warnings; use strict; my $tempdir = tempdir( 'mason-app-XXXX', TMPDIR => 1, CLEANUP => 1 ); my $comp_file = "$tempdir/hello.mc"; write_file( $comp_file, "%% has 'd';\nd * 2 = <% \$.d * 2 %>" ); # Ugly string escaping for Windows my $output = `$^X bin/mason.pl $comp_file --data-dir $tempdir/data --args "{\\"d\\":\\"4\\"}"`; is( $output, "d * 2 = 8\n", 'correct output' ); ok( -f "$tempdir/data/obj/hello.mc.mobj", "object file exists" ); $output = `$^X bin/mason.pl -e "<% 3+3 %>"`; is( $output, "6\n", 'correct output' ); Mason-2.21/t/PaxHeader/Plugins.t000644 777777 777777 00000000212 12266570730 016622 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365475 18 SCHILY.nlink=1 Mason-2.21/t/Plugins.t000644 €ˆž«€q{Ì00000000076 12266570730 015607 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Plugins; Mason::t::Plugins->runtests; Mason-2.21/t/PaxHeader/Reload.t000644 777777 777777 00000000212 12266570730 016407 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365476 18 SCHILY.nlink=1 Mason-2.21/t/Reload.t000644 €ˆž«€q{Ì00000000076 12266570730 015374 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Reload; Mason::t::Reload->runtests(); Mason-2.21/t/PaxHeader/Request.t000644 777777 777777 00000000212 12266570730 016631 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365477 18 SCHILY.nlink=1 Mason-2.21/t/Request.t000644 €ˆž«€q{Ì00000000076 12266570730 015616 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Request; Mason::t::Request->runtests; Mason-2.21/t/PaxHeader/ResolveURI.t000644 777777 777777 00000000212 12266570730 017200 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365478 18 SCHILY.nlink=1 Mason-2.21/t/ResolveURI.t000644 €ˆž«€q{Ì00000000104 12266570730 016155 0ustar00jonswart000000 000000 #!perl -w use Mason::t::ResolveURI; Mason::t::ResolveURI->runtests; Mason-2.21/t/PaxHeader/Sanity.t000644 777777 777777 00000000212 12266570730 016450 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365479 18 SCHILY.nlink=1 Mason-2.21/t/Sanity.t000644 €ˆž«€q{Ì00000000074 12266570730 015433 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Sanity; Mason::t::Sanity->runtests; Mason-2.21/t/PaxHeader/Sections.t000644 777777 777777 00000000212 12266570730 016770 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365480 18 SCHILY.nlink=1 Mason-2.21/t/Sections.t000644 €ˆž«€q{Ì00000000102 12266570730 015743 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Sections; Mason::t::Sections->runtests(); Mason-2.21/t/PaxHeader/StaticSource.t000644 777777 777777 00000000212 12266570730 017611 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365481 18 SCHILY.nlink=1 Mason-2.21/t/StaticSource.t000644 €ˆž«€q{Ì00000000110 12266570730 016563 0ustar00jonswart000000 000000 #!perl -w use Mason::t::StaticSource; Mason::t::StaticSource->runtests; Mason-2.21/t/PaxHeader/Syntax.t000644 777777 777777 00000000212 12266570730 016467 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365482 18 SCHILY.nlink=1 Mason-2.21/t/Syntax.t000644 €ˆž«€q{Ì00000000076 12266570730 015454 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Syntax; Mason::t::Syntax->runtests(); Mason-2.21/t/PaxHeader/Util.t000644 777777 777777 00000000212 12266570730 016116 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365483 18 SCHILY.nlink=1 Mason-2.21/t/Util.t000644 €ˆž«€q{Ì00000000070 12266570730 015075 0ustar00jonswart000000 000000 #!perl -w use Mason::t::Util; Mason::t::Util->runtests; Mason-2.21/lib/PaxHeader/Mason000775 777777 777777 00000000213 12266570730 016325 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365364 19 SCHILY.nlink=28 Mason-2.21/lib/Mason/000775 €ˆž«€q{Ì00000000000 12266570730 015360 5ustar00jonswart000000 000000 Mason-2.21/lib/PaxHeader/Mason.pm000644 777777 777777 00000000212 12266570730 016732 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365363 18 SCHILY.nlink=1 Mason-2.21/lib/Mason.pm000644 €ˆž«€q{Ì00000007334 12266570730 015723 0ustar00jonswart000000 000000 package Mason; { $Mason::VERSION = '2.21'; } use Mason::Interp; use Mason::PluginManager; use Mason::Util qw(can_load uniq); use Method::Signatures::Simple; use strict; use warnings; method new ($class: %params) { # Extract plugins and base_interp_class # my $plugin_specs = delete( $params{plugins} ) || []; my $base_interp_class = delete( $params{base_interp_class} ) || $class->default_base_interp_class; # Process plugins and determine real interp_class # my @plugins = Mason::PluginManager->process_top_plugin_specs($plugin_specs); my $interp_class = Mason::PluginManager->apply_plugins_to_class( $base_interp_class, 'Interp', \@plugins ); # Create and return interp # die "cannot pass mason_root_class directly" if exists( $params{mason_root_class} ); return $interp_class->new( mason_root_class => $class, plugins => \@plugins, %params ); } method default_base_interp_class ($class:) { my @candidates = map { join( '::', $_, 'Interp' ) } ( uniq( $class, 'Mason' ) ); my ($base_class) = grep { can_load($_) } @candidates or die sprintf( "cannot load %s for interp", join( ', ', @candidates ) ); return $base_class; } 1; __END__ =pod =head1 NAME Mason - Powerful, high-performance templating for the web and beyond =head1 SYNOPSIS foo.mc: % my $name = "Mason"; Hello world! Welcome to <% $name %>. #!/usr/local/bin/perl use Mason; my $mason = Mason->new(comp_root => '...'); print $mason->run('/foo')->output; =head1 DESCRIPTION Mason is a powerful Perl-based templating system, designed to generate dynamic content of all kinds. Unlike many templating systems, Mason does not attempt to invent an alternate, "easier" syntax for templates. It provides a set of syntax and features specific to template creation, but underneath it is still clearly and proudly recognizable as Perl. Mason is most often used for generating web pages. It has a companion web framework, L, designed to take maximum advantage of its routing and content generation features. It can also be used as the templating layer for web frameworks such as L and L. All documentation is indexed at L. The previous major version of Mason (1.x) is available under the name L. =head1 SUPPORT The mailing list is C. You must be subscribed to send a message. To subscribe, visit L. You can also visit us at C<#mason> on L. Bugs and feature requests will be tracked at RT: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Mason bug-mason@rt.cpan.org The latest source code can be browsed and fetched at: http://github.com/jonswar/perl-mason git clone git://github.com/jonswar/perl-mason.git The official Mason website is L, however it contains mostly information about L. We're not sure what the future of the website will be wrt Mason 2. =head1 ACKNOWLEDGEMENTS Thanks to Stevan Little and the L team for the awesomeness of Moose, which motivated me to create a second version of Mason years after I thought I was done. Thanks to Tatsuhiko Miyagawa and the L team, who freed me from ever worrying about server backends again. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/App.pm000644 777777 777777 00000000212 12266570730 017452 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365365 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/App.pm000644 €ˆž«€q{Ì00000004156 12266570730 016442 0ustar00jonswart000000 000000 package Mason::App; { $Mason::App::VERSION = '2.21'; } use Cwd qw(realpath); use File::Basename; use File::Temp qw(tempdir); use Getopt::Long; use Mason; use Mason::Util qw(json_decode); use strict; use warnings; my $usage = "usage: $0 [--data-dir dir] [--plugins Plugin1,Plugin2] [--args json-string] [-e source] [template-file]"; sub run { my ( %params, $args, $source, $help ); GetOptions( 'args=s' => \$args, 'e=s' => \$source, 'h|help' => \$help, map { dashify($_) . "=s" => \$params{$_} } qw(data_dir plugins) ) or usage(); if ($help) { system("perldoc $0"); exit; } %params = map { defined( $params{$_} ) ? ( $_, $params{$_} ) : () } keys(%params); if ( $params{plugins} ) { $params{plugins} = [ split( /\s*,\s*/, $params{plugins} ) ]; } my %run_args = defined($args) ? %{ json_decode($args) } : (); my $tempdir = tempdir( 'mason-XXXX', TMPDIR => 1, CLEANUP => 1 ); my $file; if ($source) { $file = "$tempdir/source.mc"; open( my $fh, ">", $file ); print $fh $source; } else { $file = shift(@ARGV); usage() if @ARGV; if ( !$file ) { $file = "$tempdir/stdin.mc"; open( my $fh, ">", $file ); while () { print $fh $_ } } } my $comp_root = dirname($file); my $path = "/" . basename($file); my $interp = Mason->new( comp_root => $comp_root, autoextend_request_path => 0, %params ); print $interp->run( $path, %run_args )->output . "\n"; } sub usage { print "$usage\n"; exit; } sub dashify { my $name = shift; $name =~ s/_/-/g; return $name; } 1; __END__ =pod =head1 NAME Mason::App - Implementation of bin/mason =head1 DESCRIPTION See documentation for bin/mason. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/CodeCache.pm000644 777777 777777 00000000212 12266570730 020530 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365366 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/CodeCache.pm000644 €ˆž«€q{Ì00000002421 12266570730 017511 0ustar00jonswart000000 000000 package Mason::CodeCache; { $Mason::CodeCache::VERSION = '2.21'; } use Devel::GlobalDestruction; use Mason::Moose; use Mason::Util; has 'datastore' => ( is => 'ro', isa => 'HashRef', default => sub { {} } ); method get ($key) { return $self->{datastore}->{$key}; } method set ($key, $data) { $self->{datastore}->{$key} = $data; } method remove ($key) { if ( my $entry = $self->{datastore}->{$key} ) { if ( !in_global_destruction() ) { my $compc = $entry->{compc}; $compc->_unset_class_cmeta(); $compc->meta->make_mutable(); Mason::Util::delete_package($compc); } delete $self->{datastore}->{$key}; } } method get_keys () { return keys( %{ $self->{datastore} } ); } __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::CodeCache - Result returned from Mason request =head1 DESCRIPTION Internal class that manages the cache of components for L. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/Compilation.pm000644 777777 777777 00000000212 12266570730 021210 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365367 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Compilation.pm000644 €ˆž«€q{Ì00000073271 12266570730 020204 0ustar00jonswart000000 000000 # Copyright (c) 1998-2005 by Jonathan Swartz. All rights reserved. # This program is free software; you can redistribute it and/or modify it # under the same terms as Perl itself. package Mason::Compilation; { $Mason::Compilation::VERSION = '2.21'; } use File::Basename qw(dirname); use Guard; use Mason::Component::ClassMeta; use Mason::Util qw(dump_one_line json_encode read_file taint_is_on trim); use Mason::Moose; # Passed attributes has 'interp' => ( required => 1, weak_ref => 1 ); has 'path' => ( required => 1 ); has 'source_file' => ( required => 1 ); # Derived attributes - most of these should be class attributes :( has 'bad_attribute_hash' => ( lazy_build => 1, init_arg => undef ); has 'bad_method_hash' => ( lazy_build => 1, init_arg => undef ); has 'dir_path' => ( lazy_build => 1, init_arg => undef ); has 'named_block_regex' => ( lazy_build => 1, init_arg => undef ); has 'unnamed_block_regex' => ( lazy_build => 1, init_arg => undef ); has 'valid_flags_hash' => ( lazy_build => 1, init_arg => undef ); # Valid Perl identifier my $identifier = qr/[[:alpha:]_]\w*/; # # BUILD # method BUILD () { # Initialize state $self->{blocks} = {}; $self->{blocks}->{class} = ''; $self->{source} = read_file( $self->source_file ); $self->{source} =~ s/\r\n?/\n/g; $self->{line_number} = 1; $self->{methods} = { main => $self->_new_method_hash( name => 'main' ) }; $self->{current_method} = $self->{methods}->{main}; $self->{is_pure_perl} = $self->interp->is_pure_perl_comp_path( $self->path ); } method _build_bad_attribute_hash () { return { map { ( $_, 1 ) } @{ $self->bad_attribute_names } }; } method _build_bad_method_hash () { return { map { ( $_, 1 ) } @{ $self->bad_method_names } }; } method _build_dir_path () { return dirname( $self->path ); } method _build_named_block_regex () { my $re = join '|', @{ $self->named_block_types }; return qr/$re/i; } method _build_unnamed_block_regex () { my $re = join '|', @{ $self->unnamed_block_types }; return qr/$re/i; } method _build_valid_flags_hash () { return { map { ( $_, 1 ) } @{ $self->valid_flags } }; } # # MODIFIABLE METHODS # method bad_attribute_names () { return [qw(args m cmeta handle render wrap main)]; } method bad_method_names () { return [qw(args m cmeta)]; } method compile () { $self->parse(); return $self->_output_compiled_component(); } method named_block_types () { return [qw(after augment around before filter method override)]; } method output_class_footer () { return ""; } method output_class_header () { return $self->interp->class_header; } method parse () { # We need to untaint the component source or else the regexes may fail. # ( $self->{source} ) = ( ( delete $self->{source} ) =~ /(.*)/s ) if taint_is_on(); if ( $self->{is_pure_perl} ) { $self->{source} = "<%class> " . $self->{source} . " "; delete( $self->{methods}->{main} ); } my $lm = ''; my $iter = 0; while (1) { $self->_throw_syntax_error("parse loop iterated >1000 times - infinite loop?") if ++$iter > 1000; $self->{last_match} = $lm; $self->_match_end && last; $self->_match_apply_filter_end && last; $self->_match_unnamed_block && ( $lm = 'unnamed_block' ) && next; $self->_match_named_block && ( $lm = 'named_block' ) && next; $self->_match_unknown_block && ( $lm = 'unknown_block' ) && next; $self->_match_apply_filter && ( $lm = 'apply_filter' ) && next; $self->_match_substitution && ( $lm = 'substitution' ) && next; $self->_match_component_call && ( $lm = 'component_call' ) && next; $self->_match_perl_line && ( $lm = 'perl_line' ) && next; $self->_match_bad_close_tag && ( $lm = 'bad_close_tag' ) && next; $self->_match_plain_text && ( $lm = 'plain_text' ) && next; $self->_throw_syntax_error( "could not parse next element at position " . pos( $self->{source} ) ); } } method process_perl_code ($coderef) { return $coderef; } method unnamed_block_types () { return [qw(args class doc flags init perl shared text)]; } method valid_flags () { return [qw(extends)]; } # # PRIVATE METHODS # method _add_to_class_block ($text) { # Don't add a line number comment when following a perl-line. # We know a perl-line is always _one_ line, so we know that the # line numbers are going to match up as long as the first line in # a series has a line number comment before it. Adding a comment # can break certain constructs like qw() list that spans multiple # perl-lines. if ( $self->{last_match} ne 'perl_line' ) { $text = $self->_output_line_number_comment . $text; } $self->{blocks}->{class} .= $text; } method _add_to_current_method ($text) { if ( $self->{last_match} ne 'perl_line' ) { $text = $self->_output_line_number_comment . $text; } $self->{current_method}->{body} .= $text; } method _assert_not_nested ($block_type) { $self->_throw_syntax_error( "Cannot nest <%$block_type> block inside <%$self->{in_recursive_parse}> block") if $self->{in_recursive_parse}; } method _attribute_declaration ($name, $params, $line_number) { $self->_throw_syntax_error("'$name' is reserved and cannot be used as an attribute name") if $self->bad_attribute_hash->{$name}; return $self->_processed_perl_code( sprintf( "%shas '%s' => %s", $self->_output_line_number_comment($line_number), $name, $params ) ); } method _handle_after_block () { $self->_handle_method_modifier_block( 'after', @_ ) } method _handle_around_block () { $self->_handle_method_modifier_block( 'around', @_ ) } method _handle_augment_block () { $self->_handle_method_modifier_block( 'augment', @_ ) } method _handle_before_block () { $self->_handle_method_modifier_block( 'before', @_ ) } method _handle_override_block () { $self->_handle_method_modifier_block( 'override', @_ ); } method _handle_method_modifier_block ($block_type, $contents, $name) { my $modifier = $block_type; $self->_throw_syntax_error("Invalid method modifier name '$name'") if $name !~ /^$identifier$/; $self->_assert_not_nested($block_type); my $method_key = "$block_type $name"; $self->_throw_syntax_error("Duplicate definition of method modifier '$method_key'") if exists $self->{methods}->{"$method_key"}; my $method = $self->_new_method_hash( name => $name, type => 'modifier', modifier => $modifier ); $self->{methods}->{"$method_key"} = $method; $self->_recursive_parse( $block_type, $contents, $method ); } method _handle_apply_filter ($filter_expr) { my $rest = substr( $self->{source}, pos( $self->{source} ) ); my $method = $self->_new_method_hash( type => 'apply_filter' ); local $self->{end_parse} = undef; $self->_recursive_parse( 'filter', $rest, $method ); if ( my $incr = $self->{end_parse} ) { pos( $self->{source} ) += $incr; } else { $self->_throw_syntax_error("'{{' without matching '}}'"); } my $code = sprintf( "\$self->m->_apply_filters_to_output(%s, %s);\n", $self->_processed_perl_code($filter_expr), $self->_output_method($method) ); $self->_add_to_current_method($code); } method _handle_args_block ($contents) { $self->_handle_attributes_list( $contents, 'args' ); } method _handle_attributes_list ($contents, $attr_type) { my @lines = split( "\n", $contents ); my @attributes; my $line_number = $self->{line_number} - 1; foreach my $line (@lines) { $line_number++; trim($line); next if $line =~ /^\#/ || $line !~ /\S/; if ( my ( $name, $rest ) = ( $line =~ / ^ \s* # optional whitespace (?: \$\.)? # optional $. prefix ([^\W\d]\w*) # valid Perl variable name (?:\s*=>\s*(.*))? # optional arrow then default or attribute params /x ) ) { my ($params); if ( defined($rest) && length($rest) ) { if ( $rest =~ /^\s*\(/ ) { $params = "$rest\n;"; } else { $params = sprintf( "(default => %s\n);", $rest ); } } else { $params = '();'; } if ( $attr_type eq 'shared' ) { $params = '(' . 'init_arg => undef, ' . substr( $params, 1 ); } push( @attributes, $self->_attribute_declaration( $name, $params, $line_number ) ); } else { $self->{line_number} = $line_number; $self->_throw_syntax_error("Invalid attribute line '$line'"); } } $self->{blocks}->{attributes} .= join( "\n", @attributes ) . "\n"; } method _handle_class_block ($contents) { $self->{blocks}->{class} .= $self->_output_line_number_comment . $self->_processed_perl_code($contents); } method _handle_component_call ($contents) { my ( $prespace, $call, $postspace ) = ( $contents =~ /(\s*)(.*)(\s*)/s ); if ( $call =~ m,^[\w/.], ) { my $comma = index( $call, ',' ); $comma = length $call if $comma == -1; ( my $comp = substr( $call, 0, $comma ) ) =~ s/\s+$//; $call = "'$comp'" . substr( $call, $comma ); } $call = $self->_processed_perl_code($call); my $code = "\$m->comp( $prespace $call $postspace \n); "; $self->_add_to_current_method($code); } method _handle_doc_block () { # Don't do anything - just discard the comment. } method _handle_filter_block ($contents, $name, $arglist) { my $new_contents = join( '', '<%perl>', 'return Mason::DynamicFilter->new(', 'filter => sub {', 'my $yield = shift;', '$m->capture(sub {', '', $contents, '<%perl>}); });', ); $self->_handle_method_block( $new_contents, $name, $arglist ); } method _handle_flags_block ($contents) { my $ending = qr, (?: \n | # newline or (?= ) ) # end of block (don't consume it) ,ix; while ( $contents =~ / \G [ \t]* ([\w_]+) # identifier [ \t]*=>[ \t]* # separator (\S[^\n]*?) # value ( must start with a non-space char) $ending | \G\n # a plain empty line | \G [ \t]* # an optional comment \# [^\n]* $ending | \G[ \t]+? $ending /xgc ) { my ( $flag, $value ) = ( $1, $2 ); if ( defined $flag && defined $value && length $flag && length $value ) { if ( $self->valid_flags_hash->{$flag} ) { $self->{blocks}->{flags}->{$flag} = eval($value); die $@ if $@; } else { $self->_throw_syntax_error("Invalid flag '$flag'"); } } } } method _handle_init_block ($contents) { $self->{current_method}->{init} = $self->_output_line_number_comment . $self->_processed_perl_code($contents); } method _handle_method_block ($contents, $name, $arglist) { $self->_throw_syntax_error("Invalid method name '$name'") if $name !~ /^$identifier$/; $self->_throw_syntax_error("'$name' is reserved and cannot be used as a method name") if $self->bad_method_hash->{$name}; $self->_throw_syntax_error("Duplicate definition of method '$name'") if exists $self->{methods}->{$name}; $self->_assert_not_nested('method'); my $method = $self->_new_method_hash( name => $name, arglist => $arglist ); $self->{methods}->{$name} = $method; $self->_recursive_parse( 'method', $contents, $method ); } method _handle_perl_block ($contents) { $self->_add_to_current_method( $self->_processed_perl_code($contents) ); } method _handle_perl_line ($type, $contents) { my $code = $self->_processed_perl_code( $contents . "\n" ); if ( $type eq 'perl' ) { $self->_add_to_current_method($code); } else { $self->_add_to_class_block($code); } } method _handle_plain_text ($text) { # Escape single quotes and backslashes # $text =~ s,([\'\\]),\\$1,g; my $code = "\$\$_m_buffer .= '$text';\n"; $self->_add_to_current_method($code); } method _handle_shared_block ($contents) { $self->_handle_attributes_list( $contents, 'shared' ); } method _handle_substitution ($text, $filter_list) { # This is a comment tag if all lines of text contain only whitespace # or start with whitespace and a comment marker, e.g. # # <% # # # # foo # %> # my @lines = split( /\n/, $text ); unless ( grep { /^\s*[^\s\#]/ } @lines ) { return; } $text = $self->_processed_perl_code($text); if ($filter_list) { if ( my @filters = grep { /\S/ } split( /\s*,\s*/, $filter_list ) ) { my $filter_call_list = join( ", ", map { "\$self->$_()" } @filters ); $text = sprintf( '$self->m->_apply_filters(%s, sub { local $_ = %s; defined($_) ? $_ : "" })', $filter_call_list, $text ); } } my $code = "for (scalar($text)) { \$\$_m_buffer .= \$_ if defined }\n"; $self->_add_to_current_method($code); } method _handle_text_block ($contents) { $contents =~ s/^\n//; $contents =~ s,([\'\\]),\\$1,g; $self->_add_to_current_method("\$\$_m_buffer .= '$contents';\n"); } method _match_apply_filter () { my $pos = pos( $self->{source} ); # Match % ... {{ at beginning of line if ( $self->{source} =~ / \G (?<=^) % ([^\n]*) \{\{ [^\S\n]* (?:\#.*)? \n /gcmx ) { my ($filter_expr) = ($1); $self->_handle_apply_filter($filter_expr); return 1; } # Old syntax, for backward compatibility # Match <% ... { %> if ( $self->{source} =~ /\G(\n)? <% (.+?) (\s*\{\s*) %>(\n)?/xcgs ) { my ( $preceding_newline, $filter_expr, $opening_brace, $following_newline ) = ( $1, $2, $3, $4 ); # and make sure we didn't go through a %> if ( $filter_expr !~ /%>/ ) { for ( $preceding_newline, $filter_expr, $following_newline ) { $self->{line_number} += tr/\n// if defined($_); } $self->_handle_apply_filter($filter_expr); return 1; } else { pos( $self->{source} ) = $pos; } } return 0; } method _match_apply_filter_end () { if ( $self->{source} =~ / \G (?<=^) % [ \t]+ \}\} [^\S\n]* (?:\#.*)? (?:\n\n?|\z) /gmcx ) { if ( $self->{current_method}->{type} eq 'apply_filter' ) { $self->{end_parse} = pos( $self->{source} ); return 1; } else { $self->_throw_syntax_error("'}}' without matching '{{'"); } } # Old syntax - <% } %> and - for backward compatibility if ( $self->{current_method}->{type} eq 'apply_filter' && $self->{source} =~ /\G (?: (?: <% [ \t]* \} [ \t]* %> ) | (?: <\/%> ) ) (\n?\n?)/gcx ) { $self->{end_parse} = pos( $self->{source} ); return 1; } return 0; } method _match_block ($block_regex, $named) { my $regex = qr/ \G(\n?) <% ($block_regex) (?: \s+ ([^\s\(>]+) ([^>]*) )? > /x; if ( $self->{source} =~ /$regex/gcs ) { my ( $preceding_newline, $block_type, $name, $arglist ) = ( $1, $2, $3, $4 ); $self->_throw_syntax_error("<%$block_type> block requires a name") if ( $named && !defined($name) ); $self->_throw_syntax_error("<%$block_type> block does not take a name") if ( !$named && defined($name) ); my $block_method = "_handle_${block_type}_block"; $self->{line_number}++ if $preceding_newline; my ( $block_contents, $nl ) = $self->_match_block_end($block_type); $self->$block_method( $block_contents, $name, $arglist ); $self->{line_number} += $block_contents =~ tr/\n//; $self->{line_number} += length($nl) if $nl; return 1; } return 0; } method _match_block_end ($block_type) { my $re = qr,\G(.*?)(\n?\n?),is; if ( $self->{source} =~ /$re/gc ) { return ( $1, $2 ); } else { $self->_throw_syntax_error("<%$block_type> without matching "); } } method _match_component_call () { if ( $self->{source} =~ /\G<&(?!\|)/gcs ) { if ( $self->{source} =~ /\G(.*?)&>/gcs ) { my $body = $1; $self->_handle_component_call($body); $self->{line_number} += $body =~ tr/\n//; return 1; } else { $self->_throw_syntax_error("'<&' without matching '&>'"); } } } method _match_end () { if ( $self->{source} =~ /(\G\z)/gcs ) { $self->{line_number} += $1 =~ tr/\n//; return defined $1 && length $1 ? $1 : 1; } return 0; } method _match_named_block () { $self->_match_block( $self->named_block_regex, 1 ); } method _match_perl_line () { if ( $self->{source} =~ /\G(?<=^)(%%?)([^\n]*)(?:\n|\z)/gcm ) { my ( $percents, $line ) = ( $1, $2 ); if ( length($line) && $line !~ /^\s/ ) { $self->_throw_syntax_error("$percents must be followed by whitespace or EOL"); } if ( $percents eq '%%' ) { if ( $line =~ /\{\s*$/ && $self->{source} =~ /\G(?!%%)/gcm ) { $self->_throw_syntax_error("%%-lines cannot be used to surround content"); } } $self->_handle_perl_line( ( $percents eq '%' ? 'perl' : 'class' ), $line ); $self->{line_number}++; return 1; } return 0; } method _match_plain_text () { # Most of these terminator patterns actually belong to the next # lexeme in the source, so we use a lookahead if we don't want to # consume them. We use a lookbehind when we want to consume # something in the matched text, like the newline before a '%'. if ( $self->{source} =~ m{ \G (.*?) # anything, followed by: ( (?<=\n)(?=%) # an eval line - consume the \n | (?=<%\s) # a substitution tag | (?=[%&]>) # an end substitution or component call | (?={source}, pos( $self->{source} ), 3 ) =~ /<%[a-z]/ ) { chomp($text); } $self->_handle_plain_text($text) if length $text; # Not checking definedness seems to cause extra lines to be # counted with Perl 5.00503. I'm not sure why - dave $self->{line_number} += tr/\n// foreach grep defined, ( $orig_text, $swallowed ); return 1; } return 0; } method _match_substitution () { return 0 unless $self->{source} =~ /\G<%/gcs; if ( $self->{source} =~ m{ \G (\s*) # Initial whitespace (.+?) # Substitution body ($1) ( \s* (? # Closing tag }xcigs ) { my ( $start_ws, $body, $after_body, $filters, $end_ws ) = ( $1, $2, $3, $4, $5 ); $self->_throw_syntax_error("whitespace required after '<%'") unless length($start_ws); $self->{line_number} += tr/\n// foreach grep defined, ( $start_ws, $body, $after_body, $end_ws ); $self->_throw_syntax_error("whitespace required before '%>'") unless length($end_ws); $self->_handle_substitution( $body, $filters ); return 1; } else { $self->_throw_syntax_error("'<%' without matching '%>'"); } } method _match_unknown_block () { if ( $self->{source} =~ /\G(?:\n?)<%([A-Za-z_]+)>/gc ) { $self->_throw_syntax_error("unknown block '<%$1>'"); } } method _match_unnamed_block () { $self->_match_block( $self->unnamed_block_regex, 0 ); } method _match_bad_close_tag () { if ( my ($end_tag) = ( $self->{source} =~ /\G\s*(%>|&>)/gc ) ) { ( my $begin_tag = reverse($end_tag) ) =~ s/>/_throw_syntax_error("'$end_tag' without matching '$begin_tag'"); } } method _new_method_hash () { return { body => '', init => '', type => 'method', @_ }; } method _output_attributes () { return $self->{blocks}->{attributes} || ''; } method _output_class_block () { return $self->{blocks}->{class} || ''; } method _output_class_initialization () { return join( "\n", "our (\$_class_cmeta, \$m, \$_m_buffer, \$_interp);", "BEGIN { ", "local \$_interp = Mason::Interp->current_load_interp;", "\$_interp->component_moose_class->import;", "\$_interp->component_import_class->import;", "}", "*m = \\\$Mason::Request::current_request;", "*_m_buffer = \\\$Mason::Request::current_buffer;", # Must be defined here since inner relies on caller() "sub _inner { inner() }" ); } method _output_cmeta () { my $q = sub { "'$_[0]'" }; my %cmeta_info = ( dir_path => $q->( $self->dir_path ), is_top_level => $q->( $self->interp->is_top_level_comp_path( $self->path ) ), path => $q->( $self->path ), source_file => $q->( $self->source_file ), object_file => '__FILE__', class => 'CLASS', interp => '$interp', ); return join( "\n", "method _set_class_cmeta (\$interp) {", "\$_class_cmeta = \$interp->component_class_meta_class->new(", ( map { sprintf( "'%s' => %s,", $_, $cmeta_info{$_} ) } sort( keys(%cmeta_info) ) ), ');', '}', 'sub _unset_class_cmeta { undef $_class_cmeta }', 'sub _class_cmeta { $_class_cmeta }' ); } method _output_compiled_component () { return join( "\n", map { trim($_) } grep { defined($_) && length($_) } ( $self->_output_flag_comment, $self->_output_class_initialization, $self->output_class_header, $self->_output_global_declarations, $self->_output_cmeta, $self->_output_attributes, $self->_output_class_block, $self->_output_methods, $self->output_class_footer, ) ) . "\n"; } method _output_flag_comment () { if ( my $flags = $self->{blocks}->{flags} ) { if (%$flags) { ( my $json = json_encode($flags) ) =~ s/\n//g; return "# FLAGS: $json\n\n"; } } } method _output_global_declaration ($spec) { my ( $sigil, $name ) = $self->interp->_parse_global_spec($spec); return sprintf( 'our %s%s; *%s = \%s%s::%s;' . "\n", $sigil, $name, $name, $sigil, $self->interp->globals_package, $name ); } method _output_global_declarations () { return join( "\n", map { $self->_output_global_declaration($_) } @{ $self->interp->allow_globals } ); } method _output_line_number_comment ($line_number) { if ( !$self->interp->no_source_line_numbers ) { $line_number ||= $self->{line_number}; if ($line_number) { my $comment = sprintf( qq{#line %s "%s"\n}, $line_number, $self->source_file ); return $comment; } } return ""; } method _output_method ($method) { my $path = $self->path; my $name = $method->{name}; my $type = $method->{type}; my $modifier = $method->{modifier} || ''; my $arglist = $method->{arglist} || ''; my $contents = join( "\n", grep { /\S/ } ( $method->{init}, $method->{body} ) ); my $start = $type eq 'apply_filter' ? "sub {" : $modifier eq 'around' ? "around '$name' => sub {\nmy \$orig = shift; my \$self = shift;" : $type eq 'modifier' ? "$modifier '$name' => sub {\nmy \$self = shift;" : "method $name $arglist {"; my $end = $modifier ? "};" : "}"; return join( "\n", $start, # do not add a block around this, it introduces # a separate scope and might break cleanup # blocks (or all sort of other things!) $contents, # don't return values explicitly. semi before return will help catch # syntax errors in component body. ";return;", $end, ); } method _output_methods () { # Sort methods so that modifiers come after # my @sorted_methods_keys = sort { ( index( $a, ' ' ) <=> index( $b, ' ' ) ) || $a cmp $b } keys( %{ $self->{methods} } ); return join( "\n", map { $self->_output_method( $self->{methods}->{$_} ) } @sorted_methods_keys ); } method _processed_perl_code ($code) { my $coderef = \$code; $self->process_perl_code($coderef); return $$coderef; } method _recursive_parse ($block_type, $contents, $method) { # Save current regex position, then locally set source to the contents and # recursively parse. # local $self->{in_recursive_parse} = $block_type; my $save_pos = pos( $self->{source} ); scope_guard { pos( $self->{source} ) = $save_pos }; { local $self->{source} = $contents; local $self->{current_method} = $method; local $self->{line_number} = $self->{line_number}; $self->parse(); } } method _throw_syntax_error ($msg) { die sprintf( "%s at %s line %d\n", $msg, $self->source_file, $self->{line_number} ); } __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::Compilation - Performs compilation of a single component =head1 DESCRIPTION A new C object is created by L to compile each component. This class has no public API at this time. =head1 MODIFIABLE METHODS These methods are not intended to be called externally, but may be useful to modify with method modifiers in L and L. Their APIs will be kept as stable as possible. =over =item bad_attribute_names () A list of attribute names that should not be used because they are reserved for built-in attributes or methods: C, C, C, C, C
, etc. =item bad_method_names () A list of method names that should not be used because they are reserved for built-in attributes: C, C, C, etc. Not as extensive as bad_attribute_names above because methods like C and C
can be overridden but make no sense as attributes. =item compile () The top-level method called to compile the component. Returns the generated component class. =item named_block_types () An arrayref of valid named block types: C, C, C, etc. Add to this list if you want to create your own named blocks (i.e. blocks that take a name argument). =item output_class_footer () Perl code to be added at the bottom of the class. Empty by default. =item output_class_header () Perl code to be added at the top of the class, just after initialization of Moose, C<$m> and other required pieces. By default it consults the L. # Add to the top of every component class: # use Modern::Perl; # use JSON::XS qw(encode_json decode_json); # override 'output_class_header' => sub { return join( "\n", super(), 'use Modern::Perl;', 'use JSON::XS qw(encode_json decode_json);' ); }; =item process_perl_code ($coderef) This method is called on each distinct piece of Perl code in the component. I<$coderef> is a reference to a string containing the code; the method can modify the code as desired. See L for a sample usage. =item unnamed_block_types () An arrayref of valid unnamed block types: C, C, C, etc. Add to this list if you want to create your own unnamed blocks. =item valid_flags () An arrayref of valid flags: contains only C at time of writing. Add to this list if you want to create your own flags. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/Component000775 777777 777777 00000000212 12266570730 020266 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365383 18 SCHILY.nlink=5 Mason-2.21/lib/Mason/Component/000775 €ˆž«€q{Ì00000000000 12266570730 017322 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/PaxHeader/Component.pm000644 777777 777777 00000000212 12266570730 020674 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365368 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Component.pm000644 €ˆž«€q{Ì00000012263 12266570730 017662 0ustar00jonswart000000 000000 package Mason::Component; { $Mason::Component::VERSION = '2.21'; } use Moose; # no Mason::Moose - don't want StrictConstructor use MooseX::HasDefaults::RO; use Method::Signatures::Simple; use Log::Any; use Scalar::Util qw(weaken); with 'Mason::Filters::Standard'; # Passed attributes # has 'args' => ( init_arg => undef, lazy_build => 1 ); has 'm' => ( required => 1, weak_ref => 1 ); __PACKAGE__->meta->make_immutable(); method BUILD ($params) { # Make a copy of params and re-weaken m # $self->{_orig_params} = $params; weaken $self->{_orig_params}->{m}; } method cmeta () { return $self->can('_class_cmeta') ? $self->_class_cmeta : undef; } method _build_args () { my $orig_params = $self->{_orig_params}; return { map { ( $_, $orig_params->{$_} ) } grep { $_ ne 'm' } keys(%$orig_params) }; } # Default handle - call render # method handle () { $self->render(@_); } # Default render - call wrap # method render () { $self->wrap(@_); } # Top wrap # method wrap () { inner(); } # By default, do not allow path_info # method allow_path_info () { return 0; } # Shorcut for skipping wrap # method no_wrap ($class:) { $class->meta->add_method( 'render' => sub { $_[0]->main(@_) } ); } 1; __END__ =pod =head1 NAME Mason::Component - Mason Component base class =head1 DESCRIPTION Every Mason component corresponds to a unique class that inherits, directly or indirectly, from this base class. A new instance of the component class is created whenever a component is called - whether via a top level request, C<< <& &> >> tags, or an << $m->comp >> call. A component instance is only valid for the Mason request in which it was created. We leave this class as devoid of built-in methods as possible, allowing you to create methods in your own components without worrying about name clashes. =head1 STRUCTURAL METHODS This is the standard call chain for the page component (the initial component of a request). handle -> render -> wrap -> main In many cases only C
will actually do anything. =over =item handle This is the top-most method called on the page component. Its job is to decide how to handle the request, e.g. =over =item * throw an error (e.g. permission denied) =item * take some action and redirect (e.g. if handling a form in a web environment) =item * defer to another component via C<< $m->go >> =item * render the page =back It should not output any content itself. By default, it simply calls L. =item render This method is invoked from L on the page component. Its job is to output the full content of the page. By default, it simply calls L. =item wrap This method is invoked from L on the page component. By convention, C is an L method, with each superclass calling the next subclass. This is useful for cascading templates in which the top-most superclass generates the surrounding content. <%augment wrap>

Subtitle section

<% inner() %>
By default, C simply calls C<< inner() >> to go to the next subclass, and then L at the bottom subclass. To override a component's parent wrapper, a component can define its own C using C instead of C: <%method wrap>

Parent wrapper will be ignored

<% inner() %> To do no wrapping at all, call the component class method L: <%class> CLASS->no_wrap; =item main This method is invoked when a non-page component is called, and from the default L method as well. It consists of the code and output in the main part of the component that is not inside a C<< <%method> >> or C<< <%class> >> tag. =back =head1 CLASS METHODS =over =item no_wrap A convenience method that redefines L to call L instead of L, thus skipping any content wrapper inherited from parent. <%class> CLASS->no_wrap; =item allow_path_info This method is called when the request path has a path_info portion, to determine whether the path_info is allowed. Default is false. See L. <%class> method allow_path_info { 1 } =back =head1 OTHER METHODS =over =item args Returns the hashref of arguments passed to this component's constructor, e.g. the arguments passed in a L. =item cmeta Returns the L object associated with this component class, containing information such as the component's path and source file. my $path = $self->cmeta->path; =item m Returns the current request. This is also available via C<< $m >> inside Mason components. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/DynamicFilter.pm000644 777777 777777 00000000212 12266570730 021464 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365369 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/DynamicFilter.pm000644 €ˆž«€q{Ì00000000723 12266570730 020450 0ustar00jonswart000000 000000 package Mason::DynamicFilter; { $Mason::DynamicFilter::VERSION = '2.21'; } use Mason::Moose; has 'filter' => ( isa => 'CodeRef' ); around 'BUILDARGS' => sub { my $orig = shift; my $class = shift; if ( @_ == 1 ) { return $class->$orig( filter => $_[0] ); } else { return $class->$orig(@_); } }; method apply_filter () { my ($yield) = @_; return $self->filter->($yield); } __PACKAGE__->meta->make_immutable(); 1; Mason-2.21/lib/Mason/PaxHeader/Exceptions.pm000644 777777 777777 00000000212 12266570730 021053 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365370 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Exceptions.pm000644 €ˆž«€q{Ì00000003035 12266570730 020036 0ustar00jonswart000000 000000 package Mason::Exceptions; { $Mason::Exceptions::VERSION = '2.21'; } use strict; use warnings; use Exception::Class ( 'Mason::Exception' => { description => 'generic base class for all Mason exceptions', }, 'Mason::Exception::Abort' => { isa => 'Mason::Exception', fields => [qw(aborted_value)], description => 'a component called $m->abort' }, 'Mason::Exception::TopLevelNotFound' => { isa => 'Mason::Exception', description => 'the top level component could not be found' }, ); 1; __END__ =pod =head1 NAME Mason::Exceptions - Exception objects thrown by Mason =head1 DESCRIPTION This module creates the exception classes used by Mason. Mason only throws exception objects to communicate something specific to code catching the exception; otherwise it is content to die with a string. =head1 EXCEPTIONS =over =item Mason::Exception::Abort The C<< $m->abort >> method was called. Exceptions in this class contain the field C. =item Mason::Exception::TopLevelNotFound The requested top level component passed to exec() could not be found. In a web environment, this could be used to determine that a 404 should be returned. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/Filters000775 777777 777777 00000000212 12266570730 017734 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365387 18 SCHILY.nlink=3 Mason-2.21/lib/Mason/Filters/000775 €ˆž«€q{Ì00000000000 12266570730 016770 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/PaxHeader/Interp.pm000644 777777 777777 00000000212 12266570730 020173 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365371 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Interp.pm000644 €ˆž«€q{Ì00000105601 12266570730 017160 0ustar00jonswart000000 000000 package Mason::Interp; { $Mason::Interp::VERSION = '2.21'; } use Carp; use Devel::GlobalDestruction; use File::Basename; use File::Path; use File::Temp qw(tempdir); use Guard; use Mason::CodeCache; use Mason::Request; use Mason::Result; use Mason::Types; use Mason::Util qw(can_load catdir catfile combine_similar_paths find_wanted first_index is_absolute json_decode mason_canon_path read_file taint_is_on touch_file uniq write_file); use Class::Load; use Memoize; use Moose::Util::TypeConstraints; use Mason::Moose; my $default_out = sub { print( $_[0] ) }; my $next_id = 0; my $max_depth = 16; # Passed attributes # has 'allow_globals' => ( isa => 'ArrayRef[Str]', default => sub { [] }, trigger => sub { shift->_validate_allow_globals } ); has 'autobase_names' => ( isa => 'ArrayRef[Str]', lazy_build => 1 ); has 'autoextend_request_path' => ( isa => 'Bool', default => 1 ); has 'class_header' => ( default => '' ); has 'comp_root' => ( required => 1, isa => 'Mason::Types::CompRoot', coerce => 1 ); has 'component_class_prefix' => ( lazy_build => 1 ); has 'data_dir' => ( lazy_build => 1 ); has 'dhandler_names' => ( isa => 'ArrayRef[Str]', lazy_build => 1 ); has 'index_names' => ( isa => 'ArrayRef[Str]', lazy_build => 1 ); has 'mason_root_class' => ( required => 1 ); has 'no_source_line_numbers' => ( default => 0 ); has 'object_file_extension' => ( default => '.mobj' ); has 'plugins' => ( default => sub { [] } ); has 'pure_perl_extensions' => ( default => sub { ['.mp'] } ); has 'static_source' => (); has 'static_source_touch_file' => (); has 'top_level_extensions' => ( default => sub { ['.mc', '.mp'] } ); # Derived attributes # has 'allowed_globals_hash' => ( init_arg => undef, lazy_build => 1 ); has 'code_cache' => ( init_arg => undef, lazy_build => 1 ); has 'distinct_string_count' => ( init_arg => undef, default => 0 ); has 'globals_package' => ( init_arg => undef, lazy_build => 1 ); has 'id' => ( init_arg => undef, default => sub { $next_id++ } ); has 'match_request_path' => ( init_arg => undef, lazy_build => 1 ); has 'pure_perl_regex' => ( lazy_build => 1 ); has 'request_params' => ( init_arg => undef ); has 'top_level_regex' => ( lazy_build => 1 ); # Class overrides # CLASS->_define_class_override_methods(); # Allow access to current interp while in load() # our ($current_load_interp); method current_load_interp () { $current_load_interp } # # BUILD # method BUILD ($params) { # Initialize static source mode # if ( $self->{static_source} ) { $self->{static_source_touch_file} ||= catfile( $self->data_dir, 'purge.dat' ); $self->{static_source_touch_lastmod} = 0; $self->_check_static_source_touch_file(); } # Separate out request parameters # $self->{request_params} = {}; my %is_request_attribute = map { ( $_->init_arg || $_->name, 1 ) } $self->request_class->meta->get_all_attributes(); foreach my $key ( keys(%$params) ) { if ( $is_request_attribute{$key} ) { $self->{request_params}->{$key} = delete( $params->{$key} ); } } } method _build_allowed_globals_hash () { my @allow_globals = uniq( @{ $self->allow_globals } ); my @canon_globals = map { join( "", $self->_parse_global_spec($_) ) } @allow_globals; return { map { ( $_, 1 ) } @canon_globals }; } method _build_globals_package () { return "Mason::Globals" . $self->id; } method _build_autobase_names () { return [ map { "Base" . $_ } @{ $self->top_level_extensions } ]; } method _build_code_cache () { return $self->code_cache_class->new(); } method _build_component_class_prefix () { return "MC" . $self->id; } method _build_data_dir () { return tempdir( 'mason-data-XXXX', TMPDIR => 1, CLEANUP => 1 ); } method _build_dhandler_names () { return [ map { "dhandler" . $_ } @{ $self->top_level_extensions } ]; } method _build_index_names () { return [ map { "index" . $_ } @{ $self->top_level_extensions } ]; } method _build_pure_perl_regex () { my $extensions = $self->pure_perl_extensions; if ( !@$extensions ) { return qr/(?!)/; # matches nothing } else { my $regex = join( '|', @$extensions ) . '$'; return qr/$regex/; } } method _build_top_level_regex () { my $extensions = $self->top_level_extensions; if ( !@$extensions ) { return qr/./; # matches everything } else { my $regex = join( '|', @$extensions ); if ( my @other_names = grep { !/$regex/ } @{ $self->dhandler_names }, @{ $self->index_names } ) { $regex .= '|(?:/(?:' . join( '|', @other_names ) . '))'; } $regex = '(?:' . $regex . ')$'; return qr/$regex/; } } # # PUBLIC METHODS # method all_paths ($dir_path) { $dir_path ||= '/'; $self->_assert_absolute_path($dir_path); return $self->_collect_paths_for_all_comp_roots( sub { my $root_path = shift; my $dir = $root_path . $dir_path; return ( -d $dir ) ? find_wanted( sub { -f }, $dir ) : (); } ); } method comp_exists ($path) { # Canonicalize path # croak "path required" if !defined($path); $path = Mason::Util::mason_canon_path($path); return ( ( $self->static_source && $self->code_cache->get($path) ) || $self->_source_file_for_path($path) ) ? 1 : 0; } method flush_code_cache () { my $code_cache = $self->code_cache; foreach my $key ( $code_cache->get_keys() ) { $code_cache->remove($key); } } method glob_paths ($glob_pattern) { return $self->_collect_paths_for_all_comp_roots( sub { my $root_path = shift; return glob( $root_path . $glob_pattern ); } ); } our $in_load = 0; method load ($path) { local $current_load_interp = $self; my $code_cache = $self->code_cache; # Canonicalize path # croak "path required" if !defined($path); $path = Mason::Util::mason_canon_path($path); # Quick check memory cache in static source mode # if ( $self->static_source ) { if ( my $entry = $code_cache->get($path) ) { return $entry->{compc}; } } local $in_load = $in_load + 1; if ( $in_load > $max_depth ) { die ">$max_depth levels deep in inheritance determination (inheritance cycle?)" if $in_load >= $max_depth; } my $compile = 0; my ( $default_parent_path, $source_file, $source_lastmod, $object_file, $object_lastmod, @source_stat, @object_stat ); my $stat_source_file = sub { if ( $source_file = $self->_source_file_for_path($path) ) { @source_stat = stat $source_file; if ( @source_stat && !-f _ ) { die "source file '$source_file' exists but it is not a file"; } } $source_lastmod = @source_stat ? $source_stat[9] : 0; }; my $stat_object_file = sub { $object_file = $self->_object_file_for_path($path); @object_stat = stat $object_file; if ( @object_stat && !-f _ ) { die "object file '$object_file' exists but it is not a file"; } $object_lastmod = @object_stat ? $object_stat[9] : 0; }; # Determine source and object files and their modified times # $stat_source_file->() or return; # Determine default parent comp # $default_parent_path = $self->_default_parent_path($path); if ( $self->static_source ) { if ( $stat_object_file->() ) { # If touch file is more recent than object file, we can't trust object file. # if ( $self->{static_source_touch_lastmod} >= $object_lastmod ) { # If source file is more recent, recompile. Otherwise, touch # the object file so it will be trusted. # if ( $source_lastmod > $object_lastmod ) { $compile = 1; } else { touch_file($object_file); } } } else { $compile = 1; } } else { # Check memory cache # if ( my $entry = $code_cache->get($path) ) { if ( $entry->{source_lastmod} >= $source_lastmod && $entry->{source_file} eq $source_file && $entry->{default_parent_path} eq $default_parent_path ) { my $compc = $entry->{compc}; if ( $entry->{superclass_signature} eq $self->_superclass_signature($compc) ) { return $compc; } } $code_cache->remove($path); } # Determine object file and its last modified time # $stat_object_file->(); $compile = ( !$object_lastmod || $object_lastmod < $source_lastmod ); } $self->_compile_to_file( $source_file, $path, $object_file ) if $compile; my $compc = $self->_comp_class_for_path($path); $self->_load_class_from_object_file( $compc, $object_file, $path, $default_parent_path ); $compc->meta->make_immutable(); # Save component class in the cache. # $code_cache->set( $path, { source_file => $source_file, source_lastmod => $source_lastmod, default_parent_path => $default_parent_path, compc => $compc, superclass_signature => $self->_superclass_signature($compc), } ); return $compc; } method _superclass_signature ($compc) { my @superclasses = $compc->meta->superclasses; # Recursively load the superclasses for an existing component class in # case they have changed. # foreach my $superclass (@superclasses) { if ( my $cmeta = $superclass->cmeta ) { my $path = $cmeta->path; $self->load( $cmeta->path ); } } # Return a unique signature representing the component class's superclasses # and their versions. # return join( ",", map { join( "-", $_, $_->cmeta ? $_->cmeta->id : 0 ) } @superclasses ); } # Memoize comp_exists() and load() - this helps both with components used # multiple times in a request, and with determining default parent # components. The memoize cache is cleared at the beginning of each # request, or in static_source_mode, when the purge file is touched. # memoize('comp_exists'); memoize('load'); method object_dir () { return catdir( $self->data_dir, 'obj' ); } method run () { my %request_params; if ( ref( $_[0] ) eq 'HASH' ) { %request_params = %{ shift(@_) }; } my $path = shift; my $request = $self->_make_request(%request_params); $request->run( $path, @_ ); } method set_global () { my ( $spec, $value ) = @_; croak "set_global expects a var name and value" unless $value; my ( $sigil, $name ) = $self->_parse_global_spec($spec); croak "${sigil}${name} is not in the allowed globals list" unless $self->allowed_globals_hash->{"${sigil}${name}"}; my $varname = sprintf( "%s::%s", $self->globals_package, $name ); no strict 'refs'; no warnings 'once'; $$varname = $value; } # # MODIFIABLE METHODS # method DEMOLISH () { return if in_global_destruction; # We have to check for code_cache slot directly, in case the object gets # destroyed before it has been fully formed (e.g. missing required attr). # $self->flush_code_cache() if defined( $self->{code_cache} ); } method _compile ($source_file, $path) { my $compilation = $self->compilation_class->new( source_file => $source_file, path => $path, interp => $self ); return $compilation->compile(); } method _compile_to_file ($source_file, $path, $object_file) { # We attempt to handle several cases in which a file already exists # and we wish to create a directory, or vice versa. However, not # every case is handled; to be complete, mkpath would have to unlink # any existing file in its way. # if ( defined $object_file && !-f $object_file ) { my ($dirname) = dirname($object_file); if ( !-d $dirname ) { unlink($dirname) if ( -e _ ); mkpath( $dirname, 0, 0775 ); } rmtree($object_file) if ( -d $object_file ); } my $object_contents = $self->_compile( $source_file, $path ); $self->write_object_file( $object_file, $object_contents ); } method is_pure_perl_comp_path ($path) { return ( $path =~ $self->pure_perl_regex ) ? 1 : 0; } method is_top_level_comp_path ($path) { return ( $path =~ $self->top_level_regex ) ? 1 : 0; } method _load_class_from_object_file ($compc, $object_file, $path, $default_parent_path) { my $flags = $self->_extract_flags_from_object_file($object_file); my $parent_compc = $self->_determine_parent_compc( $path, $flags ) || ( $default_parent_path eq '/' && $self->component_class ) || $self->load($default_parent_path); my $code = sprintf( 'package %s; use Moose; extends \'%s\'; do(\'%s\'); die $@ if $@', $compc, $parent_compc, $object_file ); ($code) = ( $code =~ /^(.*)/s ) if taint_is_on(); eval($code); die $@ if $@; $compc->_set_class_cmeta($self); $self->modify_loaded_class($compc); } method modify_loaded_class ($compc) { $self->_add_default_wrap_method($compc); } method write_object_file ($object_file, $object_contents) { write_file( $object_file, $object_contents ); } # Given /foo/bar, look for (by default): # /foo/bar/index.{mp,mc}, # /foo/bar/dhandler.{mp,mc}, # /foo/bar.{mp,mc}, # /dhandler.{mp,mc}, # /foo.{mp,mc} # method _build_match_request_path ($interp:) { # Create a closure for efficiency - all this data is immutable for an interp. # my @dhandler_subpaths = map { "/$_" } @{ $interp->dhandler_names }; my $ignore_file_regex = '(/' . join( "|", @{ $interp->autobase_names }, @{ $interp->dhandler_names } ) . ')$'; $ignore_file_regex = qr/$ignore_file_regex/; my @autoextensions = $interp->autoextend_request_path ? @{ $interp->top_level_extensions } : (); my @index_names = @{ $interp->index_names }; undef $interp; # So this doesn't end up in closure and cause cycle return sub { my ( $request, $request_path ) = @_; my $interp = $request->interp; my $path_info = ''; my $declined_paths = $request->declined_paths; my @index_subpaths = map { "/$_" } @index_names; my $path = $request_path; my @tried_paths; # Deal with trailing slash # $path_info = chop($path) if $path ne '/' && substr( $path, -1 ) eq '/'; while (1) { my @candidate_paths = ( $path_info eq '' && !@autoextensions ) ? ($path) : ( $path eq '/' ) ? ( @index_subpaths, @dhandler_subpaths ) : ( ( grep { !/$ignore_file_regex/ } map { $path . $_ } @autoextensions ), ( map { $path . $_ } ( @index_subpaths, @dhandler_subpaths ) ) ); push( @tried_paths, @candidate_paths ); foreach my $candidate_path (@candidate_paths) { next if $declined_paths->{$candidate_path}; if ( my $compc = $interp->load($candidate_path) ) { if ( $compc->cmeta->is_top_level && ( $path_info eq '' || $compc->cmeta->is_dhandler || $compc->allow_path_info ) ) { $request->{path_info} = $path_info; return $compc->cmeta->path; } } } $interp->_top_level_not_found( $request_path, \@tried_paths ) if $path eq '/'; my $name = basename($path); $path_info = $path_info eq '/' ? "$name/" : length($path_info) ? "$name/$path_info" : $name; $path = dirname($path); @index_subpaths = (); # only match index file in same directory } }; } # # PRIVATE METHODS # method _parse_global_spec () { my $spec = shift; croak "only scalar globals supported at this time (not '$spec')" if $spec =~ /^[@%]/; $spec =~ s/^\$//; die "'$spec' is not a valid global var name" unless $spec =~ qr/^[[:alpha:]_]\w*$/; return ( '$', $spec ); } method _add_default_wrap_method ($compc) { # Default wrap method for any component that doesn't define one. # Call inner() until we're back down at the page component ($self), # then call main(). # unless ( $compc->meta->has_method('wrap') ) { my $path = $compc->cmeta->path; my $code = sub { my $self = shift; if ( $self->cmeta->path eq $path ) { if ( $self->can('main') ) { $self->main(@_); } else { die sprintf( "component '%s' ('%s') was called but has no main method - did you forget to define 'main' or 'handle'?", $path, $compc->cmeta->source_file ); } } else { $compc->_inner(); } }; $compc->meta->add_augment_method_modifier( wrap => $code ); } } method _assert_absolute_path ($path) { $path ||= ''; croak "'$path' is not an absolute path" unless is_absolute($path); } method _check_static_source_touch_file () { # Check the static_source_touch_file, if one exists, to see if it has # changed since we last checked. If it has, clear the code cache. # if ( my $touch_file = $self->static_source_touch_file ) { return unless -f $touch_file; my $touch_file_lastmod = ( stat($touch_file) )[9]; if ( $touch_file_lastmod > $self->{static_source_touch_lastmod} ) { $self->flush_code_cache; $self->{static_source_touch_lastmod} = $touch_file_lastmod; } } } method _collect_paths_for_all_comp_roots ($code) { my @paths; foreach my $root_path ( @{ $self->comp_root } ) { my $root_path_length = length($root_path); my @files = $code->($root_path); push( @paths, map { substr( $_, $root_path_length ) } @files ); } return uniq(@paths); } method _comp_class_for_path ($path) { my $classname = substr( $path, 1 ); $classname =~ s/[^\w]/_/g; $classname =~ s/\//::/g; $classname = join( "::", $self->component_class_prefix, $classname ); return $classname; } method _construct_distinct_string () { my $number = ++$self->{distinct_string_count}; my $str = $self->_construct_distinct_string_for_number($number); return $str; } method _construct_distinct_string_for_number ($number) { my $distinct_delimeter = "__MASON__"; return sprintf( "%s%d%s", $distinct_delimeter, $number, $distinct_delimeter ); } method _default_parent_path ($orig_path) { # Given /foo/bar.mc, look for (by default): # /foo/Base.mp, /foo/Base.mc, # /Base.mp, /Base.mc # # Split path into dir_path and base_name - validate that it has a # starting slash and ends with at least one non-slash character # my ( $dir_path, $base_name ) = ( $orig_path =~ m{^(/.*?)/?([^/]+)$} ) or die "not a valid absolute component path - '$orig_path'"; my $path = $dir_path; my @autobase_subpaths = map { "/$_" } @{ $self->autobase_names }; while (1) { my @candidate_paths = ( $path eq '/' ) ? @autobase_subpaths : ( map { $path . $_ } @autobase_subpaths ); if ( ( my $index = first_index { $_ eq $orig_path } @candidate_paths ) != -1 ) { splice( @candidate_paths, 0, $index + 1 ); } foreach my $candidate_path (@candidate_paths) { if ( $self->comp_exists($candidate_path) ) { return $candidate_path; } } if ( $path eq '/' ) { return '/'; } $path = dirname($path); } } method _determine_parent_compc ($path, $flags) { my $parent_compc; if ( exists( $flags->{extends} ) ) { my $extends = $flags->{extends}; if ( defined($extends) ) { $extends = mason_canon_path( join( "/", dirname($path), $extends ) ) if substr( $extends, 0, 1 ) ne '/'; $parent_compc = $self->load($extends) or die "could not load '$extends' for extends flag"; } else { $parent_compc = $self->component_class; } } return $parent_compc; } method _extract_flags_from_object_file ($object_file) { my $flags = {}; open( my $fh, "<", $object_file ) or die "could not open '$object_file': $!"; my $line = <$fh>; if ( my ($flags_str) = ( $line =~ /\# FLAGS: (.*)/ ) ) { $flags = json_decode($flags_str); } return $flags; } method _flush_load_cache () { Memoize::flush_cache('comp_exists'); Memoize::flush_cache('load'); } method _make_request () { return $self->request_class->new( interp => $self, %{ $self->request_params }, @_ ); } method _object_file_for_path ($path) { return catfile( $self->object_dir, ( split /\//, $path ) ) . $self->object_file_extension; } method _source_file_for_path ($path) { $self->_assert_absolute_path($path); foreach my $root_path ( @{ $self->comp_root } ) { my $source_file = $root_path . $path; return $source_file if -f $source_file; } return undef; } method _top_level_not_found ($path, $tried_paths) { my @combined_paths = combine_similar_paths(@$tried_paths); Mason::Exception::TopLevelNotFound->throw( error => sprintf( "could not resolve request path '%s'; searched for components (%s) under %s\n", $path, join( ", ", map { "'$_'" } @combined_paths ), @{ $self->comp_root } > 1 ? "component roots " . join( ", ", map { "'$_'" } @{ $self->comp_root } ) : "component root '" . $self->comp_root->[0] . "'" ) ); } method _validate_allow_globals () { # Will build allowed_globals_hash and also validate the param # $self->allowed_globals_hash; } # # Class overrides. Put here at the bottom because it strangely messes up # Perl line numbering if at the top. # sub _define_class_override_methods { my %class_overrides = ( code_cache_class => 'CodeCache', compilation_class => 'Compilation', component_class => 'Component', component_class_meta_class => 'Component::ClassMeta', component_import_class => 'Component::Import', component_moose_class => 'Component::Moose', request_class => 'Request', result_class => 'Result', ); # e.g. # $method_name = component_moose_class # $base_method_name = base_component_moose_class # $name = Component::Moose # $default_base_class = Mason::Component::Moose # while ( my ( $method_name, $name ) = each(%class_overrides) ) { my $base_method_name = "base_$method_name"; has $method_name => ( init_arg => undef, lazy_build => 1 ); has $base_method_name => ( isa => 'Str', lazy_build => 1 ); __PACKAGE__->meta->add_method( "_build_$method_name" => sub { my $self = shift; my $base_class = $self->$base_method_name; Class::Load::load_class($base_class); return Mason::PluginManager->apply_plugins_to_class( $base_class, $name, $self->plugins ); } ); __PACKAGE__->meta->add_method( "_build_$base_method_name" => sub { my $self = shift; my @candidates = map { join( '::', $_, $name ) } ( uniq( $self->mason_root_class, 'Mason' ) ); my ($base_class) = grep { can_load($_) } @candidates or die sprintf( "cannot load %s for %s", join( ', ', @candidates ), $base_method_name ); return $base_class; } ); } } __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::Interp - Mason Interpreter =head1 SYNOPSIS my $interp = Mason->new( comp_root => '/path/to/comps', data_dir => '/path/to/data', ... ); my $output = $interp->run( '/request/path', foo => 5 )->output(); =head1 DESCRIPTION Interp is the central Mason object, returned from C<< Mason->new >>. It is responsible for creating new requests, compiling components, and maintaining the cache of loaded components. =head1 PARAMETERS TO THE new() CONSTRUCTOR =over =item allow_globals (varnames) List of one or more global variable names that will be available in all components, like C<< $m >> is by default. allow_globals => [qw($dbh)] As in any programming environment, globals should be created sparingly (if at all) and only when other mechanisms (parameter passing, attributes, singletons) will not suffice. L, for example, creates a C<< $c >> global set to the context object in each request. Set the values of globals with L. =item autobase_names Array reference of L filenames to check in order when determining a component's superclass. Default is C<< ["Base.mp", "Base.mc"] >>. =item autoextend_request_path Whether to automatically add the L (by default ".mp" and ".mc") to the request path when searching for a matching page component. Defaults to true. =item class_header Perl code to be added at the top of the compiled class for every component, e.g. to bring in common features or import common methods. Default is the empty string. # Add to the top of every component class: # use Modern::Perl; # use JSON::XS qw(encode_json decode_json); # my $mason = Mason->new( ... class_header => qq( use Modern::Perl; use JSON::XS qw(encode_json decode_json); ), ); This is used by L. For more advanced usage you can override that method in a subclass or plugin. =item comp_root Required. The component root marks the top of your component hierarchy and defines how component paths are translated into real file paths. For example, if your component root is F, a component path of F translates to the file F. This parameter may be either a single path or an array reference of paths. If it is an array reference, the paths will be searched in the provided order whenever a component path is resolved, much like Perl's C<< @INC >>. =item component_class_prefix Prefix to use in generated component classnames. Defaults to 'MC' plus the interpreter's count, e.g. MC0. So a component '/foo/bar' would get a classname like 'MC0::foo::bar'. =item data_dir The data directory is a writable directory that Mason uses for various features and optimizations: for example, component object files and data cache files. Mason will create the directory on startup if necessary. Defaults to a temporary directory that will be cleaned up at process end. This will hurt performance as Mason will have to recompile components on each run. =item dhandler_names Array reference of dhandler file names to check in order when resolving a top-level path. Default is C<< ["dhandler.mp", "dhandler.mc"] >>. An empty list disables this feature. =item index_names Array reference of index file names to check in order when resolving a top-level path. Default is C<< ["index.mp", "index.mc"] >>. An empty list disables this feature. =item no_source_line_numbers Do not put in source line number comments when generating code. Setting this to true will cause error line numbers to reflect the real object file, rather than the source component. =item object_file_extension Extension to add to the end of object files. Default is ".mobj". =item plugins A list of plugins and/or plugin bundles: plugins => [ 'OnePlugin', 'AnotherPlugin', '+My::Mason::Plugin::AThirdPlugin', '@APluginBundle', '-DontLikeThisPlugin', ]); See L. =item out_method Default L passed to each new request. =item pure_perl_extensions A listref of file extensions of components to be considered as pure perl (see L). Default is C<< ['.mp'] >>. If an empty list is specified, then no components will be considered pure perl. =item static_source True or false, default is false. When false, Mason checks the timestamp of the component source file each time the component is used to see if it has changed. This provides the instant feedback for source changes that is expected for development. However it does entail a file stat for each component executed. When true, Mason assumes that the component source tree is unchanging: it will not check component source files to determine if the memory cache or object file has expired. This can save many file stats per request. However, in order to get Mason to recognize a component source change, you must touch the L. We recommend turning this mode on in your production sites if possible, if performance is of any concern. =item static_source_touch_file Specifies a filename that Mason will check once at the beginning of every request when in L mode. When the file timestamp changes (indicating that a component has changed), Mason will clear its in-memory component cache and recheck existing object files. =item top_level_extensions A listref of file extensions of components to be considered "top level", accessible directly from C<< $interp->run >> or a web request. Default is C<< ['.mp', '.mc'] >>. If an empty list is specified, then there will be I restriction; that is, I components will be considered top level. =back =head1 CUSTOM MASON CLASSES These parameters specify alternate classes to use instead of the default Mason:: classes. For example, to use your own Compilation base class: my $interp = Mason->new(base_compilation_class => 'MyApp::Mason::Compilation', ...); L, if any, will applied to this class to create a final class, which you can get with $interp->compilation_class =over =item base_code_cache_class Specify alternate to L =item base_compilation_class Specify alternate to L =item base_component_class Specify alternate to L =item base_component_moose_class Specify alternate to L =item base_component_class_meta_class Specify alternate to L =item base_component_import_class Specify alternate to L =item base_request_class Specify alternate to L =item base_result_class Specify alternate to L =back =head1 PUBLIC METHODS =over =item all_paths ([dir_path]) Returns a list of distinct component paths under I, which defaults to '/' if not provided. For example, $interp->all_paths('/foo/bar') => ('/foo/bar/baz.mc', '/foo/bar/blargh.mc') Note that these are all component paths, not filenames, and all component roots are searched if there are multiple ones. =item comp_exists (path) Returns a boolean indicating whether a component exists for the absolute component I. =item count Returns the number of this interpreter, a monotonically increasing integer for the process starting at 0. =item flush_code_cache Empties the component cache and removes all component classes. =item glob_paths (pattern) Returns a list of all component paths matching the glob I. e.g. $interp->glob_paths('/foo/b*.mc') => ('/foo/bar.mc', '/foo/baz.mc') Note that these are all component paths, not filenames, and all component roots are searched if there are multiple ones. =item load (path) Returns the component object corresponding to an absolute component I, or undef if none exists. Dies with an error if the component fails to load because of a syntax error. =item object_dir Returns the directory containing component object files. =item run ([request params], path, args...) Creates a new L object for the given I and I, and executes it. Returns a L object, which is generally accessed to get the output. e.g. my $output = $interp->run('/foo/bar', baz => 5)->output; The first argument may optionally be a hashref of request parameters, which are passed to the Mason::Request constructor. e.g. this tells the request to output to standard output: $interp->run({out_method => sub { print $_[0] }}, '/foo/bar', baz => 5); =item set_global (varname, value) Set the global I to I. This will be visible in all components loaded by this interpreter. The variables must be on the L list. $interp->set_global('$scalar', 5); $interp->set_global('$scalar2', $some_object); See also L. =back =head1 MODIFIABLE METHODS These methods are not intended to be called externally, but may be useful to modify with method modifiers in L and L. Their APIs will be kept as stable as possible. =over =item is_pure_perl_comp_path ($path) Determines whether I<$path> is a pure Perl component - by default, uses L. =item is_top_level_comp_path ($path) Determines whether I<$path> is a valid top-level component - by default, uses L. =item modify_loaded_class ( $compc ) An opportunity to modify loaded component class I<$compc> (e.g. add additional methods or apply roles) before it is made immutable. =item write_object_file ($object_file, $object_contents) Write compiled component I<$object_contents> to I<$object_file>. This is an opportunity to modify I<$object_contents> before it is written, or I<$object_file> after it is written. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/Manual000775 777777 777777 00000000213 12266570730 017542 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365389 19 SCHILY.nlink=14 Mason-2.21/lib/Mason/Manual/000775 €ˆž«€q{Ì00000000000 12266570730 016575 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/PaxHeader/Manual.pod000644 777777 777777 00000000212 12266570730 020315 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365372 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual.pod000644 €ˆž«€q{Ì00000003476 12266570730 017311 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual - Index of Mason documentation =head1 MANUALS =over =item L A quick introduction to get your feet wet. =item L How to set up Mason in a web environment and a non-web environment. =item L All about components, the building blocks of Mason. =item L A full reference of syntax that can be used in components. =item L How request paths get mapped to page components. =item L Recipes for common Mason tasks. =item L Frequently asked questions. =item L Using and creating filters that can be applied to portions of content in a component. =item L Using and creating plugins to modify Mason behavior. =item L Summary of differences between Mason 1 and Mason 2. =back =head1 OBJECT DOCUMENTATION =over =item L Mason::Interp is the central Mason object, returned from C<< Mason->new >>. It is responsible for creating new requests, compiling components, and maintaining the cache of loaded components. =item L Mason::Request represents a single request for a page, and is the access point for most Mason features not provided by syntactic tags. =item L Mason::Component is the base class from which all generated component classes inherit, directly or indirectly. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/Moose000775 777777 777777 00000000212 12266570730 017406 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365402 18 SCHILY.nlink=3 Mason-2.21/lib/Mason/Moose/000775 €ˆž«€q{Ì00000000000 12266570730 016442 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/PaxHeader/Moose.pm000644 777777 777777 00000000212 12266570730 020014 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365373 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Moose.pm000644 €ˆž«€q{Ì00000002732 12266570730 017002 0ustar00jonswart000000 000000 package Mason::Moose; { $Mason::Moose::VERSION = '2.21'; } ## no critic (Moose::RequireMakeImmutable) use Moose (); use MooseX::HasDefaults::RO (); use MooseX::StrictConstructor (); use Method::Signatures::Simple (); use Moose::Exporter; use strict; use warnings; Moose::Exporter->setup_import_methods( also => ['Moose'] ); sub init_meta { my $class = shift; my %params = @_; my $for_class = $params{for_class}; Method::Signatures::Simple->import( into => $for_class ); Moose->init_meta(@_); MooseX::StrictConstructor->import( { into => $for_class } ); MooseX::HasDefaults::RO->import( { into => $for_class } ); { no strict 'refs'; *{ $for_class . '::CLASS' } = sub () { $for_class }; # like CLASS.pm } } 1; __END__ =pod =head1 NAME Mason::Moose - Mason Moose policies =head1 SYNOPSIS # instead of use Moose; use Mason::Moose; =head1 DESCRIPTION Sets certain Moose behaviors for Mason's internal classes. Using this module is equivalent to use CLASS; use Moose; use MooseX::HasDefaults::RO; use MooseX::StrictConstructor; use Method::Signatures::Simple; =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/Plugin000775 777777 777777 00000000213 12266570730 017563 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365404 19 SCHILY.nlink=10 Mason-2.21/lib/Mason/Plugin/000775 €ˆž«€q{Ì00000000000 12266570730 016616 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/PaxHeader/Plugin.pm000644 777777 777777 00000000212 12266570730 020170 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365374 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin.pm000644 €ˆž«€q{Ì00000001301 12266570730 017145 0ustar00jonswart000000 000000 package Mason::Plugin; { $Mason::Plugin::VERSION = '2.21'; } use Mason::PluginRole; use Mason::Util qw(can_load); use Class::Load; method requires_plugins ($plugin_class:) { return (); } method expand_to_plugins ($plugin_class:) { return ( $plugin_class, Mason::PluginManager->process_plugin_specs( [ $plugin_class->requires_plugins ] ) ); } method get_roles_for_mason_class ($plugin_class: $name) { my @roles_to_try = join( "::", $plugin_class, $name ); if ( $name eq 'Component' ) { push( @roles_to_try, join( "::", $plugin_class, 'Filters' ) ); } my @roles = grep { Class::Load::is_class_loaded($_) || can_load($_) } @roles_to_try; return @roles; } 1; Mason-2.21/lib/Mason/PaxHeader/PluginBundle000775 777777 777777 00000000212 12266570730 020714 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365418 18 SCHILY.nlink=3 Mason-2.21/lib/Mason/PluginBundle/000775 €ˆž«€q{Ì00000000000 12266570730 017750 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/PaxHeader/PluginBundle.pm000644 777777 777777 00000000212 12266570730 021322 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365375 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/PluginBundle.pm000644 €ˆž«€q{Ì00000000421 12266570730 020301 0ustar00jonswart000000 000000 package Mason::PluginBundle; { $Mason::PluginBundle::VERSION = '2.21'; } use Mason::PluginRole; method expand_to_plugins ($bundle_class:) { return Mason::PluginManager->process_plugin_specs( [ $bundle_class->requires_plugins ] ); } requires 'requires_plugins'; 1; Mason-2.21/lib/Mason/PaxHeader/PluginManager.pm000644 777777 777777 00000000212 12266570730 021463 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365376 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/PluginManager.pm000644 €ˆž«€q{Ì00000005672 12266570730 020457 0ustar00jonswart000000 000000 package Mason::PluginManager; { $Mason::PluginManager::VERSION = '2.21'; } use Carp; use Log::Any qw($log); use Mason::Moose; use Mason::Util qw(can_load uniq); my ( %apply_plugins_cache, %final_subclass_seen ); # CLASS METHODS # our $depth; our %visited; my $max_depth = 16; method process_top_plugin_specs ($class: $plugin_specs) { local $depth = 0; local %visited = (); my @positive_plugin_specs = grep { !/^\-/ } @$plugin_specs; my @negative_plugin_specs = map { substr( $_, 1 ) } grep { /^\-/ } @$plugin_specs; push( @positive_plugin_specs, '@Default' ); my %exclude_plugin_modules = map { ( $_, 1 ) } $class->process_plugin_specs( \@negative_plugin_specs ); my @modules = grep { !$exclude_plugin_modules{$_} } $class->process_plugin_specs( \@positive_plugin_specs ); return @modules; } method process_plugin_specs ($class: $plugin_specs) { local $depth = $depth + 1; local %visited = %visited; die ">$max_depth levels deep in process_plugins_list (plugin cycle?)" if $depth >= $max_depth; croak 'plugins must be an array reference' unless ref($plugin_specs) eq 'ARRAY'; my @modules = ( uniq( map { $class->process_plugin_spec($_) } @$plugin_specs ) ); return @modules; } method process_plugin_spec ($class: $plugin_spec) { my $module = $class->plugin_spec_to_module($plugin_spec); my @modules = !$visited{$module}++ ? $module->expand_to_plugins : (); return @modules; } method plugin_spec_to_module ($class: $plugin_spec) { my $module = substr( $plugin_spec, 0, 1 ) eq '+' ? ( substr( $plugin_spec, 1 ) ) : substr( $plugin_spec, 0, 1 ) eq '@' ? ( "Mason::PluginBundle::" . substr( $plugin_spec, 1 ) ) : "Mason::Plugin::$plugin_spec"; return can_load($module) ? $module : die "could not load '$module' for plugin spec '$plugin_spec'"; } method apply_plugins_to_class ($class: $base_subclass, $name, $plugins) { my $subclass; my $key = join( ",", $base_subclass, @$plugins ); return $apply_plugins_cache{$key} if defined( $apply_plugins_cache{$key} ); my $final_subclass; my @roles = map { $_->get_roles_for_mason_class($name) } @$plugins; if (@roles) { my $meta = Moose::Meta::Class->create_anon_class( superclasses => [$base_subclass], roles => \@roles, cache => 1 ); $final_subclass = $meta->name; $meta->add_method( 'meta' => sub { $meta } ) if !$final_subclass_seen{$final_subclass}++; } else { $final_subclass = $base_subclass; } $log->debugf( "apply_plugins - base_subclass=%s, name=%s, plugins=%s, roles=%s - %s", $base_subclass, $name, $plugins, \@roles, $final_subclass ) if $log->is_debug; $final_subclass->meta->make_immutable if $final_subclass->can('meta'); $apply_plugins_cache{$key} = $final_subclass; return $final_subclass; } __PACKAGE__->meta->make_immutable(); 1; Mason-2.21/lib/Mason/PaxHeader/PluginRole.pm000644 777777 777777 00000000212 12266570730 021012 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365377 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/PluginRole.pm000644 €ˆž«€q{Ì00000002107 12266570730 017774 0ustar00jonswart000000 000000 package Mason::PluginRole; { $Mason::PluginRole::VERSION = '2.21'; } use Moose::Role (); use Method::Signatures::Simple (); use Moose::Exporter; Moose::Exporter->setup_import_methods( also => ['Moose::Role'] ); sub init_meta { my $class = shift; my %params = @_; my $for_class = $params{for_class}; Method::Signatures::Simple->import( into => $for_class ); Moose::Role->init_meta(@_); } 1; __END__ =pod =head1 NAME Mason::PluginRole - Helper for defining Mason plugin roles =head1 SYNOPSIS # instead of use Moose::Role; use Mason::PluginRole; =head1 DESCRIPTION A variant on Moose::Role that can be used in Mason plugin roles. Using this module is equivalent to use Moose::Role; use Method::Signatures::Simple; =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/Request.pm000644 777777 777777 00000000212 12266570730 020362 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365378 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Request.pm000644 €ˆž«€q{Ì00000050415 12266570730 017351 0ustar00jonswart000000 000000 package Mason::Request; { $Mason::Request::VERSION = '2.21'; } use Carp; use File::Basename; use Guard; use Log::Any qw($log); use Mason::Exceptions; use Mason::TieHandle; use Mason::Types; use Mason::Moose; use Scalar::Util qw(blessed reftype weaken); use Try::Tiny; my $default_out = sub { my ( $text, $self ) = @_; $self->result->_append_output($text) }; my $next_id = 0; # Passed attributes # has 'interp' => ( required => 1, weak_ref => 1 ); has 'out_method' => ( isa => 'Mason::Types::OutMethod', default => sub { $default_out }, coerce => 1 ); # Derived attributes # has 'buffer_stack' => ( init_arg => undef, default => sub { [] } ); has 'declined' => ( init_arg => undef, is => 'rw' ); has 'declined_paths' => ( default => sub { {} } ); has 'go_result' => ( init_arg => undef ); has 'id' => ( init_arg => undef, default => sub { $next_id++ } ); has 'output' => ( init_arg => undef, default => '' ); has 'page' => ( init_arg => undef ); has 'path_info' => ( init_arg => undef, default => '' ); has 'request_args' => ( init_arg => undef ); has 'request_code_cache' => ( init_arg => undef, default => sub { {} } ); has 'request_path' => ( init_arg => undef ); has 'result' => ( init_arg => undef, lazy_build => 1 ); has 'run_params' => ( init_arg => undef ); # Globals, localized to each request # our ( $current_request, $current_buffer ); method current_request () { $current_request } # # BUILD # method BUILD ($params) { # Make a copy of params sans interp # $self->{orig_request_params} = $params; delete( $self->{orig_request_params}->{interp} ); } method _build_result () { return $self->interp->result_class->new; } # # PUBLIC METHODS # method abort ($aborted_value) { Mason::Exception::Abort->throw( error => 'Request->abort was called', aborted_value => $aborted_value ); } method aborted ($err) { return blessed($err) && $err->isa('Mason::Exception::Abort'); } method add_cleanup ($code) { push( @{ $self->{cleanups} }, $code ); } method cache () { die 'caching is now in the cache plugin (Mason::Plugin::Cache)'; } method capture ($code) { croak "capture() expects a code reference" unless defined($code) && ref($code) eq 'CODE'; my $output; { $self->_push_buffer; scope_guard { $output = ${ $self->_current_buffer }; $self->_pop_buffer; }; $code->(); } return $output; } method clear_and_abort () { $self->clear_buffer; $self->abort(@_); } method clear_buffer () { foreach my $buffer ( @{ $self->buffer_stack } ) { $$buffer = ''; } } method comp () { $self->construct(@_)->main(); } method comp_exists ($path) { return $self->interp->comp_exists( $self->rel_to_abs($path) ); } method construct () { my $path = shift; my $compc = $self->load($path) or $self->_comp_not_found($path); return $compc->new( @_, 'm' => $self ); } method current_comp_class () { my $cnt = 1; while (1) { if ( my $pkg = ( caller($cnt) )[0] ) { return $pkg if $pkg->isa('Mason::Component') && $pkg ne 'Mason::Component'; } else { confess("cannot determine current_comp_class from stack"); } $cnt++; } } method decline () { $self->declined(1); $self->clear_and_abort; } method filter () { $self->_apply_filters(@_); } method flush_buffer () { my $request_buffer = $self->_request_buffer; $self->process_output($request_buffer); $self->out_method->( $$request_buffer, $self ) if length $$request_buffer; $$request_buffer = ''; } method go () { $self->clear_buffer; my %request_params = ( %{ $self->{orig_request_params} } ); if ( ref( $_[0] ) eq 'HASH' ) { %request_params = ( %request_params, %{ shift(@_) } ); } $self->{go_result} = $self->_run_subrequest( \%request_params, @_ ); $self->abort(); } method load ($path) { my $compc = $self->interp->load( $self->rel_to_abs($path) ); } method log () { return $self->current_comp_class->cmeta->log(); } method notes () { return $self->{notes} unless @_; my $key = shift; return $self->{notes}->{$key} unless @_; return $self->{notes}->{$key} = shift; } method print () { my $buffer = $self->_current_buffer; for (@_) { $$buffer .= $_ if defined; } } method rel_to_abs ($path) { $path = join( "/", $self->current_comp_class->cmeta->dir_path, $path ) unless substr( $path, 0, 1 ) eq '/'; return $path; } method scomp () { my @params = @_; my $buf = $self->capture( sub { $self->comp(@params) } ); return $buf; } method visit () { my $buf; my %request_params = ( %{ $self->{orig_request_params} }, out_method => \$buf ); if ( ref( $_[0] ) eq 'HASH' ) { %request_params = ( %request_params, %{ shift(@_) } ); } my $result = $self->_run_subrequest( \%request_params, @_ ); $self->print($buf); return $result; } # # MODIFIABLE METHODS # method cleanup_request () { $self->interp->_flush_load_cache(); foreach my $cleanup ( @{ $self->{cleanups} } ) { try { $cleanup->($self); } catch { warn "error during request cleanup: $_"; }; } } method construct_page_component ($compc, $args) { return $compc->new( %$args, 'm' => $self ); } method catch_abort ($code) { my $retval; try { $retval = $code->(); } catch { my $err = $_; if ( $self->aborted($err) ) { $retval = $err->aborted_value; } else { die $err; } }; return $retval; } method match_request_path ($request_path) { $self->interp->match_request_path->( $self, $request_path ); } method process_output ($outref) { # No-op by default } method run () { # Get path and either hash or hashref of arguments # my $request_path = shift; $self->interp->_assert_absolute_path($request_path); my $request_args; if ( @_ == 1 && reftype( $_[0] ) eq 'HASH' ) { $request_args = shift; } else { $request_args = {@_}; } # Save off the requested path and args # $self->{request_path} = $request_path; $self->{request_args} = $request_args; # Localize current_request and current_buffer until end of scope. Use a guard # because 'local' doesn't work with the aliases inside components. # my $save_current_request = $current_request; my $save_current_buffer = $current_buffer; scope_guard { $current_request = $save_current_request; $current_buffer = $save_current_buffer }; $current_request = $self; $self->_push_buffer(); # Clean up after request # scope_guard { $self->cleanup_request() }; # Flush interp load cache # $self->interp->_flush_load_cache(); # Check the static_source touch file, if it exists, before the # first component is loaded. # $self->interp->_check_static_source_touch_file(); # Turn request path into a page component # match_request_path: my $page_path = $self->match_request_path($request_path); my $page_compc = $self->interp->load($page_path); $log->debugf( "starting request with component '%s'", $page_path ) if $log->is_debug; $self->catch_abort( sub { # Construct page component # my $page = $self->construct_page_component( $page_compc, $request_args ); $self->{page} = $page; # Dispatch to page component, with 'print' tied to component output. # $self->with_tied_print( sub { $page->handle } ); } ); # If declined, retry match # if ( $self->declined ) { $self->declined(0); $self->{declined_paths}->{$page_path} = 1; goto match_request_path; } # If go() was called in this request, return the result of the subrequest # return $self->go_result if defined( $self->go_result ); # Send output to its final destination # $self->flush_buffer; return $self->result; } method with_tied_print ($code) { local *TH; tie *TH, 'Mason::TieHandle'; my $old = select TH; scope_guard { select $old }; return $code->(); } # # PRIVATE METHODS # method _apply_one_filter ($filter, $yield) { my $filtered_output; if ( ref($yield) ne 'CODE' ) { my $orig_yield = defined($yield) ? $yield : ''; $yield = sub { $orig_yield }; } if ( ref($filter) eq 'CODE' ) { local $_ = $yield->(); $_ = '' if !defined($_); $filtered_output = $filter->($_); } elsif ( blessed($filter) && $filter->can('apply_filter') ) { $filtered_output = $filter->apply_filter($yield); } else { die "'$filter' is neither a code ref nor a filter object"; } return $filtered_output; } method _apply_filters () { my $yield = pop(@_); if ( ref($yield) ne 'CODE' ) { my $orig_yield = defined($yield) ? $yield : ''; $yield = sub { $orig_yield }; } if ( !@_ ) { return $yield->(); } else { my $filter = pop(@_); return $self->_apply_filters( @_, sub { $self->_apply_one_filter( $filter, $yield ) } ); } } method _apply_filters_to_output () { my $output_method = pop(@_); my $yield = sub { my @args = @_; $self->capture( sub { $output_method->(@args) } ); }; my $filtered_output = $self->_apply_filters( @_, $yield ); $self->print($filtered_output); } method _comp_not_found ($path) { croak sprintf( "could not find component for path '%s' - component root is [%s]", $path, join( ", ", @{ $self->interp->comp_root } ) ); } method _current_buffer () { $self->{buffer_stack}->[-1]; } method _pop_buffer () { pop( @{ $self->{buffer_stack} } ); $current_buffer = $self->_current_buffer; } method _push_buffer () { my $s = ''; push( @{ $self->{buffer_stack} }, \$s ); $current_buffer = \$s; } method _request_buffer () { $self->{buffer_stack}->[0]; } method _reset_next_id () { # for testing $next_id = 0; } method _run_subrequest () { my $request_params = shift(@_); my $path = $self->rel_to_abs( shift(@_) ); $self->interp->run( $request_params, $path, @_ ); } __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::Request - Mason Request Class =head1 SYNOPSIS $m->abort (...) $m->comp (...) etc. =head1 DESCRIPTION Mason::Request represents a single request for a page, and is the access point for most Mason features not provided by syntactic tags. A Mason request is created when you call C<< $interp->run >>, or in a web environment, for each new web request. A new (sub-)request is also created when you call L or L on the current request. Inside a component you can access the current request object via the global C<$m>. Outside of a component, you can use the class method Ccurrent_request>. =head1 COMPONENT PATHS The methods L, L, L, L, L, and L take a component path argument. If the path does not begin with a '/', then it is made absolute based on the current component path (using L). Component paths are like URL paths, and always use a forward slash (/) as the separator, regardless of what your operating system uses. =head1 PARAMETERS TO THE new() CONSTRUCTOR These parameters would normally be passed in an initial hashref to C<< $interp->run >>, C<< $m->visit >>, or C<< $m->go >>. =over =item out_method Indicates where to send the page output. If out_method is a scalar reference, output is appended to the scalar. If out_method is a code reference, the code is called with the output string. For example, to send output to a file called "mason.out": open(my $fh, ">", "mason.out); ... out_method => sub { $fh->print($_[0]) } When C is unspecified, the output can be obtained from the L object returned from C<< $interp->run >>. =back =head1 PUBLIC METHODS =over =item abort () Ends the current request, finishing the page without returning through components. C is implemented by throwing an C object and can thus be caught by C. The C method is a shortcut for determining whether a caught error was generated by C. =item aborted ([$err]) Returns true or undef indicating whether the specified C<$err> was generated by C. If no C<$err> was passed, uses C<$@>. In this L code, we catch and process fatal errors while letting C exceptions pass through: try { code_that_may_fail_or_abort() } catch { die $_ if $m->aborted($_); # handle fatal errors... }; =item add_cleanup (code) Add a code reference to be executed when the request is L. =item clear_and_abort () This method is syntactic sugar for calling C and then C. If you are aborting the request because of an error (or, in a web environment, to do a redirect), you will often want to clear the buffer first so that any output generated up to that point is not sent to the client. =item capture (code) Execute the I, capturing and returning any Mason output instead of outputting it. e.g. the following my $buf = $m->capture(sub { $m->comp('/foo') }); is equivalent to my $buf = $m->scomp('/foo'); =item clear_buffer () Clears the Mason output buffer. Any output sent before this line is discarded. Useful for handling error conditions that can only be detected in the middle of a request. clear_buffer is, of course, thwarted by L. =item comp (path[, params ...]) Creates a new instance of the component designated by I, and calls its C
method. I, if any, are passed to the constructor. The C<< <& &> >> tag provides a shortcut for C<$m-Ecomp>. =item comp_exists (path) Makes the component I absolute if necessary, and calls L to determine whether a component exists at that path. =item current_comp_class () Returns the current component class. This is determined by walking up the Perl caller() stack until the first Mason::Component subclass is found. =item current_request () This class method returns the C currently in use. If called when no Mason request is active it will return C. =item construct (path[, params ...]) Constructs and return a new instance of the component designated by I. I, if any, are passed to the constructor. Throws an error if I does not exist. =item decline () Clears the output buffer and tries the current request again, but acting as if the previously chosen page component(s) do not exist. For example, if the following components exist: /news/sports.mc /news/dhandler.mc /dhandler.mc then a request for path C will initially resolve to C. A call to C<< $m->decline >> would restart the request and resolve to C, a second C<< $m->decline >> would resolve to C, and a third would throw a "not found" error. =item filter (filter_expr, [filter_expr...], string|coderef) Applies one or more filters to a string or to a coderef that returns a string. my $filtered_string = $m->filter($.Trim, $.NoBlankLines, $string); =item flush_buffer () Flushes the main output buffer. Anything currently in the buffer is sent to the request's L. Note that anything output within a C<< $m->scomp >> or C<< $m->capture >> will not have made it to the main output buffer, and thus cannot be flushed. =item go ([request params], path, args...) Performs an internal redirect. Clears the output buffer, runs a new request for the given I and I, and then L when that request is done. The first argument may optionally be a hashref of parameters which are passed to the C constructor. See also L. =item interp () Returns the L object associated with this request. =item load (path) Makes the component I absolute if necessary, and calls L to load the component class associated with the path. =item log () Returns a C logger with a log category specific to the current component. The category for a component "/foo/bar" would be "Mason::Component::foo::bar". =item notes ([key[, value]]) The C method provides a place to store application data between components - essentially, a hash which persists for the duration of the request. C stores a new entry in the hash; C returns a previously stored value; and C without any arguments returns a reference to the entire hash of key-value pairs. Consider storing this kind of data in a read-write attribute of the page component. =item print (string) Add the given I to the Mason output buffer. This happens implicitly for all content placed in the main component body. =item page () Returns the page component originally called in the request. =item path_info () Returns the remainder of the request path beyond the path of the page component, with no leading slash. e.g. If a request for '/foo/bar/baz' resolves to "/foo.mc", the path_info is "bar/baz". For an exact match, it will contain the empty string (never undef), so you can determine whether there's a path_info with if ( length($m->path_info) ) =item rel_to_abs (path) Converts a component I to absolute form based on the current component, if it does not already begin with a '/'. =item request_args () Returns the original hashref of arguments passed to the request, e.g. via C<< $interp->run >>. =item request_path () Returns the original path passed to the request, e.g. in C<< $interp->run >>. =item scomp (comp, args...) Like L, but returns the component output as a string instead of printing it. (Think sprintf versus printf.) See also L. =item visit ([request params], path, args...) Performs a subrequest with the given I and I, with output being sent to the current output buffer. The first argument may optionally be a hashref of parameters which are passed to the C constructor. e.g. to capture the output of the subrequest: $m->visit({out_method => \my $buffer}, ...); See also L. =back =head1 MODIFIABLE METHODS These methods are not intended to be called externally, but may be useful to modify with method modifiers in L and L. Their APIs will be kept as stable as possible. =over =item cleanup_request () A place to perform cleanup duties when the request finishes or dies with an error, even if the request object is not immediately destroyed. Includes anything registered with L. =item construct_page_component ($compc, $args) Constructs the page component of class I<$compc>, with hashref of constructor arguments I<$args>. =item match_request_path ($request_path) Given a top level I<$request_path>, return a corresponding component path or undef if none was found. Search includes dhandlers and index files. See L. =item process_output ($outref) This method is called on the output buffer right before it is sent to its final destination. I<$outref> is a reference to the output string; the method can modify it as desired. =item run ($request_path, args) Runs the request with I<$request_path> and I, where the latter can be either a hashref or a hash. This is generally called via << $interp->run >>. =item with_tied_print ($code) Execute the given I<$code> with the current selected filehandle ('print') tied to the Mason output stream. You could disable the filehandle selection by overriding this to just call I<$code>. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/Result.pm000644 777777 777777 00000000212 12266570730 020210 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365379 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Result.pm000644 €ˆž«€q{Ì00000002370 12266570730 017174 0ustar00jonswart000000 000000 package Mason::Result; { $Mason::Result::VERSION = '2.21'; } use Mason::Moose; # Public attributes has 'data' => ( default => sub { {} } ); has 'output' => ( is => 'rw', default => '' ); method _append_output ($text) { $self->{output} .= $text; } __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::Result - Result returned from Mason request =head1 SYNOPSIS my $interp = Mason->new(...); my $output = $result->output; my $data = $result->data; =head1 DESCRIPTION An object of this class is returned from C<< $interp->run >>. It contains the page output and any values set in C<< $m->result >>. Plugins may add additional accessors. =head1 METHODS =over =item output The output of the entire page, unless L was defined in which case this will be empty. =item data A hashref of arbitrary data that can be set via $m->result->data->{'key'} = 'value'; =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/PaxHeader/t000775 777777 777777 00000000213 12266570730 016570 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365420 19 SCHILY.nlink=25 Mason-2.21/lib/Mason/t/000775 €ˆž«€q{Ì00000000000 12266570730 015623 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/PaxHeader/Test000775 777777 777777 00000000212 12266570730 017243 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365444 18 SCHILY.nlink=7 Mason-2.21/lib/Mason/Test/000775 €ˆž«€q{Ì00000000000 12266570730 016277 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/PaxHeader/TieHandle.pm000644 777777 777777 00000000212 12266570730 020567 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365380 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/TieHandle.pm000644 €ˆž«€q{Ì00000001016 12266570730 017547 0ustar00jonswart000000 000000 package Mason::TieHandle; { $Mason::TieHandle::VERSION = '2.21'; } use strict; use warnings; sub TIEHANDLE { my $class = shift; return bless {}, $class; } sub PRINT { my $self = shift; # TODO - why do we need to select STDOUT here? my $old = select STDOUT; $Mason::Request::current_request->print(@_); select $old; } sub PRINTF { my $self = shift; # apparently sprintf(@_) won't work, it needs to be a scalar # followed by a list $self->PRINT( sprintf( shift, @_ ) ); } 1; Mason-2.21/lib/Mason/PaxHeader/Types.pm000644 777777 777777 00000000212 12266570730 020036 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365381 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Types.pm000644 €ˆž«€q{Ì00000001253 12266570730 017021 0ustar00jonswart000000 000000 package Mason::Types; { $Mason::Types::VERSION = '2.21'; } use Moose::Util::TypeConstraints; use strict; use warnings; subtype 'Mason::Types::CompRoot' => as 'ArrayRef[Str]'; coerce 'Mason::Types::CompRoot' => from 'Str' => via { [$_] }; subtype 'Mason::Types::OutMethod' => as 'CodeRef'; coerce 'Mason::Types::OutMethod' => from 'ScalarRef' => via { my $ref = $_; sub { $$ref .= $_[0] } }; subtype 'Mason::Types::RegexpRefOrStr' => as 'RegexpRef'; coerce 'Mason::Types::RegexpRefOrStr' => from 'Str' => via { qr/$/ }; subtype 'Mason::Types::Autoextend' => as 'ArrayRef[Str]'; coerce 'Mason::Types::Autoextend' => from 'Bool' => via { $_ ? [ '.mp', '.mc' ] : [] }; 1; Mason-2.21/lib/Mason/PaxHeader/Util.pm000644 777777 777777 00000000212 12266570730 017647 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365382 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Util.pm000644 €ˆž«€q{Ì00000015015 12266570730 016633 0ustar00jonswart000000 000000 package Mason::Util; { $Mason::Util::VERSION = '2.21'; } use Carp; use Class::Unload; use Class::Load; use Data::Dumper; use Fcntl qw( :DEFAULT :seek ); use File::Find; use File::Spec::Functions (); use JSON; use Try::Tiny; use strict; use warnings; use base qw(Exporter); our @EXPORT_OK = qw(can_load catdir catfile checksum combine_similar_paths dump_one_line find_wanted first_index is_absolute json_encode json_decode mason_canon_path read_file taint_is_on touch_file trim uniq write_file); my $Fetch_Flags = O_RDONLY | O_BINARY; my $Store_Flags = O_WRONLY | O_CREAT | O_BINARY; my $File_Spec_Using_Unix = $File::Spec::ISA[0] eq 'File::Spec::Unix'; # Map null, true and false to real Perl values if ( JSON->VERSION < 2 ) { $JSON::UnMapping = 1; } sub can_load { # Load $class_name if possible. Return 1 if successful, 0 if it could not be # found, and rethrow load error (other than not found). # my ($class_name) = @_; my $result; try { Class::Load::load_class($class_name); $result = 1; } catch { if ( /Can\'t locate .* in \@INC/ && !/Compilation failed/ ) { $result = 0; } else { die $_; } }; return $result; } sub catdir { return $File_Spec_Using_Unix ? join( "/", @_ ) : File::Spec::Functions::catdir(@_); } sub catfile { return $File_Spec_Using_Unix ? join( "/", @_ ) : File::Spec::Functions::catfile(@_); } sub checksum { my ($str) = @_; # Adler32 algorithm my $s1 = 1; my $s2 = 1; for my $c ( unpack( "C*", $str ) ) { $s1 = ( $s1 + $c ) % 65521; $s2 = ( $s2 + $s1 ) % 65521; } return ( $s2 << 16 ) + $s1; } # Convert /foo/bar.m, /foo/bar.pm, /foo.m, /foo.pm to # /foo/bar.{m,pm}, /foo.{m,pm}. I have no idea why this takes # so much code. # sub combine_similar_paths { my @paths = @_; my ( @final, $current_base, @current_exts ); foreach my $path (@paths) { if ( my ( $base, $ext ) = ( $path =~ /^(.*)\.(.*)$/ ) ) { if ( defined($current_base) && $current_base ne $base ) { push( @final, "$current_base." . ( ( @current_exts == 1 ) ? $current_exts[0] : sprintf( '{%s}', join( ',', @current_exts ) ) ) ); @current_exts = ($ext); } else { push( @current_exts, $ext ); } $current_base = $base; } else { push( @final, $path ); } } if ( defined($current_base) ) { push( @final, "$current_base." . ( ( @current_exts == 1 ) ? $current_exts[0] : sprintf( '{%s}', join( ',', @current_exts ) ) ) ); } return @final; } sub delete_package { my $pkg = shift; Class::Unload->unload($pkg); } sub dump_one_line { my ($value) = @_; return Data::Dumper->new( [$value] )->Indent(0)->Sortkeys(1)->Quotekeys(0)->Terse(1)->Dump(); } # From File::Find::Wanted sub find_wanted { my $func = shift; my @files; local $_; find( sub { push @files, $File::Find::name if &$func }, @_ ); return @files; } # From List::MoreUtils sub first_index (&@) { my $f = shift; for my $i ( 0 .. $#_ ) { local *_ = \$_[$i]; return $i if $f->(); } return -1; } sub is_absolute { my ($path) = @_; return substr( $path, 0, 1 ) eq '/'; } # Maintain compatibility with both JSON 1 and 2. Borrowed from Data::Serializer::JSON. # sub json_decode { my ($text) = @_; return JSON->VERSION < 2 ? JSON->new->jsonToObj($text) : JSON->new->decode($text); } sub json_encode { my ($data) = @_; return JSON->VERSION < 2 ? JSON->new->objToJson($data) : JSON->new->utf8->encode($data); } sub mason_canon_path { # Like File::Spec::canonpath but with a few fixes. # my $path = shift; $path =~ s|/+|/|g; # xx////yy -> xx/yy $path =~ s|(?:/\.)+/|/|g; # xx/././yy -> xx/yy { $path =~ s|^(?:\./)+||s unless $path eq "./"; # ./xx -> xx $path =~ s|^/(?:\.\./)+|/|s; # /../../xx -> xx $path =~ s|/\Z(?!\n)|| unless $path eq "/"; # xx/ -> xx $path =~ s|/[^/]+/\.\.$|| && redo; # /xx/.. -> / $path =~ s|[^/]+/\.\./|| && redo; # /xx/../yy -> /yy } return $path; } sub read_file { my ($file) = @_; # Fast slurp, adapted from File::Slurp::read, with unnecessary options removed # my $buf = ""; my $read_fh; unless ( sysopen( $read_fh, $file, $Fetch_Flags ) ) { croak "read_file '$file' - sysopen: $!"; } my $size_left = -s $read_fh; while (1) { my $read_cnt = sysread( $read_fh, $buf, $size_left, length $buf ); if ( defined $read_cnt ) { last if $read_cnt == 0; $size_left -= $read_cnt; last if $size_left <= 0; } else { croak "read_file '$file' - sysread: $!"; } } return $buf; } sub taint_is_on { return ${^TAINT} ? 1 : 0; } sub touch_file { my ($file) = @_; if ( -f $file ) { my $time = time; utime( $time, $time, $file ); } else { write_file( $file, "" ); } } sub trim { my ($str) = @_; if ( defined($str) ) { for ($str) { s/^\s+//; s/\s+$// } } return $str; } # From List::MoreUtils sub uniq (@) { my %h; map { $h{$_}++ == 0 ? $_ : () } @_; } sub write_file { my ( $file, $data, $file_create_mode ) = @_; ($file) = $file =~ /^(.*)/s if taint_is_on(); # Untaint blindly $file_create_mode = oct(666) if !defined($file_create_mode); # Fast spew, adapted from File::Slurp::write, with unnecessary options removed # { my $write_fh; unless ( sysopen( $write_fh, $file, $Store_Flags, $file_create_mode ) ) { croak "write_file '$file' - sysopen: $!"; } my $size_left = length($data); my $offset = 0; do { my $write_cnt = syswrite( $write_fh, $data, $size_left, $offset ); unless ( defined $write_cnt ) { croak "write_file '$file' - syswrite: $!"; } $size_left -= $write_cnt; $offset += $write_cnt; } while ( $size_left > 0 ); truncate( $write_fh, sysseek( $write_fh, 0, SEEK_CUR ) ) } } 1; Mason-2.21/lib/Mason/Test/PaxHeader/Class.pm000644 777777 777777 00000000212 12266570730 020716 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365445 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/Class.pm000644 €ˆž«€q{Ì00000014464 12266570730 017711 0ustar00jonswart000000 000000 package Mason::Test::Class; { $Mason::Test::Class::VERSION = '2.21'; } use Carp; use File::Basename; use File::Path; use File::Temp qw(tempdir); use Mason; use Mason::Util qw(trim write_file); use Method::Signatures::Simple; use Test::Class::Most; use Test::LongString; use Class::Load; use strict; use warnings; __PACKAGE__->SKIP_CLASS("abstract base class"); # RO accessors sub comp_root { $_[0]->{comp_root} } sub data_dir { $_[0]->{data_dir} } sub interp { $_[0]->{interp} } sub temp_dir { $_[0]->{temp_dir} } sub temp_root { $_[0]->{temp_root} } # RW class accessors my $default_plugins = []; sub default_plugins { $default_plugins = $_[1] if defined( $_[1] ); $default_plugins; } my $gen_path_count = 0; my $parse_count = 0; my $temp_dir_count = 0; our $current_test_object; sub _startup : Test(startup) { my $self = shift; my $verbose = $ENV{TEST_VERBOSE}; $self->{temp_root} = tempdir( 'mason-test-XXXX', TMPDIR => 1, CLEANUP => $verbose ? 0 : 1 ); printf STDERR ( "\n*** temp_root = %s, no cleanup\n", $self->{temp_root} ) if $verbose; $self->setup_dirs; } method setup_dirs () { $self->{temp_dir} = join( "/", $self->{temp_root}, $temp_dir_count++ ); $self->{comp_root} = $self->{temp_dir} . "/comps"; $self->{data_dir} = $self->{temp_dir} . "/data"; mkpath( [ $self->{comp_root}, $self->{data_dir} ], 0, 0775 ); $self->setup_interp(@_); } method setup_interp () { $self->{interp} = $self->create_interp(@_); } method create_interp () { my (%params) = @_; $params{plugins} = $default_plugins if @$default_plugins; my $mason_root_class = delete( $params{mason_root_class} ) || 'Mason'; Class::Load::load_class($mason_root_class); rmtree( $self->data_dir ); return $mason_root_class->new( comp_root => $self->comp_root, data_dir => $self->data_dir, %params, ); } method add_comp (%params) { $self->_validate_keys( \%params, qw(path src v verbose) ); my $path = $params{path} || die "must pass path"; my $source = $params{src} || " "; my $verbose = $params{v} || $params{verbose}; die "'$path' is not absolute" unless substr( $path, 0, 1 ) eq '/'; my $source_file = $self->comp_root . $path; $self->mkpath_and_write_file( $source_file, $source ); if ($verbose) { print STDERR "*** $path ***\n"; my $output = $self->interp->_compile( $source_file, $path ); print STDERR "$output\n"; } } method remove_comp (%params) { my $path = $params{path} || die "must pass path"; my $source_file = join( "/", $self->comp_root, $path ); unlink($source_file); } method _gen_comp_path () { my $caller = ( caller(2) )[3]; my ($caller_base) = ( $caller =~ /([^:]+)$/ ); my $path = "/$caller_base" . ( ++$gen_path_count ) . ".mc"; return $path; } method test_comp (%params) { my $path = $params{path} || $self->_gen_comp_path; my $source = $params{src} || " "; my $verbose = $params{v} || $params{verbose}; $self->add_comp( path => $path, src => $source, verbose => $verbose ); delete( $params{src} ); $self->test_existing_comp( %params, path => $path ); } method test_existing_comp (%params) { $self->_validate_keys( \%params, qw(args desc expect expect_data expect_error path v verbose) ); my $path = $params{path} or die "must pass path"; my $caller = ( caller(1) )[3]; my $desc = $params{desc} || $path; my $expect = trim( $params{expect} ); my $expect_error = $params{expect_error}; my $expect_data = $params{expect_data}; my $verbose = $params{v} || $params{verbose}; my $args = $params{args} || {}; ( my $request_path = $path ) =~ s/\.m[cpi]$//; my @run_params = ( $request_path, %$args ); local $current_test_object = $self; if ( defined($expect_error) ) { $desc ||= $expect_error; throws_ok( sub { $self->interp->run(@run_params) }, $expect_error, $desc ); } if ( defined($expect) ) { $desc ||= $caller; my $output = trim( $self->interp->run(@run_params)->output ); if ( ref($expect) eq 'Regexp' ) { like( $output, $expect, $desc ); } else { is( $output, $expect, $desc ); } } if ( defined($expect_data) ) { $desc ||= $caller; cmp_deeply( $self->interp->run(@run_params)->data, $expect_data, $desc ); } } method run_test_in_comp (%params) { my $test = delete( $params{test} ) || die "must pass test"; my $args = delete( $params{args} ) || {}; $params{path} ||= $self->_gen_comp_path; $self->add_comp( %params, src => '% $.args->{_test}->($self);' ); ( my $request_path = $params{path} ) =~ s/\.m[cpi]$//; my @run_params = ( $request_path, %$args ); $self->interp->run( @run_params, _test => $test ); } method test_parse (%params) { my $caller = ( caller(1) )[3]; my ($caller_base) = ( $caller =~ /([^:]+)$/ ); my $desc = $params{desc}; my $source = $params{src} || croak "must pass src"; my $expect_list = $params{expect}; my $expect_error = $params{expect_error}; croak "must pass either expect or expect_error" unless $expect_list || $expect_error; my $path = "/parse/comp" . $parse_count++; my $file = $self->temp_dir . $path; $self->mkpath_and_write_file( $file, $source ); if ($expect_error) { $desc ||= $expect_error; throws_ok( sub { $self->interp->_compile( $file, $path ) }, $expect_error, $desc ); } else { $desc ||= $caller; my $output = $self->interp->_compile( $file, $path ); foreach my $expect (@$expect_list) { if ( ref($expect) eq 'Regexp' ) { like_string( $output, $expect, "$desc - $expect" ); } else { contains_string( $output, $expect, "$desc - $expect" ); } } } } method mkpath_and_write_file ($source_file, $source) { unlink($source_file) if -e $source_file; mkpath( dirname($source_file), 0, 0775 ); write_file( $source_file, $source ); } method _validate_keys ($params, @allowed_keys) { my %is_allowed = map { ( $_, 1 ) } @allowed_keys; if ( my @bad_keys = grep { !$is_allowed{$_} } keys(%$params) ) { croak "bad parameters: " . join( ", ", @bad_keys ); } } 1; Mason-2.21/lib/Mason/Test/PaxHeader/Overrides000775 777777 777777 00000000212 12266570730 021205 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365447 18 SCHILY.nlink=3 Mason-2.21/lib/Mason/Test/Overrides/000775 €ˆž«€q{Ì00000000000 12266570730 020241 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/Test/PaxHeader/Plugins000775 777777 777777 00000000212 12266570730 020664 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365450 18 SCHILY.nlink=4 Mason-2.21/lib/Mason/Test/Plugins/000775 €ˆž«€q{Ì00000000000 12266570730 017720 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/Test/PaxHeader/RootClass000775 777777 777777 00000000212 12266570730 021154 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365457 18 SCHILY.nlink=6 Mason-2.21/lib/Mason/Test/RootClass/000775 €ˆž«€q{Ì00000000000 12266570730 020210 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/Test/PaxHeader/RootClass.pm000644 777777 777777 00000000212 12266570730 021562 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365446 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/RootClass.pm000644 €ˆž«€q{Ì00000000203 12266570730 020537 0ustar00jonswart000000 000000 package Mason::Test::RootClass; { $Mason::Test::RootClass::VERSION = '2.21'; } use strict; use warnings; use base qw(Mason); 1; Mason-2.21/lib/Mason/Test/RootClass/PaxHeader/Compilation.pm000644 777777 777777 00000000212 12266570730 024040 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365458 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/RootClass/Compilation.pm000644 €ˆž«€q{Ì00000000466 12266570730 023030 0ustar00jonswart000000 000000 package Mason::Test::RootClass::Compilation; { $Mason::Test::RootClass::Compilation::VERSION = '2.21'; } use Moose; extends 'Mason::Compilation'; before 'parse' => sub { my ($self) = @_; print STDERR "starting compilation parse - " . $self->path . "\n"; }; __PACKAGE__->meta->make_immutable(); 1; Mason-2.21/lib/Mason/Test/RootClass/PaxHeader/Component.pm000644 777777 777777 00000000212 12266570730 023524 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365459 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/RootClass/Component.pm000644 €ˆž«€q{Ì00000000617 12266570730 022512 0ustar00jonswart000000 000000 package Mason::Test::RootClass::Component; { $Mason::Test::RootClass::Component::VERSION = '2.21'; } use Moose; extends 'Mason::Component'; # This doesn't work - it interrupts the inner() chain. Investigate later. # # before 'render' => sub { # my ($self) = @_; # print STDERR "starting component render - " . $self->cmeta->path . "\n"; # }; __PACKAGE__->meta->make_immutable(); 1; Mason-2.21/lib/Mason/Test/RootClass/PaxHeader/Interp.pm000644 777777 777777 00000000212 12266570730 023023 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365460 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/RootClass/Interp.pm000644 €ˆž«€q{Ì00000000363 12266570730 022007 0ustar00jonswart000000 000000 package Mason::Test::RootClass::Interp; { $Mason::Test::RootClass::Interp::VERSION = '2.21'; } use Moose; extends 'Mason::Interp'; before 'run' => sub { print STDERR "starting interp run\n"; }; __PACKAGE__->meta->make_immutable(); 1; Mason-2.21/lib/Mason/Test/RootClass/PaxHeader/Request.pm000644 777777 777777 00000000212 12266570730 023212 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365461 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/RootClass/Request.pm000644 €ˆž«€q{Ì00000000612 12266570730 022173 0ustar00jonswart000000 000000 package Mason::Test::RootClass::Request; { $Mason::Test::RootClass::Request::VERSION = '2.21'; } use Moose; extends 'Mason::Request'; before 'run' => sub { my ( $self, $path ) = @_; print STDERR "starting request run - $path\n"; }; before 'comp' => sub { my ( $self, $path ) = @_; print STDERR "starting request comp - $path\n"; }; __PACKAGE__->meta->make_immutable(); 1; Mason-2.21/lib/Mason/Test/Plugins/PaxHeader/Notify000775 777777 777777 00000000212 12266570730 022134 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365452 18 SCHILY.nlink=6 Mason-2.21/lib/Mason/Test/Plugins/Notify/000775 €ˆž«€q{Ì00000000000 12266570730 021170 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/Test/Plugins/PaxHeader/Notify.pm000644 777777 777777 00000000212 12266570730 022542 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365451 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/Plugins/Notify.pm000644 €ˆž«€q{Ì00000000227 12266570730 021525 0ustar00jonswart000000 000000 package Mason::Test::Plugins::Notify; { $Mason::Test::Plugins::Notify::VERSION = '2.21'; } use strict; use warnings; use base qw(Mason::Plugin); 1; Mason-2.21/lib/Mason/Test/Plugins/Notify/PaxHeader/Compilation.pm000644 777777 777777 00000000212 12266570730 025020 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365453 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/Plugins/Notify/Compilation.pm000644 €ˆž«€q{Ì00000000412 12266570730 023777 0ustar00jonswart000000 000000 package Mason::Test::Plugins::Notify::Compilation; { $Mason::Test::Plugins::Notify::Compilation::VERSION = '2.21'; } use Mason::PluginRole; before 'parse' => sub { my ($self) = @_; print STDERR "starting compilation parse - " . $self->path . "\n"; }; 1; Mason-2.21/lib/Mason/Test/Plugins/Notify/PaxHeader/Component.pm000644 777777 777777 00000000212 12266570730 024504 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365454 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/Plugins/Notify/Component.pm000644 €ˆž«€q{Ì00000000545 12266570730 023472 0ustar00jonswart000000 000000 package Mason::Test::Plugins::Notify::Component; { $Mason::Test::Plugins::Notify::Component::VERSION = '2.21'; } use Mason::PluginRole; # This doesn't work - it interrupts the inner() chain. Investigate later. # # before 'render' => sub { # my ($self) = @_; # print STDERR "starting component render - " . $self->cmeta->path . "\n"; # }; 1; Mason-2.21/lib/Mason/Test/Plugins/Notify/PaxHeader/Interp.pm000644 777777 777777 00000000212 12266570730 024003 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365455 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/Plugins/Notify/Interp.pm000644 €ˆž«€q{Ì00000000314 12266570730 022763 0ustar00jonswart000000 000000 package Mason::Test::Plugins::Notify::Interp; { $Mason::Test::Plugins::Notify::Interp::VERSION = '2.21'; } use Mason::PluginRole; before 'run' => sub { print STDERR "starting interp run\n"; }; 1; Mason-2.21/lib/Mason/Test/Plugins/Notify/PaxHeader/Request.pm000644 777777 777777 00000000212 12266570730 024172 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365456 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/Plugins/Notify/Request.pm000644 €ˆž«€q{Ì00000000542 12266570730 023155 0ustar00jonswart000000 000000 package Mason::Test::Plugins::Notify::Request; { $Mason::Test::Plugins::Notify::Request::VERSION = '2.21'; } use Mason::PluginRole; before 'run' => sub { my ( $self, $path ) = @_; print STDERR "starting request run - $path\n"; }; before 'comp' => sub { my ( $self, $path ) = @_; print STDERR "starting request comp - $path\n"; }; 1; Mason-2.21/lib/Mason/Test/Overrides/PaxHeader/Component000775 777777 777777 00000000212 12266570730 023147 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365448 18 SCHILY.nlink=3 Mason-2.21/lib/Mason/Test/Overrides/Component/000775 €ˆž«€q{Ì00000000000 12266570730 022203 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/Test/Overrides/Component/PaxHeader/StrictMoose.pm000644 777777 777777 00000000212 12266570730 026030 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365449 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Test/Overrides/Component/StrictMoose.pm000644 €ˆž«€q{Ì00000000753 12266570730 025017 0ustar00jonswart000000 000000 package Mason::Test::Overrides::Component::StrictMoose; { $Mason::Test::Overrides::Component::StrictMoose::VERSION = '2.21'; } use Moose::Exporter; use MooseX::StrictConstructor (); use strict; use warnings; use base qw(Mason::Component::Moose); use strict; use warnings; Moose::Exporter->setup_import_methods(); sub init_meta { my $class = shift; my %params = @_; $class->SUPER::init_meta(@_); MooseX::StrictConstructor->import( { into => $params{for_class} } ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Autobase.pm000644 777777 777777 00000000212 12266570730 020740 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365421 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Autobase.pm000644 €ˆž«€q{Ì00000013517 12266570730 017731 0ustar00jonswart000000 000000 package Mason::t::Autobase; { $Mason::t::Autobase::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_autobase : Tests { my $self = shift; my $interp = $self->interp; my $check_parent = sub { my ( $path, $parent ) = @_; my $base_comp_class = $interp->load($path) or die "could not load '$path'"; my $parent_comp_class = ( $parent =~ /\// ) ? $interp->load($parent) : $parent; cmp_deeply( [ $base_comp_class->meta->superclasses ], [$parent_comp_class], "parent of $path is $parent" ); }; my $add = sub { my ( $path, $extends ) = @_; $self->add_comp( path => $path, src => ( $extends ? "<%flags>\nextends => $extends\n" : " " ) ); }; my $remove = sub { my ($path) = @_; $self->remove_comp( path => $path, ); }; # Add components with no autobases, make sure they inherit from # Mason::Component # $add->('/comp.mc'); $add->('/foo/comp.mc'); $add->('/foo/bar/comp.mc'); $add->('/foo/bar/baz/comp.mc'); my $base_class = $self->interp->component_class; $check_parent->( '/comp.mc', $base_class ); $check_parent->( '/foo/comp.mc', $base_class ); $check_parent->( '/foo/bar/comp.mc', $base_class ); $check_parent->( '/foo/bar/baz/comp.mc', $base_class ); # Add autobases, test the parents of the components and autobases # $add->('/Base.mc'); $add->('/foo/Base.mc'); $add->('/foo/bar/baz/Base.mc'); $self->interp->_flush_load_cache(); $check_parent->( '/Base.mc', $base_class ); $check_parent->( '/foo/Base.mc', '/Base.mc' ); $check_parent->( '/foo/bar/baz/Base.mc', '/foo/Base.mc' ); $check_parent->( '/comp.mc', '/Base.mc' ); $check_parent->( '/foo/comp.mc', '/foo/Base.mc' ); $check_parent->( '/foo/bar/comp.mc', '/foo/Base.mc' ); $check_parent->( '/foo/bar/baz/comp.mc', '/foo/bar/baz/Base.mc' ); $add->( '/foo/bar/baz/none.mc', "undef" ); $check_parent->( '/foo/bar/baz/none.mc', $base_class ); $add->( '/foo/bar/baz/top.mc', "'/Base.mc'" ); $check_parent->( '/foo/bar/baz/top.mc', '/Base.mc' ); $add->( '/foo/bar/baz/top2.mc', "'../../Base.mc'" ); $check_parent->( '/foo/bar/baz/top2.mc', '/foo/Base.mc' ); # Multiple autobases same directory $add->('/Base.mp'); $add->('/foo/Base.mp'); $self->interp->_flush_load_cache(); $check_parent->( '/Base.mp', $base_class ); $check_parent->( '/Base.mc', '/Base.mp' ); $check_parent->( '/foo/Base.mp', '/Base.mc' ); $check_parent->( '/foo/Base.mc', '/foo/Base.mp' ); $check_parent->( '/foo/comp.mc', '/foo/Base.mc' ); # Remove most autobases, test parents again # $remove->('/Base.mp'); $remove->('/Base.mc'); $remove->('/foo/Base.mp'); $remove->('/foo/Base.mc'); $self->interp->_flush_load_cache(); $check_parent->( '/comp.mc', $base_class ); $check_parent->( '/foo/comp.mc', $base_class ); $check_parent->( '/foo/bar/comp.mc', $base_class ); $check_parent->( '/foo/bar/baz/comp.mc', '/foo/bar/baz/Base.mc' ); $check_parent->( '/foo/bar/baz/Base.mc', $base_class ); } sub test_cycles : Tests { my $self = shift; # An inheritance cycle # $self->add_comp( path => '/cycle/Base.mc', src => "<%flags>\nextends => '/cycle/c/index.mc'\n\n", ); $self->test_comp( path => '/cycle/c/index.mc', src => "ok", expect_error => qr/inheritance cycle/, ); # This isn't a cycle but a bug that tried to preload default parent was causing # it to infinite loop # $self->add_comp( path => '/pseudo/Base.mc', src => "<%flags>\nextends => '/pseudo/c/index.mc'\n\n", ); $self->test_comp( path => '/pseudo/c/index.mc', src => "<%flags>\nextends => undef\n\nok", expect => 'ok', ); } sub test_wrapping : Tests { my $self = shift; $self->add_comp( path => '/wrap/Base.mc', src => ' <%augment wrap> % inner(); ' ); $self->add_comp( path => '/wrap/subdir/Base.mc', src => ' <%method hello> Hello world ' ); $self->add_comp( path => '/wrap/subdir/subdir2/Base.mc', src => ' <%augment wrap> % inner(); ' ); $self->test_comp( path => '/wrap/subdir/subdir2/wrap_me.mc', src => '<% $self->hello %>', expect => ' Hello world ' ); $self->test_comp( path => '/wrap/subdir/subdir2/dont_wrap_me.mc', src => ' <%class>method wrap { $.main() } <% $self->hello() %> ', expect => 'Hello world' ); $self->test_comp( path => '/wrap/subdir/subdir2/dont_wrap_me_either.mc', src => ' <%class>CLASS->no_wrap; <% $self->hello() %> ', expect => 'Hello world' ); } # not yet implemented sub _test_no_main_in_autobase { my $self = shift; $self->test_comp( path => '/wrap/Base.mc', src => ' % inner(); ', expect_error => qr/content found in main body of autobase/, ); } sub test_recompute_inherit : Tests { my $self = shift; my $interp = $self->interp; # Test that /comp.mc class can be recomputed without garbage collection issues. # my $remove = sub { my ($path) = @_; $self->remove_comp( path => $path, ); }; $self->add_comp( path => '/comp.mc', src => ' ' ); $self->interp->load('/comp.mc'); $self->add_comp( path => '/Base.mc', src => ' ' ); $self->interp->_flush_load_cache(); $self->interp->load('/comp.mc'); ok(1); return; } 1; Mason-2.21/lib/Mason/t/PaxHeader/Cache.pm000644 777777 777777 00000000212 12266570730 020200 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365422 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Cache.pm000644 €ˆž«€q{Ì00000002761 12266570730 017170 0ustar00jonswart000000 000000 package Mason::t::Cache; { $Mason::t::Cache::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; __PACKAGE__->default_plugins( [ '@Default', 'Cache' ] ); sub test_cache_defaults : Tests { my $self = shift; $self->run_test_in_comp( path => '/cache/defaults.mc', test => sub { my $comp = shift; is( $comp->cache->label, 'File', 'cache->label' ); is( $comp->cache->namespace, $comp->cmeta->path, 'cache->namespace' ); } ); } sub test_cache_method : Tests { my $self = shift; $self->test_comp( path => '/cache.mc', src => ' <%class> has "count" => ( default => 0 ); <%method getset ($key)> <%perl>$.count($.count+1); <% $.cache->compute($key, sub { $key . $.count }) %> namespace: <% $.cache->namespace %> <% $.getset("foo") %> <% $.getset("bar") %> <% $.getset("bar") %> <% $.getset("foo") %> ', expect => ' namespace: /cache.mc foo1 bar2 bar2 foo1 ', ); } sub test_cache_filter : Tests { my $self = shift; $self->test_comp( src => ' % my $i = 1; % foreach my $key (qw(foo bar)) { % $.Repeat(3), $.Cache($key) {{ i = <% $i++ %> % }} % } ', expect => ' i = 1 i = 1 i = 1 i = 2 i = 2 i = 2 ', ); $self->test_comp( src => ' % my $i = 1; % foreach my $key (qw(foo foo)) { % $.Cache($key), $.Repeat(3) {{ i = <% $i++ %> % }} % } ', expect => ' i = 1 i = 2 i = 3 i = 1 i = 2 i = 3 ' ); } Mason-2.21/lib/Mason/t/PaxHeader/CompCalls.pm000644 777777 777777 00000000212 12266570730 021052 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365423 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/CompCalls.pm000644 €ˆž«€q{Ì00000002541 12266570730 020036 0ustar00jonswart000000 000000 package Mason::t::CompCalls; { $Mason::t::CompCalls::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_ampersand : Tests { my $self = shift; $self->add_comp( path => '/support/amper_test.mi', src => <<'EOF', amper_test.

% if (%{$self->args}) { Arguments:

% foreach my $key (sort keys %{$self->args}) { <% $key %>: <% $self->args->{$key} %>
% } % } EOF ); $self->test_comp( path => '/support/amper_call.mc', src => <<'EOF', <&/support/amper_test.mi&> <& amper_test.mi &> <& amper_test.mi, &> <& /support/amper_test.mi &> <& amper_test.mi &> <& /support/amper_test.mi &> EOF expect => <<'EOF', amper_test.

amper_test.

amper_test.

amper_test.

amper_test.

amper_test.

EOF ); $self->test_comp( src => <<'EOF', <& /support/amper_test.mi, message=>'Hello World!' &> <& support/amper_test.mi, message=>'Hello World!', to=>'Joe' &> <& "support/amper_test.mi" &> % my $dir = "support"; % my %args = (a=>17, b=>32); <& $dir . "/amper_test.mi", %args &> EOF expect => <<'EOF', amper_test.

Arguments:

message: Hello World!
amper_test.

Arguments:

message: Hello World!
to: Joe
amper_test.

amper_test.

Arguments:

a: 17
b: 32
EOF ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Compilation.pm000644 777777 777777 00000000212 12266570730 021453 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365424 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Compilation.pm000644 €ˆž«€q{Ì00000001720 12266570730 020435 0ustar00jonswart000000 000000 package Mason::t::Compilation; { $Mason::t::Compilation::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_pure_perl : Tests { my $self = shift; my $std = sub { my $num = shift; sprintf( 'method main () { my $foo = %s; print $foo; }', $num ) }; $self->add_comp( path => '/print1.pl', src => $std->(53) ); $self->test_comp( path => '/top1.mp', src => 'method main () { $m->comp("/print1.pl") }', expect => $std->(53), ); $self->setup_interp( pure_perl_extensions => ['.pl'] ); $self->add_comp( path => '/print2.pl', src => $std->(54) ); $self->test_comp( path => '/top2.mp', src => '<& print2.pl &>', expect => '54' ); $self->setup_interp( pure_perl_extensions => [] ); $self->add_comp( path => '/print3.pl', src => $std->(55) ); $self->test_comp( path => '/top3.mp', src => '<& print3.pl &>', expect => $std->(55), ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/ComponentMeta.pm000644 777777 777777 00000000212 12266570730 021746 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365425 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/ComponentMeta.pm000644 €ˆž«€q{Ì00000002064 12266570730 020732 0ustar00jonswart000000 000000 package Mason::t::ComponentMeta; { $Mason::t::ComponentMeta::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_cmeta : Tests { my $self = shift; $self->run_test_in_comp( path => '/component/meta.mc', args => { foo => 5, bar => [ 'baz', 7 ] }, test => sub { my $comp = shift; my $source_file = $self->comp_root . '/component/meta.mc'; foreach my $cmeta ( $comp->cmeta, ref($comp)->cmeta ) { is( $cmeta->path, '/component/meta.mc', 'path' ); is( $cmeta->dir_path, '/component', 'dir_path' ); is( $cmeta->is_top_level, 1, 'is_top_level' ); is( $cmeta->source_file, $source_file, 'source_file' ); like( $cmeta->object_file, qr|meta\.mc\.mobj|, 'object_file' ); } my $args = $comp->args; delete( $args->{_test} ); cmp_deeply( $args, { foo => 5, bar => [ 'baz', 7 ] } ); }, ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Defer.pm000644 777777 777777 00000000212 12266570730 020222 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365426 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Defer.pm000644 €ˆž«€q{Ì00000001107 12266570730 017203 0ustar00jonswart000000 000000 package Mason::t::Defer; { $Mason::t::Defer::VERSION = '2.21'; } use Test::More; use strict; use warnings; use base qw(Mason::Test::Class); sub test_defer : Test(1) { my $self = shift; $self->{interp} = $self->create_interp( plugins => [ '@Default', 'Defer' ] ); $self->test_comp( src => <<'EOF', <%class> my ($title, $subtitle); Title is <% $m->defer(sub { $title }) %> % $.Defer {{ Subtitle is <% $subtitle %> % }} <%perl> $title = 'foo'; $subtitle = 'bar'; EOF expect => <<'EOF', Title is foo Subtitle is bar EOF ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/DollarDot.pm000644 777777 777777 00000000212 12266570730 021061 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365427 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/DollarDot.pm000644 €ˆž«€q{Ì00000001400 12266570730 020036 0ustar00jonswart000000 000000 package Mason::t::DollarDot; { $Mason::t::DollarDot::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_dollardot : Tests { my $self = shift; $self->add_comp( path => '/helper.mi', src => '<%class>has "foo"; Helper: <% $.foo %> ', ); $self->test_comp( src => ' <%class> has "name" => ( default => "Joe" ); <%class> has "compname"; has "date"; <%method greet> Hello, <% $.name %>. Today is <% $.date %>. % $.greet(); <& $.compname, foo => $.date &> <& /helper.mi, foo => $.name &> <%init> $.date("March 5th"); $.compname("helper.mi"); ', expect => ' Hello, Joe. Today is March 5th. Helper: March 5th Helper: Joe ', ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Errors.pm000644 777777 777777 00000000212 12266570730 020451 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365428 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Errors.pm000644 €ˆž«€q{Ì00000007134 12266570730 017440 0ustar00jonswart000000 000000 package Mason::t::Errors; { $Mason::t::Errors::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_comp_errors : Tests { my $self = shift; my $try = sub { my ( $src, $expect_error, %extra ) = @_; $self->test_comp( src => $src, expect_error => $expect_error, desc => $expect_error, %extra ); }; my $root = $self->interp->comp_root->[0]; $try->( '<& /does/not/exist &>', qr/could not find component for path '\/does\/not\/exist' - component root is \Q[$root]\E/, ); $try->( '<%method>', qr/<%method> block requires a name/ ); $try->( '<%before>', qr/<%before> block requires a name/ ); $try->( '<%init>', qr/<%init> without matching <\/%init>/ ); $try->( '<%attr>', qr/unknown block '<%attr>'/ ); $try->( '<%blah>', qr/unknown block '<%blah>'/ ); $try->( '<%init foo>', qr/<%init> block does not take a name/ ); $try->( '<%', qr/'<%' without matching '%>'/ ); $try->( 'foo %>', qr/'%>' without matching '<%'/ ); $try->( '<& foo', qr/'<&' without matching '&>'/ ); $try->( 'foo &>', qr/'&>' without matching '<&'/ ); $try->( '%my $i = 1;', qr/% must be followed by whitespace/ ); $try->( "<%5\n\n%>", qr/whitespace required after '<%' at .* line 1/ ); $try->( "<%\n\n5%>", qr/whitespace required before '%>' at .* line 3/ ); $try->( "% \$.Upper {{\nHi", qr/'{{' without matching '}}'/ ); $try->( "Hi\n% }}", qr/'}}' without matching '{{'/ ); $try->( '<%method 1a>Hi', qr/Invalid method name '1a'/ ); $try->( '<%method cmeta>Hi', qr/'cmeta' is reserved.*method name/ ); $try->( "<%method a>Hi\n<%method a>Bye", qr/Duplicate definition of method 'a'/ ); $try->( "<%before 1a>Hi", qr/Invalid method modifier name '1a'/ ); $try->( "<%before a>Hi\n<%before a>Bye", qr/Duplicate definition of method modifier 'before a'/ ); $try->( '<%method b><%after main>Hi', qr/Cannot nest <%after> block inside <%method> block/ ); $try->( "% 'foobar' {{\nHi\n% }}\n", qr/'foobar' is neither a code ref/ ); $try->( "<%flags>\nfoo => 1\n", qr/Invalid flag 'foo'/ ); $try->( "<%flags>\nextends => 'blah'\n", qr/could not load '\/blah' for extends flag/ ); $try->( "<%flags>\nextends => %foo\n", qr/Global symbol/ ); $try->( '<% $foo %>', qr/Global symbol "\$foo" requires explicit package name/ ); $try->( 'die "blargh";', qr/blargh/, path => '/blargh.mp' ); # Error line numbers # $try->( "%\nb\n% die;", qr/Died at .* line 3/ ); $try->( "<%method foo>\n1\n2\n3\n\n% die;", qr/Died at .* line 6/ ); } sub test_bad_allow_globals : Tests { my $self = shift; throws_ok { $self->create_interp( allow_globals => ['@p'] ) } qr/only scalar globals supported/; throws_ok { $self->create_interp( allow_globals => ['i-'] ) } qr/not a valid/; } sub test_non_comp_errors : Tests { my $self = shift; throws_ok { $self->interp->_make_request()->current_comp_class } qr/cannot determine current_comp_class/; throws_ok { Mason->new() } qr/Attribute \(comp_root\) is required/; } 1; Mason-2.21/lib/Mason/t/PaxHeader/Filters.pm000644 777777 777777 00000000212 12266570730 020605 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365429 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Filters.pm000644 €ˆž«€q{Ì00000011756 12266570730 017601 0ustar00jonswart000000 000000 package Mason::t::Filters; { $Mason::t::Filters::VERSION = '2.21'; } use Test::Warn; use Test::Class::Most parent => 'Mason::Test::Class'; sub test_basic : Tests { my $self = shift; $self->test_comp( src => ' % sub { ucfirst(shift) } {{ <% "hello world?" %> % }} ', expect => ' Hello world? ', ); } sub test_filters : Tests { my $self = shift; $self->test_comp( src => ' <%class> method Upper () { sub { uc(shift) } } % $.Upper {{ # start Upper Hello World. % }} # end Upper % sub { ucfirst(shift) } {{ <% "hello world?" %> % }} % sub { tr/A-Z/a-z/; $_ } {{ Hello World! % }} ', expect => ' HELLO WORLD. Hello world? hello world! ', ); } sub test_filter_pipe : Tests { my $self = shift; $self->test_comp( src => ' <%class> method Upper () { sub { uc(shift) } } method Lower () { sub { lc(shift) } } method UpFirst () { sub { ucfirst(shift) } } <% "HELLO" | Lower %> <% "hello" | UpFirst %> <% "HELLO" | UpFirst,Lower %> <% "hello" | Lower, UpFirst %> <% "HeLlO" | Lower, Upper %> <% "HeLlO" | Upper, Lower %> ', expect => ' hello Hello Hello hello hello HELLO ', ); } sub test_filter_block : Tests { my $self = shift; $self->test_comp( src => ' <%filter MyRepeat ($count)> % for (my $i=0; $i<$count; $i++) { * <% $yield->() %>\ % } % my $count = 0; % $.MyRepeat(3) {{ count = <% ++$count %> % }} <%perl> my $content = $m->filter($.MyRepeat(2), sub { "count == " . ++$count . "\n" }); print(uc($content)); ', expect => ' * count = 1 * count = 2 * count = 3 * COUNT == 4 * COUNT == 5 ', ); } sub test_lexical : Tests { my $self = shift; $self->test_comp( src => <<'EOF', % my $msg = "Hello World"; % sub { lc(shift) } {{ <% $msg %> % }} EOF expect => 'hello world', ); } sub test_repeat : Tests { my $self = shift; $self->test_comp( src => <<'EOF', % my $i = 1; % $.Repeat(3) {{ i = <% $i++ %> % }} EOF expect => <<'EOF', i = 1 i = 2 i = 3 EOF ); } sub test_nested : Tests { my $self = shift; $self->test_comp( src => <<'EOF', % sub { ucfirst(shift) } {{ % sub { tr/e/a/; $_ } {{ % sub { lc(shift) } {{ HELLO % }} % }} % }} goodbye % sub { ucfirst(shift) }, sub { tr/e/a/; $_ }, sub { lc(shift) } {{ HELLO % }} goodbye EOF expect => <<'EOF', Hallo goodbye Hallo goodbye EOF ); } sub test_misc_standard_filters : Tests { my $self = shift; $self->test_comp( src => 'the <% $m->filter($.Trim, " quick brown ") %> fox', expect => 'the quick brown fox' ); $self->test_comp( src => ' % $.Capture(\my $buf) {{ 2 + 2 = <% 2+2 %> % }} <% reverse($buf) %> % $.Tee(\my $buf2) {{ 3 + 3 = <% 3+3 %> % }} <% reverse($buf2) %> --- % $.NoBlankLines {{ one two % }} --- ', expect => ' 4 = 2 + 2 3 + 3 = 6 6 = 3 + 3 --- one two --- ', ); } sub test_compcall_filter : Tests { my $self = shift; $self->add_comp( path => '/list_items.mi', src => ' <%class> has "items"; has "yield"; % foreach my $item (@{$.items}) { <% $.yield->($item) %> % } ', ); $self->test_comp( src => ' % $.CompCall ("list_items.mi", items => [1,2,3]) {{

  • <% $_[0] %>
  • % }} ', expect => '
  • 1
  • 2
  • 3
  • ', ); } sub test_around : Tests { my $self = shift; $self->test_comp( src => <<'EOF', hello <%around main> % sub { uc($_[0]) } {{ % $self->$orig(); % }} EOF expect => <<'EOF', HELLO EOF ); } # Test old filter syntax, still currently supported # sub test_old_syntax : Tests { my $self = shift; $self->test_comp( src => ' <%class> method Upper () { sub { uc(shift) } } <% $.Upper { %> Hello World. <% sub { ucfirst(shift) } { %> <% "hello world?" %> <% } %> <% sub { lc(shift) } { %> Hello World! ', expect => ' HELLO WORLD. Hello world? hello world! ', ); } sub test_filter_comment : Tests { my $self = shift; $self->test_comp( src => ' <%class> method LESSp () { sub { uc(shift) } } % $.LESSp {{ #header { text-align: left; } % }} #footer { text-align: right; } ', expect => ' #HEADER { TEXT-ALIGN: LEFT; } #footer { text-align: right; } ', ); } sub test_no_undef_warning : Tests { my $self = shift; warnings_are { $self->test_comp( src => ' <%class> method Upper () { sub { uc(shift) } } method Upper2 () { return Mason::DynamicFilter->new( filter => sub { my $yield = $_[0]; return uc($yield->()); } ); } <%filter Upper3> <% uc($yield->()) %> a = <% "a" | Upper %>. undef = <% undef | Upper %>. a = <% "a" | Upper2 %>. undef = <% undef | Upper2 %>. a = <% "a" | Upper3 %>. undef = <% undef | Upper3 %>. ', expect => ' a = A. undef = . a = A. undef = . a = A. undef = . ', ); } [], "no warnings on undef"; } 1; Mason-2.21/lib/Mason/t/PaxHeader/Globals.pm000644 777777 777777 00000000212 12266570730 020560 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365430 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Globals.pm000644 €ˆž«€q{Ì00000001425 12266570730 017544 0ustar00jonswart000000 000000 package Mason::t::Globals; { $Mason::t::Globals::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_globals : Tests { my $self = shift; $self->setup_interp( allow_globals => [qw(scalar $scalar2)] ); my $interp = $self->interp; $interp->set_global( 'scalar', 5 ); $interp->set_global( '$scalar2', 'vanilla' ); throws_ok { $interp->set_global( '$bad', 8 ) } qr/\$bad is not in the allowed globals list/; $self->add_comp( path => '/values', src => ' scalar = <% $scalar %> $scalar2 = <% $scalar2 %> ', ); $self->test_comp( src => ' <& /values &> % $scalar++; % $scalar2 .= "s"; <& /values &> ', expect => ' scalar = 5 $scalar2 = vanilla scalar = 6 $scalar2 = vanillas ', ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/HTMLFilters.pm000644 777777 777777 00000000212 12266570730 021272 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365431 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/HTMLFilters.pm000644 €ˆž«€q{Ì00000001443 12266570730 020256 0ustar00jonswart000000 000000 package Mason::t::HTMLFilters; { $Mason::t::HTMLFilters::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_html_filters : Tests { my $self = shift; $self->setup_interp( plugins => [ '@Default', 'HTMLFilters' ] ); $self->test_comp( src => '<% "" | HTML %>', expect => '<a>' ); $self->test_comp( src => '<% "/foo/bar?a=5" | URI %>', expect => '%2Ffoo%2Fbar%3Fa%3D5' ); $self->test_comp( src => '<% "First\n\nSecond\n\nThird\n\n" | HTMLPara %>', expect => "

    \nFirst\n

    \n\n

    \nSecond\n

    \n\n

    \nThird

    \n" ); $self->test_comp( src => '<% "First\n\nSecond\n\nThird\n\n" | NoBlankLines,HTMLPara %>', expect => "

    \nFirst\n

    \n

    \nSecond\n

    \n

    \nThird

    \n" ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Interp.pm000644 777777 777777 00000000212 12266570730 020436 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365432 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Interp.pm000644 €ˆž«€q{Ì00000011225 12266570730 017421 0ustar00jonswart000000 000000 package Mason::t::Interp; { $Mason::t::Interp::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; use Capture::Tiny qw(capture); { package MyInterp; { $MyInterp::VERSION = '2.21'; } use Moose; extends 'Mason::Interp'; __PACKAGE__->meta->make_immutable() } sub test_base_interp_class : Tests { my $self = shift; my $interp = $self->create_interp( base_interp_class => 'MyInterp' ); is( ref($interp), 'MyInterp' ); } sub test_find_paths : Tests { my $self = shift; my $r1 = $self->temp_dir . "/r1"; my $r2 = $self->temp_dir . "/r2"; my $interp = $self->create_interp( comp_root => [ $r1, $r2 ] ); my @files = ( "$r1/foo.mc", "$r1/foo/bar.mc", "$r2/foo/baz.mc", "$r1/foo/blarg.mc", "$r2/foo/blarg.mc" ); foreach my $file (@files) { $self->mkpath_and_write_file( $file, " " ); } cmp_set( [ $interp->all_paths("/") ], [qw(/foo.mc /foo/bar.mc /foo/baz.mc /foo/blarg.mc)], "all_paths(/)" ); cmp_set( [ $interp->all_paths() ], [qw(/foo.mc /foo/bar.mc /foo/baz.mc /foo/blarg.mc)], "all_paths(/)" ); cmp_set( [ $interp->all_paths("/foo") ], [qw(/foo/bar.mc /foo/baz.mc /foo/blarg.mc)], "all_paths(/foo)" ); cmp_set( [ $interp->all_paths("/bar") ], [], "all_paths(/bar)" ); cmp_set( [ $interp->glob_paths("/foo/ba*.mc") ], [qw(/foo/bar.mc /foo/baz.mc)], "glob_paths(/foo/ba*.mc)" ); cmp_set( [ $interp->glob_paths("/foo/bl*.mc") ], [qw(/foo/blarg.mc)], "glob_paths(/foo/bl*.mc)" ); cmp_set( [ $interp->glob_paths("/foo/d*") ], [], "glob_paths(/foo/d*)" ); } sub test_component_class_prefix : Tests { my $self = shift; my $check_prefix = sub { my $interp = shift; my $regex = "^" . $interp->component_class_prefix . "::"; like( $interp->load('/foo.mc'), qr/$regex/, "prefix at beginning of path" ); }; $self->add_comp( path => '/foo.mc', src => 'foo' ); my @interp = map { $self->create_interp() } ( 0 .. 1 ); ok( $interp[0]->component_class_prefix ne $interp[1]->component_class_prefix, "different prefixes" ); ok( $interp[0]->load('/foo.mc') ne $interp[1]->load('/foo.mc'), "different classnames" ); $check_prefix->( $interp[0] ); $check_prefix->( $interp[1] ); $interp[2] = $self->create_interp( component_class_prefix => 'Blah' ); is( $interp[2]->component_class_prefix, 'Blah', 'specified prefix' ); $check_prefix->( $interp[2] ); } sub test_no_data_dir : Tests { my $self = shift; my $interp = Mason->new( comp_root => $self->comp_root ); ok( -d $interp->data_dir ); } sub test_bad_param : Tests { my $self = shift; throws_ok { $self->create_interp( foo => 5 ) } qr/Found unknown attribute/; } sub test_comp_exists : Tests { my $self = shift; $self->add_comp( path => '/comp_exists/one.mc', src => 'hi' ); my $interp = $self->interp; ok( $interp->comp_exists('/comp_exists/one.mc') ); ok( !$interp->comp_exists('/comp_exists/two.mc') ); throws_ok { $interp->comp_exists('one.mc') } qr/not an absolute/; } sub test_out_method : Tests { my $self = shift; $self->add_comp( path => '/out_method/hi.mc', src => 'hi' ); my $buffer = ''; my $try = sub { my ( $out_method, $expect_result, $expect_buffer, $expect_stdout, $desc ) = @_; my ( $result, $stdout ); my @params = ( $out_method ? ( { out_method => $out_method } ) : () ); ($stdout) = capture { $result = $self->interp->run( @params, '/out_method/hi' ); }; is( $stdout, $expect_stdout, "stdout - $desc" ); is( $buffer, $expect_buffer, "buffer - $desc" ); is( $result->output, $expect_result, "result->output - $desc" ); }; $try->( undef, 'hi', '', '', 'undef' ); $try->( sub { print $_[0] }, '', '', 'hi', 'sub print' ); $try->( sub { $buffer .= uc( $_[0] ) }, '', 'HI', '', 'sub buffer .=' ); $try->( \$buffer, '', 'HIhi', '', '\$buffer' ); $buffer = ''; $self->setup_interp( out_method => sub { print scalar( reverse( $_[0] ) ) } ); $try->( undef, '', '', 'ih', 'print reverse' ); } sub test_no_source_line_numbers : Tests { my $self = shift; $self->test_parse( src => "hi\n<%init>my \$d = 0", expect => [qr/\#line/] ); $self->setup_interp( no_source_line_numbers => 1 ); $self->test_parse( src => "hi\n<%init>my \$d = 0", expect => [qr/^(?!(?s:.*)\#line)/] ); } sub test_class_header : Tests { my $self = shift; $self->setup_interp( class_header => '# header' ); $self->test_parse( src => "hi", expect => [qr/\# header/] ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/LvalueAttributes.pm000644 777777 777777 00000000212 12266570730 022474 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365433 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/LvalueAttributes.pm000644 €ˆž«€q{Ì00000001062 12266570730 021455 0ustar00jonswart000000 000000 package Mason::t::LvalueAttributes; { $Mason::t::LvalueAttributes::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; __PACKAGE__->default_plugins( [ '@Default', 'LvalueAttributes' ] ); sub test_lvalue : Tests { my $self = shift; $self->test_comp( src => ' <%class> has "a" => (is => "rw"); has "b" => (is => "ro"); <%init> $.a = 5; print "a = " . $.a . "\n"; $.a(6); print "a = " . $.a . "\n"; eval { $.b = 6 }; print $@ . "\n"; ', expect => qr/a = 5\na = 6\nCan't modify.*/, ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Plugins.pm000644 777777 777777 00000000212 12266570730 020616 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365434 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Plugins.pm000644 €ˆž«€q{Ì00000013667 12266570730 017615 0ustar00jonswart000000 000000 package Mason::t::Plugins; { $Mason::t::Plugins::VERSION = '2.21'; } ## no critic (Moose::RequireMakeImmutable) use Test::Class::Most parent => 'Mason::Test::Class'; use Capture::Tiny qw(capture_merged); use Mason::Util qw(dump_one_line); sub test_notify_plugin : Tests { my $self = shift; $self->setup_interp( plugins => ['+Mason::Test::Plugins::Notify'], no_source_line_numbers => 1, ); $self->add_comp( path => '/test_plugin_support.mi', src => 'hi' ); my $output = capture_merged { $self->test_comp( path => '/test_plugin.mc', src => '<& test_plugin_support.mi &>', expect => 'hi' ); }; my $like = sub { my $regex = shift; like( $output, $regex, $regex ) }; $like->(qr/starting interp run/); $like->(qr/starting request run - \/test_plugin/); $like->(qr/starting request comp - test_plugin_support.mi/); $like->(qr/starting compilation parse - \/test_plugin.mc/); } # Call Mason::Test::RootClass->new, then make base classes like # Mason::Test::RootClass::Interp are used automatically # sub test_notify_root_class : Tests { my $self = shift; my $mrc = 'Mason::Test::RootClass'; $self->setup_interp( mason_root_class => $mrc ); is( $self->interp->mason_root_class, $mrc, "mason_root_class" ); is( $self->interp->base_compilation_class, "${mrc}::Compilation", "base_compilation_class" ); is( $self->interp->base_component_class, "${mrc}::Component", "base_component_class" ); is( $self->interp->base_request_class, "${mrc}::Request", "base_request_class" ); is( $self->interp->base_result_class, "Mason::Result", "base_result_class" ); isa_ok( $self->interp, "${mrc}::Interp", "base_interp_class" ); $self->add_comp( path => '/test_plugin_support.mi', src => 'hi' ); my $output = capture_merged { $self->test_comp( path => '/test_plugin.mc', src => '<& test_plugin_support.mi &>', expect => 'hi' ); }; my $like = sub { my $regex = shift; like( $output, $regex, $regex ) }; $like->(qr/starting interp run/); $like->(qr/starting request run - \/test_plugin/); $like->(qr/starting request comp - test_plugin_support.mi/); $like->(qr/starting compilation parse - \/test_plugin.mc/); } sub test_strict_plugin : Tests { my $self = shift; $self->setup_interp( base_component_moose_class => 'Mason::Test::Overrides::Component::StrictMoose', ); $self->add_comp( path => '/test_strict_plugin.mc', src => 'hi' ); lives_ok { $self->interp->run('/test_strict_plugin') }; throws_ok { $self->interp->run( '/test_strict_plugin', foo => 5 ) } qr/Found unknown attribute/; } { package Mason::Test::Plugins::A; { $Mason::Test::Plugins::A::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; } { package Mason::Plugin::B; { $Mason::Plugin::B::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; } { package Mason::Plugin::C; { $Mason::Plugin::C::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; } { package Mason::Plugin::D; { $Mason::Plugin::D::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; } { package Mason::Plugin::E; { $Mason::Plugin::E::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; } { package Mason::PluginBundle::F; { $Mason::PluginBundle::F::VERSION = '2.21'; } use Moose; with 'Mason::PluginBundle'; sub requires_plugins { return qw(C D) } } { package Mason::Test::PluginBundle::G; { $Mason::Test::PluginBundle::G::VERSION = '2.21'; } use Moose; with 'Mason::PluginBundle'; sub requires_plugins { return qw(C E) } } { package Mason::Plugin::H; { $Mason::Plugin::H::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; sub requires_plugins { return qw(@F) } } { package Mason::PluginBundle::I; { $Mason::PluginBundle::I::VERSION = '2.21'; } use Moose; with 'Mason::PluginBundle'; sub requires_plugins { return ( '+Mason::Test::Plugins::A', 'B', '@F', '+Mason::Test::PluginBundle::G', ); } } { package Mason::PluginBundle::J; { $Mason::PluginBundle::J::VERSION = '2.21'; } use Moose; with 'Mason::PluginBundle'; sub requires_plugins { return ('@I'); } } sub test_plugin_specs : Tests { my $self = shift; require Mason::PluginBundle::Default; my @default_plugins = Mason::PluginBundle::Default->requires_plugins or die "no default plugins"; my $test = sub { my ( $plugin_list, $expected_plugins ) = @_; my $interp = Mason->new( comp_root => $self->comp_root, plugins => $plugin_list ); my $got_plugins = [ map { /Mason::Plugin::/ ? substr( $_, 15 ) : $_ } @{ $interp->plugins } ]; cmp_deeply( $got_plugins, [ @$expected_plugins, @default_plugins ], dump_one_line($plugin_list) ); }; $test->( [], [] ); $test->( ['E'], ['E'] ); $test->( ['H'], [ 'H', 'C', 'D' ] ); $test->( ['@F'], [ 'C', 'D' ] ); $test->( ['@I'], [ 'Mason::Test::Plugins::A', 'B', 'C', 'D', 'E' ] ); $test->( [ '-C', '@I', '-+Mason::Test::Plugins::A' ], [ 'B', 'D', 'E' ] ); $test->( [ '-@I', '@J' ], [] ); throws_ok { $test->( ['@X'] ) } qr/could not load 'Mason::PluginBundle::X'/; throws_ok { $test->( ['Y'] ) } qr/could not load 'Mason::Plugin::Y'/; } { package Mason::Test::Plugins::Upper; { $Mason::Test::Plugins::Upper::VERSION = '2.21'; } use Moose; with 'Mason::Plugin' } { package Mason::Test::Plugins::Upper::Request; { $Mason::Test::Plugins::Upper::Request::VERSION = '2.21'; } use Mason::PluginRole; after 'process_output' => sub { my ( $self, $bufref ) = @_; $$bufref = uc($$bufref); }; } sub test_process_output_plugin : Tests { my $self = shift; $self->setup_interp( plugins => ['+Mason::Test::Plugins::Upper'] ); $self->test_comp( src => 'Hello', expect => 'HELLO' ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Reload.pm000644 777777 777777 00000000212 12266570730 020403 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365435 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Reload.pm000644 €ˆž«€q{Ì00000006554 12266570730 017377 0ustar00jonswart000000 000000 package Mason::t::Reload; { $Mason::t::Reload::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_reload : Tests { my $self = shift; my $class; $self->add_comp( path => "/reload.mc", src => <<'EOF', <%class> sub foo { 'foo' } sub baz { 'baz1' } Foo EOF ); is( $self->interp->run("/reload")->output, "Foo\n", "before reload" ); $class = $self->interp->load("/reload.mc"); is( $class->foo(), 'foo', "method foo" ); is( $class->baz(), 'baz1', "method baz" ); ok( $class->can('foo'), "can call foo before reload" ); ok( !$class->can('bar'), "cannot call bar before reload" ); ok( $class->can('baz'), "can call baz before reload" ); sleep(1); # so timestamp will be different $self->add_comp( path => "/reload.mc", src => <<'EOF', <%class> sub bar { 'bar' } sub baz { 'baz2' } Bar EOF ); is( $self->interp->run("/reload")->output, "Bar\n", "after reload" ); is( $class->bar(), 'bar', "method bar" ); is( $class->baz(), 'baz2', "method baz" ); ok( $class->can('bar'), "can call bar after reload" ); ok( !$class->can('foo'), "cannot call foo after reload" ); ok( $class->can('baz'), "can call baz after reload" ); } sub test_reload_parent : Tests { my $self = shift; my $interp = $self->interp; $self->add_comp( path => '/foo/bar/baz.mc', src => '<% $.num1 %> <% $.num2 %>' ); $self->add_comp( path => '/foo/Base.mc', src => '<%class>method num1 { 5 }' ); $self->add_comp( path => '/Base.mc', src => '<%class>method num2 { 6 }' ); $self->test_existing_comp( path => '/foo/bar/baz.mc', expect => '5 6' ); $self->interp->_flush_load_cache(); sleep(1); $self->add_comp( path => '/foo/Base.mc', src => "<%class>method num1 { 7 }" ); $self->add_comp( path => '/Base.mc', src => "<%class>method num2 { 8 }" ); $self->test_existing_comp( path => '/foo/bar/baz.mc', expect => '7 8' ); $self->interp->_flush_load_cache(); sleep(1); $self->add_comp( path => '/Base.mc', src => "<%class>method num1 { 10 }\nmethod num2 { 11 }\n" ); $self->test_existing_comp( path => '/foo/bar/baz.mc', expect => '7 11' ); $self->interp->_flush_load_cache(); sleep(1); $self->remove_comp( path => '/foo/Base.mc' ); $self->test_existing_comp( path => '/foo/bar/baz.mc', expect => '10 11' ); $self->interp->_flush_load_cache(); sleep(1); $self->remove_comp( path => '/foo/Base.mc' ); $self->add_comp( path => '/foo/bar/baz.mc', src => 'hi' ); $self->add_comp( path => '/Base.mp', src => 'method wrap { print "wrap1" }' ); $self->test_existing_comp( path => '/foo/bar/baz.mc', expect => 'wrap1' ); $self->interp->_flush_load_cache(); sleep(1); $self->add_comp( path => '/Base.mp', src => 'method wrap { print "wrap2" }' ); $self->test_existing_comp( path => '/foo/bar/baz.mc', expect => 'wrap2' ); } sub test_no_unnecessary_reload : Tests { my $self = shift; my $interp = $self->interp; $self->add_comp( path => '/foo.mc', src => ' ' ); my $id1 = $interp->load('/foo.mc')->cmeta->id; $self->interp->_flush_load_cache(); my $id2 = $interp->load('/foo.mc')->cmeta->id; ok( $id1 == $id2 ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Request.pm000644 777777 777777 00000000212 12266570730 020625 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365436 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Request.pm000644 €ˆž«€q{Ì00000013142 12266570730 017610 0ustar00jonswart000000 000000 package Mason::t::Request; { $Mason::t::Request::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; use Log::Any::Test; use Log::Any qw($log); sub _get_current_comp_class { my $m = shift; return $m->current_comp_class; } sub test_add_cleanup : Tests { my $self = shift; my $foo = 1; $self->test_comp( src => ' % my $ref = $.args->{ref}; % $m->add_cleanup(sub { $$ref++ }); foo = <% $$ref %> ', args => { ref => \$foo }, expect => 'foo = 1' ); is( $foo, 2, "foo now 2" ); } sub test_capture : Tests { my $self = shift; $self->run_test_in_comp( test => sub { my $comp = shift; my $m = $comp->m; is( $m->capture( sub { print "abcde" } ), 'abcde' ); } ); } sub test_comp_exists : Tests { my $self = shift; $self->add_comp( path => '/comp_exists/one.mc', src => 'hi' ); $self->test_comp( path => '/comp_exists/two.mc', src => ' % foreach my $path (qw(/comp_exists/one.mc /comp_exists/two.mc /comp_exists/three.mc one.mc two.mc three.mc)) { <% $path %>: <% $m->comp_exists($path) ? "yes" : "no" %> % } ', expect => ' /comp_exists/one.mc: yes /comp_exists/two.mc: yes /comp_exists/three.mc: no one.mc: yes two.mc: yes three.mc: no ', ); } sub test_current_comp_class : Tests { shift->test_comp( path => '/current_comp_class.mc', src => '<% ' . __PACKAGE__ . '::_get_current_comp_class($m)->cmeta->path %>', expect => '/current_comp_class.mc' ); } sub test_id : Tests { my $self = shift; $self->setup_dirs; $self->add_comp( path => '/id.mc', src => 'id=<% $m->id %>' ); my ($id1) = ( $self->interp->run('/id')->output =~ /id=(\d+)/ ); my ($id2) = ( $self->interp->run('/id')->output =~ /id=(\d+)/ ); ok( $id1 != $id2 ); } sub test_log : Tests { my $self = shift; $self->add_comp( path => '/log/one.mc', src => '% $m->log->info("message one")' ); $self->run_test_in_comp( path => '/log.mc', test => sub { my $comp = shift; my $m = $comp->m; $m->comp('/log/one.mc'); $log->contains_ok("message one"); }, ); } sub test_notes : Tests { my $self = shift; $self->add_comp( path => '/show', src => ' <% $m->notes("foo") %> % $m->notes("foo", 3); ', ); $self->test_comp( src => ' % $m->notes("foo", 2); <% $m->notes("foo") %> <& /show &> <% $m->notes("foo") %> ', expect => "2\n\n2\n\n3\n", ); } sub test_page : Tests { my $self = shift; $self->add_comp( path => '/page/other.mi', src => '<% $m->page->cmeta->path %>' ); $self->test_comp( path => '/page/first.mc', src => '<% $m->page->cmeta->path %>; <& other.mi &>', expect => '/page/first.mc; /page/first.mc' ); } sub test_result_data : Tests { my $self = shift; $self->test_comp( src => '% $m->result->data->{color} = "red"', expect_data => { color => "red" } ); } sub test_scomp : Tests { my $self = shift; $self->add_comp( path => '/str', src => 'abcde' ); $self->run_test_in_comp( test => sub { my $comp = shift; my $m = $comp->m; is( $m->scomp('/str'), 'abcde' ); is( $m->capture( sub { $m->scomp('/str') } ), '' ); } ); } sub test_go : Tests { my $self = shift; my ( $buf, $result ); reset_id(); $self->add_comp( path => '/subreq/other.mc', src => ' id=<% $m->id %> <% $m->page->cmeta->path %> <% $m->request_path %> args: <% Mason::Util::dump_one_line($m->request_args) %> ', ); $self->test_comp( path => '/subreq/go.mc', src => ' This should not get printed. <%perl>$m->go("/subreq/other", foo => 5);', expect => ' id=1 /subreq/other.mc /subreq/other args: {foo => 5} ', ); reset_id(); $self->test_comp( path => '/subreq/go_with_req_params.mc', src => ' This should not get printed. <%perl>my $buf; $m->go({out_method => \$buf}, "/subreq/other", foo => 5)', expect => '', ); reset_id(); $result = $self->interp->run( { out_method => \$buf }, '/subreq/go' ); is( $result->output, '', 'no output' ); is( $buf, ' id=1 /subreq/other.mc /subreq/other args: {foo => 5} ', 'output in buf' ); } sub test_visit : Tests { my $self = shift; my ( $buf, $result ); reset_id(); $self->add_comp( path => '/subreq/other.mc', src => ' id=<% $m->id %> <% $m->page->cmeta->path %> <% $m->request_path %> args: <% Mason::Util::dump_one_line($m->request_args) %> ', ); $self->test_comp( path => '/subreq/visit.mc', src => ' begin id=<% $m->id %> <%perl>$m->visit("/subreq/other", foo => 5); id=<% $m->id %> end ', expect => ' begin id=0 id=1 /subreq/other.mc /subreq/other args: {foo => 5} id=0 end ', ); reset_id(); $self->test_comp( path => '/subreq/visit_with_req_params.mc', src => ' begin id=<% $m->id %> <%perl>my $buf; $m->visit({out_method => \$buf}, "/subreq/other", foo => 5); print uc($buf); id=<% $m->id %> end ', expect => ' begin id=0 ID=1 /SUBREQ/OTHER.MC /SUBREQ/OTHER ARGS: {FOO => 5} id=0 end ', ); reset_id(); $result = $self->interp->run( { out_method => \$buf }, '/subreq/visit' ); is( $result->output, '', 'no output' ); is( $buf, ' begin id=0 id=1 /subreq/other.mc /subreq/other args: {foo => 5} id=0 end ', 'visit with initial out_method' ); } sub reset_id { Mason::Request->_reset_next_id; } 1; Mason-2.21/lib/Mason/t/PaxHeader/ResolveURI.pm000644 777777 777777 00000000212 12266570730 021174 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365437 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/ResolveURI.pm000644 €ˆž«€q{Ì00000016510 12266570730 020161 0ustar00jonswart000000 000000 package Mason::t::ResolveURI; { $Mason::t::ResolveURI::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_resolve : Tests { my $self = shift; my @interp_params = (); my $try = sub { my ( $run_path, $existing_paths, $resolve_path, $path_info ) = @_; $path_info ||= ''; $self->setup_dirs(@interp_params); foreach my $existing_path (@$existing_paths) { my $allow_path_info = 0; if ( $existing_path =~ /=1$/ ) { substr( $existing_path, -2, 2 ) = ''; $allow_path_info = 1; } $self->add_comp( path => $existing_path, src => join( "", ( $allow_path_info ? "<%class>method allow_path_info { 1 }\n" : "" ), "path: <% \$self->cmeta->path %>; path_info: <% \$m->path_info %>" ) ); } my $desc = sprintf( "run %s against %s", $run_path, join( ",", @$existing_paths ) ); if ( defined($resolve_path) ) { my $good = "path: $resolve_path; path_info: $path_info"; is( $self->interp->run($run_path)->output, $good, "$desc = matched $good" ); } else { throws_ok { $self->interp->run($run_path)->output } qr/could not resolve request path/, "$desc = failed to match"; } }; my $run_path = '/foo/bar/baz'; $try->( $run_path, ['/foo/bar/baz.mc'], '/foo/bar/baz.mc', '' ); $try->( $run_path, ['/foo/bar/baz/dhandler.mc'], '/foo/bar/baz/dhandler.mc', '' ); $try->( $run_path, ['/foo/bar/baz/index.mc'], '/foo/bar/baz/index.mc', '' ); $try->( $run_path, ['/foo/bar.mc=1'], '/foo/bar.mc', 'baz' ); $try->( $run_path, ['/foo/bar/dhandler.mc'], '/foo/bar/dhandler.mc', 'baz' ); $try->( $run_path, ['/foo.mc=1'], '/foo.mc', 'bar/baz' ); $try->( $run_path, ['/foo/dhandler.mc'], '/foo/dhandler.mc', 'bar/baz' ); $try->( $run_path, ['/dhandler.mc'], '/dhandler.mc', 'foo/bar/baz' ); $try->( $run_path, [ '/dhandler.mc', '/foo/dhandler.mc' ], '/foo/dhandler.mc', 'bar/baz' ); $try->( $run_path, [ '/foo/dhandler.mc', '/foo/bar.mc=1' ], '/foo/bar.mc', 'baz' ); $try->( $run_path, [ '/foo/dhandler.mc', '/foo/bar.mc' ], '/foo/dhandler.mc', 'bar/baz' ); # Not found $try->( $run_path, ['/foo/bar.mc'], undef ); $try->( $run_path, ['/foo.mc'], undef ); $try->( $run_path, ['/foo/bar/baz/blarg.mc'], undef ); $try->( $run_path, ['/foo/bar/baz/blarg/dhandler.mc'], undef ); $try->( $run_path, ['/foo/bar/baz'], undef ); $try->( $run_path, ['/foo/dhandler'], undef ); $try->( $run_path, ['/foo/bar/index.mc'], undef ); $try->( $run_path, ['/foo/blarg.mc'], undef ); $try->( $run_path, ['/foo/blarg/dhandler.mc'], undef ); # Can't access autobase or dhandler directly, but can access index $try->( '/foo/Base', ['/foo/Base.mc'], undef ); $try->( '/foo/dhandler', ['/foo/dhandler.mc'], '/foo/dhandler.mc', 'dhandler' ); $try->( '/foo/index', ['/foo/index.mc'], '/foo/index.mc' ); # no autoextend_run_path @interp_params = ( autoextend_request_path => 0, top_level_extensions => ['.html'] ); $try->( '/foo/bar/baz.html', ['/foo/bar/baz.html'], '/foo/bar/baz.html', '' ); $try->( '/foo/bar/baz.html', ['/foo/bar/baz.html.mc'], undef ); $try->( "/foo.mc/bar.mi", ['/foo.mc/bar.mi'], undef ); @interp_params = ( autoextend_request_path => 0, top_level_extensions => [] ); $try->( '/foo/bar/baz.html', ['/foo/bar/baz.html'], '/foo/bar/baz.html', '' ); $try->( "/foo.mc/bar.mi", ['/foo.mc/bar.mi'], '/foo.mc/bar.mi', '' ); # dhandler_names @interp_params = ( dhandler_names => ['dhandler'] ); $try->( $run_path, ['/foo/bar/baz/dhandler.mc'], undef ); $try->( $run_path, ['/foo/bar/baz/dhandler'], '/foo/bar/baz/dhandler', '' ); $try->( $run_path, ['/foo/bar/dhandler'], '/foo/bar/dhandler', 'baz' ); # index_names @interp_params = ( index_names => [ 'index', 'index2' ] ); $try->( $run_path, ['/foo/bar/baz/index.mc'], undef ); $try->( $run_path, ['/foo/bar/baz/index'], '/foo/bar/baz/index', '' ); $try->( $run_path, ['/foo/bar/baz/index2'], '/foo/bar/baz/index2', '' ); $try->( $run_path, [ '/foo/bar/baz/index2', '/foo/bar/baz/index' ], '/foo/bar/baz/index', '' ); # trailing slashes $try->( '/foo', ['/foo.mc=1'], '/foo.mc', '' ); $try->( '/foo/', ['/foo.mc=1'], '/foo.mc', '/' ); $try->( '/foo/bar', ['/foo.mc=1'], '/foo.mc', 'bar' ); $try->( '/foo/bar/', ['/foo.mc=1'], '/foo.mc', 'bar/' ); $try->( '/foo/', ['/foo.mc'], undef ); @interp_params = ( dhandler_names => ['dhandler'] ); $try->( '/foo/', ['/foo/dhandler'], '/foo/dhandler', '/' ); $try->( '/foo/bar', ['/foo/dhandler'], '/foo/dhandler', 'bar' ); $try->( '/foo/bar/', ['/foo/dhandler'], '/foo/dhandler', 'bar/' ); @interp_params = ( index_names => ['index'] ); $try->( '/foo/', ['/foo/index'], undef ); $try->( '/foo/', ['/foo/index=1'], '/foo/index', '/' ); @interp_params = ( dhandler_names => ['dhandler'], index_names => ['index'] ); $try->( '/foo/', [ '/foo/dhandler', '/foo/index' ], '/foo/dhandler', '/' ); $try->( '/foo/', [ '/foo/dhandler', '/foo/index=1' ], '/foo/index', '/' ); } sub test_decline : Tests { my $self = shift; my @existing_paths = qw(/foo/bar.mc /foo/bar/dhandler.mc /foo/bar/index.mc /foo.mc /foo/dhandler.mc /dhandler.mc); my @paths_to_decline = (); my $run_path = '/foo/bar'; my $try = sub { my ( $resolve_path, $path_info ) = @_; my %paths_to_decline_hash = map { ( $_, 1 ) } @paths_to_decline; $self->setup_dirs(); foreach my $existing_path (@existing_paths) { my $component = $paths_to_decline_hash{$existing_path} ? '<%perl>$m->decline();' : 'path: <% $self->cmeta->path %>; path_info: <% $m->path_info %>'; $self->add_comp( path => $existing_path, src => $component, ); $self->add_comp( path => '/Base.mp', src => 'method allow_path_info { 1 }' ); } my $desc = sprintf( "declining: %s", join( ",", @paths_to_decline ) || '' ); if ( defined($resolve_path) ) { is( $self->interp->run($run_path)->output, "path: $resolve_path; path_info: $path_info", $desc ); } else { throws_ok { $self->interp->run($run_path)->output } qr/could not resolve request path/, $desc; } push( @paths_to_decline, $resolve_path ); }; # Repeatedly try /foo/bar, test the expected page component, then add # that component to the decline list and try again. # $try->( '/foo/bar.mc', '' ); $try->( '/foo/bar/index.mc', '' ); $try->( '/foo/bar/dhandler.mc', '' ); $try->( '/foo.mc', 'bar' ); $try->( '/foo/dhandler.mc', 'bar' ); $try->( '/dhandler.mc', 'foo/bar' ); $try->(undef); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Sanity.pm000644 777777 777777 00000000212 12266570730 020444 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365438 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Sanity.pm000644 €ˆž«€q{Ì00000000373 12266570730 017431 0ustar00jonswart000000 000000 package Mason::t::Sanity; { $Mason::t::Sanity::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_ok : Tests { my $self = shift; $self->test_comp( src => '2 + 2 = <% 2 + 2 %>', expect => '2 + 2 = 4' ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Sections.pm000644 777777 777777 00000000212 12266570730 020764 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365439 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Sections.pm000644 €ˆž«€q{Ì00000003736 12266570730 017757 0ustar00jonswart000000 000000 package Mason::t::Sections; { $Mason::t::Sections::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_sections : Tests { my $self = shift; $self->test_comp( src => <<'EOF', <%doc> This should not get printed. <%init> my $init_message = $self->init_message(); <%class> my $class_message = "class message"; method init_message () { "init message" } <% $class_message %> % $self->method_call(); <% $self->method_call_with_arglist(3, 4) %> <%perl> print "$init_message\n"; <%method method_call> <% $message %> <%init> my $message = "message"; <%before method_call> before method call <%after method_call> after method call <%override render> start override <% super() %> end override <%method method_call_with_arglist ($foo, $bar)> <% $foo %> - <% $bar %> EOF expect => <<'EOF', start override class message before method call message after method call 3 - 4 init message end override EOF ); } sub test_perl_section_newlines : Tests { my $self = shift; $self->test_comp( src => <<'EOF', 1<%perl>print "2\n"; <%perl> print "3\n"; 4 <%perl> print "5\n"; 6 <%perl> print "7\n"; EOF expect => <<'EOF', 12 3 4 5 6 7 EOF ); } sub test_text_section : Tests { my $self = shift; $self->test_comp( src => <<'EOF', <%text> % <%init> <%doc> <% $x %> EOF expect => <<'EOF', % <%init> <%doc> <% $x %> EOF ); } sub test_empty_sections : Tests { my $self = shift; $self->test_comp( src => ' hi <%after foo> <%around foo> <%before foo> <%method foo> <%filter bar> <%override allow_path_info> <%class> <%doc> <%flags> <%init> <%perl> <%text> bye ', expect => "hibye", ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Skel.pm000644 777777 777777 00000000212 12266570730 020073 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365440 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Skel.pm000644 €ˆž«€q{Ì00000000360 12266570730 017054 0ustar00jonswart000000 000000 package Mason::t::Skel; { $Mason::t::Skel::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_ : Tests { my $self = shift; $self->test_comp( src => ' ', expect => ' ', ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/StaticSource.pm000644 777777 777777 00000000212 12266570730 021605 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365441 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/StaticSource.pm000644 €ˆž«€q{Ì00000005715 12266570730 020577 0ustar00jonswart000000 000000 package Mason::t::StaticSource; { $Mason::t::StaticSource::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; use Mason::Util qw(write_file touch_file); sub setup : Test(setup) { my ($self) = @_; $self->setup_dirs(); $self->add_comp( path => "/ss/remove_component.mc", src => "I will be removed.\n", ); $self->add_comp( path => "/ss/change_component.mc", src => "I will be changed.\n", ); } sub write_comp { my ( $self, $path, $contents ) = @_; my $source_file = $self->interp->load($path)->cmeta->source_file; write_file( $source_file, $contents ); } sub remove_comp { my ( $self, $path ) = @_; my $source_file = $self->interp->load($path)->cmeta->source_file; unlink($source_file); } sub test_change_no_ss : Tests { my $self = shift; $self->test_comp( src => '<& /ss/change_component.mc &>', expect => 'I will be changed.', ); sleep(1); # Make sure timestamp changes $self->write_comp( "/ss/change_component.mc", "I have changed!\n" ); $self->test_comp( src => '<& /ss/change_component.mc &>', expect => 'I have changed!', ); } sub test_change_and_touch_ss : Tests { my $self = shift; my $touch_file = $self->temp_dir . "/purge.dat"; $self->setup_interp( static_source => 1, static_source_touch_file => $touch_file ); $self->test_comp( src => '<& /ss/change_component.mc &>', expect => 'I will be changed.', ); sleep(1); # Make sure timestamp changes $self->interp->load('/ss/change_component.mc'); $self->write_comp( "/ss/change_component.mc", "I have changed!\n" ); $self->test_comp( src => '<& /ss/change_component.mc &>', expect => 'I will be changed.', ); touch_file($touch_file); $self->test_comp( src => '<& /ss/change_component.mc &>', expect => 'I have changed!', ); } sub test_remove_no_ss : Tests { my $self = shift; $self->test_comp( src => '<& /ss/remove_component.mc &>', expect => 'I will be removed.', ); $self->remove_comp("/ss/remove_component.mc"); $self->test_comp( src => '<& /ss/remove_component.mc &>', expect_error => qr/could not find component/ ); } sub test_remove_and_touch_ss : Tests { my $self = shift; my $touch_file = $self->temp_dir . "/purge.dat"; $self->setup_interp( static_source => 1, static_source_touch_file => $touch_file ); $self->test_comp( src => '<& /ss/remove_component.mc &>', expect => 'I will be removed.', ); $self->remove_comp("/ss/remove_component.mc"); $self->test_comp( src => '<& /ss/remove_component.mc &>', expect => 'I will be removed.', ); touch_file($touch_file); $self->test_comp( src => '<& /ss/remove_component.mc &>', expect_error => qr/could not find component/ ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Syntax.pm000644 777777 777777 00000000212 12266570730 020463 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365442 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Syntax.pm000644 €ˆž«€q{Ì00000007015 12266570730 017450 0ustar00jonswart000000 000000 package Mason::t::Syntax; { $Mason::t::Syntax::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; sub test_replace : Tests { shift->test_comp( src => <<'EOF', <% "Hello World!" %> EOF expect => <<'EOF', Hello World! EOF ); } sub test_percent : Tests { shift->test_comp( src => <<'EOF', % my $message = "Hello World!"; <% $message %> EOF expect => <<'EOF', Hello World! EOF ); } sub test_fake_percent : Tests { shift->test_comp( src => <<'EOF', some text, a %, and some text EOF expect => <<'EOF', some text, a %, and some text EOF ); } sub test_empty_percents : Tests { shift->test_comp( src => <<'EOF', some text, % and some more EOF expect => <<'EOF', some text, and some more EOF ); } sub test_empty_percents2 : Tests { shift->test_comp( src => <<'EOF', some text, % % $m->print('foo, '); % $m->print(undef); and some more EOF expect => <<'EOF', some text, foo, and some more EOF ); } # Deprecated syntax # sub test_double_percent : Tests { shift->test_comp( src => <<'EOF', <%class> my $i = 5; %% my $j = 0; %% if ($i == 5) { %% $j = $i+1; %% } <% $.bar %> <%method bar> j = <% $j %> EOF expect => <<'EOF', j = 6 EOF ); } sub test_pure_perl : Tests { shift->test_comp( path => '/pureperl.mp', src => 'sub main { print "hello from main" }', expect => 'hello from main', ); } # Deprecated syntax # sub test_args : Tests { my $self = shift; $self->add_comp( path => '/args.mc', src => ' <%args> a b # comment # comment c=>5 d => 6 e => "foo" # comment f => (isa => "Num", default => 7) g => (isa => "Num", default => 8) # comment a = <% $.a %> b = <% $.b %> c = <% $.c %> d = <% $.d %> e = <% $.e %> f = <% $.f %> g = <% $.g %> ', ); $self->test_comp( src => '<& /args.mc, a => 3, b => 4 &>', expect => ' a = 3 b = 4 c = 5 d = 6 e = foo f = 7 g = 8 ' ); } sub test_multiline_comment : Tests { my $self = shift; $self->test_comp( src => ' hi<% # comment # another comment %>bye ', expect => 'hibye', ); } # Deprecated syntax # sub test_shared : Tests { shift->test_parse( src => ' <%shared> $.foo # a comment $.bar => "something" $.baz => ( isa => "Num", default => 5 ) # another comment ', expect => [ q/has 'foo' => (init_arg => undef/, q/has 'bar' => (init_arg => undef, default => "something"/, q/has 'baz' => (init_arg => undef, isa => "Num", default => 5/ ], ); } sub test_dollar_dot : Tests { shift->test_comp( src => ' <%class> has "bar" => (default => 4); has "foo" => (default => 3); <% $self->show %> <%method show> foo = <% $.foo %> bar = <% $.bar %> <%init> $self->foo(5); $self->bar(6); ', expect => ' foo = 5 bar = 6 ' ); } sub test_dollar_m : Tests { my $self = shift; $self->test_comp( src => ' <%class> method foo () { $m->print("foo\n") } <%method bar><%perl>$m->print("bar\n"); <% $.foo %> <% $.bar %> % $m->print("baz\n"); ', expect => ' foo bar baz ', ); } sub test_class_global : Tests { my $self = shift; $self->test_comp( src => '<% ref($self) eq CLASS ? 1 : 0 %> <% ref($self) eq $CLASS ? 1 : 0 %>', expect => qr/1 1/, ); } 1; Mason-2.21/lib/Mason/t/PaxHeader/Util.pm000644 777777 777777 00000000212 12266570730 020112 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365443 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/t/Util.pm000644 €ˆž«€q{Ì00000000530 12266570730 017072 0ustar00jonswart000000 000000 package Mason::t::Util; { $Mason::t::Util::VERSION = '2.21'; } use Test::Class::Most parent => 'Mason::Test::Class'; use Mason::Util qw(combine_similar_paths); sub test_combine_similar_paths : Tests { cmp_deeply( [ combine_similar_paths(qw(/foo/bar.m /foo/bar.pm /foo.m /foo.pm)) ], [ '/foo/bar.{m,pm}', '/foo.{m,pm}' ] ); } 1; Mason-2.21/lib/Mason/PluginBundle/PaxHeader/Default.pm000644 777777 777777 00000000212 12266570730 022706 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365419 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/PluginBundle/Default.pm000644 €ˆž«€q{Ì00000002430 12266570730 021667 0ustar00jonswart000000 000000 package Mason::PluginBundle::Default; { $Mason::PluginBundle::Default::VERSION = '2.21'; } use Mason::PluginRole; with 'Mason::PluginBundle'; sub requires_plugins { qw(Defer DollarDot) } 1; __END__ =pod =head1 NAME Mason::PluginBundle::Default - Default plugins =head1 DESCRIPTION Plugins in this bundle are always added by default, regardless of whether you pass a plugins list to C<< Mason->new >>. You can use the '-' prefix to remove individual plugins or the whole bundle. e.g. # Will get just the default plugins Mason->new(...); Mason->new(plugins => [], ...); # Will get the default plugins plus the 'Foo' plugin Mason->new(plugins => ['Foo'], ...); # Will get the default plugins except for 'DollarDot' Mason->new(plugins => ['-DollarDot'], ...); # Will get no plugins Mason->new(plugins => ['-Default'], ...); =head1 INCLUDED PLUGINS =over =item L =item L =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Plugin/PaxHeader/Defer000775 777777 777777 00000000212 12266570730 020607 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365409 18 SCHILY.nlink=4 Mason-2.21/lib/Mason/Plugin/Defer/000775 €ˆž«€q{Ì00000000000 12266570730 017643 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/Plugin/PaxHeader/Defer.pm000644 777777 777777 00000000212 12266570730 021215 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365405 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin/Defer.pm000644 €ˆž«€q{Ì00000003107 12266570730 020200 0ustar00jonswart000000 000000 package Mason::Plugin::Defer; { $Mason::Plugin::Defer::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::Plugin::Defer - Defer computing parts of output until the end of the request =head1 SYNOPSIS <% $m->defer(sub { $m->page->title }) %> % $.Defer {{ % my $content = join(", ", @{ $m->page->meta_content }); % }} ... =head1 DESCRIPTION The I feature allows sections of output to be deferred til the end of the request. You can set up multiple deferred code blocks which will execute and insert themselves into the output stream at request end. =head1 REQUEST METHOD =over =item defer (code) Returns a marker string that is unique and will not appear in normal output. At the end of the request, each marker string is replaced with the output of its associated code. e.g. <% $m->defer(sub { $m->page->title }) %> =back =head1 FILTER =over =item Defer Applies C<< $m->defer >> to the content block. e.g. % $.Defer {{ % my $content = join(", ", @{ $m->page->meta_content }); % }} =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Plugin/PaxHeader/DollarDot000775 777777 777777 00000000212 12266570730 021446 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365412 18 SCHILY.nlink=3 Mason-2.21/lib/Mason/Plugin/DollarDot/000775 €ˆž«€q{Ì00000000000 12266570730 020502 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/Plugin/PaxHeader/DollarDot.pm000644 777777 777777 00000000212 12266570730 022054 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365406 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin/DollarDot.pm000644 €ˆž«€q{Ì00000003515 12266570730 021042 0ustar00jonswart000000 000000 package Mason::Plugin::DollarDot; { $Mason::Plugin::DollarDot::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::Plugin::DollarDot - Allow $. as substitution for $self-> and in attribute names =head1 SYNOPSIS <%class> has 'name'; has 'date'; <%method greet> Hello, <% $.name %>. Today is <% $.date %>. ... % $.greet(); <%init> # Set the date $.date(scalar(localtime)); # or, if combined with LvalueAttributes $.date = scalar(localtime); =head1 DESCRIPTION This plugin substitutes C<< $.I >> for C<< $self->I >> in all Perl code inside components, so that C<< $. >> can be used when referring to attributes and calling methods. The actual regex is s/ \$\.([^\W\d]\w*) / \$self->$1 /gx; =head1 RATIONALE In Mason 2, components have to write C<< $self-> >> a lot to refer to attributes that were simple scalars in Mason 1. This eases the transition pain. C<< $. >> was chosen because of its similar use in Perl 6. This plugin falls under the heading of gratuitous source filtering, which the author generally agrees is Evil. That said, this is a very limited filter, and seems unlikely to break any legitimate Perl syntax other than use of the C<< $. >> special variable (input line number). =head1 BUGS Will not interpolate as expected inside double quotes: "My name is $.name" # nope instead you have to do "My name is " . $.name =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Plugin/PaxHeader/LvalueAttributes000775 777777 777777 00000000212 12266570730 023061 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365414 18 SCHILY.nlink=3 Mason-2.21/lib/Mason/Plugin/LvalueAttributes/000775 €ˆž«€q{Ì00000000000 12266570730 022115 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/Plugin/PaxHeader/LvalueAttributes.pm000644 777777 777777 00000000212 12266570730 023467 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365407 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin/LvalueAttributes.pm000644 €ˆž«€q{Ì00000002615 12266570730 022455 0ustar00jonswart000000 000000 package Mason::Plugin::LvalueAttributes; { $Mason::Plugin::LvalueAttributes::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::Plugin::LvalueAttributes - Create lvalue accessors for all rw component attributes =head1 SYNOPSIS <%class> has 'a' => (is => "rw") has 'b' => (is => "ro") <%init> # set a to 5 $.a = 5; # set a to 6 $.a(6); # error $.b = 7; =head1 DESCRIPTION This plugins creates an Lvalue accessor for every read/write attribute in the component. Which means that instead of writing: $.name( "Foo" ); you can use the more natural syntax $.name = "Foo"; =head1 WARNING Standard Moose setter features such as type checking, triggers, and coercion will not work on Lvalue attributes. You should only use this plugin when the convenience of the Lvalue attributes outweighs the need for setter features. =head1 ACKNOWLEDGEMENTS Inspired by Christopher Brown's L. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Plugin/PaxHeader/TidyObjectFiles000775 777777 777777 00000000212 12266570730 022605 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365416 18 SCHILY.nlink=3 Mason-2.21/lib/Mason/Plugin/TidyObjectFiles/000775 €ˆž«€q{Ì00000000000 12266570730 021641 5ustar00jonswart000000 000000 Mason-2.21/lib/Mason/Plugin/PaxHeader/TidyObjectFiles.pm000644 777777 777777 00000000212 12266570730 023213 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365408 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin/TidyObjectFiles.pm000644 €ˆž«€q{Ì00000001674 12266570730 022205 0ustar00jonswart000000 000000 package Mason::Plugin::TidyObjectFiles; { $Mason::Plugin::TidyObjectFiles::VERSION = '2.21'; } use Moose; with 'Mason::Plugin'; __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::Plugin::TidyObjectFiles - Tidy object files =head1 DESCRIPTION Uses perltidy to tidy object files (the compiled form of Mason components). =head1 ADDITIONAL PARAMETERS =over =item tidy_options A string of perltidy options. e.g. tidy_options => '-noll -l=72' tidy_options => '--pro=/path/to/.perltidyrc' May include --pro/--profile to point to a .perltidyrc file. If omitted, will use default perltidy settings. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Plugin/TidyObjectFiles/PaxHeader/Interp.pm000644 777777 777777 00000000212 12266570730 024454 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365417 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin/TidyObjectFiles/Interp.pm000644 €ˆž«€q{Ì00000002105 12266570730 023434 0ustar00jonswart000000 000000 package Mason::Plugin::TidyObjectFiles::Interp; { $Mason::Plugin::TidyObjectFiles::Interp::VERSION = '2.21'; } use Mason::PluginRole; use Perl::Tidy; has 'tidy_options' => ( is => 'ro' ); around 'write_object_file' => sub { my ( $orig, $self, $object_file, $object_contents ) = @_; my $argv = $self->tidy_options || ''; my $tidied_object_contents; Perl::Tidy::perltidy( 'perltidyrc' => '/dev/null', source => \$object_contents, destination => \$tidied_object_contents, prefilter => sub { $self->prefilter( $_[0] ) }, postfilter => sub { $self->postfilter( $_[0] ) }, argv => $argv ); $tidied_object_contents =~ s/^\s*(\#line .*)/$1/mg; $self->$orig( $object_file, $tidied_object_contents ); }; sub prefilter { my $self = shift; $_ = $_[0]; # Turn method into sub s/^method (.*)/sub $1 \#__METHOD/gm; return $_; } sub postfilter { my $self = shift; $_ = $_[0]; # Turn sub back into method s/^sub (.*?)\s* \#__METHOD/method $1/gm; return $_; } 1; Mason-2.21/lib/Mason/Plugin/LvalueAttributes/PaxHeader/Interp.pm000644 777777 777777 00000000212 12266570730 024730 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365415 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin/LvalueAttributes/Interp.pm000644 €ˆž«€q{Ì00000001431 12266570730 023711 0ustar00jonswart000000 000000 package Mason::Plugin::LvalueAttributes::Interp; { $Mason::Plugin::LvalueAttributes::Interp::VERSION = '2.21'; } use Mason::PluginRole; after 'modify_loaded_class' => sub { my ( $self, $compc ) = @_; $self->_add_lvalue_attribute_methods($compc); }; sub _add_lvalue_attribute_methods { my ( $self, $class ) = @_; my @attrs = $class->meta->get_all_attributes(); foreach my $attr (@attrs) { if ( $attr->_is_metadata eq 'rw' ) { my $name = $attr->name; $class->meta->add_method( $name, sub : lvalue { if ( defined( $_[1] ) ) { $_[0]->{$name} = $_[1]; } $_[0]->{$name}; } ); } } } 1; Mason-2.21/lib/Mason/Plugin/DollarDot/PaxHeader/Compilation.pm000644 777777 777777 00000000212 12266570730 024332 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365413 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin/DollarDot/Compilation.pm000644 €ˆž«€q{Ì00000000450 12266570730 023313 0ustar00jonswart000000 000000 package Mason::Plugin::DollarDot::Compilation; { $Mason::Plugin::DollarDot::Compilation::VERSION = '2.21'; } use Mason::PluginRole; after 'process_perl_code' => sub { my ( $self, $coderef ) = @_; # Replace $. with $self-> $$coderef =~ s/ \$\.([^\W\d]\w*) / \$self->$1 /gx; }; 1; Mason-2.21/lib/Mason/Plugin/Defer/PaxHeader/Filters.pm000644 777777 777777 00000000212 12266570730 022625 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365410 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin/Defer/Filters.pm000644 €ˆž«€q{Ì00000000375 12266570730 021614 0ustar00jonswart000000 000000 package Mason::Plugin::Defer::Filters; { $Mason::Plugin::Defer::Filters::VERSION = '2.21'; } use Mason::PluginRole; method Defer () { Mason::DynamicFilter->new( filter => sub { $self->m->defer( $_[0] ); } ); } 1; Mason-2.21/lib/Mason/Plugin/Defer/PaxHeader/Request.pm000644 777777 777777 00000000212 12266570730 022645 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365411 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Plugin/Defer/Request.pm000644 €ˆž«€q{Ì00000001557 12266570730 021637 0ustar00jonswart000000 000000 package Mason::Plugin::Defer::Request; { $Mason::Plugin::Defer::Request::VERSION = '2.21'; } use Mason::PluginRole; has 'defers' => ( is => 'rw', init_arg => undef, default => sub { [] } ); before 'flush_buffer' => sub { my $self = shift; $self->_apply_defers_to_request_buffer(); }; method defer ($code) { my $marker = $self->interp->_construct_distinct_string(); push( @{ $self->{defers} }, { marker => $marker, code => $code } ); return $marker; } method _apply_defers_to_request_buffer () { if ( my @defers = @{ $self->{defers} } ) { my $request_buffer = ${ $self->_request_buffer }; foreach my $defer (@defers) { my $subst = $defer->{marker}; my $repl = $defer->{code}->(); $request_buffer =~ s/\Q$subst\E/$repl/; } ${ $self->_request_buffer } = $request_buffer; } } 1; Mason-2.21/lib/Mason/Moose/PaxHeader/Role.pm000644 777777 777777 00000000212 12266570730 020715 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365403 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Moose/Role.pm000644 €ˆž«€q{Ì00000002066 12266570730 017703 0ustar00jonswart000000 000000 package Mason::Moose::Role; { $Mason::Moose::Role::VERSION = '2.21'; } use Moose::Role (); use Method::Signatures::Simple (); use Moose::Exporter; Moose::Exporter->setup_import_methods( also => ['Moose::Role'] ); sub init_meta { my $class = shift; my %params = @_; my $for_class = $params{for_class}; Method::Signatures::Simple->import( into => $for_class ); Moose::Role->init_meta(@_); } 1; __END__ =pod =head1 NAME Mason::Moose::Role - Mason Moose role policies =head1 SYNOPSIS # instead of use Moose::Role; use Mason::Moose::Role; =head1 DESCRIPTION Sets certain Moose behaviors for Mason's internal roles. Using this module is equivalent to use Moose::Role; use Method::Signatures::Simple; =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/Components.pod000644 777777 777777 00000000212 12266570730 022442 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365390 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/Components.pod000644 €ˆž«€q{Ì00000032203 12266570730 021424 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::Components - The building blocks of Mason =head1 DESCRIPTION The I - a file with a mix of Perl and HTML - is Mason's basic building block. Pages are usually formed by combining the output from multiple components. An article page for a online magazine, for example, might call separate components for the company masthead, ad banner, left table of contents, and article body. +---------+------------------+ |Masthead | Banner Ad | +---------+------------------+ | | | |+-------+|Text of Article ..| || || | ||Related||Text of Article ..| ||Stories|| | || ||Text of Article ..| |+-------+| | | +------------------+ | | Footer | +---------+------------------+ The top level component decides the overall page layout. Individual cells are then filled by the output of subordinate components. Pages might be built up from as few as one, to as many as hundreds of components, with each component contributing a chunk of HTML. Splitting up a page into multiple components gives you roughly the same benefits as splitting up an application into multiple classes: encapsulation, reusability, development concurrency, separation of concerns, etc. Mason actually compiles components down to Perl/Moose classes, which means that many of the tools you use to develop regular classes - profilers, debuggers, and the like - can be used with Mason components with slight tweaking. =head1 COMPONENT FILES =head2 The component root and component paths When you use Mason, you specify a L that all component files live under. Thereafter, any component will be referred to by its virtual I relative to the root, rather than its full filename. For example, if the component root is '/opt/web/comps', then the component path '/foo/bar.mc' refers to the file '/opt/web/comps/foo/bar.mc'. It is also possible to specify multiple component roots, ala Perl's C<@INC>, in which case a component path might refer to one of several files. =head2 Component file extensions By default Mason facilitates and enforces standard file extensions for components. =over =item .mc - top-level component A top-level component can serve as the page component in a request. =item .mi - internal component An internal component can only be accessed from other components. =item .mp - pure-perl component A pure-perl component contains only code; it is parsed as if its entire content was within a L<%class|Mason::Manual::Syntax/E%classE> block. You do not need to (and are not allowed to) include Mason tags in this component, and it will not produce any output if called. This is just a way of defining a class that other components can easily interact with and extend. Some applications include: controller logic, web form handlers, and L. =back These extensions are configurable via L and L. =head1 CALLING COMPONENTS The initial component in a request, called the page component, is called from L, which in turn may be called from a PSGI handler or an web framework view depending on your setup. See L for more information about how the page component is chosen. A component can call another component with the L& &E tag|Mason::Manual::Syntax/CALLING COMPONENTS>: <& /path/to/comp.mi, name=>value, ... &> or via the L or L methods: <%init> $m->comp('/some/component.mi', foo => 5); my $output = $m->scomp('/some/other/component.mi'); From the implementation perspective, calling a component means creating a new instance of the component's class with the specified parameters, and then calling method C (for the page component) or C
    (for an internal component) on the instance. =head1 ATTRIBUTES You can declare attributes in components and pass them when calling components. =head2 Declaring attributes Use Moose 'has' syntax to declare attributes within a C<< <%class> >> section: <%class> has 'foo'; has 'bar' => (required => 1); has 'baz' => (isa => 'Int', default => 17); =head2 Attributes are read-write by default L imports L into all components, which makes attributes read-write unless stated otherwise. This is not considered best practice for general OO programming, but component instances are short-lived and not usually accessed outside of their class so we feel the convenience is warranted. =head2 Accessing attributes A declared attribute 'foo' can be accessed inside the component via the Perl6-ish syntax $.foo which is transformed by L to $self->foo In the rest of this documentation we will use C<$.> notation, but feel free to substitute C<< $self-> >> conceptually and/or in reality. To set the attribute, you must use: $.foo(5); unless you're using L, in which case you can say $.foo = 5; C<< $.args >> will return a hashref of all of the parameters passed to the component when it was created/called, regardless of whether they correspond to declared attributes. =head1 METHODS The base component class, L, has but a few built-in methods: handle, render, wrap, main, m, and cmeta. The C
    method contains the mix of HTML and Perl in the main part of the component. You can add other methods that output HTML via the C<< <$method> >> section; these methods automatically have access to C<$self> and C<$m>. <%method leftcol> ...
    <% $foo %>
    ... <% # call leftcol method and insert HTML here %> <% $.leftcol %> Methods can also take argument lists: <%method list ($style, $items)>
      % foreach my $item (@$items) { ... % }
    Both C
    and other methods defined with C<< <%method> >> automatically get a C<< return undef >> at their end, so that they don't accidentally return values. Pure-Perl methods that return a value can be added within the << <%class> >> section. <%class> method multiply ($a, $b) { return $a * $b; } ... <%init> my $value = $.multiply(5, 6); Note that L provides the C keyword and argument lists; this is used throughout Mason internals as well. If you prefer straight-up Perl subroutines: <%class> sub multiply { my ($self, $a, $b) = @_; return $a * $b; } =head2 Output versus return value Most Mason methods output content such as HTML. The content is not actually returned, but is instead appended to an implicit buffer. This is slightly more complicated but is necessary for supporting streaming applications. When Mason generates C
    and other methods declared with C<< <%method> >>, it puts an implicit return undef; at the bottom of the method, so that unless you specify otherwise, there will be no return value. This is important because of syntactical shortcuts like <% inner() %> <% $.leftcol %> which would (undesirably) print the return value if it existed. =head1 INHERITANCE Each component class naturally inherits from (or 'extends') a superclass. The default superclass for components is L, but this may be overridden in two ways: the I and I. =head2 Extends flag A component can declare its superclass via the C flag: <%flags> extends => '/some/other/component' The path may be absolute as shown above, or relative to the component's path. Note that including a raw C keyword in a C<< <%class> >> section will not work reliably. =head2 Autobase components Autobase components are specially named components that automatically become the superclass of all components in their directory and subdirectories. The default names are "Base.mp" and "Base.mc" - you can customize this with the C parameter. For example, in this directory hierarchy, Base.mp main.mc colors/ red.mc blue.mc flavors/ Base.mc vanilla.mc chocolate.mc assuming that no components have C flags, =over =item * /Base.mp is the superclass of /main.mc, /colors/red.mc, /colors/blue.mc, and /flavors/Base.mc. =item * /flavors/Base.mc is the superclass of vanilla.mc and chocolate.mc. =back If C and C appear in the same directory, they will both be recognized; everything below will inherit from C, and C will inherit from C. This might be useful for separating L from shared method definitions, for example. =head1 GENERATED CLASS It can be helpful to understand how Mason generates component classes, especially for troubleshooting unexpected component behavior. =head2 Object files Mason writes the generated class into an I, located in /obj/.mobj For example if your L is F and the component path is F, the corresponding object file will be /home/myapp/data/obj/foo/bar.mc.mobj The object file is rewritten whenever Mason detects a change in the source file. Object files aren't generated in a particularly clean way, so if you're going to be peeking at them, consider using the L. =head2 Class name The class name is determined at load time by prepending the C to the component path, which slashes replaced with '::'. Two different Interp objects loading the same object file will thus create two separate classes. =head2 A simple example Here's a simple component: Hello world! The local time is <% scalar(localtime) %>. and here's the class that gets generated for it, filtered with C: 1 use Mason::Component::Moose; 2 our ( $m, $_m_buffer ); 3 *m = \$Mason::Request::current_request; 4 *_m_buffer = \$Mason::Request::current_buffer; 5 sub _inner { inner() } 6 my $_class_cmeta; 7 8 method _set_class_cmeta ($interp) { 9 $_class_cmeta = $interp->component_class_meta_class->new( 10 'class' => CLASS, 11 'dir_path' => '/', 12 'interp' => $interp, 13 'is_top_level' => '1', 14 'object_file' => __FILE__, 15 'path' => '/hi.mc', 16 'source_file' => '/home/myapp/comps/hi.mc', 17 ); 18 } 19 sub _class_cmeta { $_class_cmeta } 20 21 method main { 22 #line 1 "/home/myapp/comps/hi.mc" 23 $$_m_buffer .= 'Hi there! The time is '; 24 #line 1 "/home/myapp/comps/hi.mc" 25 for ( scalar( scalar(localtime) ) ) { $$_m_buffer .= $_ if defined } 26 #line 1 "/home/myapp/comps/hi.mc" 27 $$_m_buffer .= '. 28 '; 29 30 return; 31 } (Caveat: the above is as of time of writing and may well be out of date with the current code generator, but it is accurate enough for explanatory purposes.) Line 1 brings in L, which imports L, L, L and other things into the current package. Lines 2-4 defines two dynamic globals, C<$m> (the current request) and C<$_m_buffer> (the current output buffer). These are aliased so that they can be changed for every component from a single place. Lines 6-19 create the L object returned from L. Lines 21-31 contain the L method, which encapsulates all the output and Perl statements in the component that aren't explicitly inside a C<< <%method> >> or C<< <%class> >> block. Lines 22, 24, and 26 contain '#line' statements which make error messages appear to come from the source file rather than the object file (and hence more useful). This can be disabled with L. Lines 23, 25, and 27 output plain strings or the results of code by appending them to the current output buffer. The current output buffer can change within a request, for example when L or L is called. Two things that would be in a normal class are missing above: the C and C declarations. These are added dynamically when the object file is evaluated. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/Cookbook.pod000644 777777 777777 00000000212 12266570730 022063 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365391 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/Cookbook.pod000644 €ˆž«€q{Ì00000001477 12266570730 021056 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::Cookbook - Recipes for common Mason tasks =head1 RECIPES =head2 HTML list formed from array
      % foreach $item (@list) {
    • <% $item %>
    • % }
    =head2 HTML table formed from list of objects % foreach my $obj (@objects) { % }
    FooBarBaz
    <% $obj->foo %> <% $obj->bar %> <% $obj->baz %>
    =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/FAQ.pod000644 777777 777777 00000000212 12266570730 020724 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365392 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/FAQ.pod000644 €ˆž«€q{Ì00000012412 12266570730 017706 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::FAQ - Frequently asked questions about Mason =head1 COMPONENTS =head2 Can I create global variable(s) that can be seen from all components? Mason components each run in their own packages, so if you set a regular global in one you won't be able to see it in the others. But you can use L and L to create globals accessible from all components. =head2 Why does my output have extra newlines/whitespace and how can I get rid of it? See L in the syntax manual. To suppress extra newlines you can use a backslash at the end of each line, or you can use the L filter. To emit binary data without the risk of inserting extra whitespace, surround your code with L<$m-Eclear_buffer|Mason::Request/clear_buffer> and L<$m-Eabort|Mason::Request/abort>: <%init> $m->clear_buffer; open(my $fh, '<', 'binary-file') or die $!; my $buffer; while (read $fh, $buffer, 8192) { $m->print($buffer); } $m->abort; =head2 I'm trying to generate an image or other binary file, but it seems to be getting corrupted. This is almost always caused by unwanted whitespace or other output at the beginning or end of your binary data. Use L<$m-Eclear_buffer|Mason::Request/clear_buffer> and L<$m-Eabort|Mason::Request/abort> as in previous answer. =head2 How do I put comments in components? See L section in the syntax manual for reference. =over =item * Put general comments in the C<< <%doc> >> section. =item * Within code blocks (C<< <%class> >>, C<< <%init> >>, C<< <%perl> >>, etc.), use standard Perl comments ('#'). =item * Use C<< <% # %> >> for single or multi-line comments anywhere outside of Perl sections. =item * If you are producing HTML, you can use standard HTML comments delimited by . The difference is that these comments will appear in the final output. =back =head2 What's a good way to temporarily comment out code in a component? For HTML, you might be tempted to surround the section with C<< >>. But be careful! Any code inside the section will still execute. Here's a example of commenting out a call to an ad server: The ad will still be fetched and counted, but not displayed! A better way to block out a section is C: % if (0) { ... % } Code blocked out in this way will neither be executed nor displayed, and multiple C blocks can be nested inside each other (unlike HTML comments). Another way to block out code is with a C<< <%doc> >> tag, although this not cannot be nested. =head2 How can I capture the output of a component (and modify it, etc.) instead of having it automatically output? Use L<$m-Escomp|Mason::Request/scomp>. =head2 How can I capture the output from arbitrary code that calls components, etc.? Use L<$m-Ecapture|Mason::Request/capture>. =head2 How can I get a list of components matching a path pattern? Use L<$m-Eglob_paths|Mason::Interp/glob_paths>, e.g. my @paths = $m->glob_paths('/some/comp/path/*'); This will work even with multiple component roots; you'll get a combined list of all matching component paths in all component roots. =head2 How can I access $m (the request object) from outside a component, e.g. inside a regular class? Use Lcurrent_request|Mason::Request/current_request>: package Foo; sub bar { my $m = Mason::Request->current_request; } =head2 When using multiple component roots, is there a way to explicitly call a component in a specific root? Multiple component roots were designed to work just like Perl's C<@INC>. A given component path matches exactly one file, the first file found in an ordered search through the roots. There is no way to explicitly ask for a file in a specific root. =head1 HTTP and HTML =head2 How do I use Mason to process web requests? You need to use Mason in conjunction with a web framework. L is a web framework designed specially for Mason. L and L can also use Mason for their templating layer. See L. =head2 How can I HTML-escape the output of C<< <% %> >> tags? See the C filter in L. If you want to do this automatically for all C<< <% %> >> tags, see L. =head2 Why is Mason so slow with standard CGI? Under standard CGI you must load all modules and initialize your environment with every request. Mason's startup cost (mostly due to L) will make this particularly sub-optimal. Ask yourself whether you absolutely have to use CGI, and if not, switch to a persistent solution like mod_perl or Fast CGI or L. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/Filters.pod000644 777777 777777 00000000212 12266570730 021725 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365393 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/Filters.pod000644 €ˆž«€q{Ì00000020111 12266570730 020702 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::Filters - Content filters in Mason =head1 DESCRIPTION Filters can be used to process portions of content in a component. A set of filters comes built-in with Mason - see L. Others will be available on CPAN, and it is easy to create your own. =head1 INVOKING =head2 Block invocation Here's the standard way of invoking a filter: % $.Trim {{ This string will be trimmed % }} # end Trim A double open brace (C<< {{ >>) at the end of a C<< %-line >> denotes a filter call. The filtered content begins just afterwards and ends at the C<< }} >>. Both C<< {{ >> and C<< }} >> may be followed by a comment. The expression C<< $.Trim >>, aka C<< $self->Trim >>, is a method call on the component object which returns a filter. In general everything before the C<< {{ >> is evaluated and is expected to return a filter or list of filters. By convention, and to avoid name clashes with other component methods, filters use CamelCase rather than traditional underscore names. Filters can take arguments: % $.Repeat(3) {{ There's no place like home. % }} ==> There's no place like home. There's no place like home. There's no place like home. Since the expression C<< $.Repeat(3) >> returns a filter, it can be curried: % my $repeat_three = $.Repeat(3); % $repeat_three {{ There's no place like home. % }} You can create one-off filters with anonymous subroutines. The subroutine receives the content in both C<< $_[0] >> and C<< $_ >>, and should return the filtered content. % sub { reverse($_[0]) } {{ Hello % }} ==> olleH % sub { s/ //g; $_[0] } {{ A bunch of words % }} ==> Abunchofwords Filters can be nested, with separate lines: % $.Trim {{ % sub { uc($_[0]) } {{ This string will be trimmed and uppercased % }} % }} or on a single line: % $.Trim, sub { uc($_[0]) } {{ This will be trimmed and uppercased % }} Multiple filters within the same tag are applied, intuitively, in reverse order with the last one being innermost. e.g. in this block % my $i = 1; % $.Repeat(3), $.Cache($key, '1 hour') {{ <% $i++ %> % }} => 1 1 1 the output of C<< <% $i++ %> >> is cached, and then repeated three times, whereas in this block % my $i = 1; % $.Cache($key, '1 hour'), $.Repeat(3) {{ <% $i++ %> % }} => 1 2 3 C<< <% $i++ %> >> is executed and output three times, and then the whole thing cached. =head2 Pipe invocation Filters can also appear in a limited way inside a regular C<< <% %> >> tag: <% $content | NoBlankLines,Trim %> The filter list appears after a << | >> character and must contain one or more comma-separated names. The names are treated as methods on the current component class. With this syntax you cannot use anonymous subroutines or variables as filters, or pass arguments to filters. However in a pinch you can define local filter methods to get around this, e.g. <%class> method Repeat3 { $.Repeat(3); } ... <% $message_body | Repeat3 %> For consistency with other syntax, multiple names are applied in reverse order with the rightmost applied first. One common use of this form is to escape HTML strings in web content, using the C filter in L: <% $message_body | H %> =head2 Default filters L allows you to define default filters that will automatically apply to all substitution tags. It is analagous to L setting. =head2 Manual invocation L<$m-Efilter|Mason::Request/filter> can be used to manually apply filter(s) to a string. It returns the filtered output. e.g. <%init> ... my $filtered_string = $m->filter($.Trim, $.NoBlankLines, $string); =head1 CREATING A FILTER =head2 Package and naming By convention, filters are placed in roles so that they can be composed into L or a subclass thereof. Take a look at L for an example. Also by convention, filters use CamelCase rather than traditional underscore_separated naming. Filter methods have to coexist with other methods in the Mason::Component namespace, so have to be distinguishable somehow, and we thought this was preferable to a "filter_" prefix or suffix. Of course, you are free to choose your own convention, but you should expect this naming in the standard filters at least. Here's a filter package that implements two filters, C and C: package MyApp::Filters; use Mason::PluginRole; method Upper () { return sub { uc($_[0]) } } method Lower () { return sub { lc($_[0]) } } 1; To use these in a component: <%class> with 'MyApp::Filters'; % $.Upper {{ ... % }} Or if you want them available to all components, put them in C at the top of your component hierarchy, or in your application's C subclass. =head2 Simple vs. dynamic filters A I is a code ref which takes a string (via either $_[0] and $_) and returns the output. Your filter method should return this code ref. e.g. # Uses $_[0] method Upper () { return sub { uc($_[0]) }; } # Uses $_ method Rot13 () { return sub { tr/a-zA-Z/n-za-mN-ZA-M/; $_ }; } A I is an object of class C. It contains a code ref which takes a I and returns the output. A yield block is a zero-argument code ref that returns a content string. e.g. this is functionally identical to the above: method Rot13 () { return Mason::DynamicFilter->new( filter => sub { my $yield = $_[0]; my $text = $yield->(); $text =~ tr/a-zA-Z/n-za-mN-ZA-M/; return $text; } ); } The dynamic filter obviously doesn't buy you anything in this case, and for the majority of filters they are unneeded. The real power of dynamic filters is that they can choose if and when to execute the yield block. For example, here is an implementation (slightly expanded for explanatory purposes) of the C<< Cache >> filter in L: method Cache ( $key, $set_options ) { return Mason::DynamicFilter->new( filter => sub { my $yield = $_[0]; my $cache = $self->cache; my $output = $cache->get( $key ); if (!$output) { $output = $yield->(); $cache->set( $key, $output, $set_options ); } return $output; } ); } Notice that we call C<< $cache->get >> first, and return the output immediately if it is in the cache. Only on a cache miss do we actually execute the (presumably expensive) yield block. C<< Defer >> and C<< Repeat >> are two other examples of dynamic filters. See L for their implementations. =head2 <%filter> block You can use the C<< <%filter> >> block to define filters that output content. It works just like a C<< <%method> >> block, except that you can call C<< $yield->() >> to generate the original content. e.g. <%filter Item ($class)>
  • <% $yield->() %>
  • % $.Item('std') {{ First % }} % $.Item('std') {{ Second % }} generates
  • First
  • Second
  • =head1 SEE ALSO L, L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/Intro.pod000644 777777 777777 00000000212 12266570730 021410 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365394 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/Intro.pod000644 €ˆž«€q{Ì00000005534 12266570730 020401 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::Intro - Getting started with Mason =head1 DESCRIPTION A few quick examples to get your feet wet with Mason. See L for how to use Mason to generate web sites. =head1 EXAMPLE 1 =head2 Hello world (from command-line) After installing Mason, you should have a C command in your installation path (e.g. C). Try this: % mason Hello! The local time is <% scalar(localtime) %>. ^D (where '^D' means ctrl-D or EOF). You should see something like Hello! The local time is Wed Mar 2 17:11:54 2011. The C command reads in a Mason I (template), runs it, and prints the result to standard output. Notice that the tag <% scalar(localtime) %> was replaced with the value of its expression. This is called a I and is a central piece of Mason syntax. =head1 EXAMPLE 2 =head2 Email generator (from script) The command line is good for trying quick things, but eventually you're going to want to put your Mason components in files. In a test directory, create a directory C and create a file C with the following: <%class> has 'amount'; has 'name'; Dear <% $.name %>, We are pleased to inform you that you have won $<% sprintf("%.2f", $.amount) %>! Sincerely, The Lottery Commission <%init> die "amount must be a positive value!" unless $.amount > 0; In addition to the substitution tag we've seen before, we declare two I, C and C, to be passed into the component; and we declare a piece of initialization code to validate the amount. In the same test directory, create a script C with the following: 1 #!/usr/local/bin/perl 2 use Mason; 3 my $interp = Mason->new(comp_root => 'comps', data_dir => 'data'); 4 print $interp->run('/email', name => 'Joe', amount => '1500')->output; Line 3 creates a I, the main Mason object. It specifies two parameters: a I, indicating the directory hierarchy where your components will live; and a I, which Mason will use for internal purposes such as class generation and caching. Line 4 runs the template - notice that the C<.mc> extension is added automatically - passing values for the C and C attributes. Run C, and you should see Dear Joe, We are pleased to inform you that you have won $1500.00! Sincerely, The Lottery Commission =head1 SEE ALSO L, L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/Plugins.pod000644 777777 777777 00000000212 12266570730 021736 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365395 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/Plugins.pod000644 €ˆž«€q{Ì00000011774 12266570730 020732 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::Plugins - Mason plugins =head1 DESCRIPTION A Mason plugin modifies behavior in one or more of Mason's main classes simultaneously, using Moose roles. Many Mason features, even some that might be considered "core", are implemented with plugins. =head1 FINDING PLUGINS By convention plugins live in the "Mason::Plugin::*" namespace, and plugin bundles live in the "Mason::PluginBundle::*" namespace. You can find both with this search: http://search.cpan.org/search?query=Mason%3A%3APlugin&mode=all =head1 USING PLUGINS Pass a list of plugin specs to the Mason constructor: Mason->new(plugins => [ 'OnePlugin', 'AnotherPlugin', '+My::Mason::Plugin::AThirdPlugin', '@APluginBundle', '+My::Mason::PluginBundle::AnotherBundle', '-PluginIDontLike', ]); Each plugin spec can be one of the following; =over =item * A simple name, which will have "Mason::Plugin::" prepended to it. =item * A bundle name, prefixed with '@', which will have "Mason::PluginBundle::" prepended to it. =item * A full plugin or bundle class name prefixed with '+'. =item * Any spec prefixed with '-', which means do not include these plugin(s) in the final list. =back See Mason::t::Plugins::test_plugin_specs in the Mason distribution for some examples. =head1 DEFAULT PLUGINS Mason will always add the L<@Default|Mason::PluginBundle::Default> bundle regardless of whether you pass your own list. You can remove individual default plugins that you don't like: plugins => ['-DollarDot', ...] or the whole list: plugins => ['-@Default', ...] =head1 CREATING PLUGINS Note: If you want to modify behavior for a particular application only, it might be more convenient to create L. A plugin consists of the main plugin class and one or more roles. The main class currently looks like this: package Mason::Plugin::MyPlugin; use Moose; with 'Mason::Plugin'; # Optional: declare other plugin dependencies method requires_plugins { qw(A @D) } 1; __END__ =pod =head1 NAME Mason::Plugin::MyPlugin - My plugin .... Its main responsibilities are to include the role 'Mason::Plugin' and document itself. It may also specify a C that returns a list of dependencies with the same syntax as the C parameter to Cnew>. The real action is in the role classes, which live underneath, and each modify a single Mason class: package Mason::Plugin::MyPlugin::Interp; use Mason::PluginRole; # Modify Mason::Interp ... package Mason::Plugin::MyPlugin::Compilation; use Mason::PluginRole; # Modify Mason::Compilation ... When a plugin is applied, each of its roles will be automatically applied to the appropriate Mason class. For example, in the example above C and C will be applied to Mason::Interp and Mason::Compilation respectively. =head2 Pluggable Mason classes As of this writing the following Mason classes can be modified with plugins: Mason::CodeCache Mason::Compilation Mason::Component Mason::Component::ClassMeta Mason::Component::Import Mason::Component::Moose Mason::Interp Mason::Request Mason::Result =head2 Extra classes in plugin If you have extra classes in your plugin that aren't automatically providing a role to a Mason class, put them in C or the C subdirectory, e.g. package Mason::Plugin::MyPlugin::Extra::Utils; ... That will ensure that your classname will not conflict with a future Mason class name. =head1 CREATING PLUGIN BUNDLES A plugin bundle just collects one or more plugins and/or other bundles. It looks like this: package Mason::PluginBundle::MyBundle use Moose; with 'Mason::PluginBundle'; sub requires_plugins { return ( 'A', 'B', '+My::Plugin::C', '@D', '+My::PluginBundle::E', ); } 1; __END__ =pod =head1 NAME Mason::PluginBundle::MyBundle - My plugin bundle =head1 INCLUDED PLUGINS =over =item A =item B =item +My::Plugin::C =item @D =item +My::PluginBundle::E =back .... The C method returns a list of entries, with the same syntax as the C parameter to Cnew>. =head1 ACKNOWLEDGEMENTS Thanks to Ricardo Signes for L and L, which got me thinking in plugins and lent the plugin and bundle name syntax. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/RequestDispatch.pod000644 777777 777777 00000000212 12266570730 023425 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365396 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/RequestDispatch.pod000644 €ˆž«€q{Ì00000007556 12266570730 022424 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::RequestDispatch - How request paths get mapped to page components =head1 DESCRIPTION Given the request path /news/sports/hockey Mason searches for the following components in order, setting $m->path_info as noted. /news/sports/hockey.{mp,mc} /news/sports/hockey/index.{mp,mc} /news/sports/hockey/dhandler.{mp,mc} /news/sports/dhandler.{mp,mc} # $m->path_info = hockey /news/sports.{mp,mc} # $m->path_info = hockey (but see next section) /news/dhandler.{mp,mc} # $m->path_info = sports/hockey /news.{mp,mc} # $m->path_info = sports/hockey (but see next section) /dhandler.{mp,mc} # $m->path_info = news/sports/hockey where C<< .{mp,mc} >> means either C<.mp> (indicating a I component). or C<.mc> (indicating a I component). The following sections describe these elements in more detail. =head2 Autoextended path The request path is suffixed with ".mp" and ".mc" to translate it to a component path. /news/sports/hockey.{mp,mc} =head2 Index An index matches its exact directory, nothing underneath. /news/sports/hockey/index.{mp,mc} =head2 Dhandlers A dhandler matches its directory as well as anything underneath, setting C<< $m->path_info >> to the remainder. /news/sports/hockey/dhandler.{mp,mc} /news/sports/dhandler.{mp,mc} # $m->path_info = hockey /news/dhandler.{mp,mc} # $m->path_info = sports/hockey /dhandler.{mp,mc} # $m->path_info = news/sports/hockey =head2 Partial paths A component can match an initial part of the URL, setting C<< $m->path_info >> to the remainder: /news/sports.{mp,mc} # $m->path_info = hockey /news.{mp,mc} # $m->path_info = sports/hockey Since this isn't always desirable behavior, it must be explicitly enabled for the component. Mason will call method C on the component class, and will only allow the match if it returns true: <%class> method allow_path_info { 1 } The default C returns false. C is not checked on dhandlers, since the whole point of dhandlers is to match partial paths. =head2 Trailing slash If the request URL has a trailing slash (ends with C), we remove it before the match process begins and add it to the C<< $m->path_info >>. Components that should match must have C return true. For example: ## request URL /news/ /news/index.{mp,mc} # $m->path_info = / if index.{mp,mc} has # allow_path_info => true /news/dhandler.{mp,mc} # $m->path_info = / /news.{mp,mc} # $m->path_info = / if news.{mp,mc} has # allow_path_info => true ## request URL /news/sports/ /news/sports/index.{mp,mc} # $m->path_info = / if index.{mp,mc} has # allow_path_info => true /news/sports/dhandler.{mp,mc} # $m->path_info = / /news/sports.{mp,mc} # $m->path_info = / if sports.{mp,mc} # has allow_path_info => true /news/dhandler.{mp,mc} # $m->path_info = sports/ /news.{mp,mc} # $m->path_info = /sports/ if news.{mp,mc} # has allow_path_info => true =head2 Routes It is possible to use route syntax to more elegantly parse C<< $m->path_info >> for dhandlers and partial paths, e.g. <%class> route "{year:[0-9]+}/{month:[0-9]{2}}"; See L. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/Setup.pod000644 777777 777777 00000000212 12266570730 021415 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365397 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/Setup.pod000644 €ˆž«€q{Ì00000004216 12266570730 020402 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::Setup - Setting up Mason =head1 SETUP =head2 Web development The most common use of Mason is to generate dynamic web content. L is a web framework designed specifically to work with Mason. Given an HTTP request, Poet generates a corresponding Mason request, and uses the output from Mason to form the HTTP response. Poet takes care of the web development details that are outside of Mason's domain, such as server integration and configuration. L shows how to set up a Poet/Mason site in great detail. Mason can also be used in the popular web frameworks L and L, as a drop-in replacement for their default template engines. See L and L. =head2 Non-web development Mason can be used to generate any kind of dynamic content. I have personally used it to generate Apache configuration files, emails, and C++ code. To use Mason from a script or library, use the L API: my $interp = Mason->new( comp_root => '/path/to/comps', data_dir => '/path/to/data', ... ); my $output = $interp->run( '/request/path', foo => 5 )->output(); If you want to process a directory with a mix of Mason templates and static files, check out L. To try out Mason syntax from the command line, use the L script: % mason 2 + 2 = <% 2+2 %> ^D 2 + 2 = 4 =head1 LOGGING Mason uses L to log various events, such as the start and end of each request. You can direct thesse logs to the output of your choice; see L. If you don't specify anything then the logs will go into the void. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/Subclasses.pod000644 777777 777777 00000000212 12266570730 022424 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365398 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/Subclasses.pod000644 €ˆž«€q{Ì00000004147 12266570730 021414 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::Subclasses - Creating custom subclasses of Mason's classes =head1 DESCRIPTION You can subclass the following Mason classes for your application: Mason::CodeCache Mason::Compilation Mason::Component Mason::Component::ClassMeta Mason::Component::Import Mason::Component::Moose Mason::Interp Mason::Request Mason::Result and arrange things so that Mason always uses your subclass instead of its default class. Note: if you want to create a general purpose modification to Mason to use in multiple applications, you should probably create a L instead of a subclass. =head1 CREATING A SUBCLASS A subclass should look something like this: package My::Mason::Interp; use Moose; extends 'Mason::Interp'; # put your modifications here 1; =head1 LETTING MASON KNOW ABOUT YOUR SUBCLASSES There are two ways to let Mason know about your subclasses: by naming convention, and by parameters to C<< Mason->new >>. =head2 By naming convention First, create a subclass of Mason itself: package My::Mason; use Moose; extends 'Mason'; 1; and use that in place of C<< Mason >> in construction: my $interp = My::Mason->new(); Now, you can place any subclasses under 'My::Mason' and they'll automatically be picked up. e.g. My::Mason::Compilation My::Mason::Interp My::Mason::Request =head1 By constructor parameter You can specify your subclasses via "base_*" parameters to C<< Mason->new() >>. e.g. my $interp = Mason->new( base_compilation_class => 'My::Mason::Compilation', base_interp_class => 'My::Mason::Interp' base_request_class => 'Some::Other::Mason::Request' ); See L for a complete list. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/Syntax.pod000644 777777 777777 00000000212 12266570730 021603 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365399 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/Syntax.pod000644 €ˆž«€q{Ì00000022770 12266570730 020575 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::Syntax - Mason component syntax reference =head1 DESCRIPTION A reference for all the syntax that can be used in components. =head1 SUBSTITUTION TAGS =head2 <% I %> Blocks of the form C<< <% expr %> >> are replaced with the result of evaluating C as a Perl expression in scalar context. Hello, <% $name %>! The current time is <% scalar(localtime) %>. Whitespace after '<%' and before '%>' is required. This gives us a little leeway in implementing variations on this tag in the future - it also just looks better. =head2 <% I | I,I... %> A filter list may appear after a << | >> character in a substitution, containing one or more names separated by commas. The names are as filter methods on the current component class. The filters are applied to the result before it is output. <% $content | NoBlankLines,Trim %> See L for more information on filters. =head1 PERL LINES =head2 %-lines Lines beginning with a single '%' are treated as Perl. The '%' must be followed by at least one whitespace character.
      % foreach my $item (@items) {
    • <% $item %>
    • % }
    % if ($.logged_in) {
    Welcome, <% $.username %>.
    % } % else { Click here to log in % } =head1 UNNAMED BLOCKS Blocks that do not take a name argument. =head2 <%class> Contains Perl code code that executes once when the component is loaded, in the main body of the class outside of any methods. This is the place to use modules, declare attributes, and do other things on a class level. <%class> =head2 <%doc> Text in this section is treated as a comment and ignored. <%doc> Name: foo.mc Purpose: ... =head2 <%flags> Specifies flags that affect the compilation of the component. Each flag is listed one per line in C<< key => value >> form. <%flags> extends => '/foo/bar' The C<< <%flags> >> block is extracted in a special first pass through the component, so that it can affect the remainder of the compilation. The built-in flags are: =over =item extends Declares the component's superclass (another component). The path may be absolute as shown above, or relative to the component's path. This is the only way to declare the component's superclass; using an C<< extends >> keyword directly will not work reliably. If not provided, the component's superclass is determined automatically via L. =back Plugins may implement additional flags. =head2 <%init> Contains Perl code that is executed at the beginning of the current method. Equivalent to a C<< <%perl> >> section at the top of the method. <%init> my $article = MyApp::Article->find($.article_id); my $title = $article->title; =head2 <%perl> Contains Perl code that is executed in place. The return value, if any, is discarded. May appear anywhere in the text and any number of times. <%perl> my $article = MyApp::Article->find($.article_id); my $title = $article->title; =head2 <%text> Text in this section is printed as-is with all Mason syntax ignored. <%text> % This is an example of a Perl line. <% This is an example of an expression block. %> This works for almost everything, but doesn't let you output C<< >> itself! When all else fails, use L: % $m->print('The tags are <%text> and .'); =head1 NAMED BLOCKS Blocks that take a name argument. =head2 <%method I I> Creates a new method with the specified I and I. Uses L underneath, so C<$self> and any other declared parameters are automatically shifted off of C<@_>. <%method greet ($name, $color)>
    Hello, <% $name %>!
    =head2 <%after I> =head2 <%augment I> =head2 <%around I> =head2 <%before I> =head2 <%override I> Modifies a content-producing method with the specified I. See L for a description of each modifier. C<$self> is automatically shifted off for the body of C<< <%after> >>, C<< <%augment> >>, C<< <%before> >> and C< <%override> >. C<$orig> and C<$self> are automatically shifted off for the body of C<< <%around> >>. <%after render> <% # Add analytics line after everything has rendered %> <& /shared/google_analytics_line.mi &> <%augment wrap> <% inner() %> <%around navbar> <%override navbar> <% super() %> extra =head2 <%filter I I> Creates a filter method with the specified I and I. Works just like a C<< <%method> >> block, except that you can call C<< $yield->() >> to generate the original content. e.g. <%filter Row ($class)> % foreach my $item (split(/\s/, $yield->())) { <% $item %> % } % $.Row('std') {{ First Second Third % }} generates First Second Third See L for more information on filters. =head1 CALLING COMPONENTS =head2 <& I, I &> <& /path/to/comp.mi, name=>value, ... &> I is an absolute or relative component path. If the latter, it is considered relative to the location of the current component. I is a list of one or more name/value pairs. The path may be a literal string (quotes optional) or a Perl expression that evaluates to a string. To eliminate the need for quotes in most cases, Mason employs some magic parsing: If the first character is one of C<[\w/\.]>, comp_path is assumed to be a literal string running up to the first comma or &>. Otherwise, comp_path is evaluated as an expression. Here are some examples: # relative component paths <& topimage.mi &> <& tools/searchbox.mi &> # absolute component path <& /shared/masthead.mi, color=>'salmon' &> # this component path MUST have quotes because it contains a comma <& "sugar,eggs.mi", mix=>1 &> # variable component path <& $comp &> # variable component and attributes <& $comp, %args &> # you can use arbitrary expression for component path, but it cannot # begin with a letter or number; delimit with () to remedy this <& (int(rand(2)) ? 'thiscomp.mi' : 'thatcomp.mi'), id=>123 &> You can also call components with the L and L methods. =head1 COMMENTS =head2 <% # comment... %> A C<< <% %> >> tag is considered a comment if all of its lines are either whitespace, or begin with a '#' optionally preceded by whitespace. For example, <% # This is a single-line comment %> <% # This is a # multi-line comment %> =head2 % # comment Because a line beginning with C<%> is treated as Perl, C<% #> automatically works as a comment. However we prefer the C<< <% # comment %> >> form over C<< % # >>, because it stands out a little more as a comment and because it is more flexible with regards to preceding whitespace. =head2 % if (0) { } Anything between these two lines % if (0) { ... % } will be skipped by Mason, including component calls. While we don't recomend this for comments per se, it is a useful notation for "commenting out" code that you don't want to run. =head2 HTML/XML/... comments HTML and other markup languages will have their own comment markers, for example C<< >>. Note two important differences with these comments versus the above comments: =over =item * They will be sent to the client and appear in the source of the page. =item * They do not block component calls and other code from running, so don't try to use them to comment out code! =back =head1 WHITESPACE AND NEWLINES =head2 Newlines between blocks Mason will ignore a single newline between blocks, so that you can space them nicely. Additional newlines beyond that will be displayed. <%class> ... <-- ignored <%method foo> ... <-- ignored <-- displayed <%method bar> ... =head2 Backslash at end of line A backslash (\) at the end of a line suppresses the newline. In HTML components, this is mostly useful for fixed width areas like C<<
     >> tags,
    since browsers ignore white space for the most part. An example:
    
        
        foo
        % if (1) {
        bar
        % }
        baz
        
    outputs foo bar baz because of the newlines on lines 2 and 4. (Lines 3 and 5 do not generate a newline because the entire line is taken by Perl.) To suppress the newlines:
        foo\
        % if (1) {
        bar\
        % }
        baz
        
    which prints foobarbaz =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/Tutorial.pod000644 777777 777777 00000000212 12266570730 022120 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365400 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/Tutorial.pod000644 €ˆž«€q{Ì00000000772 12266570730 021110 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::Tutorial - Mason tutorial (DEPRECATED - SEE POET) =head1 DESCRIPTION This tutorial has moved to L. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Manual/PaxHeader/UpgradingFromMason1.pod000644 777777 777777 00000000212 12266570730 024140 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365401 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Manual/UpgradingFromMason1.pod000644 €ˆž«€q{Ì00000015261 12266570730 023127 0ustar00jonswart000000 000000 __END__ =pod =head1 NAME Mason::Manual::UpgradingFromMason1 - Summary of differences between Mason 1 and Mason 2 =head1 DESCRIPTION Mason 2.x comes ten years after Mason 1.0 (known as L) and twelve years after the original Mason release. It has been rearchitected and reimplemented from the ground up. That said, the philosophy and core syntax are similar enough that it should still be recognizable and "feel like Mason" to existing users. This manual attempts to summarize the differences between Mason 1 and 2, to help existing users decide if they are interested and, if so, migrate their projects. There is currently no automated way to convert a Mason 1 to a Mason 2 site, but there hopefully will be someday. (Contributions welcome. :)) =head1 ARCHITECTURE =over =item * In Mason 1, each component was an instance of a common Component class. In Mason 2, each component is its I Moose class, with a class name generated from the component path. =item * The main component body - the content and the inline Perl sections - are placed into a C
    method. =item * Calling a component (via C<< <& &> >> or C<< $m->comp >> ) entails creating a new instance of the component class, and calling its C
    method. Component call parameters are passed to the constructor and placed in attributes. =back =head1 MAJOR FEATURES =over =item * B now utilize Moose roles and are much more powerful and flexible than in Mason 1. Some features that were (or would have been) in the core of Mason 1 are now in plugins. See L. =item * B in Mason 1 was centered around mod_perl and was part of the core. In Mason 2 all web integration has been split out into a companion web framework, L, which in turn uses L to integrate with any server backend. You can also use Mason as the templating layer in popular web frameworks such as L and L. There is no longer anything web-specific in the Mason core. =item * B have been eliminated, replaced with class methods. =item * B has been eliminated. Mason now simply throws fatal errors to the caller. In a L environment, L will catch the error and format it nicely. =item * B and B have been eliminated. Components need to be in files. If your components live in another data source, you could use L or a custom plugin to keep a file hierarchy up to date with the data source. =item * B support has been simplified. C<< $m->cache >> simply returns a L object with an appropriate namespace for the component. =back =head1 SYNTAX =over =item * C<< <%once> >> has been replaced with C<< <%class> >>. =item * C<< <%cleanup> >> has been eliminated; it was not very useful anyway, since it was not guaranteed to run after an exception. You can use L to add cleanup code for the end of the request, which is good enough in most cases, or you can add a C method to the component. =item * Single blank lines between blocks are now removed, so you can space blocks out for readability without generating a ton of newlines. =item * Whitespace is required after a %-line and around the expression in a C<< <% %> >> tag. This improves readability and leaves open the possibility of additional syntax. =item * C<< <%args> >> and C<< <%shared> >> are gone. Use Moose attributes instead. =item * The C<< <%ARGS> >> hash is gone, you can instead use C<< $.args >> or C<< $self->args >> to get all the parameters passed to a component. =item * C<< <%method> >> and C<< <%def> >> have been replaced with just C<< <%method> >>, which creates a true class method rather than a subcomponent. =item * The C<< <%filter> >> tag is now used to define filters, instead of automatically applying a filter to the current component. =item * C<< Components with content >> syntax has been eliminated; use the L filter instead. =item * C<< Escape flags >> in substitution tags now utilize L. =back =head1 MISC PARAMETER CHANGES =head2 Interp parameters =over =item * C, C and C have been deemed unnecessary and eliminated. =item * C has been eliminated; define filters instead. =item * C now defaults to a directory created with L. =item * C has been eliminated; this code does roughly the same: $interp->load($_) for (grep { /some_condition/ } $interp->all_paths); =back =head2 Request parameters =over =item * C and C have been eliminated because they are too difficult to implement efficiently. =back =head2 Compiler parameters =over =item * C, C, and C have been eliminated; similar effects can be achieved with plugins targeting L. =item * C has been eliminated, but see L for a third-party substitute. =back =head1 MISC METHOD CHANGES =head2 Interp methods =over =item * C has been renamed to L. =back =head2 Request methods =over =item * C has been eliminated; use the L instead. =item * C, C and C have been eliminated; now that component calls are simply method calls underneath, they are too difficult to implement efficiently. =item * C has been replaced with Moose's C. =item * C has been eliminated; use L instead. =item * C has been eliminated. Within a component, use C<< $self >>; outside a component you can call L, which will at least get you the class. =item * C has been renamed to L. =item * C has been renamed to L. =item * C has been renamed to L. =item * C has been replaced with L and L. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Filters/PaxHeader/Standard.pm000644 777777 777777 00000000212 12266570730 022102 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365388 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Filters/Standard.pm000644 €ˆž«€q{Ì00000006167 12266570730 021076 0ustar00jonswart000000 000000 package Mason::Filters::Standard; { $Mason::Filters::Standard::VERSION = '2.21'; } use Mason::DynamicFilter; use Mason::Util; use Mason::PluginRole; method Capture ($outref) { sub { $$outref = $_[0]; return '' } } method CompCall ($path, @params) { Mason::DynamicFilter->new( filter => sub { my $m = $self->m; return $m->scomp( $path, @params, yield => $_[0] ); } ); } method NoBlankLines () { sub { my $text = $_[0]; $text =~ s/^\s*\n//mg; return $text; }; } method Repeat ($times) { Mason::DynamicFilter->new( filter => sub { my $content = ''; for ( my $i = 0 ; $i < $times ; $i++ ) { $content .= $_[0]->(); } return $content; } ); } method Tee ($outref) { sub { $$outref = $_[0]; return $_[0] } } method Trim () { sub { Mason::Util::trim( $_[0] ) } } 1; __END__ =pod =head1 NAME Mason::Filters::Standard - Standard filters =head1 DESCRIPTION These filters are automatically composed into L. =head1 FILTERS =over =item Capture ($ref) Uses C<< $m->capture >> to capture the content in I<$ref> instead of outputting it. % $.Capture(\my $content) {{ % }} ... do something with $content =item CompCall ($path, @args...) Calls the component with I and I<@args>, just as with C<< $m->scomp >>, with an additional coderef argument C that can be invoked to generate the content. Arguments passed to C can be accessed inside the content via C<@_>. This is the replacement for Mason 1's L. In index.mc: % $.CompCall ('list_items.mi', items => \@items) {{
  • <% $_[0] %>
  • % }} In list_items.mi: <%class> has 'items'; has 'yield'; % foreach my $item (@{$.items}) { <% $.yield->($item) %> % } =item NoBlankLines Remove lines with only whitespace from content. This % $.NoBlankLines {{ hello world % }} yields hello world =item Repeat ($count) Repeat the content block I<$count> times. Note that the block is re-executed each time, which may result in different content. % my $i = 1; % $.Repeat(5) {{ <% $i++ %>
    % }} =item Tee ($ref) Uses C<< $m->capture >> to capture the content in I<$ref>, and also output it. % $.Tee(\my $content) {{ % }} ... <% $content %> =item Trim Remove whitespace from the beginning and end of the content. =back =head1 SEE ALSO L, L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Component/PaxHeader/ClassMeta.pm000644 777777 777777 00000000212 12266570730 022550 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365384 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Component/ClassMeta.pm000644 €ˆž«€q{Ì00000005210 12266570730 021530 0ustar00jonswart000000 000000 package Mason::Component::ClassMeta; { $Mason::Component::ClassMeta::VERSION = '2.21'; } use File::Basename; use Mason::Moose; use Log::Any; my $next_id = 0; # Passed attributes (generated in compiled component) has 'class' => ( required => 1 ); has 'dir_path' => ( required => 1 ); has 'interp' => ( required => 1, weak_ref => 1 ); has 'is_dhandler' => ( init_arg => undef, lazy_build => 1 ); has 'is_top_level' => ( required => 1 ); has 'object_file' => ( required => 1 ); has 'path' => ( required => 1 ); has 'source_file' => ( required => 1 ); # Derived attributes has 'id' => ( init_arg => undef, default => sub { $next_id++ } ); has 'log' => ( init_arg => undef, lazy_build => 1 ); has 'name' => ( init_arg => undef, lazy_build => 1 ); method _build_is_dhandler () { return grep { $self->name eq $_ } @{ $self->interp->dhandler_names }; } method _build_log () { my $log_category = "Mason::Component" . $self->path; $log_category =~ s/\//::/g; return Log::Any->get_logger( category => $log_category ); } method _build_name () { return basename( $self->path ); } __PACKAGE__->meta->make_immutable(); 1; __END__ =pod =head1 NAME Mason::Component::ClassMeta - Meta-information about Mason component class =head1 SYNOPSIS # In a component: My path is <% $.cmeta->path %> My source file is <% $.cmeta->source_file %> =head1 DESCRIPTION Every L class has an associated L object, containing meta-information such as the component's path and source file. It can be accessed with the L method. =over =item class The component class that this meta object is associated with. =item dir_path The directory of the component path, relative to the component root - e.g. for a component '/foo/bar', the dir_path is '/foo'. =item is_top_level Whether the component is considered "top level", accessible directly from C<< $interp->run >> or a web request. See L. =item name The component base name, e.g. 'bar' for component '/foo/bar'. =item object_file The object file produced from compiling the component. =item path The component path, relative to the component root - e.g. '/foo/bar'. =item source_file The component source file. =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Component/PaxHeader/Import.pm000644 777777 777777 00000000212 12266570730 022146 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365385 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Component/Import.pm000644 €ˆž«€q{Ì00000001570 12266570730 021133 0ustar00jonswart000000 000000 package Mason::Component::Import; { $Mason::Component::Import::VERSION = '2.21'; } use strict; use warnings; sub import { my $class = shift; my $caller = caller; $class->import_into($caller); } sub import_into { my ( $class, $for_class ) = @_; # no-op by default } 1; __END__ =pod =head1 NAME Mason::Component::Import - Extra component imports =head1 DESCRIPTION This module is automatically use'd in each generated Mason component class. It imports nothing by default, but you can modify the C method in plugins to add imports. =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/lib/Mason/Component/PaxHeader/Moose.pm000644 777777 777777 00000000212 12266570730 021756 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365386 18 SCHILY.nlink=1 Mason-2.21/lib/Mason/Component/Moose.pm000644 €ˆž«€q{Ì00000003737 12266570730 020752 0ustar00jonswart000000 000000 package Mason::Component::Moose; { $Mason::Component::Moose::VERSION = '2.21'; } ## no critic (Moose::RequireMakeImmutable) use Moose (); use MooseX::HasDefaults::RW (); use Method::Signatures::Simple (); use Moose::Exporter; use strict; use warnings; Moose::Exporter->setup_import_methods( also => ['Moose'] ); sub init_meta { my $class = shift; my %params = @_; my $for_class = $params{for_class}; Method::Signatures::Simple->import( into => $for_class ); MooseX::HasDefaults::RW->import( { into => $for_class } ); { no strict 'refs'; *{ $for_class . '::CLASS' } = sub () { $for_class }; # like CLASS.pm *{ $for_class . '::CLASS' } = \$for_class; } } 1; __END__ =pod =head1 NAME Mason::Component::Moose - Moose policies and exports for Mason components =head1 DESCRIPTION This module is automatically included in each generated Mason component class, and is equivalent to use CLASS; use Moose; use MooseX::HasDefaults::RW; use Method::Signatures::Simple; =head1 OVERRIDING To override the default behavior, subclass this class and specify it as C to L. For example, to use L in every component: package My::Mason::Component::Moose; use Moose::Exporter; use MooseX::StrictConstructor (); use base qw(Mason::Component::Moose); sub init_meta { my $class = shift; $class->SUPER::init_meta(@_); MooseX::StrictConstructor->init_meta(@_); } ... my $interp = Mason::Interp->new(..., base_component_moose_class => 'My::Mason::Component::Moose'); =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut Mason-2.21/eg/PaxHeader/blog000775 777777 777777 00000000212 12266570730 016017 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365360 18 SCHILY.nlink=3 Mason-2.21/eg/blog/000775 €ˆž«€q{Ì00000000000 12266570730 015053 5ustar00jonswart000000 000000 Mason-2.21/eg/blog/PaxHeader/README000644 777777 777777 00000000212 12266570730 016747 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365361 18 SCHILY.nlink=1 Mason-2.21/eg/blog/README000644 €ˆž«€q{Ì00000000177 12266570730 015736 0ustar00jonswart000000 000000 Moved to eg/blog in Poet. http://search.cpan.org/perldoc?Poet https://github.com/jonswar/perl-poet/tree/master/eg/blog Mason-2.21/bin/PaxHeader/mason.pl000755 777777 777777 00000000212 12266570730 016776 xustar00jonswart000000 000000 18 gid=1896053708 17 uid=512269995 20 ctime=1390080472 20 atime=1390080472 23 SCHILY.dev=16777220 22 SCHILY.ino=9365358 18 SCHILY.nlink=1 Mason-2.21/bin/mason.pl000755 €ˆž«€q{Ì00000003260 12266570730 015761 0ustar00jonswart000000 000000 #!/usr/bin/perl use strict; use warnings; use Mason::App; Mason::App->run(); __END__ =pod =head1 NAME mason.pl - evaluate a mason template and output the result =head1 SYNOPSIS # Evaluate template from STDIN mason.pl [mason options] [--args json-string] # Evaluate template in string mason.pl [mason options] [--args json-string] -e "string" # Evaluate template in file mason.pl [mason options] [--args json-string] template-file =head1 DESCRIPTION Reads a Mason template (component) from STDIN, a string, or a file. Runs the template and outputs the result to STDOUT. =head1 MASON OPTIONS The following Mason options can be specified on the command line: --data-dir /path/to/data_dir --plugins MyPlugin,MyOtherPlugin The C will be set to the directory of the template file or to a temporary directory if using STDIN. If not specified C will be set to a temporary directory. =head1 ADDITIONAL OPTIONS =over =item --args json-string A hash of arguments to pass to the page component, in JSON form. e.g. --args '{"count":5,"names":["Alice","Bob"]}' =back =head1 SEE ALSO L =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2011 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =head1 AUTHOR Jonathan Swartz =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2012 by Jonathan Swartz. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut