diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index d7fac99..118f5fb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,70 @@ -# Etherpad-lite for YunoHost +# Etherpad for YunoHost -[![Integration level](https://dash.yunohost.org/integration/REPLACEBYYOURAPP.svg)](https://dash.yunohost.org/appci/app/etherpadlite) ![](https://ci-apps.yunohost.org/ci/badges/etherpadlite.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/etherpadlite.maintain.svg) -[![Install Etherpad-lite with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=etherpadlite) +[![Integration level](https://dash.yunohost.org/integration/etherpad.svg)](https://dash.yunohost.org/appci/app/etherpad) ![](https://ci-apps.yunohost.org/ci/badges/etherpad.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/etherpad.maintain.svg) +[![Install Etherpad with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=etherpad) + +*[Lire ce readme en français.](./README_fr.md)* + +> *This package allow you to install Etherpad quickly and simply on a YunoHost server. +If you don't have YunoHost, please see [here](https://yunohost.org/#/install) to know how to install and enjoy it.* + +## Overview +Etherpad is a highly customizable Open Source online editor providing collaborative editing in really real-time. + +**Shipped version:** 1.8.6 + +## Screenshots + +![](https://github.com/ether/etherpad/blob/develop/doc/images/etherpad_demo.gif) + +## Demo + +* [Official demo](https://video.etherpad.com/) + +## Configuration + +You can access two different admin panels, for Etherpad by accessing `domain.tld/admin`. +You can also find a configuration file for Etherpad at this path `/var/www/etherpad/settings.json`. + +*Skin Builder* (accessible at this address `domain.tld/pad/p/test#skinvariantsbuilder`) allows you to customize the skin of your pad. It will give you a parameter to copy into your configuration file `/var/www/etherpad/settings.json`. + +## Documentation + + * Official documentation: http://etherpad.org/doc/v1.8.6 + * YunoHost documentation: https://yunohost.org/#/app_etherpad + +## YunoHost specific features + +#### Multi-users support + + * Is LDAP auth supported? **No** + * Can the app be used by multiple users? **Yes** + +#### Supported architectures + +* x86-64 - [![](https://ci-apps.yunohost.org/ci/logs/etherpad%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/etherpad/) +* ARMv8-A - [![](https://ci-apps-arm.yunohost.org/ci/logs/etherpad%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/etherpad/) + +## Limitations + +## Additionnal informations + +## Links + + * Report a bug: https://github.com/YunoHost-Apps/etherpad_ynh/issues + * Etherpad website: http://etherpad.org/ + * Upstream app repository: https://github.com/ether/etherpad-lite + * YunoHost website: https://yunohost.org/ + +--- + +## Developers infos + +Please do your pull request to the [testing branch](https://github.com/YunoHost-Apps/etherpad_ynh/tree/testing). + +To try the testing branch, please proceed like that. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/etherpad_ynh/tree/testing --debug +or +sudo yunohost app upgrade etherpad -u https://github.com/YunoHost-Apps/etherpad_ynh/tree/testing --debug +``` diff --git a/README_fr.md b/README_fr.md new file mode 100644 index 0000000..48720f3 --- /dev/null +++ b/README_fr.md @@ -0,0 +1,70 @@ +# Etherpad pour YunoHost + +[![Niveau d'intégration](https://dash.yunohost.org/integration/etherpad.svg)](https://dash.yunohost.org/appci/app/etherpad) ![](https://ci-apps.yunohost.org/ci/badges/etherpad.status.svg) [![](https://ci-apps.yunohost.org/ci/badges/etherpad.maintain.svg)](https://github.com/YunoHost/Apps/#what-to-do-if-i-cant-maintain-my-app-anymore-) +[![Installer Etherpad avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=etherpad) + +*[Read this readme in english.](./README.md)* + +> *Ce package vous permet d'installer Etherpad rapidement et simplement sur un serveur YunoHost. +Si vous n'avez pas YunoHost, merci de regarder [ici](https://yunohost.org/#/install_fr) pour savoir comment l'installer et en profiter.* + +## Résumé +Etherpad est un éditeur en ligne Open Source hautement personnalisable qui permet l'édition collaborative en temps réel. +Ce paquet installera les mêmes plugins que [Framapad](https://framapad.org/). + +**Version embarquée :** 1.8.6 + +## Captures d'écran + +![](https://github.com/ether/etherpad-lite/blob/develop/doc/images/etherpad_demo.gif) + +## Démo + +* [Démo officielle](https://video.etherpad.com/) + +## Configuration + +Vous pouvez accéder à deux panneaux d'administration différents, pour Etherpad en accédant à `domain.tld/admin` et pour MyPads par `domain.tld/mypads/?/admin`. Vous pouvez également trouver le fichier de configuration pour Etherpad à `/var/www/etherpad/settings.json`. + +*Skin Builder* (accessible à cette adresse `domain.tld/pad/p/test#skinvariantsbuilder`) vous permet de personnaliser l'apparence de votre pad. Il vous donnera un paramètre à copier dans votre fichier de configuration `/var/www/etherpad/settings.json`. + +## Documentation + + * Documentation officielle : http://etherpad.org/doc/v1.8.6 + * Documentation YunoHost : https://yunohost.org/#/app_etherpad + +## Fonctionnalités spécifiques à YunoHost + +#### Support multi-utilisateurs + + * L'authentification LDAP est-elle prise en charge ? **Non** + * L'application peut-elle être utilisée par plusieurs utilisateurs ? **Oui** + +#### Architectures supportées + +* x86-64 - [![](https://ci-apps.yunohost.org/ci/logs/etherpad%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/etherpad/) +* ARMv8-A - [![](https://ci-apps-arm.yunohost.org/ci/logs/etherpad%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/etherpad/) + +## Limitations + +## Informations additionnelles + +## Liens + + * Reporter un bug : https://github.com/YunoHost-Apps/etherpad_ynh/issues + * Site d'Etherpad : http://etherpad.org/ + * Dépôt GitHub de l'application : https://github.com/ether/etherpad-lite + * Site de YunoHost : https://yunohost.org/ + +--- + +## Informations à l'intention des développeurs + +Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/etherpad_ynh/tree/testing). + +Pour tester la branche testing, merci de procéder ainsi. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/etherpad_ynh/tree/testing --debug +ou +sudo yunohost app upgrade etherpad -u https://github.com/YunoHost-Apps/etherpad_ynh/tree/testing --debug +``` diff --git a/check_process b/check_process new file mode 100644 index 0000000..d0be191 --- /dev/null +++ b/check_process @@ -0,0 +1,35 @@ +# See here for more information +# https://github.com/YunoHost/package_check#syntax-check_process-file + +# Move this file from check_process.default to check_process when you have filled it. + +;; Test complet + ; Manifest + domain="domain.tld" (DOMAIN) + path="/path" (PATH) + admin="john" (USER) + language="fr" + is_public=1 (PUBLIC|public=1|private=0) + password="pass" + port="9001" (PORT) + ; Checks + pkg_linter=1 + setup_sub_dir=1 + setup_root=1 + setup_nourl=0 + setup_private=1 + setup_public=1 + upgrade=1 + backup_restore=1 + multi_instance=1 + port_already_use=0 + change_url=1 +;;; Levels + Level 5=auto +;;; Options +Email= +Notification=none +;;; Upgrade options + ; commit=CommitHash + name=Name and date of the commit. + manifest_arg=domain=DOMAIN&path=PATH&admin=USER&language=fr&is_public=1&password=pass&port=9001& diff --git a/conf/app.src b/conf/app.src new file mode 100644 index 0000000..a8a7630 --- /dev/null +++ b/conf/app.src @@ -0,0 +1,6 @@ +SOURCE_URL=https://github.com/ether/etherpad-lite/archive/1.8.6.tar.gz +SOURCE_SUM=89f9c8e8b2aff4335e02b5ec00eec67410eb3ab08f0d55d5dd0670a5c558bf09 +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=tar.gz +SOURCE_IN_SUBDIR=true +SOURCE_FILENAME= diff --git a/conf/credentials.json b/conf/credentials.json new file mode 100644 index 0000000..5bea828 --- /dev/null +++ b/conf/credentials.json @@ -0,0 +1,49 @@ +/* + This file must be valid JSON. But comments are allowed +*/ +{ + /* + * The type of the database. + * + * You can choose between many DB drivers, for example: dirty, postgres, + * sqlite, mysql. + * + * You shouldn't use "dirty" for for anything else than testing or + * development. + * + * + * Database specific settings are dependent on dbType, and go in dbSettings. + * Remember that since Etherpad 1.6.0 you can also store these informations in + * credentials.json. + * + * For a complete list of the supported drivers, please refer to: + * https://www.npmjs.com/package/ueberdb2 + */ + + /* An Example of MySQL Configuration */ + "dbType" : "postgres", + "dbSettings" : { + "user" : "__DB_NAME__", + "host" : "localhost", + "password": "__DB_PWD__", + "database": "__DB_NAME__" + }, + + /* + * Users for basic authentication. + * + * is_admin = true gives access to /admin. + * If you do not uncomment this, /admin will not be available! + * + * WARNING: passwords should not be stored in plaintext in this file. + * If you want to mitigate this, please install ep_hash_auth and + * follow the section "secure your installation" in README.md + */ + + "users": { + "__ADMIN__": { + "password": "__PASSWORD__", + "is_admin": true + } + } +} diff --git a/conf/etherpad-lite b/conf/etherpad-lite deleted file mode 100644 index d3d1f06..0000000 --- a/conf/etherpad-lite +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: etherpad-lite -# Required-Start: $local_fs $remote_fs $network $syslog -# Required-Stop: $local_fs $remote_fs $network $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: starts etherpad lite -# Description: starts etherpad lite using start-stop-daemon -### END INIT INFO - -PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/node/bin" -LOGFILE="/var/log/APPTOCHANGE/APPTOCHANGE.log" -EPLITE_DIR="/var/www/APPTOCHANGE" -EPLITE_BIN="bin/safeRun.sh" -USER="www-data" -GROUP="www-data" -DESC="Etherpad Lite" -NAME="APPTOCHANGE" - -set -e - -. /lib/lsb/init-functions - -start() { - echo "Starting $DESC... " - - start-stop-daemon --start --chuid "$USER:$GROUP" --background --make-pidfile --pidfile /var/run/$NAME.pid --exec $EPLITE_DIR/$EPLITE_BIN -- $LOGFILE || true - echo "done" -} - -#We need this function to ensure the whole process tree will be killed -killtree() { - local _pid=$1 - local _sig=${2-TERM} - for _child in $(ps -o pid --no-headers --ppid ${_pid}); do - killtree ${_child} ${_sig} - done - kill -${_sig} ${_pid} -} - -stop() { - echo "Stopping $DESC... " - if test -f /var/run/$NAME.pid; then - while test -d /proc/$(cat /var/run/$NAME.pid); do - killtree $(cat /var/run/$NAME.pid) 15 - sleep 0.5 - done - rm /var/run/$NAME.pid - fi - echo "done" -} - -status() { - status_of_proc -p /var/run/$NAME.pid "" "APPTOCHANGE" && exit 0 || exit $? -} - -case "$1" in - start) - start - ;; - stop) - stop - ;; - restart) - stop - start - ;; - status) - status - ;; - *) - echo "Usage: $NAME {start|stop|restart|status}" >&2 - exit 1 - ;; -esac - -exit 0 diff --git a/conf/nginx.conf b/conf/nginx.conf index 732dcc6..bff47bc 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,6 +1,22 @@ -location YNH_PATH/ { - rewrite ^YNH_PATH$ YNH_PATH/ permanent; - proxy_pass http://YNH_DOMAIN:YNH_PORT/; - proxy_set_header Host $host; - proxy_buffering off; +location __PATH__/ { + + # Force usage of https + if ($scheme = http) { + rewrite ^ https://$server_name$request_uri? permanent; + } + + proxy_pass http://127.0.0.1:__PORT__/; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Include SSOWAT user panel. + include conf.d/yunohost_panel.conf.inc; } diff --git a/conf/nginx.conf-nosub b/conf/nginx.conf-nosub deleted file mode 100644 index 954771d..0000000 --- a/conf/nginx.conf-nosub +++ /dev/null @@ -1,6 +0,0 @@ -location / { - proxy_pass http://localhost:9001/; - proxy_set_header Host $host; - # be careful, this line doesn't override any proxy_buffering on set in a conf.d/file.conf - proxy_buffering off; -} diff --git a/conf/settings.json b/conf/settings.json index 44b4d84..66ee42b 100644 --- a/conf/settings.json +++ b/conf/settings.json @@ -1,150 +1,534 @@ /* - This file must be valid JSON. But comments are allowed - - Please edit settings.json, not settings.json.template -*/ + * This file must be valid JSON. But comments are allowed + * + * Please edit settings.json, not settings.json.template + * + * Please note that starting from Etherpad 1.6.0 you can store DB credentials in + * a separate file (credentials.json). + * + * + * ENVIRONMENT VARIABLE SUBSTITUTION + * ================================= + * + * All the configuration values can be read from environment variables using the + * syntax "${ENV_VAR}" or "${ENV_VAR:default_value}". + * + * This is useful, for example, when running in a Docker container. + * + * EXAMPLE: + * "port": "${PORT:9001}" + * "minify": "${MINIFY}" + * "skinName": "${SKIN_NAME:colibris}" + * + * Would read the configuration values for those items from the environment + * variables PORT, MINIFY and SKIN_NAME. + * + * If PORT and SKIN_NAME variables were not defined, the default values 9001 and + * "colibris" would be used. + * The configuration value "minify", on the other hand, does not have a + * designated default value. Thus, if the environment variable MINIFY were + * undefined, "minify" would be null. + * + * REMARKS: + * 1) please note that variable substitution always needs to be quoted. + * + * "port": 9001, <-- Literal values. When not using + * "minify": false substitution, only strings must be + * "skinName": "colibris" quoted. Booleans and numbers must not. + * + * "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable + * "minify": "${MINIFY:true}" substitution, put quotes around its name, + * "skinName": "${SKIN_NAME}" even if the required value is a number or + * a boolean. + * Etherpad will take care of rewriting it + * to the proper type if necessary. + * + * "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes + * "minify": ${MINIFY} around variable names are missing. + * "skinName": ${SKIN_NAME} + * + * 2) Beware of undefined variables and default values: nulls and empty strings + * are different! + * + * This is particularly important for user's passwords (see the relevant + * section): + * + * "password": "${PASSW}" // if PASSW is not defined would result in password === null + * "password": "${PASSW:}" // if PASSW is not defined would result in password === '' + * + * If you want to use an empty value (null) as default value for a variable, + * simply do not set it, without putting any colons: "${ABIWORD}". + * + * 3) if you want to use newlines in the default value of a string parameter, + * use "\n" as usual. + * + * "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2" + */ { - // Name your instance! + /* + * Name your instance! + */ "title": "Etherpad", - // favicon default name - // alternatively, set up a fully specified Url to your own favicon + /* + * favicon default name + * alternatively, set up a fully specified Url to your own favicon + */ "favicon": "favicon.ico", - //IP and port which etherpad should bind at - "ip": "0.0.0.0", - "port" : 9001, - - // Session Key, used for reconnecting user sessions - // Set this to a secure string at least 10 characters long. Do not share this value. - "sessionKey" : "KEY", + /* + * Skin name. + * + * Its value has to be an existing directory under src/static/skins. + * You can write your own, or use one of the included ones: + * + * - "no-skin": an empty skin (default). This yields the unmodified, + * traditional Etherpad theme. + * - "colibris": the new experimental skin (since Etherpad 1.8), candidate to + * become the default in Etherpad 2.0 + */ + "skinName": "colibris", /* - // Node native SSL support - // this is disabled by default - // - // make sure to have the minimum and correct file access permissions set - // so that the Etherpad server can access them + * Skin Variants + * + * Use the UI skin variants builder at /p/test#skinvariantsbuilder + * + * For the colibris skin only, you can choose how to render the three main + * containers: + * - toolbar (top menu with icons) + * - editor (containing the text of the pad) + * - background (area outside of editor, mostly visible when using page style) + * + * For each of the 3 containers you can choose 4 color combinations: + * super-light, light, dark, super-dark. + * + * For example, to make the toolbar dark, you will include "dark-toolbar" into + * skinVariants. + * + * You can provide multiple skin variants separated by spaces. Default + * skinVariant is "super-light-toolbar super-light-editor light-background". + * + * For the editor container, you can also make it full width by adding + * "full-width-editor" variant (by default editor is rendered as a page, with + * a max-width of 900px). + */ + "skinVariants": "dark-toolbar super-light-editor light-background", + /* + * IP and port which Etherpad should bind at. + * + * Binding to a Unix socket is also supported: just use an empty string for + * the ip, and put the full path to the socket in the port parameter. + * + * EXAMPLE USING UNIX SOCKET: + * "ip": "", // <-- has to be an empty string + * "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket + */ + "ip": "127.0.0.1", + "port": __PORT__, + + /* + * Option to hide/show the settings.json in admin page. + * + * Default option is set to true + */ + "showSettingsInAdminPage": true, + + /* + * Node native SSL support + * + * This is disabled by default. + * Make sure to have the minimum and correct file access permissions set so + * that the Etherpad server can access them + */ + + /* "ssl" : { - "key" : "/path-to-your/epl-server.key", - "cert" : "/path-to-your/epl-server.crt" + "key" : "/path-to-your/epl-server.key", + "cert" : "/path-to-your/epl-server.crt", + "ca": ["/path-to-your/epl-intermediate-cert1.crt", "/path-to-your/epl-intermediate-cert2.crt"] }, - */ - /*The Type of the database. You can choose between dirty, postgres, sqlite and mysql - //You shouldn't use "dirty" for for anything else than testing or development - "dbType" : "dirty", - //the database specific settings - "dbSettings" : { - "filename" : "var/dirty.db" - }, - */ + /* + * The type of the database. + * + * You can choose between many DB drivers, for example: dirty, postgres, + * sqlite, mysql. + * + * You shouldn't use "dirty" for for anything else than testing or + * development. + */ - // An Example of MySQL Configuration - "dbType" : "mysql", - "dbSettings" : { - "user" : "yunouser", - "host" : "localhost", - "password": "yunopass", - "database": "yunobase" - }, + /* + * The default text of a pad + */ + "defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at https:\/\/etherpad.org\n", - //the default text of a pad - "defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n", + /* + * Default Pad behavior. + * + * Change them if you want to override. + */ + "padOptions": { + "noColors": false, + "showControls": true, + "showChat": true, + "showLineNumbers": true, + "useMonospaceFont": false, + "userName": false, + "userColor": false, + "rtl": false, + "alwaysShowChat": false, + "chatAndUsers": false, + "lang": "__LANGUAGE__" + }, - /* Users must have a session to access pads. This effectively allows only group pads to be accessed. */ - "requireSession" : false, + /* + * Pad Shortcut Keys + */ + "padShortcutEnabled" : { + "altF9": true, /* focus on the File Menu and/or editbar */ + "altC": true, /* focus on the Chat window */ + "cmdShift2": true, /* shows a gritter popup showing a line author */ + "delete": true, + "return": true, + "esc": true, /* in mozilla versions 14-19 avoid reconnecting pad */ + "cmdS": true, /* save a revision */ + "tab": true, /* indent */ + "cmdZ": true, /* undo/redo */ + "cmdY": true, /* redo */ + "cmdI": true, /* italic */ + "cmdB": true, /* bold */ + "cmdU": true, /* underline */ + "cmd5": true, /* strike through */ + "cmdShiftL": true, /* unordered list */ + "cmdShiftN": true, /* ordered list */ + "cmdShift1": true, /* ordered list */ + "cmdShiftC": true, /* clear authorship */ + "cmdH": true, /* backspace */ + "ctrlHome": true, /* scroll to top of pad */ + "pageUp": true, + "pageDown": true + }, - /* Users may edit pads but not create new ones. Pad creation is only via the API. This applies both to group pads and regular pads. */ - "editOnly" : false, + /* + * Should we suppress errors from being visible in the default Pad Text? + */ + "suppressErrorsInPadText": false, - /* if true, all css & js will be minified before sending to the client. This will improve the loading performance massivly, - but makes it impossible to debug the javascript/css */ - "minify" : true, + /* + * If this option is enabled, a user must have a session to access pads. + * This effectively allows only group pads to be accessed. + */ + "requireSession": false, - /* How long may clients use served javascript code (in seconds)? Without versioning this - may cause problems during deployment. Set to 0 to disable caching */ - "maxAge" : 21600, // 60 * 60 * 6 = 6 hours + /* + * Users may edit pads but not create new ones. + * + * Pad creation is only via the API. + * This applies both to group pads and regular pads. + */ + "editOnly": false, - /* This is the path to the Abiword executable. Setting it to null, disables abiword. - Abiword is needed to advanced import/export features of pads*/ - "abiword" : null, + /* + * If set to true, those users who have a valid session will automatically be + * granted access to password protected pads. + */ + "sessionNoPassword": false, - /* This setting is used if you require authentication of all users. - Note: /admin always requires authentication. */ + /* + * If true, all css & js will be minified before sending to the client. + * + * This will improve the loading performance massively, but makes it difficult + * to debug the javascript/css + */ + "minify": true, + + /* + * How long may clients use served javascript code (in seconds)? + * + * Not setting this may cause problems during deployment. + * Set to 0 to disable caching. + */ + "maxAge": 21600, // 60 * 60 * 6 = 6 hours + + /* + * Absolute path to the Abiword executable. + * + * Abiword is needed to get advanced import/export features of pads. Setting + * it to null disables Abiword and will only allow plain text and HTML + * import/exports. + */ + "abiword": null, + + /* + * This is the absolute path to the soffice executable. + * + * LibreOffice can be used in lieu of Abiword to export pads. + * Setting it to null disables LibreOffice exporting. + */ + "soffice": null, + + /* + * Path to the Tidy executable. + * + * Tidy is used to improve the quality of exported pads. + * Setting it to null disables Tidy. + */ + "tidyHtml": null, + + /* + * Allow import of file types other than the supported ones: + * txt, doc, docx, rtf, odt, html & htm + */ + "allowUnknownFileEnds": true, + + /* + * This setting is used if you require authentication of all users. + * + * Note: "/admin" always requires authentication. + */ "requireAuthentication": false, - /* Require authorization by a module, or a user with is_admin set, see below. */ + /* + * Require authorization by a module, or a user with is_admin set, see below. + */ "requireAuthorization": false, - /*when you use NginX or another proxy/ load-balancer set this to true*/ - "trustProxy": true, + /* + * When you use NGINX or another proxy/load-balancer set this to true. + * + * This is especially necessary when the reverse proxy performs SSL + * termination, otherwise the cookies will not have the "secure" flag. + * + * The other effect will be that the logs will contain the real client's IP, + * instead of the reverse proxy's IP. + */ + "trustProxy": false, - /* Privacy: disable IP logging */ + /* + * Privacy: disable IP logging + */ "disableIPlogging": false, - /* Users for basic authentication. is_admin = true gives access to /admin. - If you do not uncomment this, /admin will not be available! */ /* - TODO add argument to ask ynh user admin, and change that here - "users": { - "admin": { - "password": "changeme1", - "is_admin": true + * Time (in seconds) to automatically reconnect pad when a "Force reconnect" + * message is shown to user. + * + * Set to 0 to disable automatic reconnection. + */ + "automaticReconnectionTimeout": 0, + + /* + * By default, when caret is moved out of viewport, it scrolls the minimum + * height needed to make this line visible. + */ + "scrollWhenFocusLineIsOutOfViewport": { + + /* + * Percentage of viewport height to be additionally scrolled. + * + * E.g.: use "percentage.editionAboveViewport": 0.5, to place caret line in + * the middle of viewport, when user edits a line above of the + * viewport + * + * Set to 0 to disable extra scrolling + */ + "percentage": { + "editionAboveViewport": 0, + "editionBelowViewport": 0 }, - "user": { - "password": "changeme1", - "is_admin": false - } + + /* + * Time (in milliseconds) used to animate the scroll transition. + * Set to 0 to disable animation + */ + "duration": 0, + + /* + * Flag to control if it should scroll when user places the caret in the + * last line of the viewport + */ + "scrollWhenCaretIsInTheLastLineOfViewport": false, + + /* + * Percentage of viewport height to be additionally scrolled when user + * presses arrow up in the line of the top of the viewport. + * + * Set to 0 to let the scroll to be handled as default by Etherpad + */ + "percentageToScrollWhenUserPressesArrowUp": 0 + }, + + /* + * Restrict socket.io transport methods + */ + "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], + + /* + * Allow Load Testing tools to hit the Etherpad Instance. + * + * WARNING: this will disable security on the instance. + */ + "loadTest": false, + + /* + * Disable indentation on new line when previous line ends with some special + * chars (':', '[', '(', '{') + */ + + /* + "indentationOnNewLine": false, + */ + + /* + * From Etherpad 1.8.3 onwards, import and export of pads is always rate + * limited. + * + * The default is to allow at most 10 requests per IP in a 90 seconds window. + * After that the import/export request is rejected. + * + * See https://github.com/nfriedly/express-rate-limit for more options + */ + "importExportRateLimiting": { + // duration of the rate limit window (milliseconds) + "windowMs": 90000, + + // maximum number of requests per IP to allow during the rate limit window + "max": 10 + }, + + /* + * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported + * file is always bounded. + * + * File size is specified in bytes. Default is 50 MB. + */ + "importMaxFileSize": 52428800, // 50 * 1024 * 1024 + + + /* + * From Etherpad 1.8.3 onwards import was restricted to authors who had + * content within the pad. + * + * This setting will override that restriction and allow any user to import + * without the requirement to add content to a pad. + * + * This setting is useful for when you use a plugin for authentication so you + * can already trust each user. + */ + "allowAnyoneToImport": false, + + /* + * From Etherpad 1.9.0 onwards, when Etherpad is in production mode commits from individual users are rate limited + * + * The default is to allow at most 10 changes per IP in a 1 second window. + * After that the change is rejected. + * + * See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options + */ + "commitRateLimiting": { + // duration of the rate limit window (seconds) + "duration": 1, + + // maximum number of chanes per IP to allow during the rate limit window + "points": 10 + }, + + + /* + * Toolbar buttons configuration. + * + * Uncomment to customize. + */ + + /* + "toolbar": { + "left": [ + ["bold", "italic", "underline", "strikethrough"], + ["orderedlist", "unorderedlist", "indent", "outdent"], + ["undo", "redo"], + ["clearauthorship"] + ], + "right": [ + ["importexport", "timeslider", "savedrevision"], + ["settings", "embed"], + ["showusers"] + ], + "timeslider": [ + ["timeslider_export", "timeslider_returnToPad"] + ] }, */ - // restrict socket.io transport methods - "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], + /* + * Expose Etherpad version in the web interface and in the Server http header. + * + * Do not enable on production machines. + */ + "exposeVersion": false, - /* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */ + /* + * The log level we are using. + * + * Valid values: DEBUG, INFO, WARN, ERROR + */ "loglevel": "INFO", - //Logging configuration. See log4js documentation for further information - // https://github.com/nomiddlename/log4js-node - // You can add as many appenders as you want here: + /* + * Logging configuration. See log4js documentation for further information: + * https://github.com/nomiddlename/log4js-node + * + * You can add as many appenders as you want here. + */ "logconfig" : - { "appenders": [ - { "type": "console" - //, "category": "access"// only logs pad access - } - /* - , { "type": "file" + { "appenders": [ + { "type": "console" + //, "category": "access"// only logs pad access + } + + /* + , { "type": "file" , "filename": "your-log-file-here.log" , "maxLogSize": 1024 , "backups": 3 // how many log files there're gonna be at max //, "category": "test" // only log a specific category - }*/ - /* - , { "type": "logLevelFilter" - , "level": "warn" // filters out all log messages that have a lower level than "error" - , "appender": - { Use whatever appender you want here } - }*/ - /* - , { "type": "logLevelFilter" - , "level": "error" // filters out all log messages that have a lower level than "error" - , "appender": - { "type": "smtp" - , "subject": "An error occured in your EPL instance!" - , "recipients": "bar@blurdybloop.com, baz@blurdybloop.com" - , "sendInterval": 60*5 // in secs -- will buffer log messages; set to 0 to send a mail for every message - , "transport": "SMTP", "SMTP": { // see https://github.com/andris9/Nodemailer#possible-transport-methods - "host": "smtp.example.com", "port": 465, - "secureConnection": true, - "auth": { - "user": "foo@example.com", - "pass": "bar_foo" + } + */ + + /* + , { "type": "logLevelFilter" + , "level": "warn" // filters out all log messages that have a lower level than "error" + , "appender": + { Use whatever appender you want here } + } + */ + + /* + , { "type": "logLevelFilter" + , "level": "error" // filters out all log messages that have a lower level than "error" + , "appender": + { "type": "smtp" + , "subject": "An error occurred in your EPL instance!" + , "recipients": "bar@blurdybloop.com, baz@blurdybloop.com" + , "sendInterval": 300 // 60 * 5 = 5 minutes -- will buffer log messages; set to 0 to send a mail for every message + , "transport": "SMTP", "SMTP": { // see https://github.com/andris9/Nodemailer#possible-transport-methods + "host": "smtp.example.com", "port": 465, + "secureConnection": true, + "auth": { + "user": "foo@example.com", + "pass": "bar_foo" + } } + } } - } - }*/ - ] } + */ + + ] + }, // logconfig + + /* Override any strings found in locale directories */ + "customLocaleStrings": {} } diff --git a/conf/systemd.service b/conf/systemd.service new file mode 100644 index 0000000..47d6b59 --- /dev/null +++ b/conf/systemd.service @@ -0,0 +1,16 @@ +[Unit] +Description=Etherpad-lite, the collaborative editor. +After=syslog.target network.target postgresql.service + +[Service] +Type=simple +User=__APP__ +Group=__APP__ +WorkingDirectory=__FINALPATH__ +Environment="NODE_ENV=production" +Environment="__YNH_NODE_LOAD_PATH__" +ExecStart=__FINALPATH__/node_modules/ep_etherpad-lite/node/server.js +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/manifest.json b/manifest.json index 1dabd09..9aa487d 100644 --- a/manifest.json +++ b/manifest.json @@ -1,45 +1,45 @@ { - "name": "Etherpad Lite", - "id": "etherpadlite", + "name": "Etherpad", + "id": "etherpad", "packaging_format": 1, "description": { - "en": "online editor providing collaborative editing in really real-time", - "fr": "editeur multiutilisiteur en temps réel en ligne" + "en": "Online editor providing collaborative editing in real-time.", + "fr": "Éditeur en ligne fournissant l'édition collaborative en temps réel." }, - "url":"http://etherpad.org/", - "license":"free", + "version": "1.8.6~ynh1", + "url": "https://etherpad.org/", + "license": "Apache-2.0", "maintainer": { - "name": "beudbeud", - "email": "beudbeud@beudibox.fr" + "name": "" }, "requirements": { - "yunohost": ">= 2.4.0" + "yunohost": ">= 4.0.7" }, - "multi_instance": "true", - "services":[ - "nginx", - "mysql" + "multi_instance": true, + "services": [ + "nginx", + "mysql" ], "arguments": { "install" : [ { "name": "domain", - "type":"domain", + "type": "domain", "ask": { - "en": "Choose a domain for Etherpad", - "fr": "Choisissez un domaine pour Etherpad" + "en": "Choose a domain name for Etherpad", + "fr": "Choisissez un nom de domaine pour Etherpad" }, - "example": "domain.org" + "example": "example.com" }, { "name": "path", - "type":"path", + "type": "path", "ask": { "en": "Choose a path for Etherpad", "fr": "Choisissez un chemin pour Etherpad" }, - "example": "/pad", - "default": "/pad" + "example": "/etherpad", + "default": "/etherpad" }, { "name": "is_public", @@ -48,7 +48,39 @@ "en": "Is it a public application?", "fr": "Est-ce une application publique ?" }, + "help": { + "en": "If enabled, Etherpad will be accessible by people who do not have an account. This can be changed later via the webadmin.", + "fr": "Si cette case est cochée, Etherpad sera accessible aux personnes n’ayant pas de compte. Vous pourrez changer ceci plus tard via la webadmin." + }, "default": true + }, + { + "name": "language", + "type": "string", + "ask": { + "en": "Choose the application language", + "fr": "Choisissez la langue de l'application" + }, + "choices": ["fr", "en"], + "default": "fr" + }, + { + "name": "admin", + "type": "user", + "ask": { + "en": "Choose an admin user", + "fr": "Choisissez l'administrateur" + }, + "example": "johndoe" + }, + { + "name": "password", + "type": "password", + "ask": { + "en": "Set the administrator password", + "fr": "Définissez le mot de passe administrateur" + }, + "example": "Choose a password" } ] } diff --git a/scripts/_common.sh b/scripts/_common.sh new file mode 100644 index 0000000..b31c95a --- /dev/null +++ b/scripts/_common.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +#================================================= +# COMMON VARIABLES +#================================================= + +# dependencies used by the app +pkg_dependencies="postgresql apt-transport-https" + +nodejs_version=12 + +#================================================= +# PERSONAL HELPERS +#================================================= + +#================================================= +# EXPERIMENTAL HELPERS +#================================================= + +#================================================= +# FUTURE OFFICIAL HELPERS +#================================================= + +# Execute a command as another user +# usage: ynh_exec_as USER COMMAND [ARG ...] +ynh_exec_as() { + local USER=$1 + shift 1 + + if [[ $USER = $(whoami) ]]; then + eval "$@" + else + sudo -u "$USER" "$@" + fi +} \ No newline at end of file diff --git a/scripts/backup b/scripts/backup index 2714b39..7b33d39 100644 --- a/scripts/backup +++ b/scripts/backup @@ -1,24 +1,67 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# See comments in install script -app=$YNH_APP_INSTANCE_NAME - -# Source YunoHost helpers +source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -# Backup sources & data -# Note: the last argument is where to save this path, see the restore script. -ynh_backup "/var/www/${app}" "sources" +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= -# Dump the database -dbname=$app -dbuser=$app -dbpass=$(ynh_app_setting_get "$app" dbpass) -mysqldump -u "$dbuser" -p"$dbpass" --no-create-db "$dbname" > ./dump.sql +ynh_clean_setup () { + ynh_clean_check_starting +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors -# Copy NGINX configuration -domain=$(ynh_app_setting_get "$app" domain) -ynh_backup "/etc/nginx/conf.d/${domain}.d/${app}.conf" "nginx.conf" +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info --message="Loading installation settings..." + +app=$YNH_APP_INSTANCE_NAME + +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) + +#================================================= +# DECLARE DATA AND CONF FILES TO BACKUP +#================================================= +ynh_print_info --message="Declaring files to be backed up..." + +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= + +ynh_backup --src_path="$final_path" + +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# BACKUP SYSTEMD +#================================================= + +ynh_backup --src_path="/etc/systemd/system/$app.service" + +#================================================= +# BACKUP THE POSTQRESQL DATABASE +#================================================= +ynh_print_info --message="Backing up the PostgreSQL database..." + +ynh_psql_dump_db --database="$db_name" > db.sql + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info --message="Backup script completed for Etherpad. (YunoHost will then actually copy those files to the archive)." diff --git a/scripts/change_url b/scripts/change_url new file mode 100644 index 0000000..42d9e9e --- /dev/null +++ b/scripts/change_url @@ -0,0 +1,123 @@ +#!/bin/bash + +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +old_domain=$YNH_APP_OLD_DOMAIN +old_path=$YNH_APP_OLD_PATH + +new_domain=$YNH_APP_NEW_DOMAIN +new_path=$YNH_APP_NEW_PATH + +app=$YNH_APP_INSTANCE_NAME + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 + +# Needed for helper "ynh_add_nginx_config" +final_path=$(ynh_app_setting_get --app=$app --key=final_path) + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up Etherpad before changing its URL (may take a while)..." --weight=2 + +# Backup the current version of Etherpad +ynh_backup_before_upgrade +ynh_clean_setup () { + # Remove the new domain config file, the remove script won't do it as it doesn't know yet its location. + ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" + + # restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# CHECK WHICH PARTS SHOULD BE CHANGED +#================================================= + +change_domain=0 +if [ "$old_domain" != "$new_domain" ] +then + change_domain=1 +fi + +change_path=0 +if [ "$old_path" != "$new_path" ] +then + change_path=1 +fi + +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" + +#================================================= +# MODIFY URL IN NGINX CONF +#================================================= +ynh_script_progression --message="Updating NGINX web server configuration..." --time --weight=1 + +nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf + +# Change the path in the NGINX config file +if [ $change_path -eq 1 ] +then + # Make a backup of the original NGINX config file if modified + ynh_backup_if_checksum_is_different --file="$nginx_conf_path" + # Set global variables for NGINX helper + domain="$old_domain" + path_url="$new_path" + # Create a dedicated NGINX config + ynh_add_nginx_config +fi + +# Change the domain for NGINX +if [ $change_domain -eq 1 ] +then + # Delete file checksum for the old conf file location + ynh_delete_file_checksum --file="$nginx_conf_path" + mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf + # Store file checksum for the new config file location + ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" +fi + +#================================================= +# GENERIC FINALISATION +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=2 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Change of URL completed for Etherpad" --last diff --git a/scripts/install b/scripts/install index 35c9727..5795428 100644 --- a/scripts/install +++ b/scripts/install @@ -1,100 +1,212 @@ #!/bin/bash +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ynh_clean_check_starting +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# RETRIEVE ARGUMENTS FROM THE MANIFEST +#================================================= + +domain=$YNH_APP_ARG_DOMAIN +path_url=$YNH_APP_ARG_PATH +admin=$YNH_APP_ARG_ADMIN +is_public=$YNH_APP_ARG_IS_PUBLIC +language=$YNH_APP_ARG_LANGUAGE +password=$YNH_APP_ARG_PASSWORD + app=$YNH_APP_INSTANCE_NAME -# Source YunoHost helpers -source /usr/share/yunohost/helpers +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= +ynh_script_progression --message="Validating installation parameters..." --weight=2 -# Retrieve arguments -domain=$YNH_APP_ARG_DOMAIN -path=$YNH_APP_ARG_PATH -is_public=$YNH_APP_ARG_IS_PUBLIC -port=9001 - -# Check domain/path availability -sudo yunohost app checkurl $domain$path -a $app -if [[ ! $? -eq 0 ]]; then - exit 1 -fi - -# Store config on YunoHost instance -ynh_app_setting_set "$app" domain "$domain" -ynh_app_setting_set "$app" path "$path" -ynh_app_setting_set "$app" is_public "$is_public" - -# Remove trailing "/" for next commands -path=${path%/} - -# Generate random key -# key=$(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d '[A-Za-z0-9]' | sed -n 's/\(.\{40\}\).*/\1/p') -key=$(ynh_string_random 12) - -# Generate MySQL password and create database -dbuser=$app -dbname=$app -dbpass=$(ynh_string_random 12) -ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" -ynh_app_setting_set "$app" dbpass "$dbpass" -ynh_app_setting_set "$app" dbuser "$dbuser" -ynh_app_setting_set "$app" dbname "$dbname" - - -# Install dependances -if ! ynh_package_is_installed "nodejs-legacy" ; then - sudo apt-get install nodejs-legacy npm -y -fi - -# create app dir and copy sources final_path=/var/www/$app -sudo mkdir -p $final_path +test ! -e "$final_path" || ynh_die --message="This path already contains a folder" -sudo cp -a ../sources/* $final_path +# Register (book) web path +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url -sudo cp ../conf/settings.json $final_path -# Change variables in etherpad configuration -sudo sed -i "s/yunouser/$dbuser/g" $final_path/settings.json -sudo sed -i "s/yunopass/$dbpass/g" $final_path/settings.json -sudo sed -i "s/yunobase/$dbname/g" $final_path/settings.json -sudo sed -i "s/KEY/$key/g" $final_path/settings.json +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= +ynh_script_progression --message="Storing installation settings..." --weight=2 -sudo npm cache clear -sudo $final_path/bin/installDeps.sh > /dev/null 2>&1 -sudo npm install forever -g > /dev/null 2>&1 +ynh_app_setting_set --app=$app --key=domain --value=$domain +ynh_app_setting_set --app=$app --key=path --value=$path_url +ynh_app_setting_set --app=$app --key=admin --value=$admin +ynh_app_setting_set --app=$app --key=is_public --value=$is_public +ynh_app_setting_set --app=$app --key=language --value=$language +ynh_app_setting_set --app=$app --key=password --value=$password -# Set permissions to etherpad directory -sudo chown -R www-data: $final_path +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# FIND AND OPEN A PORT +#================================================= +ynh_script_progression --message="Configuring firewall..." --weight=1 -# service -sudo cp ../conf/etherpad-lite /etc/init.d/$app -sudo sed -i "s/APPTOCHANGE/$app/g" /etc/init.d/$app -sudo chmod +x /etc/init.d/$app -sudo update-rc.d $app defaults +# Find an available port +port=$(ynh_find_port --port=9001) +ynh_app_setting_set --app=$app --key=port --value=$port -# logs -sudo mkdir /var/log/$app -sudo touch /var/log/$app/$app.log -sudo chown www-data /var/log/$app/$app.log +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Installing dependencies..." --weight=12 -# nginx -nginx_conf_path=/etc/nginx/conf.d/$domain.d/$app.conf -if [ "$path" = "" ]; then - sudo cp ../conf/nginx.conf-nosub $nginx_conf_path -else - sudo cp ../conf/nginx.conf $nginx_conf_path - # Modify Nginx configuration file and copy it to Nginx conf directory +ynh_install_app_dependencies $pkg_dependencies - sudo sed -i "s@YNH_PATH@$path@g" $nginx_conf_path - sudo sed -i "s@YNH_PORT@$port@g" $nginx_conf_path - sudo sed -i "s@YNH_DOMAIN@$domain@g" $nginx_conf_path -fi -# Reload Nginx and regenerate SSOwat conf -sudo service nginx reload -# If app is public, add url to SSOWat conf as skipped_uris -if [[ $is_public -eq 1 ]]; then - # unprotected_uris allows SSO credentials to be passed anyway. - ynh_app_setting_set "$app" unprotected_uris "/" +ynh_install_nodejs --nodejs_version=$nodejs_version + +#================================================= +# CREATE A POSTQRESQL DATABASE +#================================================= +ynh_script_progression --message="Creating a PostgreSQL database..." --weight=5 + +db_name=$(ynh_sanitize_dbid --db_name=$app) +db_user=$db_name +db_pwd=$(ynh_string_random --length=30) + +ynh_app_setting_set --app=$app --key=db_name --value=$db_name +ynh_app_setting_set --app=$app --key=db_pwd --value=$db_pwd + +ynh_psql_test_if_first_run +ynh_psql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= +ynh_script_progression --message="Setting up source files..." --weight=1 + +ynh_app_setting_set --app=$app --key=final_path --value=$final_path +# Download, check integrity, uncompress and patch the source from app.src +ynh_setup_source --dest_dir="$final_path" + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Configuring NGINX web server..." --weight=4 + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Configuring system user..." --weight=4 + +# Create a system user +ynh_system_user_create --username=$app --home_dir=$final_path + +#================================================= +# INSTALL ETHERPAD +#================================================= +ynh_script_progression --message="Installing Etherpad..." --weight=90 + +chown -R $app: $final_path + +pushd "$final_path" || ynh_die + ynh_use_nodejs + ynh_exec_as $app env "$ynh_node_load_PATH" bin/installDeps.sh +popd || ynh_die + +#================================================= +# MODIFY A CONFIG FILE +#================================================= +ynh_script_progression --message="Configuring Etherpad..." --weight=6 + +cp ../conf/settings.json $final_path/settings.json + +ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$final_path/settings.json" +ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$final_path/settings.json" + +cp ../conf/credentials.json $final_path/credentials.json + +ynh_replace_string --match_string="__DB_NAME__" --replace_string="$db_name" --target_file="$final_path/credentials.json" +ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$final_path/credentials.json" +ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$final_path/credentials.json" +ynh_replace_string --match_string="__PASSWORD__" --replace_string="$password" --target_file="$final_path/credentials.json" + +#================================================= +# STORE THE CONFIG FILE CHECKSUM +#================================================= + +# Calculate and store the config file checksum into the app settings +ynh_store_file_checksum --file="$final_path/settings.json" +ynh_store_file_checksum --file="$final_path/credentials.json" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +# Set permissions to app files +chown -R $app: $final_path +chmod 600 $final_path/credentials.json + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_script_progression --message="Configuring a systemd service..." --weight=4 + +# Create a dedicated systemd config +ynh_add_systemd_config --others_var="ynh_node_load_PATH" + +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --weight=3 + +yunohost service add $app --description "Etherpad-lite, the collaborative editor." --log "/var/log/$app/$app.log" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=1 + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" --line_match="Your Etherpad version is" + +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Configuring SSOwat..." --weight=1 + +# Make app public if necessary +if [ $is_public -eq 1 ] +then + # Everyone can access the app. + # The "main" permission is automatically created before the install script. + ynh_permission_update --permission "main" --add "visitors" fi -sudo yunohost app ssowatconf +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=1 -sudo service etherpad-lite start +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Installation of Etherpad completed" --last diff --git a/scripts/remove b/scripts/remove index 8bf0b5d..c9b0a9b 100644 --- a/scripts/remove +++ b/scripts/remove @@ -1,31 +1,84 @@ #!/bin/bash +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# See comments in install script -app=$YNH_APP_INSTANCE_NAME - -# Source YunoHost helpers +source _common.sh source /usr/share/yunohost/helpers -# Retrieve app settings -domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_app_setting_get "$app" path) -dbuser=$(ynh_app_setting_get "$app" dbuser) -dbname=$(ynh_app_setting_get "$app" dbname) -# dbpass=$(ynh_app_setting_get "$app" dbpass) +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 +app=$YNH_APP_INSTANCE_NAME -#mysql -u root -p $root_pwd -e "DROP DATABASE $dbname ; DROP USER $dbuser@localhost ;" -# Drop MySQL database and user -ynh_mysql_drop_db "$dbname" || true -ynh_mysql_drop_user "$dbuser" || true +domain=$(ynh_app_setting_get --app=$app --key=domain) +port=$(ynh_app_setting_get --app=$app --key=port) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +final_path=$(ynh_app_setting_get --app=$app --key=final_path) -sudo rm -rf /var/www/$app +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE SERVICE INTEGRATION IN YUNOHOST +#================================================= -sudo rm -f /etc/nginx/conf.d/$domain.d/$app.conf -sudo service nginx reload -sudo rm -Rf /var/log/$app +# Remove the service from the list of services known by YunoHost (added from `yunohost service add`) +if ynh_exec_warn_less yunohost service status $app >/dev/null +then + ynh_script_progression --message="Removing Etherpad service integration..." --weight=2 + yunohost service remove $app +fi -sudo update-rc.d $app remove -sudo service $app stop -sudo rm /etc/init.d/$app +#================================================= +# STOP AND REMOVE SERVICE +#================================================= +ynh_script_progression --message="Stopping and removing the systemd service..." --weight=1 + +# Remove the dedicated systemd config +ynh_remove_systemd_config + +#================================================= +# REMOVE THE POSTQRESQL DATABASE +#================================================= +ynh_script_progression --message="Removing the PostgreSQL database..." --weight=2 + +# Remove a database if it exists, along with the associated user +ynh_psql_remove_db --db_user=$db_user --db_name=$db_name + +#================================================= +# REMOVE ETHERPAD MAIN DIR +#================================================= +ynh_script_progression --message="Removing Etherpad main directory..." --weight=3 + +# Remove the app directory securely +ynh_secure_remove --file="$final_path" + +#================================================= +# REMOVE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Removing NGINX web server configuration..." --weight=1 + +# Remove the dedicated NGINX config +ynh_remove_nginx_config + +#================================================= +# GENERIC FINALIZATION +#================================================= +# REMOVE DEDICATED USER +#================================================= +ynh_script_progression --message="Removing the dedicated system user..." --weight=1 + +# Delete a system user +ynh_system_user_delete --username=$app + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Removal of Etherpad completed" --last diff --git a/scripts/restore b/scripts/restore index 153f2fd..ba54e67 100644 --- a/scripts/restore +++ b/scripts/restore @@ -1,42 +1,121 @@ #!/bin/bash -# Note: each files and directories you've saved using the ynh_backup helper -# will be located in the current directory, regarding the last argument. +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Exit on command errors and treat unset variables as an error -set -eu - -# See comments in install script -app=$YNH_APP_INSTANCE_NAME - -# Source YunoHost helpers +source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -# Retrieve old app settings -domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_app_setting_get "$app" path) +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= -# Check domain/path availability -sudo yunohost app checkurl "${domain}${path}" -a "$app" \ - || ynh_die "Path not available: ${domain}${path}" +ynh_clean_setup () { + ynh_clean_check_starting +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors -# Restore sources & data -src_path="/var/www/${app}" -sudo cp -a ./sources "$src_path" +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 -# Restore permissions to app files -# you may need to make some file and/or directory writeable by www-data (nginx user) -sudo chown -R root: "$src_path" +app=$YNH_APP_INSTANCE_NAME -# Create and restore the database -dbname=$app -dbuser=$app -dbpass=$(ynh_app_setting_get "$app" dbpass) -ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" -ynh_mysql_connect_as "$dbuser" "$dbpass" "$dbname" < ./dump.sql +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) -# Restore NGINX configuration -sudo cp -a ./nginx.conf "/etc/nginx/conf.d/${domain}.d/${app}.conf" +#================================================= +# CHECK IF ETHERPAD CAN BE RESTORED +#================================================= +ynh_script_progression --message="Validating restoration parameters..." --weight=2 -# Restart webserver -sudo service nginx reload +ynh_webpath_available --domain=$domain --path_url=$path_url \ + || ynh_die --message="Path not available: ${domain}${path_url}" +test ! -d $final_path \ + || ynh_die --message="There is already a directory: $final_path " + +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= + +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Restoring the app main directory..." --weight=2 + +ynh_restore_file --origin_path="$final_path" + +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 + +# Create the dedicated user (if not existing) +ynh_system_user_create --username=$app + +#================================================= +# RESTORE USER RIGHTS +#================================================= + +# Restore permissions on app files +chown -R $app: $final_path +chmod 600 $final_path/credentials.json + +#================================================= +# RESTORE THE POSTQRESQL DATABASE +#================================================= +ynh_script_progression --message="Restoring the PostgreSQL database..." --weight=2 + +ynh_psql_test_if_first_run +ynh_psql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd +ynh_psql_execute_file_as_root --file="./db.sql" --database=$db_name + +#================================================= +# RESTORE SYSTEMD +#================================================= +ynh_script_progression --message="Restoring the systemd configuration..." --weight=8 + +ynh_restore_file --origin_path="/etc/systemd/system/$app.service" +systemctl enable $app.service + +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --weight=3 + +yunohost service add $app --description "Etherpad-lite, the collaborative editor." --log "/var/log/$app/$app.log" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=8 + +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX AND PHP-FPM +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=2 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for Etherpad" --last diff --git a/scripts/upgrade b/scripts/upgrade index 2e52f1a..12deddd 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,70 +1,182 @@ #!/bin/bash +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=1 + app=$YNH_APP_INSTANCE_NAME -# Source YunoHost helpers -source /usr/share/yunohost/helpers +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +admin=$(ynh_app_setting_get --app=$app --key=admin) +is_public=$(ynh_app_setting_get --app=$app --key=is_public) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +language=$(ynh_app_setting_get --app=$app --key=language) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) -# Retrieve app settings -domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_app_setting_get "$app" path) -dbuser=$(ynh_app_setting_get "$app" dbuser) -dbname=$(ynh_app_setting_get "$app" dbname) -is_public=$(ynh_app_setting_get "$app" is_public) -port=9001 +#================================================= +# CHECK VERSION +#================================================= -root_pwd=$(sudo cat /etc/yunohost/mysql) +upgrade_type=$(ynh_check_app_version_changed) -# Remove trailing "/" for next commands -path=${path%/} +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= +ynh_script_progression --message="Ensuring downward compatibility..." --weight=2 - -# create app dir and compy sources -final_path=/var/www/$app -sudo mkdir -p $final_path - -sudo cp -a ../sources/* $final_path - -sudo cp ../conf/settings.json $final_path -# Change variables in etherpad configuration -sudo sed -i "s/yunouser/$dbuser/g" $final_path/settings.json -sudo sed -i "s/yunopass/$dbpass/g" $final_path/settings.json -sudo sed -i "s/yunobase/$dbname/g" $final_path/settings.json -sudo sed -i "s/KEY/$key/g" $final_path/settings.json - -sudo npm cache clear -sudo $final_path/bin/installDeps.sh > /dev/null 2>&1 -sudo npm install forever -g > /dev/null 2>&1 - -# Set permissions to etherpad directory -sudo chown -R www-data: $final_path - -# service -sudo cp ../conf/etherpad-lite /etc/init.d/$app -sudo sed -i "s/APPTOCHANGE/$app/g" /etc/init.d/$app -sudo chmod +x /etc/init.d/$app -sudo update-rc.d $app defaults - -# nginx -nginx_conf_path=/etc/nginx/conf.d/$domain.d/$app.conf -if [ "$path" = "" ]; then - sudo cp ../conf/nginx.conf-nosub $nginx_conf_path -else - sudo cp ../conf/nginx.conf $nginx_conf_path - # Modify Nginx configuration file and copy it to Nginx conf directory - sudo sed -i "s@YNH_PATH@$path@g" $nginx_conf_path - sudo sed -i "s@YNH_PORT@$port@g" $nginx_conf_path - sudo sed -i "s@YNH_DOMAIN@$domain@g" $nginx_conf_path +# Fix is_public as a boolean value +if [ "$is_public" = "Yes" ]; then + ynh_app_setting_set --app=$app --key=is_public --value=1 + is_public=1 +elif [ "$is_public" = "No" ]; then + ynh_app_setting_set --app=$app --key=is_public --value=0 + is_public=0 fi -# Reload Nginx and regenerate SSOwat conf -sudo service nginx reload -# If app is public, add url to SSOWat conf as skipped_uris -if [[ $is_public -eq 1 ]]; then - # unprotected_uris allows SSO credentials to be passed anyway. - ynh_app_setting_set "$app" unprotected_uris "/" +# If db_name doesn't exist, create it +if [ -z "$db_name" ]; then + db_name=$(ynh_sanitize_dbid --db_name=$app) + ynh_app_setting_set --app=$app --key=db_name --value=$db_name fi -sudo yunohost app ssowatconf +# If final_path doesn't exist, create it +if [ -z "$final_path" ]; then + final_path=/var/www/$app + ynh_app_setting_set --app=$app --key=final_path --value=$final_path +fi -sudo service etherpad-lite start +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up Etherpad before upgrading (may take a while)..." --weight=1 + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + # restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# STANDARD UPGRADE STEPS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --weight=42 + +ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Upgrading source files..." --weight=1 + + # Download, check integrity, uncompress and patch the source from app.src + ynh_setup_source --dest_dir="$final_path" +fi + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Upgrading NGINX web server configuration..." --weight=3 + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Making sure dedicated system user exists..." --time --weight=1 + +# Create a dedicated user (if not existing) +ynh_system_user_create --username=$app + +#================================================= +# INSTALL ETHERPAD +#================================================= +ynh_script_progression --message="Installing Etherpad..." --weight=90 + +chown -R $app: $final_path + +pushd "$final_path" || ynh_die + ynh_use_nodejs + ynh_exec_as $app env $ynh_node_load_PATH bin/installDeps.sh +popd || ynh_die + +#================================================= +# MODIFY A CONFIG FILE +#================================================= +ynh_script_progression --message="Reconfiguring Etherpad..." --weight=6 + +cp ../conf/settings.json $final_path/settings.json + +ynh_replace_string --match_string="__PORT__" --replace_string="$port" --target_file="$final_path/settings.json" +ynh_replace_string --match_string="__LANGUAGE__" --replace_string="$language" --target_file="$final_path/settings.json" + +cp ../conf/credentials.json $final_path/credentials.json + +ynh_replace_string --match_string="__DB_NAME__" --replace_string="$db_name" --target_file="$final_path/credentials.json" +ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$final_path/credentials.json" +ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$final_path/credentials.json" +ynh_replace_string --match_string="__PASSWORD__" --replace_string="$password" --target_file="$final_path/credentials.json" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +# Set permissions on app files +chown -R $app: $final_path +chmod 600 $final_path/credentials.json + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_script_progression --message="Upgrading systemd configuration..." --time --weight=1 + +# Create a dedicated systemd config +ynh_add_systemd_config --others_var="ynh_node_load_PATH" + +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --time --weight=1 + +yunohost service add $app --description "Etherpad-lite, the collaborative editor." --log "/var/log/$app/$app.log" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" --line_match="Your Etherpad version is" + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=2 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Upgrade of Etherpad completed" --last diff --git a/sources/.gitignore b/sources/.gitignore deleted file mode 100644 index 7615acd..0000000 --- a/sources/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -node_modules -settings.json -!settings.json.template -APIKEY.txt -SESSIONKEY.txt -bin/abiword.exe -bin/node.exe -etherpad-lite-win.zip -var/dirty.db -bin/convertSettings.json -*~ -*.patch -src/static/js/jquery.js -npm-debug.log -*.DS_Store -.ep_initialized -*.crt -*.key -bin/etherpad-1.deb -credentials.json -out/ diff --git a/sources/.travis.yml b/sources/.travis.yml deleted file mode 100644 index 908aca4..0000000 --- a/sources/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: node_js -node_js: - - "0.10" -install: - - "bin/installDeps.sh" - - "export GIT_HASH=$(git rev-parse --verify --short HEAD)" - - "npm install ep_test_line_attrib" -script: - - "tests/frontend/travis/runner.sh" -env: - global: - - secure: "WMGxFkOeTTlhWB+ChMucRtIqVmMbwzYdNHuHQjKCcj8HBEPdZLfCuK/kf4rG\nVLcLQiIsyllqzNhBGVHG1nyqWr0/LTm8JRqSCDDVIhpyzp9KpCJQQJG2Uwjk\n6/HIJJh/wbxsEdLNV2crYU/EiVO3A4Bq0YTHUlbhUqG3mSCr5Ec=" - - secure: "gejXUAHYscbR6Bodw35XexpToqWkv2ifeECsbeEmjaLkYzXmUUNWJGknKSu7\nEUsSfQV8w+hxApr1Z+jNqk9aX3K1I4btL3cwk2trnNI8XRAvu1c1Iv60eerI\nkE82Rsd5lwUaMEh+/HoL8ztFCZamVndoNgX7HWp5J/NRZZMmh4g=" -jdk: - - oraclejdk6 -notifications: - irc: - channels: - - "irc.freenode.org#etherpad-lite-dev" diff --git a/sources/CHANGELOG.md b/sources/CHANGELOG.md deleted file mode 100644 index 1293b57..0000000 --- a/sources/CHANGELOG.md +++ /dev/null @@ -1,527 +0,0 @@ -# 1.6.6 - * FIX: line numbers are aligned with text again (broken in 1.6.4) - * FIX: text entered between connection loss and reconnection was not saved - * FIX: diagnostic call failed when etherpad was exposed in a subdirectory - -# 1.6.5 - * SECURITY: Escape data when listing available plugins - * FIX: Fix typo in apicalls.js which prevented importing isValidJSONPName - * FIX: fixed plugin dependency issue - * FIX: Update iframe_editor.css - * FIX: unbreak Safari iOS line wrapping - -# 1.6.4 - * SECURITY: Access Control bypass on /admin - CVE-2018-9845 - * SECURITY: Remote Code Execution through pad export - CVE-2018-9327 - * SECURITY: Remote Code Execution through JSONP handling - CVE-2018-9326 - * SECURITY: Pad data leak - CVE-2018-9325 - * Fix: Admin redirect URL - * Fix: Various script Fixes - * Fix: Various CSS/Style/Layout fixes - * NEW: Improved Pad contents readability - * NEW: Hook: onAccessCheck - * NEW: SESSIONKEY and APIKey customizable path - * NEW: checkPads script - * NEW: Support "cluster mode" - -# 1.6.3 - * SECURITY: Update ejs - * SECURITY: xss vulnerability when reading window.location.href - * SECURITY: sanitize jsonp - * NEW: Catch SIGTERM for graceful shutdown - * NEW: Show actual applied text formatting for caret position - * NEW: Add settings to improve scrolling of viewport on line changes - -# 1.6.2 - * NEW: Added pad shortcut disabling feature - * NEW: Create option to automatically reconnect after a few seconds - * Update: socket.io to 1.7.3 - * Update: l10n lib - * Update: request to 2.83.0 - * Update: Node for windows to 8.9.0 - * Fix: minification of code - -# 1.6.1 - * NEW: Hook aceRegisterNonScrollableEditEvents to register events that shouldn't scroll - * NEW: Added 'item' parameter to registerAceCommand Hook - * NEW: Added LibreJS support - * Fix: Crash on malformed export url - * Fix: Re-enable editor after user is reconnected to server - * Fix: minification - * Other: Added 'no-referrer' for all pads - * Other: Improved cookie security - * Other: Fixed compatibility with nodejs 7 - * Other: Updates - - socket.io to 1.6.0 - - express to 4.13.4 - - express-session to 1.13.0 - - clean-css to 3.4.12 - - uglify-js to 2.6.2 - - log4js to 0.6.35 - - cheerio to 0.20.0 - - ejs to 2.4.1 - - graceful-fs to 4.1.3 - - semver to 5.1.0 - - unorm to 1.4.1 - - jsonminify to 0.4.1 - - measured to 1.1.0 - - mocha to 2.4.5 - - supertest to 1.2.0 - - npm to 4.0.2 - - Node.js for Windows to 6.9.2 - -# 1.6.0 - * SECURITY: Fix a possible xss attack in iframe link - * NEW: Add a aceSelectionChanged hook to allow plugins to react when the cursor location changes. - * NEW: Accepting Arrays on 'exportHtmlAdditionalTags' to handle attributes stored as ['key', 'value'] - * NEW: Allow admin to run on a sub-directory - * NEW: Support version 5 of node.js - * NEW: Update windows build to node version 4.4.3 - * NEW: Create setting to control if a new line will be indented or not - * NEW: Add an appendText API - * NEW: Allow LibreOffice to be used when exporting a pad - * NEW: Create hook exportHtmlAdditionalTagsWithData - * NEW: Improve DB migration performance - * NEW: allow settings to be applied from the filesystem - * NEW: remove applySettings hook and allow credentials.json to be part of core - * NEW: Use exec to switch to node process - * NEW: Validate incoming color codes - * Fix: Avoid space removal when pasting text from word processor. - * Fix: Removing style that makes editor scroll to the top on iOS without any action from the user - * Fix: Fix API call appendChatMessage to send new message to all connected clients - * Fix: Timeslider "Return to pad" button - * Fix: Generating pad HTML with tags like instead of - * Fix: Get git commit hash even if the repo only points to a bare repo. - * Fix: Fix decode error if pad name contains special characters and is sanitized - * Fix: Fix handleClientMessage_USER_* payloads not containing user info - * Fix: Set language cookie on initial load - * Fix: Timeslider Not Translated - * Other: set charset for mysql connection in settings.json - * Other: Dropped support for io.js - * Other: Add support to store credentials in credentials.json - * Other: Support node version 4 or higher - * Other: Update uberDB to version 0.3.0 - -# 1.5.7 - * NEW: Add support for intermediate CA certificates for ssl - * NEW: Provide a script to clean up before running etherpad - * NEW: Use ctrl+shift+1 to do a ordered list - * NEW: Show versions of plugins on startup - * NEW: Add author on padCreate and padUpdate hook - * Fix: switchToPad method - * Fix: Dead keys - * Fix: Preserve new lines in copy-pasted text - * Fix: Compatibility mode on IE - * Fix: Content Collector to get the class of the DOM-node - * Fix: Timeslider export links - * Fix: Double prompt on file upload - * Fix: setText() replaces the entire pad text - * Fix: Accessibility features on embedded pads - * Fix: Tidy HTML before abiword conversion - * Fix: Remove edit buttons in read-only view - * Fix: Disable user input in read-only view - * Fix: Pads end with a single newline, rather than two newlines - * Fix: Toolbar and chat for mobile devices - -# 1.5.6 - * Fix: Error on windows installations - -# 1.5.5 - * SECURITY: Also don't allow read files on directory traversal on minify paths - * NEW: padOptions can be set in settings.json now - * Fix: Add check for special characters in createPad API function - * Fix: Middle click on a link in firefox don't paste text anymore - * Fix: Made setPadRaw async to import larger etherpad files - * Fix: rtl - * Fix: Problem in older IEs - * Other: Update to express 4.x - * Other: Dropped support for node 0.8 - * Other: Update ejs to version 2.x - * Other: Moved sessionKey from settings.json to a new auto-generated SESSIONKEY.txt file - -# 1.5.4 - * SECURITY: Also don't allow read files on directory traversal on frontend tests path - -# 1.5.3 - * NEW: Accessibility support for Screen readers, includes new fonts and keyboard shortcuts - * NEW: API endpoint for Append Chat Message and Chat Backend Tests - * NEW: Error messages displayed on load are included in Default Pad Text (can be supressed) - * NEW: Content Collector can handle key values - * NEW: getAttributesOnPosition Method - * FIX: Firefox keeps attributes (bold etc) on cut/copy -> paste - * Fix: showControls=false now works - * Fix: Cut and Paste works... - * SECURITY: Don't allow read files on directory traversal - -# 1.5.2 - * NEW: Support for node version 0.12.x - * NEW: API endpoint saveRevision, getSavedRevisionCount and listSavedRevisions - * NEW: setting to allow load testing - * Fix: Rare scroll issue - * Fix: Handling of custom pad path - * Fix: Better error handling of imports and exports of type "etherpad" - * Fix: Walking caret in chrome - * Fix: Better handling for changeset problems - * SECURITY Fix: Information leak for etherpad exports (CVE-2015-2298) - -# 1.5.1 - * NEW: High resolution Icon - * NEW: Use HTTPS for plugins.json download - * NEW: Add 'last update' column - * NEW: Show users and chat at the same time - * NEW: Support io.js - * Fix: removeAttributeOnLine now works properly - * Fix: Plugin search and list - * Fix: Issue where unauthed request could cause error - * Fix: Privacy issue with .etherpad export - * Fix: Freeze deps to improve bisectability - * Fix: IE, everything. IE is so broken. - * Fix: Timeslider proxy - * Fix: All backend tests pass - * Fix: Better support for Export into HTML - * Fix: Timeslider stars - * Fix: Translation update - * Fix: Check filesystem if Abiword exists - * Fix: Docs formatting - * Fix: Move Save Revision notification to a gritter message - * Fix: UeberDB MySQL Timeout issue - * Fix: Indented +9 list items - * Fix: Don't paste on middle click of link - * SECURITY Fix: Issue where a malformed URL could cause EP to disclose installation location - -# 1.5.0 - * NEW: Lots of performance improvements for page load times - * NEW: Hook for adding CSS to Exports - * NEW: Allow shardable socket io - * NEW: Allow UI to show when attr/prop is applied (CSS) - * NEW: Various scripts - * NEW: Export full fidelity pads (including authors etc.) - * NEW: Various front end tests - * NEW: Backend tests - * NEW: switchPad hook to instantly switch between pads - * NEW: Various translations - * NEW: Icon sets instead of images to provide quality high DPI experience - * Fix: HTML Import blocking / hanging server - * Fix: Export Bullet / Numbered lists HTML - * Fix: Swagger deprecated warning - * Fix: Bad session from crashing server - * Fix: Allow relative settings path - * Fix: Stop attributes being improperly assigned between 2 lines - * Fix: Copy / Move Pad API race condition - * Fix: Save all user preferences - * Fix: Upgrade majority of dependency inc upgrade to SocketIO1+ - * Fix: Provide UI button to restore maximized chat window - * Fix: Timeslider UI Fix - * Fix: Remove Dokuwiki - * Fix: Remove long paths from windows build (stops error during extract) - * Fix: Various globals remvoed - * Fix: Move all scripts into bin/ - * Fix: Various CSS bugfixes for Mobile devices - * Fix: Overflow Toolbar - * Fix: Line Attribute management - -# 1.4.1 - * NEW: Translations - * NEW: userLeave Hook - * NEW: Script to reinsert all DB values of a Pad - * NEW: Allow for absolute settings paths - * NEW: API: Get Pad ID from read Only Pad ID - * NEW: Huge improvement on MySQL database read/write (InnoDB to MyISAM) - * NEW: Hook for Export File Name - * NEW: Preprocessor Hook for DOMLine attributes (allows plugins to wrap entire line contents) - * Fix: Exception on Plugin Search and fix for plugins not being fetched - * Fix: Font on innerdoc body can be arial on paste - * Fix: Fix Dropping of messages in handleMessage - * Fix: Don't use Abiword for HTML exports - * Fix: Color issues with user Icon - * Fix: Timeslider Button - * Fix: Session Deletion error - * Fix: Allow browser tabs to be cycled when focus is in editor - * Fix: Various Editor issues with Easysync potentially entering forever loop on bad changeset - -# 1.4 - * NEW: Disable toolbar items through settings.json - * NEW: Internal stats/metrics engine - * NEW: Copy/Move Pad API functions - * NEW: getAttributeOnSelection method - * NEW: CSS function when an attribute is active on caret location - * NEW: Various new eejs blocks - * NEW: Ace afterEditHook - * NEW: Import hook to introduce alternative export methods - * NEW: preProcessDomLine allows Domline attributes to be processed before native attributes - * Fix: Allow for lighter author colors - * Fix: Improved randomness of session tokens - * Fix: Don't panic if an author2session/group2session no longer exists - * Fix: Gracefully fallback to related languages if chosen language is unavailable - * Fix: Various changeset/stability bugs - * Fix: Re-enable import buttons after failed import - * Fix: Allow browser tabs to be cycled when in editor - * Fix: Better Protocol detection - * Fix: padList API Fix - * Fix: Caret walking issue - * Fix: Better settings.json parsing - * Fix: Improved import/export handling - * Other: Various whitespace/code clean-up - * Other: .deb packaging creator - * Other: More API Documentation - * Other: Lots more translations - * Other: Support Node 0.11 - -# 1.3 - * NEW: We now follow the semantic versioning scheme! - * NEW: Option to disable IP logging - * NEW: Localisation updates from http://translatewiki.net. - * Fix: Fix readOnly group pads - * Fix: don't fetch padList on every request - -# 1.2.12 - * NEW: Add explanations for more disconnect scenarios - * NEW: export sessioninfos so plugins can access it - * NEW: pass pad in postAceInit hook - * NEW: Add trustProxy setting. ALlows to make ep use X-forwarded-for as remoteAddress - * NEW: userLeave hook (UNDOCUMENTED) - * NEW: Plural macro for translations - * NEW: backlinks to main page in Admin pages - * NEW: New translations from translatewiki.net - * SECURITY FIX: Filter author data sent to clients - * FIX: Never keep processing a changeset if it's corrupted - * FIX: Some client-side performance fixes for webkit browsers - * FIX: Only execute listAllPads query on demand (not on start-up) - * FIX: HTML import (don't crash on malformed or blank HTML input; strip title out of html during import) - * FIX: check if uploaded file only contains ascii chars when abiword disabled - * FIX: Plugin search in /admin/plugins - * FIX: Don't create new pad if a non-existant read-only pad is accessed - * FIX: Drop messages from unknown connections (would lead to a crash after a restart) - * FIX: API: fix createGroupFor endpoint, if mapped group is deleted - * FIX: Import form for other locales - * FIX: Don't stop processing changeset queue if there is an error - * FIX: Caret movement. Chrome detects blank rows line heights as incorrect - * FIX: allow colons in password - * FIX: Polish logging of client-side errors on the server - * FIX: Username url param - * FIX: Make start script POSIX ompatible - - -# 1.2.11 - * NEW: New Hook for outer_ace dynamic css manager and author style hook - * NEW: Bump log4js for improved logging - * Fix: Remove URL schemes which don't have RFC standard - * Fix: Fix safeRun subsequent restarts issue - * Fix: Allow safeRun to pass arguements to run.sh - * Fix: Include script for more efficient import - * Fix: Fix sysv comptibile script - * Fix: Fix client side changeset spamming - * Fix: Don't crash on no-auth - * Fix: Fix some IE8 errors - * Fix: Fix authorship sanitation - -# 1.2.10 - * NEW: Broadcast slider is exposed in timeslider so plugins can interact with it - * Fix: IE issue where pads wouldn't load due to missing console from i18n - * Fix: console issue in collab client would error on cross domain embeds in IE - * Fix: Only Restart Etherpad once plugin is installed - * Fix: Only redraw lines that exist after drag and drop - * Fix: Pasting into ordered list - * Fix: Import browser detection - * Fix: 2 Part Locale Specs - * Fix: Remove language string from chat element - * Fix: Make Saved revision Star fade back out on non Top frames - * Other: Remove some cruft legacy JS from old Etherpad - * Other: Express 3.1.2 breaks sessions, set Express to 3.1.0 - -# 1.2.91 - * NEW: Authors can now send custom object messages to other Authors making 3 way conversations possible. This introduces WebRTC plugin support. - * NEW: Hook for Chat Messages Allows for Desktop Notification support - * NEW: FreeBSD installation docs - * NEW: Ctrl S for save revision makes the Icon glow for a few sconds. - * NEW: Various hooks and expose the document ACE object - * NEW: Plugin page revamp makes finding and installing plugins more sane. - * NEW: Icon to enable sticky chat from the Chat box - * Fix: Cookies inside of plugins - * Fix: Don't leak event emitters when accessing admin/plugins - * Fix: Don't allow user to send messages after they have been "kicked" from a pad - * Fix: Refactor Caret navigation with Arrow and Pageup/down keys stops cursor being lost - * Fix: Long lines in Firefox now wrap properly - * Fix: Session Disconnect limit is increased from 10 to 20 to support slower restarts - * Fix: Support Node 0.10 - * Fix: Log HTTP on DEBUG log level - * Fix: Server wont crash on import fails on 0 file import. - * Fix: Import no longer fails consistantly - * Fix: Language support for non existing languages - * Fix: Mobile support for chat notifications are now usable - * Fix: Re-Enable Editbar buttons on reconnect - * Fix: Clearing authorship colors no longer disconnects all clients - * Other: New debug information for sessions - -# 1.2.9 - * Fix: MAJOR Security issue, where a hacker could submit content as another user - * Fix: security issue due to unescaped user input - * Fix: Admin page at /admin redirects to /admin/ now to prevent breaking relative links - * Fix: indentation in chrome on linux - * Fix: PadUsers API endpoint - * NEW: A script to import data to all dbms - * NEW: Add authorId to chat and userlist as a data attribute - * NEW: Refactor and fix our frontend tests - * NEW: Localisation updates - - -# 1.2.81 - * Fix: CtrlZ-Y for Undo Redo - * Fix: RTL functionality on contents & fix RTL/LTR tests and RTL in Safari - * Fix: Various other tests fixed in Android - -# 1.2.8 - ! IMPORTANT: New setting.json value is required to automatically reconnect clients on disconnect - * NEW: Use Socket IO for rooms (allows for pads to be load balanced with sticky rooms) - * NEW: Plugins can now provide their own frontend tests - * NEW: Improved server-side logging - * NEW: Admin dashboard mobile device support and new hooks for Admin dashboard - * NEW: Get current API version from API - * NEW: CLI script to delete pads - * Fix: Automatic client reconnection on disonnect - * Fix: Text Export indentation now supports multiple indentations - * Fix: Bugfix getChatHistory API method - * Fix: Stop Chrome losing caret after paste is texted - * Fix: Make colons on end of line create 4 spaces on indent - * Fix: Stop the client disconnecting if a rev is in the wrong order - * Fix: Various server crash issues based on rev in wrong order - * Fix: Various tests - * Fix: Make indent when on middle of the line stop creating list - * Fix: Stop long strings breaking the UX by moving focus away from beginning of line - * Fix: Redis findKeys support - * Fix: padUsersCount no longer hangs server - * Fix: Issue with two part locale specs not working - * Fix: Make plugin search case insensitive - * Fix: Indentation and bullets on text export - * Fix: Resolve various warnings on dependencies during install - * Fix: Page up / Page down now works in all browsers - * Fix: Stop Opera browser inserting two new lines on enter keypress - * Fix: Stop timeslider from showing NaN on pads with only one revision - * Other: Allow timeslider tests to run and provide & fix various other frontend-tests - * Other: Begin dropping referene to Lite. Etherpad Lite is now named "Etherpad" - * Other: Update to latest jQuery - * Other: Change loading message asking user to please wait on first build - * Other: Allow etherpad to use global npm installation (Safe since node 6.3) - * Other: Better documentation for log rotation and log message handling - - - -# 1.2.7 - * NEW: notifications are now modularized and can be stacked - * NEW: Visit a specific revision in the timeslider by suffixing #%revNumber% IE http://localhost/p/test/timeslider#12 - * NEW: Link to plugin on Admin page allows admins to easily see plugin details in a new window by clicking on the plugin name - * NEW: Automatically see plugins that require update and be able to one click update - * NEW: API endpoints for Chat .. getChatHistory, getChatHead - * NEW: API endpoint to see a pad diff in HTML format from revision x to revision y .. createPadDiffHTML - * NEW: Real time plugin search & unified menu UI for admin pages - * Fix: MAJOR issue where server could be crashed by malformed client message - * Fix: AuthorID is now included in padUsers API response - * Fix: make docs - * Fix: Timeslider UI bug with slider not being in position - * Fix: IE8 language issue where it wouldn't load pads due to IE8 suckling on the bussum of hatrid - * Fix: Import timeout issue - * Fix: Import now works if Params are set in pad URL - * Fix: Convert script - * Other: Various new language strings and update/bugfixes of others - * Other: Clean up the getParams functionality - * Other: Various new EEJS blocks: index, timeslider, html etc. - -# 1.2.6 - * Fix: Package file UeberDB reference - * New #users EEJS block for plugins - -# 1.2.5 - * Create timeslider EEJS blocks for plugins - * Allow for "more messages" to be loaded in chat - * Introduce better logging - * API endpoint for "listAllPads" - * Fix: Stop highlight of timeslider when dragging mouse - * Fix: Time Delta on Timeslider make date update properly - * Fix: Prevent empty chat messages from being sent - * Fix: checkPad script - * Fix: IE onLoad listener for i18n - -# 1.2.4 - * Fix IE console issue created in 1.2.3 - * Allow CI Tests to pass by ignoring timeslider test - * Fix broken placeholders in locales - * Fix extractPadData script - * Fix documentation for checkToken - * Fix hitting enter on form in admin/plugins - -# 1.2.3 - * Fix #1307: Chrome needs console.log to be called on console obj - * Fix #1309: We had broken support for node v0.6 in the last release - -# 1.2.2 - * More translations and better language support. See https://translatewiki.net/wiki/Translating:Etherpad_lite for more details - * Add a checkToken Method to the API - * Bugfix for Internal Caching issue that was causing some 404s on images. - * Bugfix for IE Import - * Bugfix for Node 0.6 compatibility - * Bugfix for multiple cookie support - * Bugfix for API when requireAuth is enabled. - * Plugin page now shows plugin version # - * Show color of Author in Chat messages - * Allow plugin search by description - * Allow for different socket IO transports - * Allow for custom favicon path - * Control S now does Create new Revision functionality - * Focus on password when required - * Frontend Timeslider test - * Allow for basic HTML etc. import without abiword - * Native HTTPS support - -# 1.2.1 - * Allow ! in urls inside the editor (Not Pad urls) - * Allow comments in language files - * More languages (Finish, Spanish, Bengali, Dutch) Thanks to TranslateWiki.net team. See https://translatewiki.net/w/i.php?title=Special:MessageGroupStats&group=out-etherpad-lite for more details - * Bugfix for IE7/8 issue with a JS error #1186 - * Bugfix windows package extraction issue and make the .zip file smaller - * Bugfix group pad API export - * Kristen Stewart is a terrible actress and Twilight sucks. - -# v1.2 - * Internationalization / Language / Translation support (i18n) with support for German/French - * A frontend/client side testing framework and backend build tests - * Customizable robots.txt - * Customizable app title (finally you can name your epl instance!) - * eejs render arguments are now passed on to eejs hooks through the newly introduced `renderContext` argument. - * Plugin-specific settings in settings.json (finally allowing for things like a google analytics plugin) - * Serve admin dashboard at /admin (still very limited, though) - * Modify your settings.json through the newly created UI at /admin/settings - * Fix: Import
    's as
      's and not as
        's! - * Added solaris compatibility (bin/installDeps.sh was broken on solaris) - * Fix a bug with IE9 and Password Protected Pads using HTTPS - -# v1.1.5 - * We updated to express v3 (please [make sure](https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x) your plugin works under express v3) - * `userColor` URL parameter which sets the initial author color - * Hooks for "padCreate", "padRemove", "padUpdate" and "padLoad" events - * Security patches concerning the handling of messages originating from clients - * Our database abstraction layer now natively supports couchDB, levelDB, mongoDB, postgres, and redis! - * We now provide a script helping you to migrate from dirtyDB to MySQL - * Support running Etherpad Lite behind IIS, using [iisnode](https://github.com/tjanczuk/iisnode/wiki) - * LibreJS Licensing information in headers of HTML templates - * Default port number to PORT env var, if port isn't specified in settings - * Fix for `convert.js` - * Raise upper char limit in chat to 999 characters - * Fixes for mobile layout - * Fixes for usage behind reverse proxy - * Improved documentation - * Fixed some opera style bugs - * Update npm and fix some bugs, this introduces - -# v1.1 -* Introduced Plugin framework -* Many bugfixes -* Faster page loading -* Various UI polishes -* Saved Revisions -* Read only Real time view -* More API functionality - -# v 1.0.1 - -* Updated MySQL driver, this fixes some problems with mysql -* Fixed export,import and timeslider link when embed parameters are used diff --git a/sources/CONTRIBUTING.md b/sources/CONTRIBUTING.md deleted file mode 100644 index 6694608..0000000 --- a/sources/CONTRIBUTING.md +++ /dev/null @@ -1,110 +0,0 @@ -# Contributor Guidelines -(Please talk to people on the mailing list before you change this page, see our section on [how to get in touch](https://github.com/ether/etherpad-lite#get-in-touch)) - -## How to write a bug report - -* Please be polite, we all are humans and problems can occur. -* Please add as much information as possible, for example - * client os(s) and version(s) - * browser(s) and version(s), is the problem reproducible on different clients - * special environments like firewalls or antivirus - * host os and version - * npm and nodejs version - * Logfiles if available - * steps to reproduce - * what you expected to happen - * what actually happened -* Please format logfiles and code examples with markdown see github Markdown help below the issue textarea for more information. - -If you send logfiles, please set the loglevel switch DEBUG in your settings.json file: - -``` -/* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */ - "loglevel": "DEBUG", -``` - -The logfile location is defined in startup script or the log is directly shown in the commandline after you have started etherpad. - - -## Important note for pull requests -**Pull requests should be issued against the develop branch**. We never pull directly into master. - -**Our goal is to iterate in small steps. Release often, release early. Evolution instead of a revolution** - -## General goals of Etherpad -To make sure everybody is going in the same direction: -* easy to install for admins and easy to use for people -* easy to integrate into other apps, but also usable as standalone -* lightweight and scalable -* extensible, as much functionality should be extendable with plugins so changes don't have to be done in core. -Also, keep it maintainable. We don't wanna end up as the monster Etherpad was! - -## How to work with git? -* Don't work in your master branch. -* Make a new branch for every feature you're working on. (This ensures that you can work you can do lots of small, independent pull requests instead of one big one with complete different features) -* Don't use the online edit function of github (this only creates ugly and not working commits!) -* Try to make clean commits that are easy readable (including descriptive commit messages!) -* Test before you push. Sounds easy, it isn't! -* Don't check in stuff that gets generated during build or runtime -* Make small pull requests that are easy to review but make sure they do add value by themselves / individually - -## Coding style -* Do write comments. (You don't have to comment every line, but if you come up with something that's a bit complex/weird, just leave a comment. Bear in mind that you will probably leave the project at some point and that other people will read your code. Undocumented huge amounts of code are worthless!) -* Never ever use tabs -* Indentation: JS/CSS: 2 spaces; HTML: 4 spaces -* Don't overengineer. Don't try to solve any possible problem in one step, but try to solve problems as easy as possible and improve the solution over time! -* Do generalize sooner or later! (if an old solution, quickly hacked together, poses more problems than it solves today, refactor it!) -* Keep it compatible. Do not introduce changes to the public API, db schema or configurations too lightly. Don't make incompatible changes without good reasons! -* If you do make changes, document them! (see below) -* Use protocol independent urls "//" - -## Branching model / git workflow -see git flow http://nvie.com/posts/a-successful-git-branching-model/ - -### `master` branch -* the stable -* This is the branch everyone should use for production stuff - -### `develop`branch -* everything that is READY to go into master at some point in time -* This stuff is tested and ready to go out - -### release branches -* stuff that should go into master very soon -* only bugfixes go into these (see http://nvie.com/posts/a-successful-git-branching-model/ for why) -* we should not be blocking new features to develop, just because we feel that we should be releasing it to master soon. This is the situation that release branches solve/handle. - -### hotfix branches -* fixes for bugs in master - -### feature branches (in your own repos) -* these are the branches where you develop your features in -* If it's ready to go out, it will be merged into develop - -Over the time we pull features from feature branches into the develop branch. Every month we pull from develop into master. Bugs in master get fixed in hotfix branches. These branches will get merged into master AND develop. There should never be commits in master that aren't in develop - -## Documentation -The docs are in the `doc/` folder in the git repository, so people can easily find the suitable docs for the current git revision. - -Documentation should be kept up-to-date. This means, whenever you add a new API method, add a new hook or change the database model, pack the relevant changes to the docs in the same pull request. - -You can build the docs e.g. produce html, using `make docs`. At some point in the future we will provide an online documentation. The current documentation in the github wiki should always reflect the state of `master` (!), since there are no docs in master, yet. - -## Testing -Front-end tests are found in the `tests/frontend/` folder in the repository. Run them by pointing your browser to `/tests/frontend`. - -## Things you can help with -Etherpad is much more than software. So if you aren't a developer then worry not, there is still a LOT you can do! A big part of what we do is community engagement. You can help in the following ways - * Triage bugs (applying labels) and confirming their existance - * Testing fixes (simply applying them and seeing if it fixes your issue or not) - Some git experience required - * Notifying large site admins of new releases - * Writing Changelogs for releases - * Creating Windows packages - * Creating releases - * Bumping dependencies periodically and checking they don't break anything - * Write proposals for grants - * Co-Author and Publish CVEs - * Work with SFC to maintain legal side of project - * Maintain TODO page - https://github.com/ether/etherpad-lite/wiki/TODO#IMPORTANT_TODOS - * Replying to messages on IRC / The Mailing list / Emails - diff --git a/sources/LICENSE b/sources/LICENSE deleted file mode 100644 index 366aa1a..0000000 --- a/sources/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2013 THE ETHERPAD FOUNDATION - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/sources/Makefile b/sources/Makefile deleted file mode 100644 index aedb937..0000000 --- a/sources/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -doc_sources = $(wildcard doc/*/*.md) $(wildcard doc/*.md) -outdoc_files = $(addprefix out/,$(doc_sources:.md=.html)) - -docassets = $(addprefix out/,$(wildcard doc/assets/*)) - -VERSION = $(shell node -e "console.log( require('./src/package.json').version )") -UNAME := $(shell uname -s) - -docs: $(outdoc_files) $(docassets) - -out/doc/assets/%: doc/assets/% - mkdir -p $(@D) - cp $< $@ - -out/doc/%.html: doc/%.md - mkdir -p $(@D) - node bin/doc/generate.js --format=html --template=doc/template.html $< > $@ -ifeq ($(UNAME),Darwin) - sed -i '' 's/__VERSION__/${VERSION}/' $@ -else - sed -i 's/__VERSION__/${VERSION}/' $@ -endif - -clean: - rm -rf out/ diff --git a/sources/README.md b/sources/README.md deleted file mode 100644 index d8d7b62..0000000 --- a/sources/README.md +++ /dev/null @@ -1,131 +0,0 @@ -### This project is looking for a new project lead. If you wish to help steer Etherpad forward please email contact@etherpad.org - -[![Deps](https://david-dm.org/ether/etherpad-lite.svg?branch=develop)](https://david-dm.org/ether/etherpad-lite) -[![NSP Status](https://nodesecurity.io/orgs/etherpad/projects/635f6185-35c6-4ed7-931a-0bc62758ece7/badge)](https://nodesecurity.io/orgs/etherpad/projects/635f6185-35c6-4ed7-931a-0bc62758ece7) - -# A really-real time collaborative word processor for the web -![Demo Etherpad Animated Jif](https://i.imgur.com/zYrGkg3.gif "Etherpad in action on PrimaryPad") - -# About -Etherpad is a really-real time collaborative editor scalable to thousands of simultanious real time users. Unlike all other collaborative tools Etherpad provides full fidelity data export and portability making it fully GDPR compliant. - -**[Try it out](http://beta.etherpad.org)** - -# Installation - -## Uber-Quick Ubuntu -``` -curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash - -sudo apt-get install -y nodejs -git clone https://github.com/ether/etherpad-lite.git && cd etherpad-lite && bin/run.sh -``` - -## GNU/Linux and other UNIX-like systems -You'll need gzip, git, curl, libssl develop libraries, python and gcc. -- *For Debian/Ubuntu*: `apt install gzip git curl python libssl-dev pkg-config build-essential` -- *For Fedora/CentOS*: `yum install gzip git curl python openssl-devel && yum groupinstall "Development Tools"` -- *For FreeBSD*: `portinstall node, npm, curl, git (optional)` - -Additionally, you'll need [node.js](https://nodejs.org) installed, Ideally the latest stable version, we recommend installing/compiling nodejs from source (avoiding apt). - -**As any user (we recommend creating a separate user called etherpad):** - -1. Move to a folder where you want to install Etherpad. Clone the git repository `git clone git://github.com/ether/etherpad-lite.git` -2. Change into the new directory containing the cloned source code `cd etherpad-lite` - -Now, run `bin/run.sh` and open in your browser. - -Update to the latest version with `git pull origin`. The next start with bin/run.sh will update the dependencies. - -[Next steps](#next-steps). - -## Windows - -### Prebuilt windows package -This package works out of the box on any windows machine, but it's not very useful for developing purposes... - -1. [Download the latest windows package](http://etherpad.org/#download) -2. Extract the folder - -Now, run `start.bat` and open in your browser. You like it? [Next steps](#next-steps). - -### Fancy install -You'll need [node.js](https://nodejs.org) and (optionally, though recommended) git. - -1. Grab the source, either - - download - - or `git clone https://github.com/ether/etherpad-lite.git` (for this you need git, obviously) -2. start `bin\installOnWindows.bat` - -Now, run `start.bat` and open in your browser. - -Update to the latest version with `git pull origin`, then run `bin\installOnWindows.bat`, again. - -If cloning to a subdirectory within another project, you may need to do the following: - -1. Start the server manually (e.g. `node/node_modules/ep_etherpad-lite/node/server.js]`) -2. Edit the db `filename` in `settings.json` to the relative directory with the file (e.g. `application/lib/etherpad-lite/var/dirty.db`) -3. Add auto-generated files to the main project `.gitignore` - -# Next Steps - -## Tweak the settings -You can initially modify the settings in `settings.json`. (If you need to handle multiple settings files, you can pass the path to a settings file to `bin/run.sh` using the `-s|--settings` option. This allows you to run multiple Etherpad instances from the same installation.) Once you have access to your /admin section settings can be modified through the web browser. - -You should use a dedicated database such as "mysql", if you are planning on using etherpad-in a production environment, since the "dirtyDB" database driver is only for testing and/or development purposes. - -## Plugins and themes - -Etherpad is very customizable through plugins. Instructions for installing themes and plugins can be found in [the plugin wiki article](https://github.com/ether/etherpad-lite/wiki/Available-Plugins). - -## Helpful resources -The [wiki](https://github.com/ether/etherpad-lite/wiki) is your one-stop resource for Tutorials and How-to's. - -Documentation can be found in `doc/`. - -# Development - -## Things you should know -Understand [git](https://training.github.com/) and watch this [video on getting started with Etherpad Development](https://youtu.be/67-Q26YH97E). - -If you're new to node.js, start with Ryan Dahl's [Introduction to Node.js](https://youtu.be/jo_B4LTHi3I). - -You can debug Etherpad using `bin/debugRun.sh`. - -If you want to find out how Etherpad's `Easysync` works (the library that makes it really realtime), start with this [PDF](https://github.com/ether/etherpad-lite/raw/master/doc/easysync/easysync-full-description.pdf) (complex, but worth reading). - -## Contributing -Read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/blob/master/CONTRIBUTING.md) - -# Get in touch -[mailinglist](https://groups.google.com/group/etherpad-lite-dev) -[#etherpad-lite-dev freenode IRC](https://webchat.freenode.net?channels=#etherpad-lite-dev)! - -# Languages -Etherpad is written in JavaScript on both the server and client so it's easy for developers to maintain and add new features. - -# HTTP API -Etherpad is designed to be easily embeddable and provides a [HTTP API](https://github.com/ether/etherpad-lite/wiki/HTTP-API) -that allows your web application to manage pads, users and groups. It is recommended to use the [available client implementations](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) in order to interact with this API. - -# jQuery plugin -There is a [jQuery plugin](https://github.com/ether/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website. - -# Plugin Framework -Etherpad offers a plugin framework, allowing you to easily add your own features. By default your Etherpad is extremely light-weight and it's up to you to customize your experience. Once you have Etherpad installed you should visit the plugin page and take control. - -# Translations / Localizations (i18n / l10n) -Etherpad comes with translations into all languages thanks to the team at TranslateWiki. - -# FAQ -Visit the **[FAQ](https://github.com/ether/etherpad-lite/wiki/FAQ)**. - -# Donate! -* [Flattr](https://flattr.com/thing/71378/Etherpad-Foundation) -* Paypal - Press the donate button on [etherpad.org](http://etherpad.org) -* [Bitcoin](https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a) - -All donations go to the Etherpad foundation which is part of Software Freedom Conservency - -# License -[Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html) diff --git a/sources/bin/backendTests.sh b/sources/bin/backendTests.sh deleted file mode 100755 index ec12775..0000000 --- a/sources/bin/backendTests.sh +++ /dev/null @@ -1 +0,0 @@ -src/node_modules/mocha/bin/mocha --timeout 5000 --reporter nyan tests/backend/specs/api diff --git a/sources/bin/buildDebian.sh b/sources/bin/buildDebian.sh deleted file mode 100755 index 58431f7..0000000 --- a/sources/bin/buildDebian.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bash - -# IMPORTANT -# Protect against misspelling a var and rm -rf / -set -u -set -e - -SRC=/tmp/etherpad-deb-src -DIST=/tmp/etherpad-deb-dist -SYSROOT=${SRC}/sysroot -DEBIAN=${SRC}/DEBIAN - -rm -rf ${DIST} -mkdir -p ${DIST}/ - -rm -rf ${SRC} -rsync -a bin/deb-src/ ${SRC}/ -mkdir -p ${SYSROOT}/opt/ - -rsync --exclude '.git' -a . ${SYSROOT}/opt/etherpad/ --delete -mkdir -p ${SYSROOT}/usr/share/doc -cp README.md ${SYSROOT}/usr/share/doc/etherpad -find ${SRC}/ -type d -exec chmod 0755 {} \; -find ${SRC}/ -type f -exec chmod go-w {} \; -chown -R root:root ${SRC}/ - -let SIZE=`du -s ${SYSROOT} | sed s'/\s\+.*//'`+8 -pushd ${SYSROOT}/ -tar czf ${DIST}/data.tar.gz [a-z]* -popd -sed s"/SIZE/${SIZE}/" -i ${DEBIAN}/control -pushd ${DEBIAN} -tar czf ${DIST}/control.tar.gz * -popd - -pushd ${DIST}/ -echo 2.0 > ./debian-binary - -find ${DIST}/ -type d -exec chmod 0755 {} \; -find ${DIST}/ -type f -exec chmod go-w {} \; -chown -R root:root ${DIST}/ -ar r ${DIST}/etherpad-1.deb debian-binary control.tar.gz data.tar.gz -popd -rsync -a ${DIST}/etherpad-1.deb ./ diff --git a/sources/bin/buildForWindows.sh b/sources/bin/buildForWindows.sh deleted file mode 100755 index a9fbd70..0000000 --- a/sources/bin/buildForWindows.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/sh - -NODE_VERSION="8.9.0" - -#Move to the folder where ep-lite is installed -cd `dirname $0` - -#Was this script started in the bin folder? if yes move out -if [ -d "../bin" ]; then - cd "../" -fi - -#Is wget installed? -hash wget > /dev/null 2>&1 || { - echo "Please install wget" >&2 - exit 1 -} - -#Is zip installed? -hash zip > /dev/null 2>&1 || { - echo "Please install zip" >&2 - exit 1 -} - -#Is zip installed? -hash unzip > /dev/null 2>&1 || { - echo "Please install unzip" >&2 - exit 1 -} - -START_FOLDER=$(pwd); -TMP_FOLDER=$(mktemp -d) - -echo "create a clean environment in $TMP_FOLDER..." -cp -ar . $TMP_FOLDER -cd $TMP_FOLDER -rm -rf node_modules -rm -f etherpad-lite-win.zip - -echo "do a normal unix install first..." -bin/installDeps.sh || exit 1 - -echo "copy the windows settings template..." -cp settings.json.template settings.json - -echo "resolve symbolic links..." -cp -rL node_modules node_modules_resolved -rm -rf node_modules -mv node_modules_resolved node_modules - -echo "download windows node..." -cd bin -wget "https://nodejs.org/dist/v$NODE_VERSION/win-x86/node.exe" -O ../node.exe - -echo "remove git history to reduce folder size" -rm -rf .git/objects - -echo "remove windows jsdom-nocontextify/test folder" -rm -rf $TMP_FOLDER/src/node_modules/wd/node_modules/request/node_modules/form-data/node_modules/combined-stream/test -rm -rf $TMP_FOLDER/src/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables - -echo "create the zip..." -cd $TMP_FOLDER -zip -9 -r $START_FOLDER/etherpad-lite-win.zip ./* - -echo "clean up..." -rm -rf $TMP_FOLDER - -echo "Finished. You can find the zip in the Etherpad root folder, it's called etherpad-lite-win.zip" diff --git a/sources/bin/checkAllPads.js b/sources/bin/checkAllPads.js deleted file mode 100644 index 90cb152..0000000 --- a/sources/bin/checkAllPads.js +++ /dev/null @@ -1,145 +0,0 @@ -/* - This is a debug tool. It checks all revisions for data corruption -*/ - -if(process.argv.length != 2) -{ - console.error("Use: node bin/checkAllPads.js"); - process.exit(1); -} - -//initalize the variables -var db, settings, padManager; -var npm = require("../src/node_modules/npm"); -var async = require("../src/node_modules/async"); - -var Changeset = require("../src/static/js/Changeset"); - -async.series([ - //load npm - function(callback) { - npm.load({}, callback); - }, - //load modules - function(callback) { - settings = require('../src/node/utils/Settings'); - db = require('../src/node/db/DB'); - - //initalize the database - db.init(callback); - }, - //load pads - function (callback) - { - padManager = require('../src/node/db/PadManager'); - - padManager.listAllPads(function(err, res) - { - padIds = res.padIDs; - callback(err); - }); - }, - function (callback) - { - async.forEach(padIds, function(padId, callback) - { - padManager.getPad(padId, function(err, pad) { - if (err) { - callback(err); - } - - //check if the pad has a pool - if(pad.pool === undefined ) - { - console.error("[" + pad.id + "] Missing attribute pool"); - callback(); - return; - } - - //create an array with key kevisions - //key revisions always save the full pad atext - var head = pad.getHeadRevisionNumber(); - var keyRevisions = []; - for(var i=0;i/dev/null - if [ $? == 0 ]; then - echo "Aborting: Release branch already present" - exit 1 - fi - git checkout -b release/$VERSION - [[ $? != 0 ]] && echo "Aborting: Error creating release branch" && exit 1 - - echo "Committing CHANGELOG.md and package.json" - git add CHANGELOG.md - git add src/package.json - git commit -m "Release version $VERSION" - - echo "Pushing release branch to github..." - git push -u $ETHER_REPO release/$VERSION - [[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1 -} - -function merge_release_branch { - echo "Merging release to master branch on github..." - API_JSON=$(printf '{"base": "master","head": "release/%s","commit_message": "Merge new release into master branch!"}' $VERSION) - CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/merges?access_token=$API_TOKEN | iconv -f utf8) - echo $CURL_RESPONSE - HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') - [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch on github" && exit 1 -} - -function create_builds { - echo "Cloning etherpad-lite repo and ether.github.com repo..." - cd $TMP_DIR - rm -rf etherpad-lite ether.github.com - git clone $ETHER_REPO --branch master - git clone $ETHER_WEB_REPO - echo "Creating windows build..." - cd etherpad-lite - bin/buildForWindows.sh - [[ $? != 0 ]] && echo "Aborting: Error creating build for windows" && exit 1 - echo "Creating docs..." - make docs - [[ $? != 0 ]] && echo "Aborting: Error generating docs" && exit 1 -} - -function push_builds { - cd $TMP_DIR/etherpad-lite/ - echo "Copying windows build and docs to website repo..." - GIT_SHA=$(git rev-parse HEAD | cut -c1-10) - mv etherpad-lite-win.zip $TMP_DIR/ether.github.com/downloads/etherpad-lite-win-$VERSION-$GIT_SHA.zip - - mv out/doc $TMP_DIR/ether.github.com/doc/v$VERSION - - cd $TMP_DIR/ether.github.com/ - sed -i "s/etherpad-lite-win.*\.zip/etherpad-lite-win-$VERSION-$GIT_SHA.zip/" index.html - sed -i "s/$LATEST_GIT_TAG/$VERSION/g" index.html - git checkout -b release_$VERSION - [[ $? != 0 ]] && echo "Aborting: Error creating new release branch" && exit 1 - git add doc/ - git add downloads/ - git commit -a -m "Release version $VERSION" - git push -u $ETHER_WEB_REPO release_$VERSION - [[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1 -} - -function merge_web_branch { - echo "Merging release to master branch on github..." - API_JSON=$(printf '{"base": "master","head": "release_%s","commit_message": "Release version %s"}' $VERSION $VERSION) - CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/ether.github.com/merges?access_token=$API_TOKEN | iconv -f utf8) - echo $CURL_RESPONSE - HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') - [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch" && exit 1 -} - -function publish_release { - echo -n "Do you want to publish a new release on github (y/n)? " - read PUBLISH_RELEASE - if [ $PUBLISH_RELEASE = "y" ]; then - # create a new release on github - API_JSON=$(printf '{"tag_name": "%s","target_commitish": "master","name": "Release %s","body": "%s","draft": false,"prerelease": false}' $VERSION $VERSION $changelogText) - CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/releases?access_token=$API_TOKEN | iconv -f utf8) - HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') - [[ $HTTP_STATUS != "201" ]] && echo "Aborting: Error publishing release on github" && exit 1 - else - echo "No release published on github!" - fi -} - -function todo_notification { - echo "Release procedure was successful, but you have to do some steps manually:" - echo "- Update the wiki at https://github.com/ether/etherpad-lite/wiki" - echo "- Create a pull request on github to merge the master branch back to develop" - echo "- Announce the new release on the mailing list, blog.etherpad.org and Twitter" -} - -# Call functions -check_api_token -modify_files -create_release_branch -merge_release_branch -create_builds -push_builds -merge_web_branch -publish_release -todo_notification diff --git a/sources/bin/deb-src/DEBIAN/control b/sources/bin/deb-src/DEBIAN/control deleted file mode 100644 index a516dc6..0000000 --- a/sources/bin/deb-src/DEBIAN/control +++ /dev/null @@ -1,9 +0,0 @@ -Package: etherpad -Version: 1.3 -Section: base -Priority: optional -Architecture: i386 -Installed-Size: SIZE -Depends: -Maintainer: John McLear -Description: Etherpad is a collaborative editor. diff --git a/sources/bin/deb-src/DEBIAN/postinst b/sources/bin/deb-src/DEBIAN/postinst deleted file mode 100755 index 2f483f7..0000000 --- a/sources/bin/deb-src/DEBIAN/postinst +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# Start the services! - -service etherpad start -echo "Give Etherpad about 3 minutes to install dependencies then visit http://localhost:9001 in your web browser" -echo "To stop etherpad type 'service etherpad stop', To restart type 'service etherpad restart'". -rm -f /tmp/etherpad.log /tmp/etherpad.err diff --git a/sources/bin/deb-src/DEBIAN/preinst b/sources/bin/deb-src/DEBIAN/preinst deleted file mode 100755 index e5b5e0b..0000000 --- a/sources/bin/deb-src/DEBIAN/preinst +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -# Installs node if it isn't already installed -# -# Don't steamroll over a previously installed node version -# TODO provide a local version of node? - -VER="0.10.4" -ARCH="x86" -if [ `arch | grep 64` ] -then - ARCH="x64" -fi - -# TODO test version -if [ ! -f /usr/local/bin/node ] -then - pushd /tmp - wget -c "http://nodejs.org/dist/v${VER}/node-v${VER}-linux-${ARCH}.tar.gz" - rm -rf /tmp/node-v${VER}-linux-${ARCH} - tar xf node-v${VER}-linux-${ARCH}.tar.gz -C /tmp/ - cp -a /tmp/node-v${VER}-linux-${ARCH}/* /usr/local/ -fi - -# Create Etherpad user -adduser --system etherpad diff --git a/sources/bin/deb-src/DEBIAN/prerm b/sources/bin/deb-src/DEBIAN/prerm deleted file mode 100755 index 5e3d0f8..0000000 --- a/sources/bin/deb-src/DEBIAN/prerm +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -# Stop the appserver: -service etherpad stop || true diff --git a/sources/bin/deb-src/sysroot/etc/init/etherpad.conf b/sources/bin/deb-src/sysroot/etc/init/etherpad.conf deleted file mode 100644 index cd6f454..0000000 --- a/sources/bin/deb-src/sysroot/etc/init/etherpad.conf +++ /dev/null @@ -1,28 +0,0 @@ -description "etherpad" - -start on started networking -stop on runlevel [!2345] - -env EPHOME=/opt/etherpad -env EPLOGS=/var/log/etherpad -env EPUSER=etherpad - -respawn - -pre-start script - cd $EPHOME - mkdir $EPLOGS ||true - chown $EPUSER $EPLOGS ||true - chmod 0755 $EPLOGS ||true - chown -R $EPUSER $EPHOME/var ||true - $EPHOME/bin/installDeps.sh >> $EPLOGS/error.log || { stop; exit 1; } -end script - -script - cd $EPHOME/ - exec su -s /bin/sh -c 'exec "$0" "$@"' $EPUSER -- node node_modules/ep_etherpad-lite/node/server.js \ - >> $EPLOGS/access.log \ - 2>> $EPLOGS/error.log - echo "Etherpad is running on http://localhost:9001 - To change settings edit /opt/etherpad/settings.json" - -end script diff --git a/sources/bin/debugRun.sh b/sources/bin/debugRun.sh deleted file mode 100755 index b42112f..0000000 --- a/sources/bin/debugRun.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -#Move to the folder where ep-lite is installed -cd `dirname $0` - -#Was this script started in the bin folder? if yes move out -if [ -d "../bin" ]; then - cd "../" -fi - -#Prepare the environment -bin/installDeps.sh || exit 1 - -hash node-inspector > /dev/null 2>&1 || { - echo "You need to install node-inspector to run the tests!" >&2 - echo "You can install it with npm" >&2 - echo "Run: npm install -g node-inspector" >&2 - exit 1 -} - -node-inspector & - -echo "If you are new to node-inspector, take a look at this video: https://youtu.be/AOnK3NVnxL8" - -node --debug node_modules/ep_etherpad-lite/node/server.js $* - -#Kill node-inspector before ending -kill $! diff --git a/sources/bin/deletePad.js b/sources/bin/deletePad.js deleted file mode 100644 index fe7761d..0000000 --- a/sources/bin/deletePad.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - A tool for deleting pads from the CLI, because sometimes a brick is required to fix a window. -*/ - -if(process.argv.length != 3) -{ - console.error("Use: node deletePad.js $PADID"); - process.exit(1); -} -//get the padID -var padId = process.argv[2]; - -var db, padManager, pad, settings; -var neededDBValues = ["pad:"+padId]; - -var npm = require("../src/node_modules/npm"); -var async = require("../src/node_modules/async"); - -async.series([ - // load npm - function(callback) { - npm.load({}, function(er) { - if(er) - { - console.error("Could not load NPM: " + er) - process.exit(1); - } - else - { - callback(); - } - }) - }, - // load modules - function(callback) { - settings = require('../src/node/utils/Settings'); - db = require('../src/node/db/DB'); - callback(); - }, - // initialize the database - function (callback) - { - db.init(callback); - }, - // delete the pad and its links - function (callback) - { - padManager = require('../src/node/db/PadManager'); - - padManager.removePad(padId, function(err){ - callback(err); - }); - callback(); - } -], function (err) -{ - if(err) throw err; - else - { - console.log("Finished deleting padId: "+padId); - process.exit(); - } -}); diff --git a/sources/bin/dirty-db-cleaner.py b/sources/bin/dirty-db-cleaner.py deleted file mode 100755 index d3e49a0..0000000 --- a/sources/bin/dirty-db-cleaner.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env PYTHONUNBUFFERED=1 python2 -# -# Created by Bjarni R. Einarsson, placed in the public domain. Go wild! -# -import json -import os -import sys - -try: - dirtydb_input = sys.argv[1] - dirtydb_output = '%s.new' % dirtydb_input - assert(os.path.exists(dirtydb_input)) - assert(not os.path.exists(dirtydb_output)) -except: - print - print 'Usage: %s /path/to/dirty.db' % sys.argv[0] - print - print 'Note: Will create a file named dirty.db.new in the same folder,' - print ' please make sure permissions are OK and a file by that' - print ' name does not exist already. This script works by omitting' - print ' duplicate lines from the dirty.db file, keeping only the' - print ' last (latest) instance. No revision data should be lost,' - print ' but be careful, make backups. If it breaks you get to keep' - print ' both pieces!' - print - sys.exit(1) - -dirtydb = {} -lines = 0 -with open(dirtydb_input, 'r') as fd: - print 'Reading %s' % dirtydb_input - for line in fd: - lines += 1 - data = json.loads(line) - dirtydb[data['key']] = line - if lines % 10000 == 0: - sys.stderr.write('.') -print -print 'OK, found %d unique keys in %d lines' % (len(dirtydb), lines) - -with open(dirtydb_output, 'w') as fd: - for data in dirtydb.values(): - fd.write(data) - -print 'Wrote data to %s. All done!' % dirtydb_output diff --git a/sources/bin/doc/LICENSE b/sources/bin/doc/LICENSE deleted file mode 100644 index e3d4e69..0000000 --- a/sources/bin/doc/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -Copyright Joyent, Inc. and other Node contributors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. diff --git a/sources/bin/doc/README.md b/sources/bin/doc/README.md deleted file mode 100644 index 4646c20..0000000 --- a/sources/bin/doc/README.md +++ /dev/null @@ -1,76 +0,0 @@ -Here's how the node docs work. - -Each type of heading has a description block. - - - ## module - - Stability: 3 - Stable - - description and examples. - - ### module.property - - * Type - - description of the property. - - ### module.someFunction(x, y, [z=100]) - - * `x` {String} the description of the string - * `y` {Boolean} Should I stay or should I go? - * `z` {Number} How many zebras to bring. - - A description of the function. - - ### Event: 'blerg' - - * Argument: SomeClass object. - - Modules don't usually raise events on themselves. `cluster` is the - only exception. - - ## Class: SomeClass - - description of the class. - - ### Class Method: SomeClass.classMethod(anArg) - - * `anArg` {Object} Just an argument - * `field` {String} anArg can have this field. - * `field2` {Boolean} Another field. Default: `false`. - * Return: {Boolean} `true` if it worked. - - Description of the method for humans. - - ### someClass.nextSibling() - - * Return: {SomeClass object | null} The next someClass in line. - - ### someClass.someProperty - - * String - - The indication of what someProperty is. - - ### Event: 'grelb' - - * `isBlerg` {Boolean} - - This event is emitted on instances of SomeClass, not on the module itself. - - -* Modules have (description, Properties, Functions, Classes, Examples) -* Properties have (type, description) -* Functions have (list of arguments, description) -* Classes have (description, Properties, Methods, Events) -* Events have (list of arguments, description) -* Methods have (list of arguments, description) -* Properties have (type, description) - -# CLI usage - -Run the following from the etherpad-lite root directory: -```sh -$ node bin/doc/generate doc/index.md --format=html --template=doc/template.html > out.html -``` \ No newline at end of file diff --git a/sources/bin/doc/generate.js b/sources/bin/doc/generate.js deleted file mode 100644 index 8d52e10..0000000 --- a/sources/bin/doc/generate.js +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env node -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var marked = require('marked'); -var fs = require('fs'); -var path = require('path'); - -// parse the args. -// Don't use nopt or whatever for this. It's simple enough. - -var args = process.argv.slice(2); -var format = 'json'; -var template = null; -var inputFile = null; - -args.forEach(function (arg) { - if (!arg.match(/^\-\-/)) { - inputFile = arg; - } else if (arg.match(/^\-\-format=/)) { - format = arg.replace(/^\-\-format=/, ''); - } else if (arg.match(/^\-\-template=/)) { - template = arg.replace(/^\-\-template=/, ''); - } -}) - - -if (!inputFile) { - throw new Error('No input file specified'); -} - - -console.error('Input file = %s', inputFile); -fs.readFile(inputFile, 'utf8', function(er, input) { - if (er) throw er; - // process the input for @include lines - processIncludes(inputFile, input, next); -}); - - -var includeExpr = /^@include\s+([A-Za-z0-9-_\/]+)(?:\.)?([a-zA-Z]*)$/gmi; -var includeData = {}; -function processIncludes(inputFile, input, cb) { - var includes = input.match(includeExpr); - if (includes === null) return cb(null, input); - var errState = null; - console.error(includes); - var incCount = includes.length; - if (incCount === 0) cb(null, input); - - includes.forEach(function(include) { - var fname = include.replace(/^@include\s+/, ''); - if (!fname.match(/\.md$/)) fname += '.md'; - - if (includeData.hasOwnProperty(fname)) { - input = input.split(include).join(includeData[fname]); - incCount--; - if (incCount === 0) { - return cb(null, input); - } - } - - var fullFname = path.resolve(path.dirname(inputFile), fname); - fs.readFile(fullFname, 'utf8', function(er, inc) { - if (errState) return; - if (er) return cb(errState = er); - processIncludes(fullFname, inc, function(er, inc) { - if (errState) return; - if (er) return cb(errState = er); - incCount--; - includeData[fname] = inc; - input = input.split(include).join(includeData[fname]); - if (incCount === 0) { - return cb(null, input); - } - }); - }); - }); -} - - -function next(er, input) { - if (er) throw er; - switch (format) { - case 'json': - require('./json.js')(input, inputFile, function(er, obj) { - console.log(JSON.stringify(obj, null, 2)); - if (er) throw er; - }); - break; - - case 'html': - require('./html.js')(input, inputFile, template, function(er, html) { - if (er) throw er; - console.log(html); - }); - break; - - default: - throw new Error('Invalid format: ' + format); - } -} diff --git a/sources/bin/doc/html.js b/sources/bin/doc/html.js deleted file mode 100644 index 700ab18..0000000 --- a/sources/bin/doc/html.js +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var fs = require('fs'); -var marked = require('marked'); -var path = require('path'); - -module.exports = toHTML; - -function toHTML(input, filename, template, cb) { - var lexed = marked.lexer(input); - fs.readFile(template, 'utf8', function(er, template) { - if (er) return cb(er); - render(lexed, filename, template, cb); - }); -} - -function render(lexed, filename, template, cb) { - // get the section - var section = getSection(lexed); - - filename = path.basename(filename, '.md'); - - lexed = parseLists(lexed); - - // generate the table of contents. - // this mutates the lexed contents in-place. - buildToc(lexed, filename, function(er, toc) { - if (er) return cb(er); - - template = template.replace(/__FILENAME__/g, filename); - template = template.replace(/__SECTION__/g, section); - template = template.replace(/__TOC__/g, toc); - - // content has to be the last thing we do with - // the lexed tokens, because it's destructive. - content = marked.parser(lexed); - template = template.replace(/__CONTENT__/g, content); - - cb(null, template); - }); -} - - -// just update the list item text in-place. -// lists that come right after a heading are what we're after. -function parseLists(input) { - var state = null; - var depth = 0; - var output = []; - output.links = input.links; - input.forEach(function(tok) { - if (state === null) { - if (tok.type === 'heading') { - state = 'AFTERHEADING'; - } - output.push(tok); - return; - } - if (state === 'AFTERHEADING') { - if (tok.type === 'list_start') { - state = 'LIST'; - if (depth === 0) { - output.push({ type:'html', text: '
        ' }); - } - depth++; - output.push(tok); - return; - } - state = null; - output.push(tok); - return; - } - if (state === 'LIST') { - if (tok.type === 'list_start') { - depth++; - output.push(tok); - return; - } - if (tok.type === 'list_end') { - depth--; - if (depth === 0) { - state = null; - output.push({ type:'html', text: '
        ' }); - } - output.push(tok); - return; - } - if (tok.text) { - tok.text = parseListItem(tok.text); - } - } - output.push(tok); - }); - - return output; -} - - -function parseListItem(text) { - text = text.replace(/\{([^\}]+)\}/, '$1'); - //XXX maybe put more stuff here? - return text; -} - - -// section is just the first heading -function getSection(lexed) { - var section = ''; - for (var i = 0, l = lexed.length; i < l; i++) { - var tok = lexed[i]; - if (tok.type === 'heading') return tok.text; - } - return ''; -} - - -function buildToc(lexed, filename, cb) { - var indent = 0; - var toc = []; - var depth = 0; - lexed.forEach(function(tok) { - if (tok.type !== 'heading') return; - if (tok.depth - depth > 1) { - return cb(new Error('Inappropriate heading level\n' + - JSON.stringify(tok))); - } - - depth = tok.depth; - var id = getId(filename + '_' + tok.text.trim()); - toc.push(new Array((depth - 1) * 2 + 1).join(' ') + - '* ' + - tok.text + ''); - tok.text += '#'; - }); - - toc = marked.parse(toc.join('\n')); - cb(null, toc); -} - -var idCounters = {}; -function getId(text) { - text = text.toLowerCase(); - text = text.replace(/[^a-z0-9]+/g, '_'); - text = text.replace(/^_+|_+$/, ''); - text = text.replace(/^([^a-z])/, '_$1'); - if (idCounters.hasOwnProperty(text)) { - text += '_' + (++idCounters[text]); - } else { - idCounters[text] = 0; - } - return text; -} - diff --git a/sources/bin/doc/json.js b/sources/bin/doc/json.js deleted file mode 100644 index a404675..0000000 --- a/sources/bin/doc/json.js +++ /dev/null @@ -1,557 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -module.exports = doJSON; - -// Take the lexed input, and return a JSON-encoded object -// A module looks like this: https://gist.github.com/1777387 - -var marked = require('marked'); - -function doJSON(input, filename, cb) { - var root = {source: filename}; - var stack = [root]; - var depth = 0; - var current = root; - var state = null; - var lexed = marked.lexer(input); - lexed.forEach(function (tok) { - var type = tok.type; - var text = tok.text; - - // - // This is for cases where the markdown semantic structure is lacking. - if (type === 'paragraph' || type === 'html') { - var metaExpr = /\n*/g; - text = text.replace(metaExpr, function(_0, k, v) { - current[k.trim()] = v.trim(); - return ''; - }); - text = text.trim(); - if (!text) return; - } - - if (type === 'heading' && - !text.trim().match(/^example/i)) { - if (tok.depth - depth > 1) { - return cb(new Error('Inappropriate heading level\n'+ - JSON.stringify(tok))); - } - - // Sometimes we have two headings with a single - // blob of description. Treat as a clone. - if (current && - state === 'AFTERHEADING' && - depth === tok.depth) { - var clone = current; - current = newSection(tok); - current.clone = clone; - // don't keep it around on the stack. - stack.pop(); - } else { - // if the level is greater than the current depth, - // then it's a child, so we should just leave the stack - // as it is. - // However, if it's a sibling or higher, then it implies - // the closure of the other sections that came before. - // root is always considered the level=0 section, - // and the lowest heading is 1, so this should always - // result in having a valid parent node. - var d = tok.depth; - while (d <= depth) { - finishSection(stack.pop(), stack[stack.length - 1]); - d++; - } - current = newSection(tok); - } - - depth = tok.depth; - stack.push(current); - state = 'AFTERHEADING'; - return; - } // heading - - // Immediately after a heading, we can expect the following - // - // { type: 'code', text: 'Stability: ...' }, - // - // a list: starting with list_start, ending with list_end, - // maybe containing other nested lists in each item. - // - // If one of these isn't found, then anything that comes between - // here and the next heading should be parsed as the desc. - var stability - if (state === 'AFTERHEADING') { - if (type === 'code' && - (stability = text.match(/^Stability: ([0-5])(?:\s*-\s*)?(.*)$/))) { - current.stability = parseInt(stability[1], 10); - current.stabilityText = stability[2].trim(); - return; - } else if (type === 'list_start' && !tok.ordered) { - state = 'AFTERHEADING_LIST'; - current.list = current.list || []; - current.list.push(tok); - current.list.level = 1; - } else { - current.desc = current.desc || []; - if (!Array.isArray(current.desc)) { - current.shortDesc = current.desc; - current.desc = []; - } - current.desc.push(tok); - state = 'DESC'; - } - return; - } - - if (state === 'AFTERHEADING_LIST') { - current.list.push(tok); - if (type === 'list_start') { - current.list.level++; - } else if (type === 'list_end') { - current.list.level--; - } - if (current.list.level === 0) { - state = 'AFTERHEADING'; - processList(current); - } - return; - } - - current.desc = current.desc || []; - current.desc.push(tok); - - }); - - // finish any sections left open - while (root !== (current = stack.pop())) { - finishSection(current, stack[stack.length - 1]); - } - - return cb(null, root) -} - - -// go from something like this: -// [ { type: 'list_item_start' }, -// { type: 'text', -// text: '`settings` Object, Optional' }, -// { type: 'list_start', ordered: false }, -// { type: 'list_item_start' }, -// { type: 'text', -// text: 'exec: String, file path to worker file. Default: `__filename`' }, -// { type: 'list_item_end' }, -// { type: 'list_item_start' }, -// { type: 'text', -// text: 'args: Array, string arguments passed to worker.' }, -// { type: 'text', -// text: 'Default: `process.argv.slice(2)`' }, -// { type: 'list_item_end' }, -// { type: 'list_item_start' }, -// { type: 'text', -// text: 'silent: Boolean, whether or not to send output to parent\'s stdio.' }, -// { type: 'text', text: 'Default: `false`' }, -// { type: 'space' }, -// { type: 'list_item_end' }, -// { type: 'list_end' }, -// { type: 'list_item_end' }, -// { type: 'list_end' } ] -// to something like: -// [ { name: 'settings', -// type: 'object', -// optional: true, -// settings: -// [ { name: 'exec', -// type: 'string', -// desc: 'file path to worker file', -// default: '__filename' }, -// { name: 'args', -// type: 'array', -// default: 'process.argv.slice(2)', -// desc: 'string arguments passed to worker.' }, -// { name: 'silent', -// type: 'boolean', -// desc: 'whether or not to send output to parent\'s stdio.', -// default: 'false' } ] } ] - -function processList(section) { - var list = section.list; - var values = []; - var current; - var stack = []; - - // for now, *just* build the hierarchical list - list.forEach(function(tok) { - var type = tok.type; - if (type === 'space') return; - if (type === 'list_item_start') { - if (!current) { - var n = {}; - values.push(n); - current = n; - } else { - current.options = current.options || []; - stack.push(current); - var n = {}; - current.options.push(n); - current = n; - } - return; - } else if (type === 'list_item_end') { - if (!current) { - throw new Error('invalid list - end without current item\n' + - JSON.stringify(tok) + '\n' + - JSON.stringify(list)); - } - current = stack.pop(); - } else if (type === 'text') { - if (!current) { - throw new Error('invalid list - text without current item\n' + - JSON.stringify(tok) + '\n' + - JSON.stringify(list)); - } - current.textRaw = current.textRaw || ''; - current.textRaw += tok.text + ' '; - } - }); - - // shove the name in there for properties, since they are always - // just going to be the value etc. - if (section.type === 'property' && values[0]) { - values[0].textRaw = '`' + section.name + '` ' + values[0].textRaw; - } - - // now pull the actual values out of the text bits. - values.forEach(parseListItem); - - // Now figure out what this list actually means. - // depending on the section type, the list could be different things. - - switch (section.type) { - case 'ctor': - case 'classMethod': - case 'method': - // each item is an argument, unless the name is 'return', - // in which case it's the return value. - section.signatures = section.signatures || []; - var sig = {} - section.signatures.push(sig); - sig.params = values.filter(function(v) { - if (v.name === 'return') { - sig.return = v; - return false; - } - return true; - }); - parseSignature(section.textRaw, sig); - break; - - case 'property': - // there should be only one item, which is the value. - // copy the data up to the section. - var value = values[0] || {}; - delete value.name; - section.typeof = value.type; - delete value.type; - Object.keys(value).forEach(function(k) { - section[k] = value[k]; - }); - break; - - case 'event': - // event: each item is an argument. - section.params = values; - break; - } - - // section.listParsed = values; - delete section.list; -} - - -// textRaw = "someobject.someMethod(a, [b=100], [c])" -function parseSignature(text, sig) { - var params = text.match(paramExpr); - if (!params) return; - params = params[1]; - // the ] is irrelevant. [ indicates optionalness. - params = params.replace(/\]/g, ''); - params = params.split(/,/) - params.forEach(function(p, i, _) { - p = p.trim(); - if (!p) return; - var param = sig.params[i]; - var optional = false; - var def; - // [foo] -> optional - if (p.charAt(0) === '[') { - optional = true; - p = p.substr(1); - } - var eq = p.indexOf('='); - if (eq !== -1) { - def = p.substr(eq + 1); - p = p.substr(0, eq); - } - if (!param) { - param = sig.params[i] = { name: p }; - } - // at this point, the name should match. - if (p !== param.name) { - console.error('Warning: invalid param "%s"', p); - console.error(' > ' + JSON.stringify(param)); - console.error(' > ' + text); - } - if (optional) param.optional = true; - if (def !== undefined) param.default = def; - }); -} - - -function parseListItem(item) { - if (item.options) item.options.forEach(parseListItem); - if (!item.textRaw) return; - - // the goal here is to find the name, type, default, and optional. - // anything left over is 'desc' - var text = item.textRaw.trim(); - // text = text.replace(/^(Argument|Param)s?\s*:?\s*/i, ''); - - text = text.replace(/^, /, '').trim(); - var retExpr = /^returns?\s*:?\s*/i; - var ret = text.match(retExpr); - if (ret) { - item.name = 'return'; - text = text.replace(retExpr, ''); - } else { - var nameExpr = /^['`"]?([^'`": \{]+)['`"]?\s*:?\s*/; - var name = text.match(nameExpr); - if (name) { - item.name = name[1]; - text = text.replace(nameExpr, ''); - } - } - - text = text.trim(); - var defaultExpr = /\(default\s*[:=]?\s*['"`]?([^, '"`]*)['"`]?\)/i; - var def = text.match(defaultExpr); - if (def) { - item.default = def[1]; - text = text.replace(defaultExpr, ''); - } - - text = text.trim(); - var typeExpr = /^\{([^\}]+)\}/; - var type = text.match(typeExpr); - if (type) { - item.type = type[1]; - text = text.replace(typeExpr, ''); - } - - text = text.trim(); - var optExpr = /^Optional\.|(?:, )?Optional$/; - var optional = text.match(optExpr); - if (optional) { - item.optional = true; - text = text.replace(optExpr, ''); - } - - text = text.replace(/^\s*-\s*/, ''); - text = text.trim(); - if (text) item.desc = text; -} - - -function finishSection(section, parent) { - if (!section || !parent) { - throw new Error('Invalid finishSection call\n'+ - JSON.stringify(section) + '\n' + - JSON.stringify(parent)); - } - - if (!section.type) { - section.type = 'module'; - if (parent && (parent.type === 'misc')) { - section.type = 'misc'; - } - section.displayName = section.name; - section.name = section.name.toLowerCase() - .trim().replace(/\s+/g, '_'); - } - - if (section.desc && Array.isArray(section.desc)) { - section.desc.links = section.desc.links || []; - section.desc = marked.parser(section.desc); - } - - if (!section.list) section.list = []; - processList(section); - - // classes sometimes have various 'ctor' children - // which are actually just descriptions of a constructor - // class signature. - // Merge them into the parent. - if (section.type === 'class' && section.ctors) { - section.signatures = section.signatures || []; - var sigs = section.signatures; - section.ctors.forEach(function(ctor) { - ctor.signatures = ctor.signatures || [{}]; - ctor.signatures.forEach(function(sig) { - sig.desc = ctor.desc; - }); - sigs.push.apply(sigs, ctor.signatures); - }); - delete section.ctors; - } - - // properties are a bit special. - // their "type" is the type of object, not "property" - if (section.properties) { - section.properties.forEach(function (p) { - if (p.typeof) p.type = p.typeof; - else delete p.type; - delete p.typeof; - }); - } - - // handle clones - if (section.clone) { - var clone = section.clone; - delete section.clone; - delete clone.clone; - deepCopy(section, clone); - finishSection(clone, parent); - } - - var plur; - if (section.type.slice(-1) === 's') { - plur = section.type + 'es'; - } else if (section.type.slice(-1) === 'y') { - plur = section.type.replace(/y$/, 'ies'); - } else { - plur = section.type + 's'; - } - - // if the parent's type is 'misc', then it's just a random - // collection of stuff, like the "globals" section. - // Make the children top-level items. - if (section.type === 'misc') { - Object.keys(section).forEach(function(k) { - switch (k) { - case 'textRaw': - case 'name': - case 'type': - case 'desc': - case 'miscs': - return; - default: - if (parent.type === 'misc') { - return; - } - if (Array.isArray(k) && parent[k]) { - parent[k] = parent[k].concat(section[k]); - } else if (!parent[k]) { - parent[k] = section[k]; - } else { - // parent already has, and it's not an array. - return; - } - } - }); - } - - parent[plur] = parent[plur] || []; - parent[plur].push(section); -} - - -// Not a general purpose deep copy. -// But sufficient for these basic things. -function deepCopy(src, dest) { - Object.keys(src).filter(function(k) { - return !dest.hasOwnProperty(k); - }).forEach(function(k) { - dest[k] = deepCopy_(src[k]); - }); -} - -function deepCopy_(src) { - if (!src) return src; - if (Array.isArray(src)) { - var c = new Array(src.length); - src.forEach(function(v, i) { - c[i] = deepCopy_(v); - }); - return c; - } - if (typeof src === 'object') { - var c = {}; - Object.keys(src).forEach(function(k) { - c[k] = deepCopy_(src[k]); - }); - return c; - } - return src; -} - - -// these parse out the contents of an H# tag -var eventExpr = /^Event(?::|\s)+['"]?([^"']+).*$/i; -var classExpr = /^Class:\s*([^ ]+).*?$/i; -var propExpr = /^(?:property:?\s*)?[^\.]+\.([^ \.\(\)]+)\s*?$/i; -var braceExpr = /^(?:property:?\s*)?[^\.\[]+(\[[^\]]+\])\s*?$/i; -var classMethExpr = - /^class\s*method\s*:?[^\.]+\.([^ \.\(\)]+)\([^\)]*\)\s*?$/i; -var methExpr = - /^(?:method:?\s*)?(?:[^\.]+\.)?([^ \.\(\)]+)\([^\)]*\)\s*?$/i; -var newExpr = /^new ([A-Z][a-z]+)\([^\)]*\)\s*?$/; -var paramExpr = /\((.*)\);?$/; - -function newSection(tok) { - var section = {}; - // infer the type from the text. - var text = section.textRaw = tok.text; - if (text.match(eventExpr)) { - section.type = 'event'; - section.name = text.replace(eventExpr, '$1'); - } else if (text.match(classExpr)) { - section.type = 'class'; - section.name = text.replace(classExpr, '$1'); - } else if (text.match(braceExpr)) { - section.type = 'property'; - section.name = text.replace(braceExpr, '$1'); - } else if (text.match(propExpr)) { - section.type = 'property'; - section.name = text.replace(propExpr, '$1'); - } else if (text.match(classMethExpr)) { - section.type = 'classMethod'; - section.name = text.replace(classMethExpr, '$1'); - } else if (text.match(methExpr)) { - section.type = 'method'; - section.name = text.replace(methExpr, '$1'); - } else if (text.match(newExpr)) { - section.type = 'ctor'; - section.name = text.replace(newExpr, '$1'); - } else { - section.name = text; - } - return section; -} diff --git a/sources/bin/doc/package.json b/sources/bin/doc/package.json deleted file mode 100644 index 5aba79e..0000000 --- a/sources/bin/doc/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "author": "Isaac Z. Schlueter (http://blog.izs.me/)", - "name": "node-doc-generator", - "description": "Internal tool for generating Node.js API docs", - "version": "0.0.0", - "engines": { - "node": ">=0.6.10" - }, - "dependencies": { - "marked": ">=0.3.6" - }, - "devDependencies": {}, - "optionalDependencies": {}, - "bin": "./generate.js" -} diff --git a/sources/bin/extractPadData.js b/sources/bin/extractPadData.js deleted file mode 100644 index 4190824..0000000 --- a/sources/bin/extractPadData.js +++ /dev/null @@ -1,109 +0,0 @@ -/* - This is a debug tool. It helps to extract all datas of a pad and move it from an productive environment and to a develop environment to reproduce bugs there. It outputs a dirtydb file -*/ - -if(process.argv.length != 3) -{ - console.error("Use: node extractPadData.js $PADID"); - process.exit(1); -} -//get the padID -var padId = process.argv[2]; - -var db, dirty, padManager, pad, settings; -var neededDBValues = ["pad:"+padId]; - -var npm = require("../node_modules/ep_etherpad-lite/node_modules/npm"); -var async = require("../node_modules/ep_etherpad-lite/node_modules/async"); - -async.series([ - // load npm - function(callback) { - npm.load({}, function(er) { - if(er) - { - console.error("Could not load NPM: " + er) - process.exit(1); - } - else - { - callback(); - } - }) - }, - // load modules - function(callback) { - settings = require('../node_modules/ep_etherpad-lite/node/utils/Settings'); - db = require('../node_modules/ep_etherpad-lite/node/db/DB'); - dirty = require("../node_modules/ep_etherpad-lite/node_modules/ueberDB/node_modules/dirty")(padId + ".db"); - callback(); - }, - //initialize the database - function (callback) - { - db.init(callback); - }, - //get the pad - function (callback) - { - padManager = require('../node_modules/ep_etherpad-lite/node/db/PadManager'); - - padManager.getPad(padId, function(err, _pad) - { - pad = _pad; - callback(err); - }); - }, - function (callback) - { - //add all authors - var authors = pad.getAllAuthors(); - for(var i=0;i /dev/null 2>&1 || { - echo "Please install ggrep (pkg install gnu-grep)" >&2 - exit 1 - } -fi - -#Is curl installed? -hash curl > /dev/null 2>&1 || { - echo "Please install curl" >&2 - exit 1 -} - -#Is node installed? -#Not checking io.js, default installation creates a symbolic link to node -hash node > /dev/null 2>&1 || { - echo "Please install node.js ( https://nodejs.org )" >&2 - exit 1 -} - -#Is npm installed? -hash npm > /dev/null 2>&1 || { - echo "Please install npm ( https://npmjs.org )" >&2 - exit 1 -} - -#Check npm version -NPM_VERSION=$(npm --version) -NPM_MAIN_VERSION=$(echo $NPM_VERSION | cut -d "." -f 1) -if [ $(echo $NPM_MAIN_VERSION) = "0" ]; then - echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.x or higher" >&2 - exit 1 -fi - -#Check node version -NODE_VERSION=$(node --version) -NODE_V_MINOR=$(echo $NODE_VERSION | cut -d "." -f 1-2) -NODE_V_MAIN=$(echo $NODE_VERSION | cut -d "." -f 1) -NODE_V_MAIN=${NODE_V_MAIN#"v"} -if [ ! $NODE_V_MINOR = "v0.10" ] && [ ! $NODE_V_MINOR = "v0.11" ] && [ ! $NODE_V_MINOR = "v0.12" ] && [ ! $NODE_V_MAIN -ge 4 ]; then - echo "You're running a wrong version of node. You're using $NODE_VERSION, we need node v0.10.x or higher" >&2 - exit 1 -fi - -#Get the name of the settings file -settings="settings.json" -a=''; -for arg in $*; do - if [ "$a" = "--settings" ] || [ "$a" = "-s" ]; then settings=$arg; fi - a=$arg -done - -#Does a $settings exist? if not copy the template -if [ ! -f $settings ]; then - echo "Copy the settings template to $settings..." - cp settings.json.template $settings || exit 1 -fi - -echo "Ensure that all dependencies are up to date... If this is the first time you have run Etherpad please be patient." -( - mkdir -p node_modules - cd node_modules - [ -e ep_etherpad-lite ] || ln -s ../src ep_etherpad-lite - cd ep_etherpad-lite - npm install --loglevel warn -) || { - rm -rf node_modules - exit 1 -} - -echo "Ensure jQuery is downloaded and up to date..." -DOWNLOAD_JQUERY="true" -NEEDED_VERSION="1.9.1" -if [ -f "src/static/js/jquery.js" ]; then - if [ $(uname) = "SunOS" ]; then - VERSION=$(head -n 3 src/static/js/jquery.js | ggrep -o "v[0-9]\.[0-9]\(\.[0-9]\)\?") - else - VERSION=$(head -n 3 src/static/js/jquery.js | grep -o "v[0-9]\.[0-9]\(\.[0-9]\)\?") - fi - - if [ ${VERSION#v} = $NEEDED_VERSION ]; then - DOWNLOAD_JQUERY="false" - fi -fi - -if [ $DOWNLOAD_JQUERY = "true" ]; then - curl -lo src/static/js/jquery.js https://code.jquery.com/jquery-$NEEDED_VERSION.js || exit 1 -fi - -#Remove all minified data to force node creating it new -echo "Clearing minified cache..." -rm -f var/minified* - -echo "Ensure custom css/js files are created..." - -for f in "index" "pad" "timeslider" -do - if [ ! -f "src/static/custom/$f.js" ]; then - cp "src/static/custom/js.template" "src/static/custom/$f.js" || exit 1 - fi - - if [ ! -f "src/static/custom/$f.css" ]; then - cp "src/static/custom/css.template" "src/static/custom/$f.css" || exit 1 - fi -done - -exit 0 diff --git a/sources/bin/installOnWindows.bat b/sources/bin/installOnWindows.bat deleted file mode 100644 index 5ba0573..0000000 --- a/sources/bin/installOnWindows.bat +++ /dev/null @@ -1,42 +0,0 @@ -@echo off - -:: Change directory to etherpad-lite root -cd /D "%~dp0\.." - -:: Is node installed? -cmd /C node -e "" || ( echo "Please install node.js ( https://nodejs.org )" && exit /B 1 ) - -echo _ -echo Ensure that all dependencies are up to date... If this is the first time you have run Etherpad please be patient. - -mkdir node_modules -cd /D node_modules -mklink /D "ep_etherpad-lite" "..\src" - -cd /D "ep_etherpad-lite" -cmd /C npm install --loglevel warn || exit /B 1 - -cd /D "%~dp0\.." - -echo _ -echo Copying custom templates... -set custom_dir=node_modules\ep_etherpad-lite\static\custom -FOR %%f IN (index pad timeslider) DO ( - if NOT EXIST "%custom_dir%\%%f.js" copy "%custom_dir%\js.template" "%custom_dir%\%%f.js" - if NOT EXIST "%custom_dir%\%%f.css" copy "%custom_dir%\css.template" "%custom_dir%\%%f.css" -) - -echo _ -echo Clearing cache... -del /S var\minified* - -echo _ -echo Setting up settings.json... -IF NOT EXIST settings.json ( - echo Can't find settings.json. - echo Copying settings.json.template... - cmd /C copy settings.json.template settings.json || exit /B 1 -) - -echo _ -echo Installed Etherpad! To run Etherpad type start.bat \ No newline at end of file diff --git a/sources/bin/migrateDirtyDBtoRealDB.js b/sources/bin/migrateDirtyDBtoRealDB.js deleted file mode 100644 index c616714..0000000 --- a/sources/bin/migrateDirtyDBtoRealDB.js +++ /dev/null @@ -1,38 +0,0 @@ -require("ep_etherpad-lite/node_modules/npm").load({}, function(er,npm) { - - process.chdir(npm.root+'/..') - - // This script requires that you have modified your settings.json file - // to work with a real database. Please make a backup of your dirty.db - // file before using this script, just to be safe. - - var settings = require("ep_etherpad-lite/node/utils/Settings"); - var dirty = require("../src/node_modules/dirty")('var/dirty.db'); - var ueberDB = require("../src/node_modules/ueberdb2"); - var log4js = require("../src/node_modules/log4js"); - var dbWrapperSettings = { - "cache": "0", // The cache slows things down when you're mostly writing. - }; - var db = new ueberDB.database(settings.dbType, settings.dbSettings, dbWrapperSettings, log4js.getLogger("ueberDB")); - - db.init(function() { - console.log("Waiting for dirtyDB to parse its file."); - dirty.on("load", function(length) { - console.log("Loaded " + length + " records, processing now."); - var remaining = length; - dirty.forEach(function(key, value) { - db.set(key, value, function(error) { - if (typeof error != 'undefined') { - console.log("Unexpected result handling: ", key, value, " was: ", error); - } - remaining -= 1; - var oldremaining = remaining; - if ((oldremaining % 100) == 0) { - console.log("Records not yet flushed to database: ", remaining); - } - }); - }); - console.log("Please wait for all records to flush to database, then kill this process."); - }); - }); -}); diff --git a/sources/bin/rebuildPad.js b/sources/bin/rebuildPad.js deleted file mode 100644 index 60c5f4e..0000000 --- a/sources/bin/rebuildPad.js +++ /dev/null @@ -1,123 +0,0 @@ -/* - This is a repair tool. It rebuilds an old pad at a new pad location up to a - known "good" revision. -*/ - -if(process.argv.length != 4 && process.argv.length != 5) { - console.error("Use: node bin/repairPad.js $PADID $REV [$NEWPADID]"); - process.exit(1); -} - -var npm = require("../src/node_modules/npm"); -var async = require("../src/node_modules/async"); -var ueberDB = require("../src/node_modules/ueberDB"); - -var padId = process.argv[2]; -var newRevHead = process.argv[3]; -var newPadId = process.argv[4] || padId + "-rebuilt"; - -var db, oldPad, newPad, settings; -var AuthorManager, ChangeSet, Pad, PadManager; - -async.series([ - function(callback) { - npm.load({}, function(err) { - if(err) { - console.error("Could not load NPM: " + err) - process.exit(1); - } else { - callback(); - } - }) - }, - function(callback) { - // Get a handle into the database - db = require('../src/node/db/DB'); - db.init(callback); - }, function(callback) { - PadManager = require('../src/node/db/PadManager'); - Pad = require('../src/node/db/Pad').Pad; - // Get references to the original pad and to a newly created pad - // HACK: This is a standalone script, so we want to write everything - // out to the database immediately. The only problem with this is - // that a driver (like the mysql driver) can hardcode these values. - db.db.db.settings = {cache: 0, writeInterval: 0, json: true}; - // Validate the newPadId if specified and that a pad with that ID does - // not already exist to avoid overwriting it. - if (!PadManager.isValidPadId(newPadId)) { - console.error("Cannot create a pad with that id as it is invalid"); - process.exit(1); - } - PadManager.doesPadExists(newPadId, function(err, exists) { - if (exists) { - console.error("Cannot create a pad with that id as it already exists"); - process.exit(1); - } - }); - PadManager.getPad(padId, function(err, pad) { - oldPad = pad; - newPad = new Pad(newPadId); - callback(); - }); - }, function(callback) { - // Clone all Chat revisions - var chatHead = oldPad.chatHead; - for(var i = 0, curHeadNum = 0; i <= chatHead; i++) { - db.db.get("pad:" + padId + ":chat:" + i, function (err, chat) { - db.db.set("pad:" + newPadId + ":chat:" + curHeadNum++, chat); - console.log("Created: Chat Revision: pad:" + newPadId + ":chat:" + curHeadNum); - }); - } - callback(); - }, function(callback) { - // Rebuild Pad from revisions up to and including the new revision head - AuthorManager = require("../src/node/db/AuthorManager"); - Changeset = require("ep_etherpad-lite/static/js/Changeset"); - // Author attributes are derived from changesets, but there can also be - // non-author attributes with specific mappings that changesets depend on - // and, AFAICT, cannot be recreated any other way - newPad.pool.numToAttrib = oldPad.pool.numToAttrib; - for(var curRevNum = 0; curRevNum <= newRevHead; curRevNum++) { - db.db.get("pad:" + padId + ":revs:" + curRevNum, function(err, rev) { - if (rev.meta) { - throw "The specified revision number could not be found."; - } - var newRevNum = ++newPad.head; - var newRevId = "pad:" + newPad.id + ":revs:" + newRevNum; - db.db.set(newRevId, rev); - AuthorManager.addPad(rev.meta.author, newPad.id); - newPad.atext = Changeset.applyToAText(rev.changeset, newPad.atext, newPad.pool); - console.log("Created: Revision: pad:" + newPad.id + ":revs:" + newRevNum); - if (newRevNum == newRevHead) { - callback(); - } - }); - } - }, function(callback) { - // Add saved revisions up to the new revision head - console.log(newPad.head); - var newSavedRevisions = []; - for(var i in oldPad.savedRevisions) { - savedRev = oldPad.savedRevisions[i] - if (savedRev.revNum <= newRevHead) { - newSavedRevisions.push(savedRev); - console.log("Added: Saved Revision: " + savedRev.revNum); - } - } - newPad.savedRevisions = newSavedRevisions; - callback(); - }, function(callback) { - // Save the source pad - db.db.set("pad:"+newPadId, newPad, function(err) { - console.log("Created: Source Pad: pad:" + newPadId); - newPad.saveToDatabase(); - callback(); - }); - } -], function (err) { - if(err) throw err; - else { - console.info("finished"); - process.exit(0); - } -}); diff --git a/sources/bin/repairPad.js b/sources/bin/repairPad.js deleted file mode 100644 index 28f28cb..0000000 --- a/sources/bin/repairPad.js +++ /dev/null @@ -1,106 +0,0 @@ -/* - This is a repair tool. It extracts all datas of a pad, removes and inserts them again. -*/ - -console.warn("WARNING: This script must not be used while etherpad is running!"); - -if(process.argv.length != 3) -{ - console.error("Use: node bin/repairPad.js $PADID"); - process.exit(1); -} -//get the padID -var padId = process.argv[2]; - -var db, padManager, pad, settings; -var neededDBValues = ["pad:"+padId]; - -var npm = require("../src/node_modules/npm"); -var async = require("../src/node_modules/async"); - -async.series([ - // load npm - function(callback) { - npm.load({}, function(er) { - if(er) - { - console.error("Could not load NPM: " + er) - process.exit(1); - } - else - { - callback(); - } - }) - }, - // load modules - function(callback) { - settings = require('../src/node/utils/Settings'); - db = require('../src/node/db/DB'); - callback(); - }, - //initialize the database - function (callback) - { - db.init(callback); - }, - //get the pad - function (callback) - { - padManager = require('../src/node/db/PadManager'); - - padManager.getPad(padId, function(err, _pad) - { - pad = _pad; - callback(err); - }); - }, - function (callback) - { - //add all authors - var authors = pad.getAllAuthors(); - for(var i=0;i>${LOG} 2>>${LOG} - - #Send email - if [ $ERROR_HANDLING = 1 ]; then - TIME_NOW=$(date +%s) - TIME_SINCE_LAST_SEND=$(($TIME_NOW - $LAST_EMAIL_SEND)) - - if [ $TIME_SINCE_LAST_SEND -gt $TIME_BETWEEN_EMAILS ]; then - printf "Server was restarted at: $(date)\nThe last 50 lines of the log before the error happens:\n $(tail -n 50 ${LOG})" | mail -s "Pad Server was restarted" $EMAIL_ADDRESS - - LAST_EMAIL_SEND=$TIME_NOW - fi - fi - - echo "RESTART!" >>${LOG} - - #Sleep 10 seconds before restart - sleep 10 -done diff --git a/sources/bin/updatePlugins.sh b/sources/bin/updatePlugins.sh deleted file mode 100755 index 63c447e..0000000 --- a/sources/bin/updatePlugins.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -#Move to the folder where ep-lite is installed -cd `dirname $0` - -#Was this script started in the bin folder? if yes move out -if [ -d "../bin" ]; then - cd "../" -fi - -# npm outdated --depth=0 | grep -v "^Package" | awk '{print $1}' | xargs npm install $1 --save-dev -OUTDATED=`npm outdated --depth=0 | grep -v "^Package" | awk '{print $1}'` -# echo $OUTDATED -if test -n "$OUTDATED"; then - echo "Plugins require update, doing this now..." - echo "Updating $OUTDATED" - npm install $OUTDATED --save-dev -else - echo "Plugins are all up to date" -fi diff --git a/sources/doc/api/api.md b/sources/doc/api/api.md deleted file mode 100644 index d124e4c..0000000 --- a/sources/doc/api/api.md +++ /dev/null @@ -1,10 +0,0 @@ -@include embed_parameters -@include http_api -@include hooks_overview -@include hooks_client-side -@include hooks_server-side -@include editorInfo -@include changeset_library -@include pluginfw -@include toolbar -@include editbar \ No newline at end of file diff --git a/sources/doc/api/changeset_library.md b/sources/doc/api/changeset_library.md deleted file mode 100644 index 3bb4f05..0000000 --- a/sources/doc/api/changeset_library.md +++ /dev/null @@ -1,151 +0,0 @@ -# Changeset Library - -``` -"Z:z>1|2=m=b*0|1+1$\n" -``` - -This is a Changeset. It's just a string and it's very difficult to read in this form. But the Changeset Library gives us some tools to read it. - -A changeset describes the diff between two revisions of the document. The Browser sends changesets to the server and the server sends them to the clients to update them. These Changesets also get saved into the history of a pad. This allows us to go back to every revision from the past. - -## Changeset.unpack(changeset) - - * `changeset` {String} - -This function returns an object representation of the changeset, similar to this: - -``` -{ oldLen: 35, newLen: 36, ops: '|2=m=b*0|1+1', charBank: '\n' } -``` - - * `oldLen` {Number} the original length of the document. - * `newLen` {Number} the length of the document after the changeset is applied. - * `ops` {String} the actual changes, introduced by this changeset. - * `charBank` {String} All characters that are added by this changeset. - -## Changeset.opIterator(ops) - - * `ops` {String} The operators, returned by `Changeset.unpack()` - -Returns an operator iterator. This iterator allows us to iterate over all operators that are in the changeset. - -You can iterate with an opIterator using its `next()` and `hasNext()` methods. Next returns the `next()` operator object and `hasNext()` indicates, whether there are any operators left. - -## The Operator object -There are 3 types of operators: `+`,`-` and `=`. These operators describe different changes to the document, beginning with the first character of the document. A `=` operator doesn't change the text, but it may add or remove text attributes. A `-` operator removes text. And a `+` Operator adds text and optionally adds some attributes to it. - - * `opcode` {String} the operator type - * `chars` {Number} the length of the text changed by this operator. - * `lines` {Number} the number of lines changed by this operator. - * `attribs` {attribs} attributes set on this text. - -### Example -``` -{ opcode: '+', - chars: 1, - lines: 1, - attribs: '*0' } -``` - -## APool - -``` -> var AttributePoolFactory = require("./utils/AttributePoolFactory"); -> var apool = AttributePoolFactory.createAttributePool(); -> console.log(apool) -{ numToAttrib: {}, - attribToNum: {}, - nextNum: 0, - putAttrib: [Function], - getAttrib: [Function], - getAttribKey: [Function], - getAttribValue: [Function], - eachAttrib: [Function], - toJsonable: [Function], - fromJsonable: [Function] } -``` - -This creates an empty apool. An apool saves which attributes were used during the history of a pad. There is one apool for each pad. It only saves the attributes that were really used, it doesn't save unused attributes. Let's fill this apool with some values - -``` -> apool.fromJsonable({"numToAttrib":{"0":["author","a.kVnWeomPADAT2pn9"],"1":["bold","true"],"2":["italic","true"]},"nextNum":3}); -> console.log(apool) -{ numToAttrib: - { '0': [ 'author', 'a.kVnWeomPADAT2pn9' ], - '1': [ 'bold', 'true' ], - '2': [ 'italic', 'true' ] }, - attribToNum: - { 'author,a.kVnWeomPADAT2pn9': 0, - 'bold,true': 1, - 'italic,true': 2 }, - nextNum: 3, - putAttrib: [Function], - getAttrib: [Function], - getAttribKey: [Function], - getAttribValue: [Function], - eachAttrib: [Function], - toJsonable: [Function], - fromJsonable: [Function] } -``` - -We used the fromJsonable function to fill the empty apool with values. the fromJsonable and toJsonable functions are used to serialize and deserialize an apool. You can see that it stores the relation between numbers and attributes. So for example the attribute 1 is the attribute bold and vise versa. An attribute is always a key value pair. For stuff like bold and italic it's just 'italic':'true'. For authors it's author:$AUTHORID. So a character can be bold and italic. But it can't belong to multiple authors - -``` -> apool.getAttrib(1) -[ 'bold', 'true' ] -``` - -Simple example of how to get the key value pair for the attribute 1 - -## AText - -``` -> var atext = {"text":"bold text\nitalic text\nnormal text\n\n","attribs":"*0*1+9*0|1+1*0*1*2+b|1+1*0+b|2+2"}; -> console.log(atext) -{ text: 'bold text\nitalic text\nnormal text\n\n', - attribs: '*0*1+9*0|1+1*0*1*2+b|1+1*0+b|2+2' } -``` - -This is an atext. An atext has two parts: text and attribs. The text is just the text of the pad as a string. We will look closer at the attribs at the next steps - -``` -> var opiterator = Changeset.opIterator(atext.attribs) -> console.log(opiterator) -{ next: [Function: next], - hasNext: [Function: hasNext], - lastIndex: [Function: lastIndex] } -> opiterator.next() -{ opcode: '+', - chars: 9, - lines: 0, - attribs: '*0*1' } -> opiterator.next() -{ opcode: '+', - chars: 1, - lines: 1, - attribs: '*0' } -> opiterator.next() -{ opcode: '+', - chars: 11, - lines: 0, - attribs: '*0*1*2' } -> opiterator.next() -{ opcode: '+', - chars: 1, - lines: 1, - attribs: '' } -> opiterator.next() -{ opcode: '+', - chars: 11, - lines: 0, - attribs: '*0' } -> opiterator.next() -{ opcode: '+', - chars: 2, - lines: 2, - attribs: '' } -``` - -The attribs are again a bunch of operators like .ops in the changeset was. But these operators are only + operators. They describe which part of the text has which attributes - -For more information see /doc/easysync/easysync-notes.txt in the source. diff --git a/sources/doc/api/editbar.md b/sources/doc/api/editbar.md deleted file mode 100644 index d297eb2..0000000 --- a/sources/doc/api/editbar.md +++ /dev/null @@ -1,28 +0,0 @@ -# Editbar -src/static/js/pad_editbar.js - -## isEnabled() - -## disable() - -## toggleDropDown(dropdown, callback) -Shows the dropdown `div.popup` whose `id` equals `dropdown`. - -## registerCommand(cmd, callback) -Register a handler for a specific command. Commands are fired if the corresponding button is clicked or the corresponding select is changed. - -## registerAceCommand(cmd, callback) -Creates an ace callstack and calls the callback with an ace instance (and a toolbar item, if applicable): `callback(cmd, ace, item)`. - -Example: -``` -toolbar.registerAceCommand("insertorderedlist", function (cmd, ace) { - ace.ace_doInsertOrderedList(); -}); -``` - -## registerDropdownCommand(cmd, dropdown) -Ties a `div.popup` where `id` equals `dropdown` to a `command` fired by clicking a button. - -## triggerCommand(cmd[, item]) -Triggers a command (optionally with some internal representation of the toolbar item that triggered it). diff --git a/sources/doc/api/editorInfo.md b/sources/doc/api/editorInfo.md deleted file mode 100644 index 7cbe3fc..0000000 --- a/sources/doc/api/editorInfo.md +++ /dev/null @@ -1,83 +0,0 @@ -# editorInfo - -## editorInfo.ace_replaceRange(start, end, text) -This function replaces a range (from `start` to `end`) with `text`. - -## editorInfo.ace_getRep() -Returns the `rep` object. - -## editorInfo.ace_getAuthor() -## editorInfo.ace_inCallStack() -## editorInfo.ace_inCallStackIfNecessary(?) -## editorInfo.ace_focus(?) -## editorInfo.ace_importText(?) -## editorInfo.ace_importAText(?) -## editorInfo.ace_exportText(?) -## editorInfo.ace_editorChangedSize(?) -## editorInfo.ace_setOnKeyPress(?) -## editorInfo.ace_setOnKeyDown(?) -## editorInfo.ace_setNotifyDirty(?) -## editorInfo.ace_dispose(?) -## editorInfo.ace_getFormattedCode(?) -## editorInfo.ace_setEditable(bool) -## editorInfo.ace_execCommand(?) -## editorInfo.ace_callWithAce(fn, callStack, normalize) -## editorInfo.ace_setProperty(key, value) -## editorInfo.ace_setBaseText(txt) -## editorInfo.ace_setBaseAttributedText(atxt, apoolJsonObj) -## editorInfo.ace_applyChangesToBase(c, optAuthor, apoolJsonObj) -## editorInfo.ace_prepareUserChangeset() -## editorInfo.ace_applyPreparedChangesetToBase() -## editorInfo.ace_setUserChangeNotificationCallback(f) -## editorInfo.ace_setAuthorInfo(author, info) -## editorInfo.ace_setAuthorSelectionRange(author, start, end) -## editorInfo.ace_getUnhandledErrors() -## editorInfo.ace_getDebugProperty(prop) -## editorInfo.ace_fastIncorp(?) -## editorInfo.ace_isCaret(?) -## editorInfo.ace_getLineAndCharForPoint(?) -## editorInfo.ace_performDocumentApplyAttributesToCharRange(?) -## editorInfo.ace_setAttributeOnSelection(attribute, enabled) -Sets an attribute on current range. -Example: `call.editorInfo.ace_setAttributeOnSelection("turkey::balls", true); // turkey is the attribute here, balls is the value -Notes: to remove the attribute pass enabled as false -## editorInfo.ace_toggleAttributeOnSelection(?) -## editorInfo.ace_getAttributeOnSelection(attribute, prevChar) -Returns a boolean if an attribute exists on a selected range. -prevChar value should be true if you want to get the previous Character attribute instead of the current selection for example -if the caret is at position 0,1 (after first character) it's probable you want the attributes on the character at 0,0 -The attribute should be the string name of the attribute applied to the selection IE subscript -Example usage: Apply the activeButton Class to a button if an attribute is on a highlighted/selected caret position or range. -Example `var isItThere = documentAttributeManager.getAttributeOnSelection("turkey::balls", true);` - -See the ep_subscript plugin for an example of this function in action. -Notes: Does not work on first or last character of a line. Suffers from a race condition if called with aceEditEvent. -## editorInfo.ace_performSelectionChange(?) -## editorInfo.ace_doIndentOutdent(?) -## editorInfo.ace_doUndoRedo(?) -## editorInfo.ace_doInsertUnorderedList(?) -## editorInfo.ace_doInsertOrderedList(?) -## editorInfo.ace_performDocumentApplyAttributesToRange() - -## editorInfo.ace_getAuthorInfos() -Returns an info object about the author. Object key = author_id and info includes author's bg color value. -Use to define your own authorship. -## editorInfo.ace_performDocumentReplaceRange(start, end, newText) -This function replaces a range (from [x1,y1] to [x2,y2]) with `newText`. -## editorInfo.ace_performDocumentReplaceCharRange(startChar, endChar, newText) -This function replaces a range (from y1 to y2) with `newText`. -## editorInfo.ace_renumberList(lineNum) -If you delete a line, calling this method will fix the line numbering. -## editorInfo.ace_doReturnKey() -Forces a return key at the current caret position. -## editorInfo.ace_isBlockElement(element) -Returns true if your passed element is registered as a block element -## editorInfo.ace_getLineListType(lineNum) -Returns the line's html list type. -## editorInfo.ace_caretLine() -Returns X position of the caret. -## editorInfo.ace_caretColumn() -Returns Y position of the caret. -## editorInfo.ace_caretDocChar() -Returns the Y offset starting from [x=0,y=0] -## editorInfo.ace_isWordChar(?) diff --git a/sources/doc/api/embed_parameters.md b/sources/doc/api/embed_parameters.md deleted file mode 100644 index ea225d8..0000000 --- a/sources/doc/api/embed_parameters.md +++ /dev/null @@ -1,68 +0,0 @@ -# Embed parameters -You can easily embed your etherpad-lite into any webpage by using iframes. You can configure the embedded pad using embed parameters. - -Example: - -Cut and paste the following code into any webpage to embed a pad. The parameters below will hide the chat and the line numbers. - -``` - -``` - -## showLineNumbers - * Boolean - -Default: true - -## showControls - * Boolean - -Default: true - -## showChat - * Boolean - -Default: true - -## useMonospaceFont - * Boolean - -Default: false - -## userName - * String - -Default: "unnamed" - -Example: `userName=Etherpad%20User` - -## userColor - * String (css hex color value) - -Default: randomly chosen by pad server - -Example: `userColor=%23ff9900` - -## noColors - * Boolean - -Default: false - -## alwaysShowChat - * Boolean - -Default: false - -## lang - * String - -Default: en - -Example: `lang=ar` (translates the interface into Arabic) - -## rtl - * Boolean - -Default: true -Displays pad text from right to left. - diff --git a/sources/doc/api/hooks_client-side.md b/sources/doc/api/hooks_client-side.md deleted file mode 100644 index 9af0356..0000000 --- a/sources/doc/api/hooks_client-side.md +++ /dev/null @@ -1,378 +0,0 @@ -# Client-side hooks -Most of these hooks are called during or in order to set up the formatting process. - -## documentReady -Called from: src/templates/pad.html - -Things in context: - -nothing - -This hook proxies the functionality of jQuery's `$(document).ready` event. - -## aceDomLinePreProcessLineAttributes -Called from: src/static/js/domline.js - -Things in context: - -1. domline - The current DOM line being processed -2. cls - The class of the current block element (useful for styling) - -This hook is called for elements in the DOM that have the "lineMarkerAttribute" set. You can add elements into this category with the aceRegisterBlockElements hook above. This hook is run BEFORE the numbered and ordered lists logic is applied. - -The return value of this hook should have the following structure: - -`{ preHtml: String, postHtml: String, processedMarker: Boolean }` - -The preHtml and postHtml values will be added to the HTML display of the element, and if processedMarker is true, the engine won't try to process it any more. - -## aceDomLineProcessLineAttributes -Called from: src/static/js/domline.js - -Things in context: - -1. domline - The current DOM line being processed -2. cls - The class of the current block element (useful for styling) - -This hook is called for elements in the DOM that have the "lineMarkerAttribute" set. You can add elements into this category with the aceRegisterBlockElements hook above. This hook is run AFTER the ordered and numbered lists logic is applied. - -The return value of this hook should have the following structure: - -`{ preHtml: String, postHtml: String, processedMarker: Boolean }` - -The preHtml and postHtml values will be added to the HTML display of the element, and if processedMarker is true, the engine won't try to process it any more. - -## aceCreateDomLine -Called from: src/static/js/domline.js - -Things in context: - -1. domline - the current DOM line being processed -2. cls - The class of the current element (useful for styling) - -This hook is called for any line being processed by the formatting engine, unless the aceDomLineProcessLineAttributes hook from above returned true, in which case this hook is skipped. - -The return value of this hook should have the following structure: - -`{ extraOpenTags: String, extraCloseTags: String, cls: String }` - -extraOpenTags and extraCloseTags will be added before and after the element in question, and cls will be the new class of the element going forward. - -## acePostWriteDomLineHTML -Called from: src/static/js/domline.js - -Things in context: - -1. node - the DOM node that just got written to the page - -This hook is for right after a node has been fully formatted and written to the page. - -## aceAttribsToClasses -Called from: src/static/js/linestylefilter.js - -Things in context: - -1. linestylefilter - the JavaScript object that's currently processing the ace attributes -2. key - the current attribute being processed -3. value - the value of the attribute being processed - -This hook is called during the attribute processing procedure, and should be used to translate key, value pairs into valid HTML classes that can be inserted into the DOM. - -The return value for this function should be a list of classes, which will then be parsed into a valid class string. - -## aceAttribClasses -Called from: src/static/js/linestylefilter.js - -Things in context: -1. Attributes - Object of Attributes - -This hook is called when attributes are investigated on a line. It is useful if you want to add another attribute type or property type to a pad. - -Example: -``` -exports.aceAttribClasses = function(hook_name, attr, cb){ - attr.sub = 'tag:sub'; - cb(attr); -} -``` - -## aceGetFilterStack -Called from: src/static/js/linestylefilter.js - -Things in context: - -1. linestylefilter - the JavaScript object that's currently processing the ace attributes -2. browser - an object indicating which browser is accessing the page - -This hook is called to apply custom regular expression filters to a set of styles. The one example available is the ep_linkify plugin, which adds internal links. They use it to find the telltale `[[ ]]` syntax that signifies internal links, and finding that syntax, they add in the internalHref attribute to be later used by the aceCreateDomLine hook (documented above). - -## aceEditorCSS -Called from: src/static/js/ace.js - -Things in context: None - -This hook is provided to allow custom CSS files to be loaded. The return value should be an array of resource urls or paths relative to the plugins directory. - -## aceInitInnerdocbodyHead -Called from: src/static/js/ace.js - -Things in context: - -1. iframeHTML - the HTML of the editor iframe up to this point, in array format - -This hook is called during the creation of the editor HTML. The array should have lines of HTML added to it, giving the plugin author a chance to add in meta, script, link, and other tags that go into the `` element of the editor HTML document. - -## aceEditEvent -Called from: src/static/js/ace2_inner.js - -Things in context: - -1. callstack - a bunch of information about the current action -2. editorInfo - information about the user who is making the change -3. rep - information about where the change is being made -4. documentAttributeManager - information about attributes in the document (this is a mystery to me) - -This hook is made available to edit the edit events that might occur when changes are made. Currently you can change the editor information, some of the meanings of the edit, and so on. You can also make internal changes (internal to your plugin) that use the information provided by the edit event. - -## aceRegisterNonScrollableEditEvents -Called from: src/static/js/ace2_inner.js - -Things in context: None - -When aceEditEvent (documented above) finishes processing the event, it scrolls the viewport to make caret visible to the user, but if you don't want that behavior to happen you can use this hook to register which edit events should not scroll viewport. The return value of this hook should be a list of event names. - -Example: -``` -exports.aceRegisterNonScrollableEditEvents = function(){ - return [ 'repaginate', 'updatePageCount' ]; -} -``` - -## aceRegisterBlockElements -Called from: src/static/js/ace2_inner.js - -Things in context: None - -The return value of this hook will add elements into the "lineMarkerAttribute" category, making the aceDomLineProcessLineAttributes hook (documented below) call for those elements. - -## aceInitialized -Called from: src/static/js/ace2_inner.js - -Things in context: - -1. editorInfo - information about the user who will be making changes through the interface, and a way to insert functions into the main ace object (see ep_headings) -2. rep - information about where the user's cursor is -3. documentAttributeManager - some kind of magic - -This hook is for inserting further information into the ace engine, for later use in formatting hooks. - -## postAceInit -Called from: src/static/js/pad.js - -Things in context: - -1. ace - the ace object that is applied to this editor. -2. pad - the pad object of the current pad. - -## postToolbarInit -Called from: src/static/js/pad_editbar.js - -Things in context: - -1. ace - the ace object that is applied to this editor. -2. toolbar - Editbar instance. See below for the Editbar documentation. - -Can be used to register custom actions to the toolbar. - -Usage examples: - -* [https://github.com/tiblu/ep_authorship_toggle]() - -## postTimesliderInit -Called from: src/static/js/timeslider.js - -There doesn't appear to be any example available of this particular hook being used, but it gets fired after the timeslider is all set up. - -## userJoinOrUpdate -Called from: src/static/js/pad_userlist.js - -Things in context: - -1. info - the user information - -This hook is called on the client side whenever a user joins or changes. This can be used to create notifications or an alternate user list. - -## chatNewMessage -Called from: src/static/js/chat.js - -Things in context: - -1. authorName - The user that wrote this message -2. author - The authorID of the user that wrote the message -2. text - the message text -3. sticky (boolean) - if you want the gritter notification bubble to fade out on its own or just sit there -3. timestamp - the timestamp of the chat message -4. timeStr - the timestamp as a formatted string - -This hook is called on the client side whenever a chat message is received from the server. It can be used to create different notifications for chat messages. - -## collectContentPre -Called from: src/static/js/contentcollector.js - -Things in context: - -1. cc - the contentcollector object -2. state - the current state of the change being made -3. tname - the tag name of this node currently being processed -4. styl - the style applied to the node (probably CSS) -- Note the typo -5. cls - the HTML class string of the node - -This hook is called before the content of a node is collected by the usual methods. The cc object can be used to do a bunch of things that modify the content of the pad. See, for example, the heading1 plugin for etherpad original. - -E.g. if you need to apply an attribute to newly inserted characters, -call cc.doAttrib(state, "attributeName") which results in an attribute attributeName=true. - -If you want to specify also a value, call cc.doAttrib(state, "attributeName::value") -which results in an attribute attributeName=value. - - -## collectContentImage -Called from: src/static/js/contentcollector.js - -Things in context: - -1. cc - the contentcollector object -2. state - the current state of the change being made -3. tname - the tag name of this node currently being processed -4. style - the style applied to the node (probably CSS) -5. cls - the HTML class string of the node -6. node - the node being modified - -This hook is called before the content of an image node is collected by the usual methods. The cc object can be used to do a bunch of things that modify the content of the pad. - -Example: - -``` -exports.collectContentImage = function(name, context){ - context.state.lineAttributes.img = context.node.outerHTML; -} - -``` - -## collectContentPost -Called from: src/static/js/contentcollector.js - -Things in context: - -1. cc - the contentcollector object -2. state - the current state of the change being made -3. tname - the tag name of this node currently being processed -4. style - the style applied to the node (probably CSS) -5. cls - the HTML class string of the node - -This hook is called after the content of a node is collected by the usual methods. The cc object can be used to do a bunch of things that modify the content of the pad. See, for example, the heading1 plugin for etherpad original. - -## handleClientMessage_`name` -Called from: `src/static/js/collab_client.js` - -Things in context: - -1. payload - the data that got sent with the message (use it for custom message content) - -This hook gets called every time the client receives a message of type `name`. This can most notably be used with the new HTTP API call, "sendClientsMessage", which sends a custom message type to all clients connected to a pad. You can also use this to handle existing types. - -`collab_client.js` has a pretty extensive list of message types, if you want to take a look. - -##aceStartLineAndCharForPoint-aceEndLineAndCharForPoint -Called from: src/static/js/ace2_inner.js - -Things in context: - -1. callstack - a bunch of information about the current action -2. editorInfo - information about the user who is making the change -3. rep - information about where the change is being made -4. root - the span element of the current line -5. point - the starting/ending element where the cursor highlights -6. documentAttributeManager - information about attributes in the document - -This hook is provided to allow a plugin to turn DOM node selection into [line,char] selection. -The return value should be an array of [line,char] - -##aceKeyEvent -Called from: src/static/js/ace2_inner.js - -Things in context: - -1. callstack - a bunch of information about the current action -2. editorInfo - information about the user who is making the change -3. rep - information about where the change is being made -4. documentAttributeManager - information about attributes in the document -5. evt - the fired event - -This hook is provided to allow a plugin to handle key events. -The return value should be true if you have handled the event. - -##collectContentLineText -Called from: src/static/js/contentcollector.js - -Things in context: - -1. cc - the contentcollector object -2. state - the current state of the change being made -3. tname - the tag name of this node currently being processed -4. text - the text for that line - -This hook allows you to validate/manipulate the text before it's sent to the server side. -The return value should be the validated/manipulated text. - -##collectContentLineBreak -Called from: src/static/js/contentcollector.js - -Things in context: - -1. cc - the contentcollector object -2. state - the current state of the change being made -3. tname - the tag name of this node currently being processed - -This hook is provided to allow whether the br tag should induce a new magic domline or not. -The return value should be either true(break the line) or false. - -##disableAuthorColorsForThisLine -Called from: src/static/js/linestylefilter.js - -Things in context: - -1. linestylefilter - the JavaScript object that's currently processing the ace attributes -2. text - the line text -3. class - line class - -This hook is provided to allow whether a given line should be deliniated with multiple authors. -Multiple authors in one line cause the creation of magic span lines. This might not suit you and -now you can disable it and handle your own deliniation. -The return value should be either true(disable) or false. - -## aceSetAuthorStyle -Called from: src/static/js/ace2_inner.js - -Things in context: - -1. dynamicCSS - css manger for inner ace -2. outerDynamicCSS - css manager for outer ace -3. parentDynamicCSS - css manager for parent document -4. info - author style info -5. author - author info -6. authorSelector - css selector for author span in inner ace - -This hook is provided to allow author highlight style to be modified. -Registered hooks should return 1 if the plugin handles highlighting. If no plugin returns 1, the core will use the default background-based highlighting. - -## aceSelectionChanged -Called from: src/static/js/ace2_inner.js - -Things in context: - -1. rep - information about where the user's cursor is -2. documentAttributeManager - information about attributes in the document - -This hook allows a plugin to react to a cursor or selection change, -perhaps to update a UI element based on the style at the cursor location. diff --git a/sources/doc/api/hooks_overview.md b/sources/doc/api/hooks_overview.md deleted file mode 100644 index c252aa8..0000000 --- a/sources/doc/api/hooks_overview.md +++ /dev/null @@ -1,11 +0,0 @@ -# Hooks -All hooks are called with two arguments: - -1. name - the name of the hook being called -2. context - an object with some relevant information about the context of the call - -## Return values -A hook should always return a list or undefined. Returning undefined is equivalent to returning an empty list. -All the returned lists are appended to each other, so if the return values where `[1, 2]`, `undefined`, `[3, 4,]`, `undefined` and `[5]`, the value returned by callHook would be `[1, 2, 3, 4, 5]`. - -This is, because it should never matter if you have one plugin or several plugins doing some work - a single plugin should be able to make callHook return the same value a set of plugins are able to return collectively. So, any plugin can return a list of values, of any length, not just one value. \ No newline at end of file diff --git a/sources/doc/api/hooks_server-side.md b/sources/doc/api/hooks_server-side.md deleted file mode 100644 index edf2051..0000000 --- a/sources/doc/api/hooks_server-side.md +++ /dev/null @@ -1,455 +0,0 @@ -# Server-side hooks -These hooks are called on server-side. - -## loadSettings -Called from: src/node/server.js - -Things in context: - -1. settings - the settings object - -Use this hook to receive the global settings in your plugin. - -## pluginUninstall -Called from: src/static/js/pluginfw/installer.js - -Things in context: - -1. plugin_name - self-explanatory - -If this hook returns an error, the callback to the uninstall function gets an error as well. This mostly seems useful for handling additional features added in based on the installation of other plugins, which is pretty cool! - -## pluginInstall -Called from: src/static/js/pluginfw/installer.js - -Things in context: - -1. plugin_name - self-explanatory - -If this hook returns an error, the callback to the install function gets an error, too. This seems useful for adding in features when a particular plugin is installed. - -## init_`` -Called from: src/static/js/pluginfw/plugins.js - -Things in context: None - -This function is called after a specific plugin is initialized. This would probably be more useful than the previous two functions if you only wanted to add in features to one specific plugin. - -## expressConfigure -Called from: src/node/hooks/express.js - -Things in context: - -1. app - the main application object - -This is a helpful hook for changing the behavior and configuration of the application. It's called right after the application gets configured. - -## expressCreateServer -Called from: src/node/hooks/express.js - -Things in context: - -1. app - the main express application object (helpful for adding new paths and such) -2. server - the http server object - -This hook gets called after the application object has been created, but before it starts listening. This is similar to the expressConfigure hook, but it's not guaranteed that the application object will have all relevant configuration variables. - -## eejsBlock_`` -Called from: src/node/eejs/index.js - -Things in context: - -1. content - the content of the block - -This hook gets called upon the rendering of an ejs template block. For any specific kind of block, you can change how that block gets rendered by modifying the content object passed in. - -Available blocks in `pad.html` are: - - * `htmlHead` - after `` and immediately before the title tag - * `styles` - the style ``s - * `body` - the contents of the body tag - * `editbarMenuLeft` - the left tool bar (consider using the toolbar controller instead of manually adding html here) - * `editbarMenuRight` - right tool bar - * `afterEditbar` - allows you to add stuff immediately after the toolbar - * `userlist` - the contents of the userlist dropdown - * `loading` - the initial loading message - * `mySettings` - the left column of the settings dropdown ("My view"); intended for adding checkboxes only - * `mySettings.dropdowns` - add your dropdown settings here - * `globalSettings` - the right column of the settings dropdown ("Global view") - * `importColumn` - import form - * `exportColumn` - export form - * `modals` - Contains all connectivity messages - * `embedPopup` - the embed dropdown - * `scripts` - Add your script tags here, if you really have to (consider use client-side hooks instead) - -`timeslider.html` blocks: - - * `timesliderStyles` - * `timesliderScripts` - * `timesliderBody` - * `timesliderTop` - * `timesliderEditbarRight` - * `modals` - - `index.html` blocks: - - * `indexWrapper` - contains the form for creating new pads - -## padInitToolbar -Called from: src/node/hooks/express/specialpages.js - -Things in context: - -1. toolbar - the toolbar controller that will render the toolbar eventually - -Here you can add custom toolbar items that will be available in the toolbar config in `settings.json`. For more about the toolbar controller see the API section. - -Usage examples: - -* https://github.com/tiblu/ep_authorship_toggle - -## onAccessCheck -Called from: src/node/db/SecurityManager.js - -Things in context: - -1. padID - the pad the user wants to access -2. password - the password the user has given to access the pad -3. token - the token of the author -4. sessionCookie - the session the use has - -This hook gets called when the access to the concrete pad is being checked. Return `false` to deny access. - -## padCreate -Called from: src/node/db/Pad.js - -Things in context: - -1. pad - the pad instance -2. author - the id of the author who created the pad - -This hook gets called when a new pad was created. - -## padLoad -Called from: src/node/db/Pad.js - -Things in context: - -1. pad - the pad instance - -This hook gets called when a pad was loaded. If a new pad was created and loaded this event will be emitted too. - -## padUpdate -Called from: src/node/db/Pad.js - -Things in context: - -1. pad - the pad instance -2. author - the id of the author who updated the pad - -This hook gets called when an existing pad was updated. - -## padCopy -Called from: src/node/db/Pad.js - -Things in context: - -1. originalPad - the source pad instance -2. destinationID - the id of the pad copied from originalPad - -This hook gets called when an existing pad was copied. - -Usage examples: - -* https://github.com/ether/ep_comments - -## padRemove -Called from: src/node/db/Pad.js - -Things in context: - -1. padID - -This hook gets called when an existing pad was removed/deleted. - -Usage examples: - -* https://github.com/ether/ep_comments - -## socketio -Called from: src/node/hooks/express/socketio.js - -Things in context: - -1. app - the application object -2. io - the socketio object -3. server - the http server object - -I have no idea what this is useful for, someone else will have to add this description. - -## authorize -Called from: src/node/hooks/express/webaccess.js - -Things in context: - -1. req - the request object -2. res - the response object -3. next - ? -4. resource - the path being accessed - -This is useful for modifying the way authentication is done, especially for specific paths. - -## authenticate -Called from: src/node/hooks/express/webaccess.js - -Things in context: - -1. req - the request object -2. res - the response object -3. next - ? -4. username - the username used (optional) -5. password - the password used (optional) - -This is useful for modifying the way authentication is done. - -## authFailure -Called from: src/node/hooks/express/webaccess.js - -Things in context: - -1. req - the request object -2. res - the response object -3. next - ? - -This is useful for modifying the way authentication is done. - -## handleMessage -Called from: src/node/handler/PadMessageHandler.js - -Things in context: - -1. message - the message being handled -2. client - the client object from socket.io - -This hook will be called once a message arrive. If a plugin calls `callback(null)` the message will be dropped. However, it is not possible to modify the message. - -Plugins may also decide to implement custom behavior once a message arrives. - -**WARNING**: handleMessage will be called, even if the client is not authorized to send this message. It's up to the plugin to check permissions. - -Example: - -``` -function handleMessage ( hook, context, callback ) { - if ( context.message.type == 'USERINFO_UPDATE' ) { - // If the message type is USERINFO_UPDATE, drop the message - callback(null); - }else{ - callback(); - } -}; -``` - -## handleMessageSecurity -Called from: src/node/handler/PadMessageHandler.js - -Things in context: - -1. message - the message being handled -2. client - the client object from socket.io - -This hook will be called once a message arrives. If a plugin calls `callback(true)` the message will be allowed to be processed. This is especially useful if you want read only pad visitors to update pad contents for whatever reason. - -**WARNING**: handleMessageSecurity will be called, even if the client is not authorized to send this message. It's up to the plugin to check permissions. - -Example: - -``` -function handleMessageSecurity ( hook, context, callback ) { - if ( context.message.boomerang == 'hipster' ) { - // If the message boomer is hipster, allow the request - callback(true); - }else{ - callback(); - } -}; -``` - - -## clientVars -Called from: src/node/handler/PadMessageHandler.js - -Things in context: - -1. clientVars - the basic `clientVars` built by the core -2. pad - the pad this session is about - -This hook will be called once a client connects and the `clientVars` are being sent. Plugins can use this hook to give the client an initial configuration, like the tracking-id of an external analytics-tool that is used on the client-side. You can also overwrite values from the original `clientVars`. - -Example: - -``` -exports.clientVars = function(hook, context, callback) -{ - // tell the client which year we are in - return callback({ "currentYear": new Date().getFullYear() }); -}; -``` - -This can be accessed on the client-side using `clientVars.currentYear`. - -## getLineHTMLForExport -Called from: src/node/utils/ExportHtml.js - -Things in context: - -1. apool - pool object -2. attribLine - line attributes -3. text - line text - -This hook will allow a plug-in developer to re-write each line when exporting to HTML. - -Example: -``` -var Changeset = require("ep_etherpad-lite/static/js/Changeset"); - -exports.getLineHTMLForExport = function (hook, context) { - var header = _analyzeLine(context.attribLine, context.apool); - if (header) { - return "<" + header + ">" + context.lineContent + ""; - } -} - -function _analyzeLine(alineAttrs, apool) { - var header = null; - if (alineAttrs) { - var opIter = Changeset.opIterator(alineAttrs); - if (opIter.hasNext()) { - var op = opIter.next(); - header = Changeset.opAttributeValue(op, 'heading', apool); - } - } - return header; -} -``` - -## stylesForExport -Called from: src/node/utils/ExportHtml.js - -Things in context: - -1. padId - The Pad Id - -This hook will allow a plug-in developer to append Styles to the Exported HTML. - -Example: - -``` -exports.stylesForExport = function(hook, padId, cb){ - cb("body{font-size:13.37em !important}"); -} -``` - -## aceAttribClasses -Called from: src/static/js/linestylefilter.js - -Things in context: -1. Attributes - Object of Attributes - -This hook is called when attributes are investigated on a line. It is useful if you want to add another attribute type or property type to a pad. - -Example: - -``` -exports.aceAttribClasses = function(hook_name, attr, cb){ - attr.sub = 'tag:sub'; - cb(attr); -} -``` - -## exportFileName -Called from src/node/handler/ExportHandler.js - -Things in context: - -1. padId - -This hook will allow a plug-in developer to modify the file name of an exported pad. This is useful if you want to export a pad under another name and/or hide the padId under export. Note that the doctype or file extension cannot be modified for security reasons. - -Example: - -``` -exports.exportFileName = function(hook, padId, callback){ - callback("newFileName"+padId); -} -``` - -## exportHtmlAdditionalTags -Called from src/node/utils/ExportHtml.js - -Things in context: - -1. Pad object - -This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. If tags are stored as `['color', 'red']` on the attribute pool, use `exportHtmlAdditionalTagsWithData` instead. An Array should be returned. - -Example: -``` -// Add the props to be supported in export -exports.exportHtmlAdditionalTags = function(hook, pad, cb){ - var padId = pad.id; - cb(["massive","jugs"]); -}; -``` - -## exportHtmlAdditionalTagsWithData -Called from src/node/utils/ExportHtml.js - -Things in context: - -1. Pad object - -Identical to `exportHtmlAdditionalTags`, but for tags that are stored with a specific value (not simply `true`) on the attribute pool. For example `['color', 'red']`, instead of `['bold', true]`. This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. An Array of arrays should be returned. The exported HTML will contain tags like `` for the content where attributes are `['color', 'red']`. - -Example: -``` -// Add the props to be supported in export -exports.exportHtmlAdditionalTagsWithData = function(hook, pad, cb){ - var padId = pad.id; - cb([["color", "red"], ["color", "blue"]]); -}; -``` - -## userLeave -Called from src/node/handler/PadMessageHandler.js - -This in context: - -1. session (including the pad id and author id) - -This hook gets called when an author leaves a pad. This is useful if you want to perform certain actions after a pad has been edited - -Example: - -``` -exports.userLeave = function(hook, session, callback) { - console.log('%s left pad %s', session.author, session.padId); -}; -``` - -### clientReady -Called from src/node/handler/PadMessageHandler.js - -This in context: - -1. message - -This hook gets called when handling a CLIENT_READY which is the first message from the client to the server. - -Example: - -``` -exports.clientReady = function(hook, message) { - console.log('Client has entered the pad' + message.padId); -}; -``` diff --git a/sources/doc/api/http_api.md b/sources/doc/api/http_api.md deleted file mode 100644 index cacefb5..0000000 --- a/sources/doc/api/http_api.md +++ /dev/null @@ -1,605 +0,0 @@ -# HTTP API - -## What can I do with this API? -The API gives another web application control of the pads. The basic functions are - -* create/delete pads -* grant/forbid access to pads -* get/set pad content - -The API is designed in a way, so you can reuse your existing user system with their permissions, and map it to Etherpad. Means: Your web application still has to do authentication, but you can tell Etherpad via the api, which visitors should get which permissions. This allows Etherpad to fit into any web application and extend it with real-time functionality. You can embed the pads via an iframe into your website. - -Take a look at [HTTP API client libraries](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) to check if a library in your favorite programming language is available. - -## Examples - -### Example 1 - -A portal (such as WordPress) wants to give a user access to a new pad. Let's assume the user have the internal id 7 and his name is michael. - -Portal maps the internal userid to an etherpad author. - -> Request: `http://pad.domain/api/1/createAuthorIfNotExistsFor?apikey=secret&name=Michael&authorMapper=7` -> -> Response: `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}` - -Portal maps the internal userid to an etherpad group: - -> Request: `http://pad.domain/api/1/createGroupIfNotExistsFor?apikey=secret&groupMapper=7` -> -> Response: `{code: 0, message:"ok", data: {groupID: "g.s8oes9dhwrvt0zif"}}` - -Portal creates a pad in the userGroup - -> Request: `http://pad.domain/api/1/createGroupPad?apikey=secret&groupID=g.s8oes9dhwrvt0zif&padName=samplePad&text=This is the first sentence in the pad` -> -> Response: `{code: 0, message:"ok", data: null}` - -Portal starts the session for the user on the group: - -> Request: `http://pad.domain/api/1/createSession?apikey=secret&groupID=g.s8oes9dhwrvt0zif&authorID=a.s8oes9dhwrvt0zif&validUntil=1312201246` -> -> Response: `{"data":{"sessionID": "s.s8oes9dhwrvt0zif"}}` - -Portal places the cookie "sessionID" with the given value on the client and creates an iframe including the pad. - -### Example 2 - -A portal (such as WordPress) wants to transform the contents of a pad that multiple admins edited into a blog post. - -Portal retrieves the contents of the pad for entry into the db as a blog post: - -> Request: `http://pad.domain/api/1/getText?apikey=secret&padID=g.s8oes9dhwrvt0zif$123` -> -> Response: `{code: 0, message:"ok", data: {text:"Welcome Text"}}` - -Portal submits content into new blog post - -> Portal.AddNewBlog(content) -> - -## Usage - -### API version -The latest version is `1.2.13` - -The current version can be queried via /api. - -### Request Format - -The API is accessible via HTTP. HTTP Requests are in the format /api/$APIVERSION/$FUNCTIONNAME. Parameters are transmitted via HTTP GET. $APIVERSION depends on the endpoints you want to use. - -### Response Format -Responses are valid JSON in the following format: - -```js -{ - "code": number, - "message": string, - "data": obj -} -``` - -* **code** a return code - * **0** everything ok - * **1** wrong parameters - * **2** internal error - * **3** no such function - * **4** no or wrong API Key -* **message** a status message. It's ok if everything is fine, else it contains an error message -* **data** the payload - -### Overview - -![API Overview](https://i.imgur.com/d0nWp.png) - -## Data Types - -* **groupID** a string, the unique id of a group. Format is g.16RANDOMCHARS, for example g.s8oes9dhwrvt0zif -* **sessionID** a string, the unique id of a session. Format is s.16RANDOMCHARS, for example s.s8oes9dhwrvt0zif -* **authorID** a string, the unique id of an author. Format is a.16RANDOMCHARS, for example a.s8oes9dhwrvt0zif -* **readOnlyID** a string, the unique id of a readonly relation to a pad. Format is r.16RANDOMCHARS, for example r.s8oes9dhwrvt0zif -* **padID** a string, format is GROUPID$PADNAME, for example the pad test of group g.s8oes9dhwrvt0zif has padID g.s8oes9dhwrvt0zif$test - -### Authentication - -Authentication works via a token that is sent with each request as a post parameter. There is a single token per Etherpad deployment. This token will be random string, generated by Etherpad at the first start. It will be saved in APIKEY.txt in the root folder of Etherpad. Only Etherpad and the requesting application knows this key. Token management will not be exposed through this API. - -### Node Interoperability - -All functions will also be available through a node module accessible from other node.js applications. - -### JSONP - -The API provides _JSONP_ support to allow requests from a server in a different domain. -Simply add `&jsonp=?` to the API call. - -Example usage: https://api.jquery.com/jQuery.getJSON/ - -## API Methods - -### Groups -Pads can belong to a group. The padID of grouppads is starting with a groupID like g.asdfasdfasdfasdf$test - -#### createGroup() - * API >= 1 - -creates a new group - -*Example returns:* - * `{code: 0, message:"ok", data: {groupID: g.s8oes9dhwrvt0zif}}` - -#### createGroupIfNotExistsFor(groupMapper) - * API >= 1 - -this functions helps you to map your application group ids to Etherpad group ids - -*Example returns:* - * `{code: 0, message:"ok", data: {groupID: g.s8oes9dhwrvt0zif}}` - -#### deleteGroup(groupID) - * API >= 1 - -deletes a group - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"groupID does not exist", data: null}` - -#### listPads(groupID) - * API >= 1 - -returns all pads of this group - -*Example returns:* - * `{code: 0, message:"ok", data: {padIDs : ["g.s8oes9dhwrvt0zif$test", "g.s8oes9dhwrvt0zif$test2"]}` - * `{code: 1, message:"groupID does not exist", data: null}` - -#### createGroupPad(groupID, padName [, text]) - * API >= 1 - -creates a new pad in this group - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"pad does already exist", data: null}` - * `{code: 1, message:"groupID does not exist", data: null}` - -#### listAllGroups() - * API >= 1.1 - -lists all existing groups - -*Example returns:* - * `{code: 0, message:"ok", data: {groupIDs: ["g.mKjkmnAbSMtCt8eL", "g.3ADWx6sbGuAiUmCy"]}}` - * `{code: 0, message:"ok", data: {groupIDs: []}}` - -### Author -These authors are bound to the attributes the users choose (color and name). - -#### createAuthor([name]) - * API >= 1 - -creates a new author - -*Example returns:* - * `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}` - -#### createAuthorIfNotExistsFor(authorMapper [, name]) - * API >= 1 - -this functions helps you to map your application author ids to Etherpad author ids - -*Example returns:* - * `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}` - -#### listPadsOfAuthor(authorID) - * API >= 1 - -returns an array of all pads this author contributed to - -*Example returns:* - * `{code: 0, message:"ok", data: {padIDs: ["g.s8oes9dhwrvt0zif$test", "g.s8oejklhwrvt0zif$foo"]}}` - * `{code: 1, message:"authorID does not exist", data: null}` - -#### getAuthorName(authorID) - * API >= 1.1 - -Returns the Author Name of the author - -*Example returns:* - * `{code: 0, message:"ok", data: {authorName: "John McLear"}}` - --> can't be deleted cause this would involve scanning all the pads where this author was - -### Session -Sessions can be created between a group and an author. This allows an author to access more than one group. The sessionID will be set as a cookie to the client and is valid until a certain date. The session cookie can also contain multiple comma-separated sessionIDs, allowing a user to edit pads in different groups at the same time. Only users with a valid session for this group, can access group pads. You can create a session after you authenticated the user at your web application, to give them access to the pads. You should save the sessionID of this session and delete it after the user logged out. - -#### createSession(groupID, authorID, validUntil) - * API >= 1 - -creates a new session. validUntil is an unix timestamp in seconds - -*Example returns:* - * `{code: 0, message:"ok", data: {sessionID: "s.s8oes9dhwrvt0zif"}}` - * `{code: 1, message:"groupID doesn't exist", data: null}` - * `{code: 1, message:"authorID doesn't exist", data: null}` - * `{code: 1, message:"validUntil is in the past", data: null}` - -#### deleteSession(sessionID) - * API >= 1 - -deletes a session - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"sessionID does not exist", data: null}` - -#### getSessionInfo(sessionID) - * API >= 1 - -returns informations about a session - -*Example returns:* - * `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif", groupID: g.s8oes9dhwrvt0zif, validUntil: 1312201246}}` - * `{code: 1, message:"sessionID does not exist", data: null}` - -#### listSessionsOfGroup(groupID) - * API >= 1 - -returns all sessions of a group - -*Example returns:* - * `{"code":0,"message":"ok","data":{"s.oxf2ras6lvhv2132":{"groupID":"g.s8oes9dhwrvt0zif","authorID":"a.akf8finncvomlqva","validUntil":2312905480}}}` - * `{code: 1, message:"groupID does not exist", data: null}` - -#### listSessionsOfAuthor(authorID) - * API >= 1 - -returns all sessions of an author - -*Example returns:* - * `{"code":0,"message":"ok","data":{"s.oxf2ras6lvhv2132":{"groupID":"g.s8oes9dhwrvt0zif","authorID":"a.akf8finncvomlqva","validUntil":2312905480}}}` - * `{code: 1, message:"authorID does not exist", data: null}` - -### Pad Content - -Pad content can be updated and retrieved through the API - -#### getText(padID, [rev]) - * API >= 1 - -returns the text of a pad - -*Example returns:* - * `{code: 0, message:"ok", data: {text:"Welcome Text"}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### setText(padID, text) - * API >= 1 - -sets the text of a pad - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does not exist", data: null}` - * `{code: 1, message:"text too long", data: null}` - -#### appendText(padID, text) - * API >= 1.2.13 - -appends text to a pad - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does not exist", data: null}` - * `{code: 1, message:"text too long", data: null}` - -#### getHTML(padID, [rev]) - * API >= 1 - -returns the text of a pad formatted as HTML - -*Example returns:* - * `{code: 0, message:"ok", data: {html:"Welcome Text
        More Text"}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### setHTML(padID, html) - * API >= 1 - -sets the text of a pad based on HTML, HTML must be well-formed. Malformed HTML will send a warning to the API log. - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### getAttributePool(padID) - * API >= 1.2.8 - -returns the attribute pool of a pad - -*Example returns:* - * `{ "code":0, - "message":"ok", - "data": { - "pool":{ - "numToAttrib":{ - "0":["author","a.X4m8bBWJBZJnWGSh"], - "1":["author","a.TotfBPzov54ihMdH"], - "2":["author","a.StiblqrzgeNTbK05"], - "3":["bold","true"] - }, - "attribToNum":{ - "author,a.X4m8bBWJBZJnWGSh":0, - "author,a.TotfBPzov54ihMdH":1, - "author,a.StiblqrzgeNTbK05":2, - "bold,true":3 - }, - "nextNum":4 - } - } - }` - * `{"code":1,"message":"padID does not exist","data":null}` - -#### getRevisionChangeset(padID, [rev]) - * API >= 1.2.8 - -get the changeset at a given revision, or last revision if 'rev' is not defined. - -*Example returns:* - * `{ "code" : 0, - "message" : "ok", - "data" : "Z:1>6b|5+6b$Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http://etherpad.org\n" - }` - * `{"code":1,"message":"padID does not exist","data":null}` - * `{"code":1,"message":"rev is higher than the head revision of the pad","data":null}` - -#### createDiffHTML(padID, startRev, endRev) - * API >= 1.2.7 - -returns an object of diffs from 2 points in a pad - -*Example returns:* - * `{"code":0,"message":"ok","data":{"html":"Welcome to Etherpad!

        This pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!

        Get involved with Etherpad at http://etherpad.org
        aw

        ","authors":["a.HKIv23mEbachFYfH",""]}}` - * `{"code":4,"message":"no or wrong API Key","data":null}` - -#### restoreRevision(padId, rev) - * API >= 1.2.11 - -Restores revision from past as new changeset - -*Example returns:* - * {code:0, message:"ok", data:null} - * {code: 1, message:"padID does not exist", data: null} - -### Chat -#### getChatHistory(padID, [start, end]) - * API >= 1.2.7 - -returns - -* a part of the chat history, when `start` and `end` are given -* the whole chat histroy, when no extra parameters are given - - -*Example returns:* - -* `{"code":0,"message":"ok","data":{"messages":[{"text":"foo","userId":"a.foo","time":1359199533759,"userName":"test"},{"text":"bar","userId":"a.foo","time":1359199534622,"userName":"test"}]}}` -* `{code: 1, message:"start is higher or equal to the current chatHead", data: null}` -* `{code: 1, message:"padID does not exist", data: null}` - -#### getChatHead(padID) - * API >= 1.2.7 - -returns the chatHead (last number of the last chat-message) of the pad - - -*Example returns:* - -* `{code: 0, message:"ok", data: {chatHead: 42}}` -* `{code: 1, message:"padID does not exist", data: null}` - -#### appendChatMessage(padID, text, authorID [, time]) - * API >= 1.2.12 - -creates a chat message, saves it to the database and sends it to all connected clients of this pad - - -*Example returns:* - -* `{code: 0, message:"ok", data: null}` -* `{code: 1, message:"text is no string", data: null}` - -### Pad -Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and it's forbidden for normal pads to include a $ in the name. - -#### createPad(padID [, text]) - * API >= 1 - -creates a new (non-group) pad. Note that if you need to create a group Pad, you should call **createGroupPad**. -You get an error message if you use one of the following characters in the padID: "/", "?", "&" or "#". - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does already exist", data: null}` - * `{code: 1, message:"malformed padID: Remove special characters", data: null}` - -#### getRevisionsCount(padID) - * API >= 1 - -returns the number of revisions of this pad - -*Example returns:* - * `{code: 0, message:"ok", data: {revisions: 56}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### getSavedRevisionsCount(padID) - * API >= 1.2.11 - -returns the number of saved revisions of this pad - -*Example returns:* - * `{code: 0, message:"ok", data: {savedRevisions: 42}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### listSavedRevisions(padID) - * API >= 1.2.11 - -returns the list of saved revisions of this pad - -*Example returns:* - * `{code: 0, message:"ok", data: {savedRevisions: [2, 42, 1337]}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### saveRevision(padID [, rev]) - * API >= 1.2.11 - -saves a revision - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### padUsersCount(padID) - * API >= 1 - -returns the number of user that are currently editing this pad - -*Example returns:* - * `{code: 0, message:"ok", data: {padUsersCount: 5}}` - -#### padUsers(padID) - * API >= 1.1 - -returns the list of users that are currently editing this pad - -*Example returns:* - * `{code: 0, message:"ok", data: {padUsers: [{colorId:"#c1a9d9","name":"username1","timestamp":1345228793126,"id":"a.n4gEeMLsvg12452n"},{"colorId":"#d9a9cd","name":"Hmmm","timestamp":1345228796042,"id":"a.n4gEeMLsvg12452n"}]}}` - * `{code: 0, message:"ok", data: {padUsers: []}}` - -#### deletePad(padID) - * API >= 1 - -deletes a pad - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### copyPad(sourceID, destinationID[, force=false]) - * API >= 1.2.8 - -copies a pad with full history and chat. If force is true and the destination pad exists, it will be overwritten. - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### movePad(sourceID, destinationID[, force=false]) - * API >= 1.2.8 - -moves a pad. If force is true and the destination pad exists, it will be overwritten. - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### getReadOnlyID(padID) - * API >= 1 - -returns the read only link of a pad - -*Example returns:* - * `{code: 0, message:"ok", data: {readOnlyID: "r.s8oes9dhwrvt0zif"}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### getPadID(readOnlyID) - * API >= 1.2.10 - -returns the id of a pad which is assigned to the readOnlyID - -*Example returns:* - * `{code: 0, message:"ok", data: {padID: "p.s8oes9dhwrvt0zif"}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### setPublicStatus(padID, publicStatus) - * API >= 1 - -sets a boolean for the public status of a pad - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### getPublicStatus(padID) - * API >= 1 - -return true of false - -*Example returns:* - * `{code: 0, message:"ok", data: {publicStatus: true}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### setPassword(padID, password) - * API >= 1 - -returns ok or an error message - -*Example returns:* - * `{code: 0, message:"ok", data: null}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### isPasswordProtected(padID) - * API >= 1 - -returns true or false - -*Example returns:* - * `{code: 0, message:"ok", data: {passwordProtection: true}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### listAuthorsOfPad(padID) - * API >= 1 - -returns an array of authors who contributed to this pad - -*Example returns:* - * `{code: 0, message:"ok", data: {authorIDs : ["a.s8oes9dhwrvt0zif", "a.akf8finncvomlqva"]}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### getLastEdited(padID) - * API >= 1 - -returns the timestamp of the last revision of the pad - -*Example returns:* - * `{code: 0, message:"ok", data: {lastEdited: 1340815946602}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### sendClientsMessage(padID, msg) - * API >= 1.1 - -sends a custom message of type `msg` to the pad - -*Example returns:* - * `{code: 0, message:"ok", data: {}}` - * `{code: 1, message:"padID does not exist", data: null}` - -#### checkToken() - * API >= 1.2 - -returns ok when the current api token is valid - -*Example returns:* - * `{"code":0,"message":"ok","data":null}` - * `{"code":4,"message":"no or wrong API Key","data":null}` - -### Pads - -#### listAllPads() - * API >= 1.2.1 - -lists all pads on this epl instance - -*Example returns:* - * `{code: 0, message:"ok", data: {padIDs: ["testPad", "thePadsOfTheOthers"]}}` diff --git a/sources/doc/api/pluginfw.md b/sources/doc/api/pluginfw.md deleted file mode 100644 index 7e0499c..0000000 --- a/sources/doc/api/pluginfw.md +++ /dev/null @@ -1,14 +0,0 @@ -# Plugin Framework -`require("ep_etherpad-lite/static/js/plugingfw/plugins")` - -## plugins.update -`require("ep_etherpad-lite/static/js/plugingfw/plugins").update()` will use npm to list all installed modules and read their ep.json files, registering the contained hooks. -A hook registration is a pair of a hook name and a function reference (filename for require() plus function name) - -## hooks.callAll -`require("ep_etherpad-lite/static/js/plugingfw/hooks").callAll("hook_name", {argname:value})` will call all hook functions registered for `hook_name` with `{argname:value}`. - -## hooks.aCallAll -? - -## ... diff --git a/sources/doc/api/toolbar.md b/sources/doc/api/toolbar.md deleted file mode 100644 index 03a3d8f..0000000 --- a/sources/doc/api/toolbar.md +++ /dev/null @@ -1,46 +0,0 @@ -# Toolbar controller -src/node/utils/toolbar.js - -## button(opts) - * {Object} `opts` - * `command` - this command fill be fired on the editbar on click - * `localizationId` - will be set as `data-l10-id` - * `class` - here you can add additional classes to the button - -Returns: {Button} - -Example: -``` -var orderedlist = toolbar.button({ - command: "insertorderedlist", - localizationId: "pad.toolbar.ol.title", - class: "buttonicon buttonicon-insertorderedlist" -}) -``` - -You can also create buttons with text: - -``` -var myButton = toolbar.button({ - command: "myButton", - localizationId: "myPlugin.toolbar.myButton", - class: "buttontext" -}) -``` - -## selectButton(opts) - * {Object} `opts` - * `id` - id of the menu item - * `selectId` - id of the select element - * `command` - this command fill be fired on the editbar on change - -Returns: {SelectButton} - -## SelectButton.addOption(value, text, attributes) - * {String} value - The value of this option - * {String} text - the label text used for this option - * {Object} attributes - any additional html attributes go here (e.g. `data-l10n-id`) - -## registerButton(name, item) - * {String} name - used to reference the item in the toolbar config in settings.json - * {Button|SelectButton} item - the button to add \ No newline at end of file diff --git a/sources/doc/assets/style.css b/sources/doc/assets/style.css deleted file mode 100644 index 09bc9a3..0000000 --- a/sources/doc/assets/style.css +++ /dev/null @@ -1,47 +0,0 @@ -html { - border-top: solid green 5pt; -} - -body.apidoc { - width: 60%; - min-width: 10cm; - margin: 0 auto; -} - -#header { - padding: 1pc 0; - color: #111; -} - -a, -a:active { - color: #272; -} -a:focus, -a:hover { - color: #050; -} - -#apicontent a.mark, -#apicontent a.mark:active { - float: right; - color: #BBB; - font-size: 0.7cm; - text-decoration: none; -} -#apicontent a.mark:focus, -#apicontent a.mark:hover { - color: #AAA; -} - -#apicontent code { - padding: 1px; - background-color: #EEE; - border-radius: 4px; - border: 1px solid #DDD; -} -#apicontent pre>code { - display: block; - overflow: auto; - padding: 5px; -} \ No newline at end of file diff --git a/sources/doc/custom_static.md b/sources/doc/custom_static.md deleted file mode 100644 index 7bb2900..0000000 --- a/sources/doc/custom_static.md +++ /dev/null @@ -1,11 +0,0 @@ -# Custom static files -Etherpad allows you to include your own static files in the browser, by modifying the files in `static/custom`. - -* `index.js` Javascript that'll be run in `/` -* `index.css` Stylesheet affecting `/` -* `pad.js` Javascript that'll be run in `/p/:padid` -* `pad.css` Stylesheet affecting `/p/:padid` -* `timeslider.js` Javascript that'll be run in `/p/:padid/timeslider` -* `timeslider.css` Stylesheet affecting `/p/:padid/timeslider` -* `favicon.ico` Overrides the default favicon. -* `robots.txt` Overrides the default `robots.txt`. \ No newline at end of file diff --git a/sources/doc/database.md b/sources/doc/database.md deleted file mode 100644 index 9f6126d..0000000 --- a/sources/doc/database.md +++ /dev/null @@ -1,67 +0,0 @@ -# Database structure - -## Keys and their values - -### groups -A list of all existing groups (a JSON object with groupIDs as keys and `1` as values). - -### pad:$PADID -Contains all information about pads - -* **atext** - the latest attributed text -* **pool** - the attribute pool -* **head** - the number of the latest revision -* **chatHead** - the number of the latest chat entry -* **public** - flag that disables security for this pad -* **passwordHash** - string that contains a bcrypt hashed password for this pad - -### pad:$PADID:revs:$REVNUM -Saves a revision $REVNUM of pad $PADID - -* **meta** - * **author** - the autorID of this revision - * **timestamp** - the timestamp of when this revision was created -* **changeset** - the changeset of this revision - -### pad:$PADID:chat:$CHATNUM -Saves a chat entry with num $CHATNUM of pad $PADID - -* **text** - the text of this chat entry -* **userId** - the authorID of this chat entry -* **time** - the timestamp of this chat entry - -### pad2readonly:$PADID -Translates a padID to a readonlyID -### readonly2pad:$READONLYID -Translates a readonlyID to a padID -### token2author:$TOKENID -Translates a token to an authorID -### globalAuthor:$AUTHORID -Information about an author - -* **name** - the name of this author as shown in the pad -* **colorID** - the colorID of this author as shown in the pad - -### mapper2group:$MAPPER -Maps an external application identifier to an internal group -### mapper2author:$MAPPER -Maps an external application identifier to an internal author -### group:$GROUPID -a group of pads - -* **pads** - object with pad names in it, values are 1 -### session:$SESSIONID -a session between an author and a group - -* **groupID** - the groupID the session belongs too -* **authorID** - the authorID the session belongs too -* **validUntil** - the timestamp until this session is valid - -### author2sessions:$AUTHORID -saves the sessions of an author - -* **sessionsIDs** - object with sessionIDs in it, values are 1 - -### group2sessions:$GROUPID - -* **sessionsIDs** - object with sessionIDs in it, values are 1 diff --git a/sources/doc/documentation.md b/sources/doc/documentation.md deleted file mode 100644 index 307c38a..0000000 --- a/sources/doc/documentation.md +++ /dev/null @@ -1,15 +0,0 @@ -# About this Documentation - - - -The goal of this documentation is to comprehensively explain Etherpad, -both from a reference as well as a conceptual point of view. - -Where appropriate, property types, method arguments, and the arguments -provided to event handlers are detailed in a list underneath the topic -heading. - -Every `.html` file is generated based on the corresponding -`.md` file in the `doc/api/` folder in the source tree. The -documentation is generated using the `bin/doc/generate.js` program. -The HTML template is located at `doc/template.html`. diff --git a/sources/doc/easysync/README.md b/sources/doc/easysync/README.md deleted file mode 100644 index 326fd81..0000000 --- a/sources/doc/easysync/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# About this folder -We put all documentations we found about the original Etherpad together in this folder. Most of this is still valid for the current (node.js based) Etherpad. \ No newline at end of file diff --git a/sources/doc/easysync/easysync-full-description.pdf b/sources/doc/easysync/easysync-full-description.pdf deleted file mode 100644 index 170b6cc..0000000 Binary files a/sources/doc/easysync/easysync-full-description.pdf and /dev/null differ diff --git a/sources/doc/easysync/easysync-full-description.tex b/sources/doc/easysync/easysync-full-description.tex deleted file mode 100644 index 5c936b2..0000000 --- a/sources/doc/easysync/easysync-full-description.tex +++ /dev/null @@ -1,372 +0,0 @@ -\documentclass{article} -\usepackage{hyperref} - -\begin{document} - -\title{Etherpad and EasySync Technical Manual} -\author{AppJet, Inc., with modifications by the Etherpad Foundation} -\date{\today} - -\maketitle - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\tableofcontents -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Documents} -\begin{itemize} -\item A document is a list of characters, or a string. -\item A document can also be represented as a list of \emph{changesets}. -\end{itemize} - -\section{Changesets} - -\begin{itemize} -\item A changeset represents a change to a document. -\item A changeset can be applied to a document to produce a new document. -\item When a document is represented as a list of changesets, it is assumed that the first changeset applies to the empty document, []. -\end{itemize} - - -\section{Changeset representation} \label{representation} - -$$(\ell \rightarrow \ell')[c_1,c_2,c_3,...]$$ - -where - -\begin{itemize} -\item[] $\ell$ is the length of the document before the change, -\item[] $\ell'$ is the length of the document after the change, -\item[] $[c_1,c_2,c_3,...]$ is an array of $\ell'$ characters that described the document after the change. -\end{itemize} - -Note that $\forall c_i : 0 \leq i \leq \ell'$ is either an integer or a character. - -\begin{itemize} -\item Integers represent retained characters in the original document. -\item Characters represent insertions. -\end{itemize} - -\section{Constraints on Changesets} - -\begin{itemize} -\item Changesets are canonical and therefor comparable. When represented in computer memory, we always use the same representation for the same changeset. If the memory representation of two changesets differ, they must be different changesets. -\item Changesets are compact. Thus, if there are two ways to represent a changeset in computer memory, then we always use the representation that takes up the fewest bytes. -\end{itemize} - -Later we will discuss optimizations to changeset -representation (using ``strips'' and other such -techniques). The two constraints must apply to any -representation of changesets. - -\section{Notation} - -\begin{itemize} -\item We use the algebraic multiplication notation to represent changeset application. -\item While changesets are defined as operations on documents, documents themselves are represented as a list of changesets, initially applying to the empty document. -\end{itemize} - -\paragraph{Example} -$A=(0\rightarrow 5)[``hello"]$ -$B=(5\rightarrow 11)[0-4, ``\ world"]$ - -We can write the document ``hello world'' as $A\cdot B$ or -just $AB$. Note that the ``initial document'' can be made -into the changeset $(0\rightarrow -N)[``<\mathit{the\ document\ text}>"]$. - -When $A$ and $B$ are changesets, we can also refer to $(AB)$ as ``the composition'' of $A$ and $B$. Changesets are closed under composition. - -\section{Composition of Changesets} - -For any two changesets $A$, $B$ such that - -\begin{itemize} -\item[] $A=(n_1\rightarrow n_2)[\cdots]$ -\item[] $B=(n_2\rightarrow n_3)[\cdots]$ -\end{itemize} -it is clear that there is a third changeset $C=(n_1\rightarrow n_3)[\cdots]$ such that applying $C$ to a document $X$ yields the same resulting document as does applying $A$ and then $B$. In this case, we write $AB=C$. - -Given the representation from Section \ref{representation}, it is straightforward to compute the composition of two changesets. - -\section{Changeset Merging} - -Now we come to realtime document editing. Suppose two different users make two different changes to the same document at the same time. It is impossible to compose these changes. For example, if we have the document $X$ of length $n$, we may have $A=(n\rightarrow n_a)[\ldots n_a \mathrm{characters}]$, $B=(n\rightarrow n_b)[\ldots n_b \mathrm{characters}]$ where $n\neq n_a\neq n_b$. - -It is impossible to compute $(XA)B$ because $B$ can only be applied to a document of length $n$, and $(XA)$ has length $n_a$. Similarly, $A$ cannot be applied to $(XB)$ because $(XB)$ has length $n_b$. - -This is where \emph{merging} comes in. Merging takes two changesets that apply to the same initial document (and that cannot be composed), and computes a single new changeset that preserves the intent of both changes. The merge of $A$ and $B$ is written as $m(A,B)$. For the Etherpad system to work, we require that $m(A,B)=m(B,A)$. - -Aside from what we have said so far about merging, there are many different implementations that will lead to a workable system. We have created one implementation for text that has the following constraints. - -\section{Follows} \label{follows} - -When users $A$ and $B$ have the same document $X$ on their screen, and they proceed to make respective changesets $A$ and $B$, it is no use to compute $m(A,B)$, because $m(A,B)$ applies to document $X$, but the users are already looking at document $XA$ and $XB$. What we really want is to compute $B'$ and $A'$ such that -$$XAB' = XBA' = Xm(A,B)$$ - -``Following'' computes these $B'$ and $A'$ changesets. The definition of the ``follow'' function $f$ is such that $Af(A,B)=Bf(B,A)=m(A,B)=m(B,A)$. When we compute $f(A,B)$ -\begin{itemize} -\item Insertions in $A$ become retained characters in $f(A,B)$ -\item Insertions in $B$ become insertions in $f(A,B)$ -\item Retain whatever characters are retained in \emph{both} $A$ and $B$ -\end{itemize} - -\paragraph{Example} - -Suppose we have the initial document $X=(0\rightarrow 8)[``\mathit{baseball}"]$ and user $A$ changes it to ``basil'' with changeset $A$, and user $B$ changes it to ``below'' with changeset $B$. - -We have -$X=(0\rightarrow 8)[``\mathit{baseball}"]$ \\ -$A=(8\rightarrow 5)[0-1, ``\mathit{si}", 7]$ \\ -$B=(8\rightarrow 5)[0, ``\mathit{e}", 6, ``\mathit{ow}"]$ \\ - -First we compute the merge $m(A,B)=m(B,A)$ according to the constraints - -$$m(A,B)=(8\rightarrow 6)[0, "e", "si", "ow"] = (8\rightarrow 6)[0, ``\mathit{esiow}"]$$ - -Then we need to compute the follows $B'=f(A,B)$ and $A'=f(B,A)$. - -$$B'=f(A,B)=(5\rightarrow 6)[0,``\mathit{e}",2,3,``\mathit{ow}"]$$ - -Note that the numbers $0$, $2$, and $3$ are indices into $A=(8\rightarrow 5)[0,1,``\mathit{si}",7]$ - -\begin{tabular}{ccccc} -0 & 1 & 2 & 3 & 4 \\ -0 & 1 & s & i & 7 -\end{tabular} - -$A'=f(B,A)=(5\rightarrow 6)[0,1,"si",3,4]$ - -We can now double check that $AB'=BA'=m(A,B)=(8\rightarrow 6)[0,``\mathit{esiow}"]$. - -Now that we have made the mathematical meaning of the -preceding pages complete, we can build a client/server -system to support realtime editing by multiple users. - -\section{System Overview} - -There is a server that holds the current state of a -document. Clients (users) can connect to the server from -their web browsers. The clients and server maintain state -and can send messages to one another in real-time, but -because we are in a web browser scenario, clients cannot -send each other messages directly, and must go through the -server always. (This may distinguish from prior art?) - -The other critical design feature of the system is that -\emph{A client must always be able to edit their local - copy of the document, so the user is never blocked from - typing because of waiting to send or receive data.} - -\section{Client State} - -At any moment in time, a client maintains its state in the -form of 3 changesets. The client document looks like -$A\cdot X \cdot Y$, where - -$A$ is the latest server version, the composition of all -changesets committed to the server, from this client or -from others, that the server has informed this client -about. Initially $A=(0\rightarrow N)[<\mathit{initial\ document\ text}>]$. - -$X$ is the composition of all changesets this client has -submitted to the server but has not heard back about yet. -Initially $X=(N\rightarrow N)[0,1,2,\ldots, N-1]$, in -other words, the identity, henceforth denoted $I_N$. - -$Y$ is the composition of all changesets this client has -made but has not yet submitted to the server yet. -Initially $Y=(N\rightarrow N)[0,1,2,\ldots, N-1]$. - -\section{Client Operations} - -A client can do 5 things. - -\begin{enumerate} -\item Incorporate new typing into local state -\item Submit a changeset to the server -\item Hear back acknowledgement of a submitted changeset -\item Hear from the server about other clients' changesets -\item Connect to the server and request the initial document -\end{enumerate} - -As these 5 events happen, the client updates its -representation $A\cdot X \cdot Y$ according to the -relations that follow. Changes ``move left'' as time goes -by: into $Y$ when the user types, into $X$ when change -sets are submitted to the server, and into $A$ when the -server acknowledges changesets. - -\subsection{New local typing} - -When a user makes an edit $E$ to the document, the client -computes the composition $(Y\cdot E)$ and updates its local -state, i.e. $Y \leftarrow Y\cdot E$. I.e., if $Y$ is the -variable holding local unsubmitted changes, it will be -assigned the new value $(Y\cdot E)$. - -\subsection{Submitting changesets to server} - -When a client submit its local changes to the server, it -transmits a copy of $Y$ and then assigns $Y$ to $X$, and -assigns the identity to $Y$. I.e., - -\begin{enumerate} -\item Send $Y$ to server, -\item $X \leftarrow Y$ -\item $Y \leftarrow I_N$ - (the identity). -\end{enumerate} - -This happens every 500ms as long as it receives an -acknowledgement. Must receive ACK before submitting -again. Note that $X$ is always equal to the identity -before the second step occurs, so no information is lost. - -\subsection{Hear ACK from server} - -When the client hears ACK from server, - -$A \leftarrow A\cdot X$ \\ -$X \leftarrow I_N$ - -\subsection{Hear about another client's changeset} - -When a client hears about another client's changeset $B$, -it computes a new $A$, $X$, and $Y$, which we will call -$A'$, $X'$, and $Y'$ respectively. It also computes a -changeset $D$ which is applied to the current text view on -the client, $V$. Because $AXY$ must always equal the -current view, $AXY=V$ before the client hears about $B$, -and $A'X'Y'=VD$ after the computation is performed. - -The steps are: - -\begin{enumerate} -\item Compute $A' = AB$ -\item Compute $X' = f(B,X)$ -\item Compute $Y' = f(f(X,B), Y)$ -\item Compute $D=f(Y,f(X,B))$ -\item Assign $A \leftarrow A'$, $X \leftarrow X'$, $Y \leftarrow Y'$. -\item Apply $D$ to the current view of the document - displayed on the user's screen. -\end{enumerate} - -In steps 2,3, and 4, $f$ is the follow operation described -in Section \ref{follows}. - -\paragraph{Proof that $\mathbf{AXY=V \Rightarrow A'X'Y'=VD}$.} -Substituting $A'X'Y'=(AB)(f(B,X))(f(f(X,B),Y))$, we -recall that merges are commutative. So for any two -changesets $P$ and $Q$, -$$m(P,Q)=m(Q,P)=Qf(Q,P)=Pf(P,Q)$$ - -Applying this to the relation above, we see -\begin{eqnarray*} -A'X'Y'&=& AB f(B,X) f(f(X,B),Y) \\ - &=&AX f(X,B) f(f(X,B),Y) \\ - &=&A X Y f(Y, f(X,B)) \\ - &=&A X Y D \\ - &=&V D -\end{eqnarray*} -As claimed. - -\subsection{Connect to server} - -When a client connects to the server for the first time, -it first generates a random unique ID and sends this to -the server. The client remembers this ID and sends it -with each changeset to the server. - -The client receives the latest version of the document -from the server, called HEADTEXT. The client then sets - -\begin{itemize} -\item[] $A \leftarrow \mathrm{HEADTEXT}$ -\item[] $X \leftarrow I_N$ -\item[] $Y \leftarrow I_N$ -\end{itemize} - -And finally, the client displays HEADTEXT on the screen. - -\section{Server Overview} - -Like the client(s), the server has state and performs -operations. Operations are only performed in response to -messages from clients. - -\section{Server State} - -The server maintains a document as an ordered list of -\emph{revision records}. A revision record is a data -structure that contains a changeset and authorship -information. - -\begin{verbatim} -RevisionRecord = { - ChangeSet, - Source (unique ID), - Revision Number (consecutive order, starting at 0) -} -\end{verbatim} - -For efficiency, the server may also store a variable -called HEADTEXT, which is the composition of all -changesets in the list of revision records. This is an -optimization, because clearly this can be computed from -the set of revision records. - -\section{Server Operations Overview} - -The server does two things in addition to maintaining -state representing the set of connected clients and -remembering what revision number each client is up to date -with: - -\begin{enumerate} -\item Respond to a client's connection requesting the initial document. -\item Respond to a client's submission of a new changeset. -\end{enumerate} - -\subsection{Respond to client connect} -When a server receives a connection request from a client, -it receives the client's unique ID and stores that in the -server's set of connected clients. It then sends the -client the contents of HEADTEXT, and the corresponding -revision number. Finally the server notes that this -client is up to date with that revision number. - -\subsection{Respond to client changeset} - -When the server receives information from a client about -the client's changeset $C$, it does five things: - -\begin{enumerate} -\item Notes that this change applies to revision number - $r_c$ (the client's latest revision). -\item Creates a new changeset $C'$ that is relative to the - server's most recent revision number, which we call - $r_H$ ($H$ for HEAD). $C'$ can be computed using - follows (Section \ref{follows}). Remember that the server has a series of - changesets, -$$S_0\rightarrow S_1\rightarrow \ldots S_{r_c}\rightarrow S_{r_c+1} \rightarrow \ldots \rightarrow S_{r_H} $$ -$C$ is relative to $S_{r_c}$, but we need to compute $C'$ relative to $S_{r_H}$. -We can compute a new $C$ relative to $S_{r_c+1}$ by computing $f(S_{r_c+1},C)$. Similarly we can repeat for -$S_{r_c+2}$ and so forth until we have $C'$ represented relative to $S_{r_H}$. -\item Send $C'$ to all other clients -\item Send ACK back to original client -\item Add $C'$ to the server's list of revision records by creating a new revision record out of this and the client's ID. - -\appendix - -\section*{Additional topics} -\begin{enumerate} -\item Optimizations (strips, more caching, etc.) -\item Pseudocode for composition, merge, and follow -\item How authorship information is used to color-code the document based on who typed what -\item How persistent connections are maintained between client and server -\end{enumerate} -\end{enumerate} - - -\end{document} diff --git a/sources/doc/easysync/easysync-notes.pdf b/sources/doc/easysync/easysync-notes.pdf deleted file mode 100644 index d0af379..0000000 Binary files a/sources/doc/easysync/easysync-notes.pdf and /dev/null differ diff --git a/sources/doc/easysync/easysync-notes.tex b/sources/doc/easysync/easysync-notes.tex deleted file mode 100644 index b2c4320..0000000 --- a/sources/doc/easysync/easysync-notes.tex +++ /dev/null @@ -1,200 +0,0 @@ -\documentclass[12pt]{article} - -\usepackage[T1]{fontenc} -\usepackage[USenglish]{babel} - - -\begin{document} - -\title{Easysync Protocol} -\author{AppJet, Inc., with modifications by the Etherpad Foundation} -\date{\today} - -\maketitle - -\section{Attributes} - -An ``attribute'' is a (key,value) pair such as -\verb|(author,abc123)| or \verb|(bold,true)|. -Sometimes an attribute is treated as an instruction to add -that attribute, in which case an empty value means to -remove it. So \verb|(bold,)| removes the ``bold'' -attribute. Attributes are interned and given numeric IDs, -so the number ``\verb|6|'' could represent -``\verb|(bold,true)|'', for example. This mapping is -stored in an attribute pool which may be shared by -multiple changesets. - -Entries in the pool must be unique, so that attributes can -be compared by their IDs. Attribute names cannot contain -commas. - -A changeset looks something like the following: - -\begin{verbatim} -Z:5g>1|5=2p=v*4*5+1$x -\end{verbatim} - -With the corresponding pool containing these entries (among others): - -\begin{itemize} -\item[] \verb|4| $\rightarrow$ \verb|(author,1059348573)| -\item[] \verb|5| $\rightarrow$ \verb|(bold,true)| -\end{itemize} - -This changeset, together with the attribute pool, -represents inserting a bold letter ``x'' into the middle -of a line. - -The string consists of: - -\begin{itemize} -\item a letter \verb|Z| (the ``magic character'' and - format version identifier) -\item a series punctuation marks (operation codes or - ``opcodes'' for short), together with alphanumerics - (numeric values in base 36). -\item a dollar sign (\verb|$|) -\item a string of characters used for insertion operations - (the ``char bank'') -\end{itemize} - -In the example above, if we separate out the operations -and convert the numbers to base 10, then we get: -\begin{verbatim} -Z :196 >1 |5=97 =31 *4 *5 +1 $x -\end{verbatim} -Here are descriptions of the operations, where capital -letters are variables: - -\begin{description} -\item{{\bf :N}} \quad \\ -Source text has length $N$ (must be first op) -\item{{\bf >N}} \quad \\ -Final text is $N$ (positive) characters longer than source -text (must be second op) -\item{{\bf 0 }} \quad \\ -Final text is same length as source text -\item{{\bf +N }} \quad \\ -Insert $N$ characters from the bank, none of them newlines -\item{{\bf -N}} \quad \\ -Skip over (delete) $N$ characters from the source text, -none of them newlines -\item{{\bf =N}} \quad \\ -Keep $N$ characters from the source text, none of them newlines -\item{{\bf |L+N}} \quad \\ -Insert $N$ characters from the source text, containing $L$ -newlines. The last character inserted MUST be a newline, -but not the (new) document's final newline. -\item{{\bf |L-N}} \quad \\ -Delete $N$ characters from the source text, containing $L$ -newlines. The last character inserted MUST be a newline, -but not the (old) document's final newline. -\item{{\bf |L=N}} \quad \\ -Keep $N$ characters from the source text, containing L -newlines. The last character kept MUST be a newline, and -the final newline of the document is allowed. -\item{{\bf *I}} \quad \\ -Apply attribute $I$ from the pool to the following -\verb|+|, \verb|=|, \verb_|+_, or \verb_|=_ command. In -other words, any number of \verb|*| ops can come before a -\verb_+_, \verb_=_, or \verb_|_ but not between a \verb_|_ -and the corresponding \verb_+_ or \verb_=_. If \verb_+_, -text is inserted having this attribute. If \verb_=_, text -is kept but with the attribute applied as an attribute -addition or removal. Consecutive attributes must be sorted -lexically by (key,value) with key and value taken as -strings. It's illegal to have duplicate keys for -(key,value) pairs that apply to the same text. It's -illegal to have an empty value for a key in the case of an -insertion (\verb_+_), the pair should just be omitted. -\end{description} - -Characters from the source text that aren't accounted for -are assumed to be kept with the same attributes. - -\paragraph{Additional Constraints} - -\begin{itemize} -\item Consecutive \verb_+_, \verb_-_, and \verb_=_ ops of - the same type that could be combined are not allowed. - Whether combination is possible depends on the - attributes of the ops and whether each is multiline or - not. For example, two multiline deletions can never be - consecutive, nor can any insertion come after a - non-multiline insertion with the same attributes. -\item ``No-op'' ops are not allowed, such as deleting 0 - characters. However, attribute applications that don't - have any effect are allowed. -\item Characters at the end of the source text cannot be - explicitly kept with no changes; if the change doesn't - affect the last $N$ characters, those ``keep'' ops must - be left off. -\item In any consecutive sequence of insertions (\verb_+_) - and deletions (\verb_-_) with no keeps (\verb_=_), the - deletions must come before the insertions. -\item The document text before and after will always end - with a newline. This policy avoids a lot of - special-casing of the end of the document. If a final - newline is always added when importing text and removed - when exporting text, then the changeset representation - can be used to process text files that may or may not - have a final newline. -\end{itemize} - -\paragraph{Attribution string} - -An \emph{attribution string} is a series of inserts with -no deletions or keeps. For example, ``\verb_*3+8|1+5_'' -describes the attributes of a string of length 13, where -the first 8 chars have attribute 3 and the next 5 chars -have no attributes, with the last of these 5 chars being a -newline. Constraints apply similar to those affecting -changesets, but the restriction about the final newline of -the new document being added doesn't apply. - -Attributes in an attribution string cannot be empty, like -``\verb|(bold,)|'', they should instead be absent. - - -\section{Further Considerations} - -\begin{itemize} -\item composing changesets/attributions with different - pools. -\item generalizing ``applyToAttribution'' to make - ``mutateAttributionLines'' and ``compose'' -\end{itemize} - -\section{Using Unicode?} - -\begin{itemize} -\item no unicode (for efficient escaping, sightliness) -\item efficient operations for ACE and collab (attributed text, etc.) -\item good for time-slider -\item good for API -\item line-ending aware -X more coherent (deleting or styling text merging with insertion) -\item server-side syntax highlighting? -\item unify author map with attribute pool -\item unify attributed text with changeset rep -\item not: reversible -\item force final newline of document to be preserved -\end{itemize} - -\paragraph{Unicode bad!} - -\begin{itemize} -\item ugly (hard to read) -\item more complex to parse -\item harder to store and transmit correctly -\item doesn't save all that much space anyway -\item blows up in size when string-escaped -\item embarrassing for API -\end{itemize} - - -\end{document} diff --git a/sources/doc/easysync/easysync-notes.txt b/sources/doc/easysync/easysync-notes.txt deleted file mode 100644 index 72adadd..0000000 --- a/sources/doc/easysync/easysync-notes.txt +++ /dev/null @@ -1,133 +0,0 @@ - - -Copied from the old Etherpad. Found in /infrastructure/ace/ - -Goals: - -- no unicode (for efficient escaping, sightliness) -- efficient operations for ACE and collab (attributed text, etc.) -- good for time-slider -- good for API -- line-ending aware -X more coherent (deleting or styling text merging with insertion) -- server-side syntax highlighting? -- unify author map with attribute pool -- unify attributed text with changeset rep -- not: reversible -- force final newline of document to be preserved - -- Unicode bad: - - ugly (hard to read) - - more complex to parse - - harder to store and transmit correctly - - doesn't save all that much space anyway - - blows up in size when string-escaped - - embarrassing for API - - -# Attributes: - -An "attribute" is a (key,value) pair such as (author,abc123456) or -(bold,true). Sometimes an attribute is treated as an instruction to -add that attribute, in which case an empty value means to remove it. -So (bold,) removes the "bold" attribute. Attributes are interned and -given numeric IDs, so the number "6" could represent "(bold,true)", -for example. This mapping is stored in an attribute "pool" which may -be shared by multiple changesets. - -Entries in the pool must be unique, so that attributes can be compared -by their IDs. Attribute names cannot contain commas. - -A changeset looks something like the following: - -Z:5g>1|5=2p=v*4*5+1$x - -With the corresponding pool containing these entries: - -... -4 -> (author,1059348573) -5 -> (bold,true) -... - -This changeset, together with the pool, represents inserting -a bold letter "x" into the middle of a line. The string consists of: - -- a letter Z (the "magic character" and format version identifier) -- a series of opcodes (punctuation) and numeric values in base 36 (the - alphanumerics) -- a dollar sign ($) -- a string of characters used by insertion operations (the "char bank") - -If we separate out the operations and convert the numbers to base 10, we get: - -Z :196 >1 |5=97 =31 *4 *5 +1 $"x" - -Here are descriptions of the operations, where capital letters are variables: - -":N" : Source text has length N (must be first op) -">N" : Final text is N (positive) characters longer than source text (must be second op) -"0" : Final text is same length as source text -"+N" : Insert N characters from the bank, none of them newlines -"-N" : Skip over (delete) N characters from the source text, none of them newlines -"=N" : Keep N characters from the source text, none of them newlines -"|L+N" : Insert N characters from the source text, containing L newlines. The last - character inserted MUST be a newline, but not the (new) document's final newline. -"|L-N" : Delete N characters from the source text, containing L newlines. The last - character inserted MUST be a newline, but not the (old) document's final newline. -"|L=N" : Keep N characters from the source text, containing L newlines. The last character - kept MUST be a newline, and the final newline of the document is allowed. -"*I" : Apply attribute I from the pool to the following +, =, |+, or |= command. - In other words, any number of * ops can come before a +, =, or | but not - between a | and the corresponding + or =. - If +, text is inserted having this attribute. If =, text is kept but with - the attribute applied as an attribute addition or removal. - Consecutive attributes must be sorted lexically by (key,value) with key - and value taken as strings. It's illegal to have duplicate keys - for (key,value) pairs that apply to the same text. It's illegal to - have an empty value for a key in the case of an insertion (+), the - pair should just be omitted. - -Characters from the source text that aren't accounted for are assumed to be kept -with the same attributes. - -Additional Constraints: - -- Consecutive +, -, and = ops of the same type that could be combined are not allowed. - Whether combination is possible depends on the attributes of the ops and whether - each is multiline or not. For example, two multiline deletions can never be - consecutive, nor can any insertion come after a non-multiline insertion with the - same attributes. -- "No-op" ops are not allowed, such as deleting 0 characters. However, attribute - applications that don't have any effect are allowed. -- Characters at the end of the source text cannot be explicitly kept with no changes; - if the change doesn't affect the last N characters, those "keep" ops must be left off. -- In any consecutive sequence of insertions (+) and deletions (-) with no keeps (=), - the deletions must come before the insertions. -- The document text before and after will always end with a newline. This policy avoids - a lot of special-casing of the end of the document. If a final newline is - always added when importing text and removed when exporting text, then the - changeset representation can be used to process text files that may or may not - have a final newline. - -Attribution string: - -An "attribution string" is a series of inserts with no deletions or keeps. -For example, "*3+8|1+5" describes the attributes of a string of length 13, -where the first 8 chars have attribute 3 and the next 5 chars have no -attributes, with the last of these 5 chars being a newline. Constraints -apply similar to those affecting changesets, but the restriction about -the final newline of the new document being added doesn't apply. - -Attributes in an attribution string cannot be empty, like "(bold,)", they should -instead be absent. - - - - - -------- -Considerations: - -- composing changesets/attributions with different pools -- generalizing "applyToAttribution" to make "mutateAttributionLines" and "compose" diff --git a/sources/doc/index.md b/sources/doc/index.md deleted file mode 100644 index 09553f6..0000000 --- a/sources/doc/index.md +++ /dev/null @@ -1,7 +0,0 @@ -@include documentation -@include stats -@include localization -@include custom_static -@include api/api -@include plugins -@include database diff --git a/sources/doc/localization.md b/sources/doc/localization.md deleted file mode 100644 index ba247ea..0000000 --- a/sources/doc/localization.md +++ /dev/null @@ -1,94 +0,0 @@ -# Localization -Etherpad provides a multi-language user interface, that's apart from your users' content, so users from different countries can collaborate on a single document, while still having the user interface displayed in their mother tongue. - - -## Translating -We rely on https://translatewiki.net to handle the translation process for us, so if you'd like to help... - -1. Sign up at https://translatewiki.net -2. Visit our [TWN project page](https://translatewiki.net/wiki/Translating:Etherpad_lite) -3. Click on `Translate Etherpad lite interface` -4. Choose a target language, you'd like to translate our interface to, and hit `Fetch` -5. Start translating! - -Translations will be send back to us regularly and will eventually appear in the next release. - -## Implementation - -### Server-side -`/src/locales` contains files for all supported languages which contain the translated strings. Translation files are simple `*.json` files and look like this: - -```json -{ "pad.modals.connected": "Connecté." -, "pad.modals.uderdup": "Ouvrir dans une nouvelle fenêtre." -, "pad.toolbar.unindent.title": "Dèsindenter" -, "pad.toolbar.undo.title": "Annuler (Ctrl-Z)" -, "timeslider.pageTitle": "{{appTitle}} Curseur temporel" -, ... -} -``` - -Each translation consists of a key (the id of the string that is to be translated) and the translated string. Terms in curly braces must not be touched but left as they are, since they represent a dynamically changing part of the string like a variable. Imagine a message welcoming a user: `Welcome, {{userName}}!` would be translated as `Ahoy, {{userName}}!` in pirate. - -### Client-side -We use a `language` cookie to save your language settings if you change them. If you don't, we autodetect your locale using information from your browser. Then, the preferred language is fed into a library called [html10n.js](https://github.com/marcelklehr/html10n.js), which loads the appropriate translations and applies them to our templates. Its features include translation params, pluralization, include rules and a nice javascript API. - - - -## Localizing plugins - -### 1. Mark the strings to translate - -In the template files of your plugin, change all hardcoded messages/strings... - -from: -```html - -``` -to: -```html - -``` - -In the javascript files of your plugin, change all hardcoded messages/strings... - -from: -```js -alert ('Chat'); -``` -to: -```js -alert(window._('pad.chat')); -``` -### 2. Create translate files in the locales directory of your plugin - -* The name of the file must be the language code of the language it contains translations for (see [supported lang codes](https://joker-x.github.com/languages4translatewiki/test/); e.g. en ? English, es ? Spanish...) -* The extension of the file must be `.json` -* The default language is English, so your plugin should always provide `en.json` -* In order to avoid naming conflicts, your message keys should start with the name of your plugin followed by a dot (see below) - -*ep_your-plugin/locales/en.json* -``` -{ "ep_your-plugin.h1": "Heading 1" -} -``` - -*ep_your-plugin/locales/es.json* -``` -{ "ep_your-plugin.h1": "Título 1" -} -``` - -Every time the http server is started, it will auto-detect your messages and merge them automatically with the core messages. - -### Overwrite core messages - -You can overwrite Etherpad's core messages in your plugin's locale files. -For example, if you want to replace `Chat` with `Notes`, simply add... - -*ep_your-plugin/locales/en.json* -``` -{ "ep_your-plugin.h1": "Heading 1" -, "pad.chat": "Notes" -} -``` diff --git a/sources/doc/plugins.md b/sources/doc/plugins.md deleted file mode 100644 index e5b0040..0000000 --- a/sources/doc/plugins.md +++ /dev/null @@ -1,119 +0,0 @@ -# Plugins -Etherpad allows you to extend its functionality with plugins. A plugin registers hooks (functions) for certain events (thus certain features) in Etherpad-lite to execute its own functionality based on these events. - -Publicly available plugins can be found in the npm registry (see ). Etherpad-lite's naming convention for plugins is to prefix your plugins with `ep_`. So, e.g. it's `ep_flubberworms`. Thus you can install plugins from npm, using `npm install ep_flubberworm` in etherpad-lite's root directory. - -You can also browse to `http://yourEtherpadInstan.ce/admin/plugins`, which will list all installed plugins and those available on npm. It even provides functionality to search through all available plugins. - -## Folder structure -A basic plugin usually has the following folder structure: -``` -ep_/ - | static/ - | templates/ - | locales/ - + ep.json - + package.json -``` -If your plugin includes client-side hooks, put them in `static/js/`. If you're adding in CSS or image files, you should put those files in `static/css/ `and `static/image/`, respectively, and templates go into `templates/`. Translations go into `locales/` - -A Standard directory structure like this makes it easier to navigate through your code. That said, do note, that this is not actually *required* to make your plugin run. If you want to make use of our i18n system, you need to put your translations into `locales/`, though, in order to have them integrated. (See "Localization" for more info on how to localize your plugin) - -## Plugin definition -Your plugin definition goes into `ep.json`. In this file you register your hooks, indicate the parts of your plugin and the order of execution. (A documentation of all available events to hook into can be found in chapter [hooks](#all_hooks).) - -A hook registration is a pairs of a hook name and a function reference (filename to require() + exported function name) - -```json -{ - "parts": [ - { - "name": "nameThisPartHoweverYouWant", - "hooks": { - "authenticate" : "ep_/:FUNCTIONNAME1", - "expressCreateServer": "ep_/:FUNCTIONNAME2" - }, - "client_hooks": { - "acePopulateDOMLine": "ep_plugin/:FUNCTIONNAME3" - } - } - ] -} -``` - -Etherpad-lite will expect the part of the hook definition before the colon to be a javascript file and will try to require it. The part after the colon is expected to be a valid function identifier of that module. So, you have to export your hooks, using [`module.exports`](https://nodejs.org/docs/latest/api/modules.html#modules_modules) and register it in `ep.json` as `ep_/path/to/:FUNCTIONNAME`. -You can omit the `FUNCTIONNAME` part, if the exported function has got the same name as the hook. So `"authorize" : "ep_flubberworm/foo"` will call the function `exports.authorize` in `ep_flubberworm/foo.js` - -### Client hooks and server hooks -There are server hooks, which will be executed on the server (e.g. `expressCreateServer`), and there are client hooks, which are executed on the client (e.g. `acePopulateDomLine`). Be sure to not make assumptions about the environment your code is running in, e.g. don't try to access `process`, if you know your code will be run on the client, and likewise, don't try to access `window` on the server... - -### Parts -As your plugins become more and more complex, you will find yourself in the need to manage dependencies between plugins. E.g. you want the hooks of a certain plugin to be executed before (or after) yours. You can also manage these dependencies in your plugin definition file `ep.json`: - -```javascript -{ - "parts": [ - { - "name": "onepart", - "pre": [], - "post": ["ep_onemoreplugin/partone"] - "hooks": { - "storeBar": "ep_monospace/plugin:storeBar", - "getFoo": "ep_monospace/plugin:getFoo", - } - }, - { - "name": "otherpart", - "pre": ["ep_my_example/somepart", "ep_otherplugin/main"], - "post": [], - "hooks": { - "someEvent": "ep_my_example/otherpart:someEvent", - "another": "ep_my_example/otherpart:another" - } - } - ] -} -``` - -Usually a plugin will add only one functionality at a time, so it will probably only use one `part` definition to register its hooks. However, sometimes you have to put different (unrelated) functionalities into one plugin. For this you will want use parts, so other plugins can depend on them. - -#### pre/post -The `"pre"` and `"post"` definitions, affect the order in which parts of a plugin are executed. This ensures that plugins and their hooks are executed in the correct order. - -`"pre"` lists parts that must be executed *before* the defining part. `"post"` lists parts that must be executed *after* the defining part. - -You can, on a basic level, think of this as double-ended dependency listing. If you have a dependency on another plugin, you can make sure it loads before yours by putting it in `"pre"`. If you are setting up things that might need to be used by a plugin later, you can ensure proper order by putting it in `"post"`. - -Note that it would be far more sane to use `"pre"` in almost any case, but if you want to change config variables for another plugin, or maybe modify its environment, `"post"` could definitely be useful. - -Also, note that dependencies should *also* be listed in your package.json, so they can be `npm install`'d automagically when your plugin gets installed. - -## Package definition -Your plugin must also contain a [package definition file](https://docs.npmjs.com/files/package.json), called package.json, in the project root - this file contains various metadata relevant to your plugin, such as the name and version number, author, project hompage, contributors, a short description, etc. If you publish your plugin on npm, these metadata are used for package search etc., but it's necessary for Etherpad-lite plugins, even if you don't publish your plugin. - -```json -{ - "name": "ep_PLUGINNAME", - "version": "0.0.1", - "description": "DESCRIPTION", - "author": "USERNAME (REAL NAME) ", - "contributors": [], - "dependencies": {"MODULE": "0.3.20"}, - "engines": { "node": ">= 0.6.0"} -} -``` - -## Templates -If your plugin adds or modifies the front end HTML (e.g. adding buttons or changing their functions), you should put the necessary HTML code for such operations in `templates/`, in files of type ".ejs", since Etherpad uses EJS for HTML templating. See the following link for more information about EJS: . - -## Writing and running front-end tests for your plugin - -Etherpad allows you to easily create front-end tests for plugins. - -1. Create a new folder -``` -%your_plugin%/static/tests/frontend/specs -``` -2. Put your spec file in here (Example spec files are visible in %etherpad_root_folder%/frontend/tests/specs) - -3. Visit http://yourserver.com/frontend/tests your front-end tests will run. diff --git a/sources/doc/stats.md b/sources/doc/stats.md deleted file mode 100644 index 7da6954..0000000 --- a/sources/doc/stats.md +++ /dev/null @@ -1,18 +0,0 @@ -# Statistics -Etherpad keeps track of the goings-on inside the edit machinery. If you'd like to have a look at this, just point your browser to `/stats`. - -We currently measure: - - - totalUsers (counter) - - connects (meter) - - disconnects (meter) - - pendingEdits (counter) - - edits (timer) - - failedChangesets (meter) - - httpRequests (timer) - - http500 (meter) - - memoryUsage (gauge) - -Under the hood, we are happy to rely on [measured](https://github.com/felixge/node-measured) for all our metrics needs. - -To modify or simply access our stats in your plugin, simply `require('ep_etherpad-lite/stats')` which is a `measured.Collection`. \ No newline at end of file diff --git a/sources/doc/template.html b/sources/doc/template.html deleted file mode 100644 index 2670632..0000000 --- a/sources/doc/template.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - __SECTION__ - Etherpad v__VERSION__ Manual & Documentation - - - - - -
        -

        Table of Contents

        - __TOC__ -
        - -
        - __CONTENT__ -
        - - - diff --git a/sources/settings.json.template b/sources/settings.json.template deleted file mode 100644 index 699880b..0000000 --- a/sources/settings.json.template +++ /dev/null @@ -1,271 +0,0 @@ -/* - This file must be valid JSON. But comments are allowed - - Please edit settings.json, not settings.json.template - - To still commit settings without credentials you can - store any credential settings in credentials.json -*/ -{ - // Name your instance! - "title": "Etherpad", - - // favicon default name - // alternatively, set up a fully specified Url to your own favicon - "favicon": "favicon.ico", - - //IP and port which etherpad should bind at - "ip": "0.0.0.0", - "port" : 9001, - - // Option to hide/show the settings.json in admin page, default option is set to true - "showSettingsInAdminPage" : true, - - /* - // Node native SSL support - // this is disabled by default - // - // make sure to have the minimum and correct file access permissions set - // so that the Etherpad server can access them - - "ssl" : { - "key" : "/path-to-your/epl-server.key", - "cert" : "/path-to-your/epl-server.crt", - "ca": ["/path-to-your/epl-intermediate-cert1.crt", "/path-to-your/epl-intermediate-cert2.crt"] - }, - - */ - - //The Type of the database. You can choose between dirty, postgres, sqlite and mysql - //You shouldn't use "dirty" for for anything else than testing or development - "dbType" : "dirty", - //the database specific settings - "dbSettings" : { - "filename" : "var/dirty.db" - }, - - /* An Example of MySQL Configuration - "dbType" : "mysql", - "dbSettings" : { - "user" : "root", - "host" : "localhost", - "password": "", - "database": "store", - "charset" : "utf8mb4" - }, - */ - - //the default text of a pad - "defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n", - - /* Default Pad behavior, users can override by changing */ - "padOptions": { - "noColors": false, - "showControls": true, - "showChat": true, - "showLineNumbers": true, - "useMonospaceFont": false, - "userName": false, - "userColor": false, - "rtl": false, - "alwaysShowChat": false, - "chatAndUsers": false, - "lang": "en-gb" - }, - - /* Pad Shortcut Keys */ - "padShortcutEnabled" : { - "altF9" : true, /* focus on the File Menu and/or editbar */ - "altC" : true, /* focus on the Chat window */ - "cmdShift2" : true, /* shows a gritter popup showing a line author */ - "delete" : true, - "return" : true, - "esc" : true, /* in mozilla versions 14-19 avoid reconnecting pad */ - "cmdS" : true, /* save a revision */ - "tab" : true, /* indent */ - "cmdZ" : true, /* undo/redo */ - "cmdY" : true, /* redo */ - "cmdI" : true, /* italic */ - "cmdB" : true, /* bold */ - "cmdU" : true, /* underline */ - "cmd5" : true, /* strike through */ - "cmdShiftL" : true, /* unordered list */ - "cmdShiftN" : true, /* ordered list */ - "cmdShift1" : true, /* ordered list */ - "cmdShiftC" : true, /* clear authorship */ - "cmdH" : true, /* backspace */ - "ctrlHome" : true, /* scroll to top of pad */ - "pageUp" : true, - "pageDown" : true - }, - - /* Should we suppress errors from being visible in the default Pad Text? */ - "suppressErrorsInPadText" : false, - - /* Users must have a session to access pads. This effectively allows only group pads to be accessed. */ - "requireSession" : false, - - /* Users may edit pads but not create new ones. Pad creation is only via the API. This applies both to group pads and regular pads. */ - "editOnly" : false, - - /* Users, who have a valid session, automatically get granted access to password protected pads */ - "sessionNoPassword" : false, - - /* if true, all css & js will be minified before sending to the client. This will improve the loading performance massivly, - but makes it impossible to debug the javascript/css */ - "minify" : true, - - /* How long may clients use served javascript code (in seconds)? Without versioning this - may cause problems during deployment. Set to 0 to disable caching */ - "maxAge" : 21600, // 60 * 60 * 6 = 6 hours - - /* This is the absolute path to the Abiword executable. Setting it to null, disables abiword. - Abiword is needed to advanced import/export features of pads*/ - "abiword" : null, - - /* This is the absolute path to the soffice executable. Setting it to null, disables LibreOffice exporting. - LibreOffice can be used in lieu of Abiword to export pads */ - "soffice" : null, - - /* This is the path to the Tidy executable. Setting it to null, disables Tidy. - Tidy is used to improve the quality of exported pads*/ - "tidyHtml" : null, - - /* Allow import of file types other than the supported types: txt, doc, docx, rtf, odt, html & htm */ - "allowUnknownFileEnds" : true, - - /* This setting is used if you require authentication of all users. - Note: /admin always requires authentication. */ - "requireAuthentication" : false, - - /* Require authorization by a module, or a user with is_admin set, see below. */ - "requireAuthorization" : false, - - /*when you use NginX or another proxy/ load-balancer set this to true*/ - "trustProxy" : false, - - /* Privacy: disable IP logging */ - "disableIPlogging" : false, - - /* Time (in seconds) to automatically reconnect pad when a "Force reconnect" - message is shown to user. Set to 0 to disable automatic reconnection */ - "automaticReconnectionTimeout" : 0, - /* - * By default, when caret is moved out of viewport, it scrolls the minimum height needed to make this - * line visible. - */ - "scrollWhenFocusLineIsOutOfViewport": { - /* - * Percentage of viewport height to be additionally scrolled. - * E.g use "percentage.editionAboveViewport": 0.5, to place caret line in the - * middle of viewport, when user edits a line above of the viewport - * Set to 0 to disable extra scrolling - */ - "percentage": { - "editionAboveViewport": 0, - "editionBelowViewport": 0 - }, - /* Time (in milliseconds) used to animate the scroll transition. Set to 0 to disable animation */ - "duration": 0, - /* - * Flag to control if it should scroll when user places the caret in the last line of the viewport - */ - "scrollWhenCaretIsInTheLastLineOfViewport": false, - /* - * Percentage of viewport height to be additionally scrolled when user presses arrow up - * in the line of the top of the viewport. - * Set to 0 to let the scroll to be handled as default by the Etherpad - */ - "percentageToScrollWhenUserPressesArrowUp": 0 - }, - - /* Users for basic authentication. is_admin = true gives access to /admin. - If you do not uncomment this, /admin will not be available! */ - /* - "users": { - "admin": { - "password": "changeme1", - "is_admin": true - }, - "user": { - "password": "changeme1", - "is_admin": false - } - }, - */ - - // restrict socket.io transport methods - "socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"], - - // Allow Load Testing tools to hit the Etherpad Instance. Warning this will disable security on the instance. - "loadTest": false, - - // Disable indentation on new line when previous line ends with some special chars (':', '[', '(', '{') - /* - "indentationOnNewLine": false, - */ - - /* The toolbar buttons configuration. - "toolbar": { - "left": [ - ["bold", "italic", "underline", "strikethrough"], - ["orderedlist", "unorderedlist", "indent", "outdent"], - ["undo", "redo"], - ["clearauthorship"] - ], - "right": [ - ["importexport", "timeslider", "savedrevision"], - ["settings", "embed"], - ["showusers"] - ], - "timeslider": [ - ["timeslider_export", "timeslider_returnToPad"] - ] - }, - */ - - /* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */ - "loglevel": "INFO", - - //Logging configuration. See log4js documentation for further information - // https://github.com/nomiddlename/log4js-node - // You can add as many appenders as you want here: - "logconfig" : - { "appenders": [ - { "type": "console" - //, "category": "access"// only logs pad access - } - /* - , { "type": "file" - , "filename": "your-log-file-here.log" - , "maxLogSize": 1024 - , "backups": 3 // how many log files there're gonna be at max - //, "category": "test" // only log a specific category - }*/ - /* - , { "type": "logLevelFilter" - , "level": "warn" // filters out all log messages that have a lower level than "error" - , "appender": - { Use whatever appender you want here } - }*/ - /* - , { "type": "logLevelFilter" - , "level": "error" // filters out all log messages that have a lower level than "error" - , "appender": - { "type": "smtp" - , "subject": "An error occurred in your EPL instance!" - , "recipients": "bar@blurdybloop.com, baz@blurdybloop.com" - , "sendInterval": 300 // 60 * 5 = 5 minutes -- will buffer log messages; set to 0 to send a mail for every message - , "transport": "SMTP", "SMTP": { // see https://github.com/andris9/Nodemailer#possible-transport-methods - "host": "smtp.example.com", "port": 465, - "secureConnection": true, - "auth": { - "user": "foo@example.com", - "pass": "bar_foo" - } - } - } - }*/ - ] - } -} diff --git a/sources/src/README.md b/sources/src/README.md deleted file mode 100644 index 8010996..0000000 --- a/sources/src/README.md +++ /dev/null @@ -1 +0,0 @@ -Ignore this file and see the file in the base installation folder diff --git a/sources/src/ep.json b/sources/src/ep.json deleted file mode 100644 index eeb5c64..0000000 --- a/sources/src/ep.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "parts": [ - { "name": "express", "hooks": { - "createServer": "ep_etherpad-lite/node/hooks/express:createServer", - "restartServer": "ep_etherpad-lite/node/hooks/express:restartServer" - } }, - { "name": "static", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/static:expressCreateServer" } }, - { "name": "i18n", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/i18n:expressCreateServer" } }, - { "name": "specialpages", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/specialpages:expressCreateServer" } }, - { "name": "padurlsanitize", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/padurlsanitize:expressCreateServer" } }, - { "name": "padreadonly", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/padreadonly:expressCreateServer" } }, - { "name": "webaccess", "hooks": { "expressConfigure": "ep_etherpad-lite/node/hooks/express/webaccess:expressConfigure" } }, - { "name": "apicalls", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/apicalls:expressCreateServer" } }, - { "name": "importexport", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/importexport:expressCreateServer" } }, - { "name": "errorhandling", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/errorhandling:expressCreateServer" } }, - { "name": "socketio", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/socketio:expressCreateServer" } }, - { "name": "tests", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/tests:expressCreateServer" } }, - { "name": "admin", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/admin:expressCreateServer" } }, - { "name": "adminplugins", "hooks": { - "expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminplugins:expressCreateServer", - "socketio": "ep_etherpad-lite/node/hooks/express/adminplugins:socketio" } - }, - { "name": "adminsettings", "hooks": { - "expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminsettings:expressCreateServer", - "socketio": "ep_etherpad-lite/node/hooks/express/adminsettings:socketio" } - }, - { "name": "swagger", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/swagger:expressCreateServer" } } - ] -} diff --git a/sources/src/etherpad_icon.svg b/sources/src/etherpad_icon.svg deleted file mode 100644 index ebdcde9..0000000 --- a/sources/src/etherpad_icon.svg +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sources/src/locales/af.json b/sources/src/locales/af.json deleted file mode 100644 index 1a9ce4c..0000000 --- a/sources/src/locales/af.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Naudefj", - "Fwolff" - ] - }, - "index.newPad": "Nuwe pad", - "index.createOpenPad": "of skep/open 'n pad met die naam:", - "pad.toolbar.bold.title": "Vet (Ctrl-B)", - "pad.toolbar.italic.title": "Kursief (Ctrl-I)", - "pad.toolbar.underline.title": "Onderstreep (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Deurgehaal (Ctrl+5)", - "pad.toolbar.ol.title": "Geordende lys (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Ongeordende lys (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Indenteer (TAB)", - "pad.toolbar.unindent.title": "Verklein indentering (Shift+TAB)", - "pad.toolbar.undo.title": "Ongedaan maak (Ctrl-Z)", - "pad.toolbar.redo.title": "Herdoen (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Verwyder skrywers se kleure (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Voer in/uit van/na verskillende lêerformate", - "pad.toolbar.settings.title": "Voorkeure", - "pad.colorpicker.save": "Stoor", - "pad.colorpicker.cancel": "Kanselleer", - "pad.loading": "Laai...", - "pad.settings.myView": "My oorsig", - "pad.settings.fontType.normal": "Normaal", - "pad.settings.fontType.monospaced": "Monospasie", - "pad.settings.language": "Taal:", - "pad.importExport.import_export": "Voer in/uit", - "pad.importExport.import": "Laai enige tekslêer of dokument op", - "pad.importExport.importSuccessful": "Sukses!", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Skoon teks", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document-formaat)", - "pad.modals.cancel": "Kanselleer", - "pad.modals.userdup.advice": "Maak weer 'n verbinding as u die venster wil gebruik.", - "pad.modals.unauth": "Nie toegestaan", - "pad.modals.deleted": "Geskrap.", - "pad.share": "Deel die pad", - "pad.share.readonly": "Lees-alleen", - "pad.share.link": "Skakel", - "pad.share.emebdcode": "Inbed URL", - "pad.chat": "Klets", - "pad.chat.title": "Maak kletsblad vir die pad oop", - "timeslider.toolbar.returnbutton": "Terug na pad", - "timeslider.toolbar.authors": "Outeurs:", - "timeslider.toolbar.authorsList": "Geen outeurs", - "timeslider.exportCurrent": "Huidige weergawe eksporteer as:", - "timeslider.version": "Weergawe {{version}}", - "timeslider.saved": "Gestoor op {{day}} {{month}} {{year}}", - "timeslider.dateformat": "{{year}}-{{month}}-{{day}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januarie", - "timeslider.month.february": "Februarie", - "timeslider.month.march": "Maart", - "timeslider.month.april": "April", - "timeslider.month.may": "Mei", - "timeslider.month.june": "Junie", - "timeslider.month.july": "Julie", - "timeslider.month.august": "Augustus", - "timeslider.month.september": "September", - "timeslider.month.october": "Oktober", - "timeslider.month.november": "November", - "timeslider.month.december": "Desember", - "pad.userlist.entername": "Verskaf u naam", - "pad.userlist.unnamed": "sonder naam", - "pad.userlist.guest": "Gas", - "pad.userlist.deny": "Keur af", - "pad.userlist.approve": "Keur goed", - "pad.impexp.importbutton": "Voer nou in", - "pad.impexp.importing": "Besig met invoer...", - "pad.impexp.importfailed": "Invoer het gefaal" -} diff --git a/sources/src/locales/ar.json b/sources/src/locales/ar.json deleted file mode 100644 index 39ec236..0000000 --- a/sources/src/locales/ar.json +++ /dev/null @@ -1,140 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Ali1", - "Tux-tn", - "Alami", - "Meno25", - "Test Create account", - "محمد أحمد عبد الفتاح", - "Haytham morsy", - "ديفيد", - "Mido", - "Shbib Al-Subaie" - ] - }, - "index.newPad": "باد جديد", - "index.createOpenPad": "أو صنع/فتح باد بوضع اسمه:", - "pad.toolbar.bold.title": "سميك (Ctrl-B)", - "pad.toolbar.italic.title": "مائل (Ctrl-I)", - "pad.toolbar.underline.title": "تسطير (Ctrl-U)", - "pad.toolbar.strikethrough.title": "شطب (Ctrl+5)", - "pad.toolbar.ol.title": "قائمة مرتبة (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "قائمة غير مرتبة (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "إزاحة", - "pad.toolbar.unindent.title": "حذف الإزاحة", - "pad.toolbar.undo.title": "فك (Ctrl-Z)", - "pad.toolbar.redo.title": "تكرار (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "مسح ألوان التأليف (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "استيراد/تصدير من/إلى تنسيقات ملفات مختلفة", - "pad.toolbar.timeslider.title": "متصفح التاريخ", - "pad.toolbar.savedRevision.title": "حفظ المراجعة", - "pad.toolbar.settings.title": "الإعدادات", - "pad.toolbar.embed.title": "تبادل و تضمين هذا الباد", - "pad.toolbar.showusers.title": "عرض المستخدمين على هذا الباد", - "pad.colorpicker.save": "تسجيل", - "pad.colorpicker.cancel": "إلغاء", - "pad.loading": "جارٍ التحميل...", - "pad.noCookie": "الكوكيز غير متاحة. الرجاء السماح بتحميل الكوكيز على متصفحك!", - "pad.passwordRequired": "تحتاج إلى كلمة مرور للوصول إلى هذا الباد", - "pad.permissionDenied": "ليس لديك إذن لدخول هذا الباد", - "pad.wrongPassword": "كانت كلمة المرور خاطئة", - "pad.settings.padSettings": "إعدادات الباد", - "pad.settings.myView": "رؤيتي", - "pad.settings.stickychat": "الدردشة دائما على الشاشة", - "pad.settings.chatandusers": "أظهر الدردشة والمستخدمين", - "pad.settings.colorcheck": "ألوان التأليف", - "pad.settings.linenocheck": "أرقام الأسطر", - "pad.settings.rtlcheck": "قراءة المحتويات من اليمين إلى اليسار؟", - "pad.settings.fontType": "نوع الخط:", - "pad.settings.fontType.normal": "عادي", - "pad.settings.fontType.monospaced": "ثابت العرض", - "pad.settings.globalView": "الرؤية الشاملة", - "pad.settings.language": "اللغة:", - "pad.importExport.import_export": "استيراد/تصدير", - "pad.importExport.import": "تحميل أي ملف نصي أو وثيقة", - "pad.importExport.importSuccessful": "ناجح!", - "pad.importExport.export": "تصدير الباد الحالي بصفة:", - "pad.importExport.exportetherpad": "إيثرباد", - "pad.importExport.exporthtml": "إتش تي إم إل", - "pad.importExport.exportplain": "نص عادي", - "pad.importExport.exportword": "مايكروسوفت وورد", - "pad.importExport.exportpdf": "صيغة المستندات المحمولة", - "pad.importExport.exportopen": "ODF (نسق المستند المفتوح)", - "pad.importExport.abiword.innerHTML": "لايمكنك الاستيراد إلا من نص عادي أو من تنسيقات إتش تي إم إل. للحصول على المزيد من ميزات الاستيراد المتقدمة، يرجى تثبيت أبيورد .", - "pad.modals.connected": "متصل.", - "pad.modals.reconnecting": "إعادة الاتصال ببادك", - "pad.modals.forcereconnect": "فرض إعادة الاتصال", - "pad.modals.reconnecttimer": "حاول إعادة الاتصال", - "pad.modals.cancel": "إلغاء", - "pad.modals.userdup": "مفتوح في نافذة أخرى", - "pad.modals.userdup.explanation": "يبدو أن هذا الباد تم فتحه في أكثر من نافذة متصفح في هذا الحاسوب.", - "pad.modals.userdup.advice": "إعادة الاتصال لاستعمال هذه النافذة بدلاً من الأخرى.", - "pad.modals.unauth": "غير مخول", - "pad.modals.unauth.explanation": "لقد تغيرت الأذونات الخاصة بك أثناء عرض هذه الصفحة. أعد محاولة الاتصال.", - "pad.modals.looping.explanation": "هناك مشاكل في الاتصال مع ملقم التزامن.", - "pad.modals.looping.cause": "ربما كنت متصلاً من خلال وكيل أو جدار حماية غير متوافق.", - "pad.modals.initsocketfail": "لا يمكن الوصول إلى الخادم", - "pad.modals.initsocketfail.explanation": "تعذر الاتصال بخادم المزامنة.", - "pad.modals.initsocketfail.cause": "هذا على الأرجح بسبب مشكلة في المستعرض الخاص بك أو الاتصال بإنترنت.", - "pad.modals.slowcommit.explanation": "الخادم لا يستجيب.", - "pad.modals.slowcommit.cause": "يمكن أن يكون هذا بسبب مشاكل في الاتصال بالشبكة.", - "pad.modals.badChangeset.explanation": "لقد صُنفَت إحدى عمليات التحرير التي قمت بها كعملية غير مسموح بها من قبل ملقم التزامن.", - "pad.modals.badChangeset.cause": "يمكن أن يكون هذا بسبب تكوين ملقم خاطئ أو بسبب سلوك آخر غير متوقع. يرجى الاتصال بمسؤول الخدمة إذا كنت تعتقد بأن هناك خطأ ما. حاول إعادة الاتصال لمتابعة التحرير.", - "pad.modals.corruptPad.explanation": "الباد الذي تحاول الوصول إليه تالف.", - "pad.modals.corruptPad.cause": "قد يكون هذا بسبب تكوين ملقم خاطئ أو بسبب سلوك آخر غير متوقع. يرجى الاتصال بمسؤول الخدمة.", - "pad.modals.deleted": "محذوف.", - "pad.modals.deleted.explanation": "تمت إزالة هذا الباد", - "pad.modals.disconnected": "لم تعد متصلا.", - "pad.modals.disconnected.explanation": "تم فقدان الاتصال بالخادم", - "pad.modals.disconnected.cause": "قد يكون الخادم غير متوفر. يرجى إعلام مسؤول الخدمة إذا كان هذا لا يزال يحدث.", - "pad.share": "شارك هذه الباد", - "pad.share.readonly": "للقراءة فقط", - "pad.share.link": "رابط", - "pad.share.emebdcode": "URL للتضمين", - "pad.chat": "دردشة", - "pad.chat.title": "فتح الدردشة لهذا الباد", - "pad.chat.loadmessages": "تحميل المزيد من الرسائل", - "timeslider.pageTitle": "{{appTitle}} متصفح التاريخ", - "timeslider.toolbar.returnbutton": "العودة إلى الباد", - "timeslider.toolbar.authors": "المؤلفون:", - "timeslider.toolbar.authorsList": "بدون مؤلفين", - "timeslider.toolbar.exportlink.title": "تصدير", - "timeslider.exportCurrent": "تصدير النسخة الحالية ك:", - "timeslider.version": "إصدار {{version}}", - "timeslider.saved": "محفوظ {{month}} {{day}}, {{year}}", - "timeslider.playPause": "تشغيل / إيقاف مؤقت لمحتويات الباد", - "timeslider.backRevision": "عد إلى مراجعة في هذه الباد", - "timeslider.forwardRevision": "انطلق إلى مراجعة في هذه الباد", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "يناير", - "timeslider.month.february": "فبراير", - "timeslider.month.march": "مارس", - "timeslider.month.april": "أبريل", - "timeslider.month.may": "مايو", - "timeslider.month.june": "يونيو", - "timeslider.month.july": "يوليو", - "timeslider.month.august": "أغسطس", - "timeslider.month.september": "سبتمبر", - "timeslider.month.october": "أكتوبر", - "timeslider.month.november": "نوفمبر", - "timeslider.month.december": "ديسمبر", - "timeslider.unnamedauthors": "بدون اسم {{num}} {[plural(num) واحد: كاتب، آخر: مؤلف]}", - "pad.savedrevs.marked": "هذا التنقيح محدد الآن كمراجعة محفوظة", - "pad.savedrevs.timeslider": "يمكنك عرض المراجعات المحفوظة بزيارة متصفح التاريخ", - "pad.userlist.entername": "أدخل اسمك", - "pad.userlist.unnamed": "غير مسمى", - "pad.userlist.guest": "ضيف", - "pad.userlist.deny": "رفض", - "pad.userlist.approve": "موافقة", - "pad.editbar.clearcolors": "مسح ألوان التأليف أو المستند بأكمله؟", - "pad.impexp.importbutton": "الاستيراد الآن", - "pad.impexp.importing": "الاستيراد...", - "pad.impexp.confirmimport": "استيراد ملف سيؤدي للكتابة فوق النص الحالي بالباد. هل أنت متأكد من أنك تريد المتابعة؟", - "pad.impexp.convertFailed": "لم نتمكن من استيراد هذا الملف. يرجى استخدام تنسيق مستند مختلف، أو النسخ واللصق يدوياً", - "pad.impexp.padHasData": "لا يمكننا استيراد هذا الملف لأن هذا الباد تم بالفعل تغييره; الرجاء استيراد باد جديد", - "pad.impexp.uploadFailed": "فشل التحميل، الرجاء المحاولة مرة أخرى", - "pad.impexp.importfailed": "فشل الاستيراد", - "pad.impexp.copypaste": "الرجاء نسخ/لصق", - "pad.impexp.exportdisabled": "تصدير التنسيق {{type}} معطل. يرجى الاتصال بمسؤول النظام الخاص بك للحصول على التفاصيل." -} diff --git a/sources/src/locales/ast.json b/sources/src/locales/ast.json deleted file mode 100644 index f1fd2f5..0000000 --- a/sources/src/locales/ast.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Xuacu" - ] - }, - "index.newPad": "Nuevu bloc", - "index.createOpenPad": "o crear/abrir un bloc col nome:", - "pad.toolbar.bold.title": "Negrina (Ctrl-B)", - "pad.toolbar.italic.title": "Cursiva (Ctrl-I)", - "pad.toolbar.underline.title": "Sorrayáu (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Tacháu (Ctrl+5)", - "pad.toolbar.ol.title": "Llista ordenada (Ctrl+Mayús+N)", - "pad.toolbar.ul.title": "Llista desordenada (Ctrl+Mayús+L)", - "pad.toolbar.indent.title": "Sangría (TAB)", - "pad.toolbar.unindent.title": "Sangría inversa (Mayúsc+TAB)", - "pad.toolbar.undo.title": "Desfacer (Ctrl-Z)", - "pad.toolbar.redo.title": "Refacer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Llimpiar los colores d'autoría (Ctrl+Mayús+C)", - "pad.toolbar.import_export.title": "Importar/Esportar ente distintos formatos de ficheru", - "pad.toolbar.timeslider.title": "Eslizador de tiempu", - "pad.toolbar.savedRevision.title": "Guardar revisión", - "pad.toolbar.settings.title": "Configuración", - "pad.toolbar.embed.title": "Compartir ya incrustar esti bloc", - "pad.toolbar.showusers.title": "Amosar los usuarios d'esti bloc", - "pad.colorpicker.save": "Guardar", - "pad.colorpicker.cancel": "Encaboxar", - "pad.loading": "Cargando...", - "pad.noCookie": "Nun pudo alcontrase la cookie. ¡Por favor, permite les cookies nel navegador!", - "pad.passwordRequired": "Necesites una contraseña pa entrar a esti bloc", - "pad.permissionDenied": "Nun tienes permisu pa entrar a esti bloc", - "pad.wrongPassword": "La contraseña era incorreuta", - "pad.settings.padSettings": "Configuración del bloc", - "pad.settings.myView": "la mio vista", - "pad.settings.stickychat": "Alderique en pantalla siempres", - "pad.settings.chatandusers": "Amosar la charra y los usuarios", - "pad.settings.colorcheck": "Colores d'autoría", - "pad.settings.linenocheck": "Númberos de llinia", - "pad.settings.rtlcheck": "¿Lleer el conteníu de drecha a izquierda?", - "pad.settings.fontType": "Tipografía:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespaciada", - "pad.settings.globalView": "Vista global", - "pad.settings.language": "Llingua:", - "pad.importExport.import_export": "Importar/Esportar", - "pad.importExport.import": "Xubir cualquier ficheru o documentu de testu", - "pad.importExport.importSuccessful": "¡Correuto!", - "pad.importExport.export": "Esportar el bloc actual como:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Testu simple", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Sólo se pue importar dende los formatos de testu planu o html. Pa carauterístiques d'importación más avanzaes instala abiword.", - "pad.modals.connected": "Coneutáu.", - "pad.modals.reconnecting": "Reconeutando col to bloc...", - "pad.modals.forcereconnect": "Forzar la reconexón", - "pad.modals.reconnecttimer": "Tentando reconeutar en", - "pad.modals.cancel": "Encaboxar", - "pad.modals.userdup": "Abiertu n'otra ventana", - "pad.modals.userdup.explanation": "Esti bloc paez que ta abiertu en más d'una ventana del navegador d'esti ordenador.", - "pad.modals.userdup.advice": "Reconeutar pa usar esta ventana.", - "pad.modals.unauth": "Non autorizáu", - "pad.modals.unauth.explanation": "Los tos permisos camudaron mientres vies esta páxina. Intenta volver a coneutar.", - "pad.modals.looping.explanation": "Hai problemes de comunicación col sirvidor de sincronización.", - "pad.modals.looping.cause": "Pues tar coneutáu per un torgafueos o un proxy incompatibles.", - "pad.modals.initsocketfail": "Sirvidor incalcanzable.", - "pad.modals.initsocketfail.explanation": "Nun se pudo coneutar col sirvidor de sincronización.", - "pad.modals.initsocketfail.cause": "Probablemente ye por aciu d'un problema col navegador o cola to conexón a internet.", - "pad.modals.slowcommit.explanation": "El sirvidor nun respuende.", - "pad.modals.slowcommit.cause": "Pue ser por problemes de coneutividá de la rede.", - "pad.modals.badChangeset.explanation": "El sirvidor de sincronización clasificó como illegal una edición que fizo.", - "pad.modals.badChangeset.cause": "Esto podría dase por una mala configuración del sirvidor o por algún otru comportamientu inesperáu. Comuníquese col alministrador del serviciu si cree qu'esto ye un error. Intente volver a coneutar pa siguir editando.", - "pad.modals.corruptPad.explanation": "El bloc al qu'intenta entrar ta corrompíu.", - "pad.modals.corruptPad.cause": "Esto pue ser por una mala configuración del sirvidor o por algún otru comportamientu inesperáu. Comuníquese col alministrador del serviciu.", - "pad.modals.deleted": "Desaniciáu", - "pad.modals.deleted.explanation": "Esti bloc se desanició.", - "pad.modals.disconnected": "Te desconeutasti.", - "pad.modals.disconnected.explanation": "Perdióse la conexón col sirvidor", - "pad.modals.disconnected.cause": "El sirvidor podría nun tar disponible. Por favor, avise al alministrador del serviciu si sigue pasando esto.", - "pad.share": "Compartir esti bloc", - "pad.share.readonly": "Sólo llectura", - "pad.share.link": "Enllaz", - "pad.share.emebdcode": "Incrustar URL", - "pad.chat": "Chat", - "pad.chat.title": "Abrir el chat d'esti bloc.", - "pad.chat.loadmessages": "Cargar más mensaxes", - "timeslider.pageTitle": "Eslizador de tiempu de {{appTitle}}", - "timeslider.toolbar.returnbutton": "Tornar al bloc", - "timeslider.toolbar.authors": "Autores:", - "timeslider.toolbar.authorsList": "Nun hai autores", - "timeslider.toolbar.exportlink.title": "Esportar", - "timeslider.exportCurrent": "Esportar la versión actual como:", - "timeslider.version": "Versión {{version}}", - "timeslider.saved": "Guardáu el {{day}} de {{month}} de {{year}}", - "timeslider.playPause": "Reproducir/posar el conteníu del bloc", - "timeslider.backRevision": "Dir a la revisión anterior d'esti bloc", - "timeslider.forwardRevision": "Dir a la revisión siguiente d'esti bloc", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "de xineru", - "timeslider.month.february": "de febreru", - "timeslider.month.march": "de marzu", - "timeslider.month.april": "d'abril", - "timeslider.month.may": "de mayu", - "timeslider.month.june": "de xunu", - "timeslider.month.july": "de xunetu", - "timeslider.month.august": "d'agostu", - "timeslider.month.september": "de setiembre", - "timeslider.month.october": "d'ochobre", - "timeslider.month.november": "de payares", - "timeslider.month.december": "d'avientu", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor anónimu, other: autores anónimos]}", - "pad.savedrevs.marked": "Esta revisión marcose como revisión guardada", - "pad.savedrevs.timeslider": "Pues ver les revisiones guardaes visitando la llinia temporal", - "pad.userlist.entername": "Escribi'l to nome", - "pad.userlist.unnamed": "ensin nome", - "pad.userlist.guest": "Invitáu", - "pad.userlist.deny": "Refugar", - "pad.userlist.approve": "Aprobar", - "pad.editbar.clearcolors": "¿Llimpiar los colores d'autoría nel documentu ensembre?", - "pad.impexp.importbutton": "Importar agora", - "pad.impexp.importing": "Importando...", - "pad.impexp.confirmimport": "La importación d'un ficheru sustituirá'l testu actual del bloc. ¿Seguro que quies siguir?", - "pad.impexp.convertFailed": "Nun pudimos importar esti ficheru. Por favor,usa otru formatu de ficheru diferente o copia y pega manualmente.", - "pad.impexp.padHasData": "Nun pudimos importar esti ficheru porque esti bloc yá tuvo cambios; impórtalu a un bloc nuevu", - "pad.impexp.uploadFailed": "Falló la carga del ficheru, intentalo otra vuelta", - "pad.impexp.importfailed": "Falló la importación", - "pad.impexp.copypaste": "Por favor, copia y apega", - "pad.impexp.exportdisabled": "La esportación en formatu {{type}} ta desactivada. Por favor, comunica col alministrador del sistema pa más detalles." -} diff --git a/sources/src/locales/awa.json b/sources/src/locales/awa.json deleted file mode 100644 index f8c0d50..0000000 --- a/sources/src/locales/awa.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "@metadata": { - "authors": [ - "1AnuraagPandey" - ] - }, - "index.newPad": "नयाँ प्याड", - "pad.toolbar.bold.title": "मोट (Ctrl-B)", - "pad.toolbar.italic.title": "तिरछा (Ctrl+I)", - "pad.toolbar.underline.title": "निम्न रेखाङ्कन (Ctrl-U)", - "pad.toolbar.indent.title": "इन्डेन्ट (TAB)", - "pad.toolbar.unindent.title": "आउटडेन्ट (Shift+TAB)", - "pad.toolbar.undo.title": "रद्द (Ctrl-Z)", - "pad.toolbar.redo.title": "पुन:लागु (Ctrl-Y)", - "pad.toolbar.timeslider.title": "टाइमस्लाइडर", - "pad.toolbar.savedRevision.title": "पुनरावलोकन संग्रह किहा जाय", - "pad.toolbar.settings.title": "सेटिङ्ग", - "pad.colorpicker.save": "सहेजा जाय", - "pad.colorpicker.cancel": "रद्द करा जाय", - "pad.loading": "लोड होत है...", - "pad.wrongPassword": "आप कय पासवर्ड गलत रहा", - "pad.settings.padSettings": "प्याड सेटिङ्ग", - "pad.settings.myView": "हमार दृष्य", - "pad.settings.colorcheck": "लेखकीय रङ्ग", - "pad.settings.linenocheck": "हरफ संख्या", - "pad.settings.fontType": "फन्ट प्रकार:", - "pad.settings.fontType.normal": "साधारण", - "pad.settings.fontType.monospaced": "मोनोस्पेस", - "pad.settings.globalView": "विश्वव्यापी दृष्य", - "pad.settings.language": "भाषा", - "pad.importExport.import_export": "आयात/निर्यात", - "pad.importExport.importSuccessful": "सफल!", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "सामान्य पाठ", - "pad.importExport.exportword": "माइक्रोसफ्ट वर्ड", - "pad.importExport.exportpdf": "पिडिएफ", - "pad.importExport.exportopen": "ओडिएफ(खुल्ला कागजात ढाँचा)", - "pad.modals.unauth": "अनाधिकृत", - "pad.modals.initsocketfail": "सर्भरमा पहुँच से बहरे है ।", - "pad.share.readonly": "पढय वाला खाली", - "pad.share.link": "लिङ्क", - "pad.share.emebdcode": "URL जोडा जाय", - "pad.chat": "बातचीत", - "timeslider.pageTitle": "{{appTitle}} समय रेखा", - "timeslider.toolbar.authors": "लेखक:", - "timeslider.toolbar.exportlink.title": "निर्यात", - "timeslider.version": "संस्करण {{version}}", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "जनवरी", - "timeslider.month.february": "फेब्रुअरी", - "timeslider.month.march": "मार्च", - "timeslider.month.april": "अप्रैल", - "timeslider.month.may": "मई", - "timeslider.month.june": "जून", - "timeslider.month.july": "जुलाई", - "timeslider.month.august": "अगस्त", - "timeslider.month.september": "सेप्टेम्बर", - "timeslider.month.october": "अक्टूबर", - "timeslider.month.november": "नोभेम्बर", - "timeslider.month.december": "डिसेम्बर", - "timeslider.unnamedauthors": "{{num}} unnamed {[plural(num) one: author, other: authors ]}", - "pad.userlist.unnamed": "बेनामी", - "pad.userlist.guest": "पहुना", - "pad.userlist.deny": "अस्वीकार", - "pad.userlist.approve": "स्वीकृत", - "pad.impexp.importing": "आयात होत है...", - "pad.impexp.importfailed": "आयात असफल रहा", - "pad.impexp.copypaste": "कृपया कपी पेस्ट कीन जाय" -} diff --git a/sources/src/locales/az.json b/sources/src/locales/az.json deleted file mode 100644 index 9727064..0000000 --- a/sources/src/locales/az.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "@metadata": { - "authors": [ - "AZISS", - "Khan27", - "Mushviq Abdulla", - "Wertuose", - "Mastizada", - "Archaeodontosaurus", - "Neriman2003" - ] - }, - "index.newPad": "Yeni lövhə", - "index.createOpenPad": "və ya lövhəni bu adla yarat/aç:", - "pad.toolbar.bold.title": "Qalın (Ctrl-B)", - "pad.toolbar.italic.title": "Kursiv (Ctrl-I)", - "pad.toolbar.underline.title": "Altından xətt çəkmə (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Üstdən xətləmək (Ctrl+5)", - "pad.toolbar.ol.title": "Sıralanmış siyahı (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Sırasız siyahı (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Abzas (TAB)", - "pad.toolbar.unindent.title": "Çıxıntı (Shift+TAB)", - "pad.toolbar.undo.title": "Geri qaytar (Ctrl+Z)", - "pad.toolbar.redo.title": "Qaytar (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Müəlliflik Rənglərini Təmizlə (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Müxtəlif fayl formatların(a/dan) idxal/ixrac", - "pad.toolbar.timeslider.title": "Vaxt cədvəli", - "pad.toolbar.savedRevision.title": "Düzəlişləri Saxla", - "pad.toolbar.settings.title": "Tənzimləmələr", - "pad.toolbar.embed.title": "Bu lövhəni paylaş və qur", - "pad.toolbar.showusers.title": "Lövhədəki istifadəçiləri göstər", - "pad.colorpicker.save": "Saxla", - "pad.colorpicker.cancel": "İmtina", - "pad.loading": "Yüklənir...", - "pad.noCookie": "Çərəz tapıla bilmədi. Lütfən səyyahınızda çərəzlərə icazə verinǃ", - "pad.passwordRequired": "Bu lövhəyə daxil olmaq üçün parol lazımdır", - "pad.permissionDenied": "Bu lövhəyə daxil olmaq üçün icazəniz yoxdur", - "pad.wrongPassword": "Sizin parolunuz səhvdir", - "pad.settings.padSettings": "Lövhə nizamlamaları", - "pad.settings.myView": "Mənim Görüntüm", - "pad.settings.stickychat": "Söhbət həmişə ekranda", - "pad.settings.chatandusers": "Gap və İstifadəçiləri Göstər", - "pad.settings.colorcheck": "Müəlliflik rəngləri", - "pad.settings.linenocheck": "Sətir nömrələri", - "pad.settings.rtlcheck": "Mühtəviyyat sağdan sola doğru oxunsunmu?", - "pad.settings.fontType": "Şriftin tipi:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoboşluq", - "pad.settings.globalView": "Ümumi görünüş", - "pad.settings.language": "Dil:", - "pad.importExport.import_export": "İdxal/İxrac", - "pad.importExport.import": "Hər hansı bir mətn faylı və ya sənəd yüklə", - "pad.importExport.importSuccessful": "Uğurlu!", - "pad.importExport.export": "Hazırkı lövhəni bu şəkildə ixrac et:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Adi mətn", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (açıq sənəd formatı)", - "pad.importExport.abiword.innerHTML": "Siz yalnız adi mətndən və ya HTML-dən idxal edə bilərsiniz. İdxalın daha mürəkkəb funksiyaları üçün, zəhmət olmasa, AbiWord-i quraşdırın.", - "pad.modals.connected": "Bağlandı.", - "pad.modals.reconnecting": "Sizin lövhə yenidən qoşulur..", - "pad.modals.forcereconnect": "Məcbur təkrarən bağlan", - "pad.modals.reconnecttimer": "Yenidən qoşulur", - "pad.modals.cancel": "Ləğv et", - "pad.modals.userdup": "Başqa pəncərədə artıq açıqdır", - "pad.modals.userdup.explanation": "Bu lövhə, ola bilsin ki, bu kompüterdəki brauzerin bir neçə pəncərəsində açılmışdır.", - "pad.modals.userdup.advice": "Bu pəncərəni istifadə etmək üçün yenidən qoşul.", - "pad.modals.unauth": "İcazəli deyil", - "pad.modals.unauth.explanation": "Bu səhifəyə baxdığınız vaxt sizin icazəniz dəyişilib. Bərpa etmək üşün yenidən cəhd edin.", - "pad.modals.looping.explanation": "Sinxronlaşdırma serveri ilə kommunikasiya xətası var.", - "pad.modals.looping.cause": "Ola bilsin ki, siz uyğun olmayan fayrvol və ya proksi vasitəsi ilə qoşulmağa cəhd göstərirsiniz.", - "pad.modals.initsocketfail": "Server əlçatmazdır.", - "pad.modals.initsocketfail.explanation": "Sinxronlaşdırma serverinə qoşulma mümkünsüzdür.", - "pad.modals.initsocketfail.cause": "Ehtimal ki, bu problem sizin brauzerinizlə və ya internet-birləşmənizlə əlaqədərdir.", - "pad.modals.slowcommit.explanation": "Server cavab vermir.", - "pad.modals.slowcommit.cause": "Bu şəbəkə bağlantısında problemlər yarana bilər.", - "pad.modals.badChangeset.explanation": "Etdiyiniz bir redaktə sinxronizasiya serveri tərəfindən qeyri-leqal/qanundan kənar olaraq təsbit edildi.", - "pad.modals.badChangeset.cause": "Bu, yanlış server tərtibatı ya da başqa bir gözlənilməyən davranışlar nəticəsində ola bilər. Bu sizə bir xəta imiş kimi görünürsə lütfən servis nəzarətçisi ilə əlaqə yaradın. Redaktəyə davam etmək üçün yenidən qoşulmanı yoxlayın.", - "pad.modals.corruptPad.explanation": "Daxil olmağa çalışdığınız lövhə zədəlidir.", - "pad.modals.corruptPad.cause": "Bu, yanlış server tərtibatı ya da başqa bir gözlənilməyən davranışlardan əmələ gələ bilər. Lütfən servis nəzarətçisi ilə əlaqə yaradın.", - "pad.modals.deleted": "Silindi.", - "pad.modals.deleted.explanation": "Bu lövhə silindi.", - "pad.modals.disconnected": "Əlaqə kəsilib.", - "pad.modals.disconnected.explanation": "Serverə qoşulma itirilib", - "pad.modals.disconnected.cause": "Server ola bilsin, əlçatmazdır. Əgər belə davam edərsə xidmət administratorunu xəbərdar edin.", - "pad.share": "Bu lövhəni paylaş", - "pad.share.readonly": "Yalnız oxuyun", - "pad.share.link": "Keçid", - "pad.share.emebdcode": "URL-ni yayımla", - "pad.chat": "Söhbət", - "pad.chat.title": "Bu lövhə üçün çat açın.", - "pad.chat.loadmessages": "Daha çox mesaj yüklə", - "timeslider.pageTitle": "{{appTitle}} Vaxt cədvəli", - "timeslider.toolbar.returnbutton": "Lövhəyə qayıt", - "timeslider.toolbar.authors": "Müəlliflər:", - "timeslider.toolbar.authorsList": "Müəllif yoxdur", - "timeslider.toolbar.exportlink.title": "İxrac", - "timeslider.exportCurrent": "Cari versiyanı ixrac etmək kimi:", - "timeslider.version": "Versiya {{version}}", - "timeslider.saved": "Saxlanıldı {{day}} {{month}}, {{year}}", - "timeslider.playPause": "Geri oxutma / Lövhə Məzmunlarını Dayandır", - "timeslider.backRevision": "Sənədin bundan əvvəlki bir versiyasına qayıtmaq", - "timeslider.forwardRevision": "Sənədin bundan sonrakı bir versiyasına qayıtmaq", - "timeslider.dateformat": "{{day}} {{month}}, {{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Yanvar", - "timeslider.month.february": "Fevral", - "timeslider.month.march": "Mart", - "timeslider.month.april": "Aprel", - "timeslider.month.may": "May", - "timeslider.month.june": "İyun", - "timeslider.month.july": "İyul", - "timeslider.month.august": "Avqust", - "timeslider.month.september": "Sentyabr", - "timeslider.month.october": "Oktyabr", - "timeslider.month.november": "Noyabr", - "timeslider.month.december": "Dekabr", - "timeslider.unnamedauthors": "{{num}} adsız {[plural(num) one: müəllif, other: müəllif]}", - "pad.savedrevs.marked": "Bu versiya indi yaddaşa saxlanmış kimi nişanlandı", - "pad.savedrevs.timeslider": "Siz görə bilərsiniz saxlanılan versiyası miqyasında vaxt", - "pad.userlist.entername": "Adınızı daxil edin", - "pad.userlist.unnamed": "adsız", - "pad.userlist.guest": "Qonaq", - "pad.userlist.deny": "İnkar etmək", - "pad.userlist.approve": "Təsdiqləmək", - "pad.editbar.clearcolors": "Bütün sənədlərdə müəllif rəngləri təmizlənsin?", - "pad.impexp.importbutton": "İndi idxal et", - "pad.impexp.importing": "İdxal...", - "pad.impexp.confirmimport": "Faylın idxalı lövhədəki cari mətni yeniləyəcək. Davam etmək istədiyinizə əminsinizmi?", - "pad.impexp.convertFailed": "Biz bu fayl idxal etmək mümkün deyil idi. Xahiş olunur müxtəlif sənəddən istifadə edin və ya kopyalayıb yapışdırmaq yolundan istifadə edin", - "pad.impexp.padHasData": "Biz bu faylı idxal edə bilmədik, çünki bu lövhədə düzəlişlər edilib, lütfən yeni lövhə idxal edin", - "pad.impexp.uploadFailed": "Yükləmədə səhv, xahiş olunur yenə cəhd edin", - "pad.impexp.importfailed": "İdxal zamanı səhv", - "pad.impexp.copypaste": "Xahiş edirik kopyalayıb yapışdırın", - "pad.impexp.exportdisabled": "{{ type}} formatında ixrac söndürülmüşdür. Ətraflı informasiya üçün sistem administratoruna müraciət ediniz." -} diff --git a/sources/src/locales/azb.json b/sources/src/locales/azb.json deleted file mode 100644 index 4eeec31..0000000 --- a/sources/src/locales/azb.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Amir a57", - "Mousa", - "Koroğlu", - "Alp Er Tunqa", - "Ilğım" - ] - }, - "index.newPad": "یئنی یادداشت دفترچه سی", - "index.createOpenPad": "یا دا ایجاد /بیر پد آدلا برابر آچماق:", - "pad.toolbar.bold.title": "بویوت", - "pad.toolbar.italic.title": "مورب", - "pad.toolbar.underline.title": "خطدین آلتی", - "pad.toolbar.strikethrough.title": "خط یئمیش (Ctrl+5)", - "pad.toolbar.ol.title": "جوتدنمیش فهرست (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "جوتدنمه‌میش لیست (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "ایچری باتما (TAB)", - "pad.toolbar.unindent.title": "ائشیگه چیخدیغی (Shift+TAB)", - "pad.toolbar.undo.title": "باطل ائتمک", - "pad.toolbar.redo.title": "یئنی دن", - "pad.toolbar.clearAuthorship.title": "یازیچی بوْیالارینی سیلمک (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "آیری قالیب لردن /ایچری توکمه / ائشیگه توکمه", - "pad.toolbar.timeslider.title": "زمان اسلایدی", - "pad.toolbar.savedRevision.title": "نۆسخه‌نی ذخیره ائت", - "pad.toolbar.settings.title": "تنظیملر", - "pad.toolbar.embed.title": "بو یادداشت دفترچه سین یئرلشدیر و پایلاش", - "pad.toolbar.showusers.title": "بو دفترچه یادداشت دا اولان کاربرلری گوستر", - "pad.colorpicker.save": "ذخیره ائت", - "pad.colorpicker.cancel": "وازگئچ", - "pad.loading": "یوکلنیر...", - "pad.noCookie": "کوکی تاپیلمادی. لوطفن براوزرینیزده کوکیلره ایجازه وئرین!", - "pad.passwordRequired": "بو نوت دفترچه سینه ال تاپماق اوچون بیر رمزه احتیاجینیز واردیر.", - "pad.permissionDenied": "بو نوت دفترچه سینه ال تاپماق اوچون ایجازه نیز یوخدور.", - "pad.wrongPassword": "سیزین رمزینیز دوز دئییل", - "pad.settings.padSettings": "یادداشت دفترچه سینین تنظیملر", - "pad.settings.myView": "منیم گورنتوم", - "pad.settings.stickychat": "نمایش صفحه سینده همیشه چت اولسون", - "pad.settings.chatandusers": "چت ایله ایشلدنلری گؤستر", - "pad.settings.colorcheck": "یازیچی رنگ لری", - "pad.settings.linenocheck": "خطوط شماره سی", - "pad.settings.rtlcheck": "ایچینده کیلری ساغدان یوخسا سولدان اوخوسون؟", - "pad.settings.fontType": "قلم نوعی", - "pad.settings.fontType.normal": "نورمال", - "pad.settings.fontType.monospaced": "مونو اسپئیس", - "pad.settings.globalView": "سراسر گورونتو", - "pad.settings.language": "دیل:", - "pad.importExport.import_export": "ایچری توکمه /ائشیگه توکمه", - "pad.importExport.import": "سند یا دا متنی پرونده یوکله", - "pad.importExport.importSuccessful": "باشاریلی اولدو!", - "pad.importExport.export": "بو یادداشت دفترچه سی عنوانا ایچری توکمه", - "pad.importExport.exportetherpad": "اترپد", - "pad.importExport.exporthtml": "اچ تی ام ال", - "pad.importExport.exportplain": "ساده متن", - "pad.importExport.exportword": "مایکروسافت وورد", - "pad.importExport.exportpdf": "پی دی اف", - "pad.importExport.exportopen": "او دی اف", - "pad.modals.connected": "باغلاندی.", - "pad.modals.reconnecting": "یادداشت دفترچه‌نیزه یئنی‌دن باغلانمایا چالیشیلیر...", - "pad.modals.forcereconnect": "تکرار باغلانماق اوچون زوْرلاما", - "pad.modals.reconnecttimer": "یئنیدن باغلانمایا چالیشیلیر", - "pad.modals.cancel": "وازگئچ", - "pad.modals.userdup": "آیری پنجره ده آچیلدی", - "pad.modals.userdup.advice": "بو پئنجره دن ایستفاده ائتمک اوچون یئنی دن متصیل اول", - "pad.modals.unauth": "اوْلماز", - "pad.modals.unauth.explanation": "سیزین ال چتما مسئله سی بو صفحه نین گورونوش زمانیندا دییشیلیب دیر .\nسعی ائدین یئنی دن متصیل اولاسینیز", - "pad.modals.looping.explanation": "ارتیباطی موشکیل بیر ائتمه سرور ده وار دیر", - "pad.modals.looping.cause": "بلکه سیز دوز دئمیین بیر فایروال یادا پروکسی طریقی ایله متصیل اولوب سینیز", - "pad.modals.initsocketfail": "سرور الده دئییلدیر.", - "pad.modals.initsocketfail.explanation": "بیرلشدیریلمه سرور لرینه متصیل اولا بیلمه دی", - "pad.modals.slowcommit.explanation": "سرور جواب وئرمه ییر.", - "pad.modals.slowcommit.cause": "بو، شبکه باغلانتیسیندا خطالار اوچون اولا بیلر.", - "pad.modals.corruptPad.explanation": "ال تاپماغا چالیشدیغینیز پد کورلانیبدیر.", - "pad.modals.corruptPad.cause": "بو، غلط سرور تنظیملری یوخسا آیری بیر گوزلنیلمز بیر داورانیشدان عمله گله بیلر. لوطفا سرویس ایداره چیسی ایله تماس توتون.", - "pad.modals.deleted": "سیلیندی.", - "pad.modals.deleted.explanation": "بۇ یادداشت دفترچه‌سی سیلینیبدیر.", - "pad.modals.disconnected": "سیزین باغلانتینیز کسیلیبدیر.", - "pad.modals.disconnected.explanation": "سروره باغلانتی کسیلیبدیر.", - "pad.modals.disconnected.cause": "سرور ال چاتماز اولا بیلر. بئله قالیرسا سرویس ایداره چیسینی آییق سالین.", - "pad.share": "بو نوت دفترچه سینی پایلاش", - "pad.share.readonly": "ساده‌جه اوْخومالی", - "pad.share.link": "باغلانتی", - "pad.share.emebdcode": "یۇآرالی یئرلشدیرمک", - "pad.chat": "چت", - "pad.chat.title": "بو یادداشت دفترچه‌سینه چتی آچ.", - "pad.chat.loadmessages": "داها آرتیق پیام یوکله", - "timeslider.pageTitle": "{{appTitle}}زمان اسلایدری", - "timeslider.toolbar.returnbutton": "یادداشت دفترچه‌سینه قاییت.", - "timeslider.toolbar.authors": "یازیچیلار", - "timeslider.toolbar.authorsList": "یازیچی‌سیز", - "timeslider.toolbar.exportlink.title": "ائشیگه آپارماق", - "timeslider.exportCurrent": "موجود نوسخه نی بو عونوانلا ائشیگه چیخارت:", - "timeslider.version": "{{version}} ورژنی", - "timeslider.saved": "ساخلانیلدی {{day}} {{month}}, {{year}}", - "timeslider.playPause": "پد ایچینده‌کیلری یئنه اوْخوت/دۇردور", - "timeslider.month.january": "ژانویه", - "timeslider.month.february": "فوریه", - "timeslider.month.march": "مارس", - "timeslider.month.april": "آوریل", - "timeslider.month.may": "مئی", - "timeslider.month.june": "ژوئن", - "timeslider.month.july": "جولای", - "timeslider.month.august": "آقوست", - "timeslider.month.september": "سپتامبر", - "timeslider.month.october": "اوْکتوبر", - "timeslider.month.november": "نوْوامبر", - "timeslider.month.december": "دسامبر", - "pad.savedrevs.marked": "بۇ نوسخه ایندی ذخیره اوْلونموش کیمی علامتلندی.", - "pad.userlist.entername": "آدینیزی یازین", - "pad.userlist.unnamed": "آدسیز", - "pad.userlist.guest": "قوْناق", - "pad.userlist.deny": "دانماق", - "pad.userlist.approve": "اوْنایلا", - "pad.editbar.clearcolors": "بوتون سندلرده یازار بوْیالاری سیلینسین می؟", - "pad.impexp.importbutton": "ایندی ایچری گتیر", - "pad.impexp.importing": "ایچری گتیریلیر...", - "pad.impexp.uploadFailed": "آپلود اولونمادی، یئنه چالیشین", - "pad.impexp.importfailed": "ایچری گتیرمه اولونمادی", - "pad.impexp.copypaste": "لوطفن کوپی ائدیب، یاپیشدیرین" -} diff --git a/sources/src/locales/bcc.json b/sources/src/locales/bcc.json deleted file mode 100644 index 7ae4200..0000000 --- a/sources/src/locales/bcc.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Baloch Afghanistan" - ] - }, - "index.newPad": "دفترچه یادداشت تازه", - "index.createOpenPad": "یا ایجاد/بازکردن یک دفترچه یادداشت با نام:", - "pad.toolbar.bold.title": "پررنگ (Ctrl-B)", - "pad.toolbar.italic.title": "کج (Ctrl-I)", - "pad.toolbar.underline.title": "زیرخط (Ctrl-U)", - "pad.toolbar.strikethrough.title": "خط خورده", - "pad.toolbar.ol.title": "فهرست مرتب شده", - "pad.toolbar.ul.title": "فهرست مرتب نشده", - "pad.toolbar.indent.title": "تورفتگی (TAB)", - "pad.toolbar.unindent.title": "بیرون رفتگی (Shift+TAB)", - "pad.toolbar.undo.title": "باطل‌کردن (Ctrl-Z)", - "pad.toolbar.redo.title": "از نو (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "پاک‌کردن رنگ‌های نویسندگی", - "pad.toolbar.import_export.title": "درون‌ریزی/برون‌ریزی از/به قالب‌های مختلف", - "pad.toolbar.timeslider.title": "لغزندهٔ زمان", - "pad.toolbar.savedRevision.title": "ذخیره‌سازی نسخه", - "pad.toolbar.settings.title": "تنظیمات", - "pad.toolbar.embed.title": "اشتراک و جاسازی این دفترچه یادداشت", - "pad.toolbar.showusers.title": "نمایش کاربران در این دفترچه یادداشت", - "pad.colorpicker.save": "زاپاس کورتین", - "pad.colorpicker.cancel": "کنسیل", - "pad.loading": "...بار بیت", - "pad.passwordRequired": "برای دسترسی به این دفترچه یادداشت نیاز به یک گذرواژه دارید", - "pad.permissionDenied": "شرمنده، شما را اجازت په دسترسی ای صفحه نیست.", - "pad.wrongPassword": "گذرواژه‌ی شما درست نیست", - "pad.settings.padSettings": "تنظیمات دفترچه یادداشت", - "pad.settings.myView": "نمای من", - "pad.settings.stickychat": "گفتگو همیشه روی صفحه نمایش باشد", - "pad.settings.colorcheck": "رنگ‌های نویسندگی", - "pad.settings.linenocheck": "شماره‌ی خطوط", - "pad.settings.rtlcheck": "خواندن محتوا از راست به چپ؟", - "pad.settings.fontType": "نوع قلم:", - "pad.settings.fontType.normal": "نرمال", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "نمای سراسری", - "pad.settings.language": "زبان:", - "pad.importExport.import_export": "درون‌ریزی/برون‌ریزی", - "pad.importExport.import": "بارگذاری پرونده‌ی متنی یا سند", - "pad.importExport.importSuccessful": "موفقیت آمیز بود!", - "pad.importExport.export": "برون‌ریزی این دفترچه یادداشت با قالب:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "سادگین متن", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (قالب سند باز)", - "pad.importExport.abiword.innerHTML": "شما تنها می‌توانید از قالب متن ساده یا اچ‌تی‌ام‌ال درون‌ریزی کنید. برای بیشتر شدن ویژگی‌های درون‌ریزی پیشرفته AbiWord را نصب کنید.", - "pad.modals.connected": "متصل شد.", - "pad.modals.reconnecting": "در حال اتصال دوباره به دفترچه یادداشت شما..", - "pad.modals.forcereconnect": "واداشتن به اتصال دوباره", - "pad.modals.userdup": "در پنجره‌ای دیگر باز شد", - "pad.modals.userdup.explanation": "گمان می‌رود این دفترچه یادداشت در بیش از یک پنجره‌ی مرورگر باز شده‌است.", - "pad.modals.userdup.advice": "برای استفاده از این پنجره دوباره وصل شوید.", - "pad.modals.unauth": "مجاز نیست", - "pad.modals.unauth.explanation": "دسترسی شما در حین مشاهده‌ی این برگه تغییر یافته‌است. دوباره متصل شوید.", - "pad.modals.looping.explanation": "مشکلاتی ارتباطی با سرور همگام‌سازی وجود دارد.", - "pad.modals.looping.cause": "شاید شما از طریق یک فایروال یا پروکسی ناسازگار متصل شده‌اید.", - "pad.modals.initsocketfail": "سرور در دسترس نیست.", - "pad.modals.initsocketfail.explanation": "نمی‌توان به سرور همگام سازی وصل شد.", - "pad.modals.initsocketfail.cause": "شاید این به خاطر مشکلی در مرورگر یا اتصال اینترنتی شما باشد.", - "pad.modals.slowcommit.explanation": "سرور پاسخ نمی‌دهد.", - "pad.modals.slowcommit.cause": "این می‌تواند به خاطر مشکلاتی در اتصال به شبکه باشد.", - "pad.modals.badChangeset.explanation": "ویرایشی که شما انجام داده‌اید توسط سرور همگام‌سازی نادرست طیقه‌بندی شده‌است.", - "pad.modals.badChangeset.cause": "این می‌تواند به دلیل پیکربندی اشتباه یا سایر رفتارهای غیرمنتظره باشد. اگر فکر می‌کنید این یک خطا است لطفاً با مدیر خدمت تماس بگیرید. برای ادامهٔ ویرایش سعی کنید که دوباره متصل شوید.", - "pad.modals.corruptPad.explanation": "پدی که شما سعی دارید دسترسی پیدا کنید خراب است.", - "pad.modals.corruptPad.cause": "این احتمالاً به دلیل تنظیمات اشتباه کارساز یا سایر رفتارهای غیرمنتظره است. لطفاً با مدیر خدمت تماس حاصل کنید.", - "pad.modals.deleted": "پاک کورتین", - "pad.modals.deleted.explanation": "این دفترچه یادداشت پاک شده‌است.", - "pad.modals.disconnected": "اتصال شما قطع شده‌است.", - "pad.modals.disconnected.explanation": "اتصال به سرور قطع شده‌است.", - "pad.modals.disconnected.cause": "ممکن است سرور در دسترس نباشد. اگر این مشکل باز هم رخ داد مدیر حدمت را آگاه کنید.", - "pad.share": "به اشتراک‌گذاری این دفترچه یادداشت", - "pad.share.readonly": "فقط خواندنی", - "pad.share.link": "پیوند", - "pad.share.emebdcode": "جاسازی نشانی", - "pad.chat": "گفتگو", - "pad.chat.title": "بازکردن گفتگو برای این دفترچه یادداشت", - "pad.chat.loadmessages": "بارگیری پیام‌های بیشتر", - "timeslider.pageTitle": "لغزندهٔ زمان {{appTitle}}", - "timeslider.toolbar.returnbutton": "بازگشت به دفترچه یادداشت", - "timeslider.toolbar.authors": "نویسوک:", - "timeslider.toolbar.authorsList": "بدون نویسنده", - "timeslider.toolbar.exportlink.title": "درگیزگ", - "timeslider.exportCurrent": "برون‌ریزی نگارش کنونی به عنوان:", - "timeslider.version": "نگارش {{version}}", - "timeslider.saved": "{{month}} {{day}}، {{year}} ذخیره شد", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "جنوری", - "timeslider.month.february": "پیبروری", - "timeslider.month.march": "مارچ", - "timeslider.month.april": "آپریل", - "timeslider.month.may": "می", - "timeslider.month.june": "جون", - "timeslider.month.july": "جولای", - "timeslider.month.august": "آگوست", - "timeslider.month.september": "سپٹامبر", - "timeslider.month.october": "اکتوبر", - "timeslider.month.november": "نوامبر", - "timeslider.month.december": "دسمبر", - "timeslider.unnamedauthors": "{{num}} نویسندهٔ بی‌نام", - "pad.savedrevs.marked": "این بازنویسی هم اکنون به عنوان ذخیره شده علامت‌گذاری شد", - "pad.userlist.entername": "وتی یوزرنامء بلک ات", - "pad.userlist.unnamed": "بدون نام", - "pad.userlist.guest": "مهمان", - "pad.userlist.deny": "رد کردن", - "pad.userlist.approve": "تایید", - "pad.editbar.clearcolors": "رنگ نویسندگی از همه‌ی سند پاک شود؟", - "pad.impexp.importbutton": "هم اکنون درون‌ریزی کن", - "pad.impexp.importing": "در حال درون‌ریزی...", - "pad.impexp.confirmimport": "با درون‌ریزی یک پرونده نوشتهٔ کنونی دفترچه پاک می‌شود. آیا می‌خواهید ادامه دهید؟", - "pad.impexp.convertFailed": "ما نمی‌توانیم این پرونده را درون‌ریزی کنیم. خواهشمندیم قالب دیگری برای سندتان انتخاب کرده یا بصورت دستی آنرا کپی کنید", - "pad.impexp.uploadFailed": "آپلود انجام نشد، دوباره تلاش کنید", - "pad.impexp.importfailed": "درون‌ریزی انجام نشد", - "pad.impexp.copypaste": "کپی پیست کنید", - "pad.impexp.exportdisabled": "برون‌ریزی با قالب {{type}} از کار افتاده است. برای جزئیات بیشتر با مدیر سیستمتان تماس بگیرید." -} diff --git a/sources/src/locales/be-tarask.json b/sources/src/locales/be-tarask.json deleted file mode 100644 index 84af731..0000000 --- a/sources/src/locales/be-tarask.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Jim-by", - "Wizardist", - "Red Winged Duck" - ] - }, - "index.newPad": "Стварыць", - "index.createOpenPad": "ці тварыць/адкрыць дакумэнт з назвай:", - "pad.toolbar.bold.title": "Тоўсты (Ctrl-B)", - "pad.toolbar.italic.title": "Курсіў (Ctrl-I)", - "pad.toolbar.underline.title": "Падкрэсьліваньне (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Закрэсьліваньне (Ctrl+5)", - "pad.toolbar.ol.title": "Упарадкаваны сьпіс (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Неўпарадкаваны сьпіс (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Водступ (TAB)", - "pad.toolbar.unindent.title": "Выступ (Shift+TAB)", - "pad.toolbar.undo.title": "Скасаваць(Ctrl-Z)", - "pad.toolbar.redo.title": "Вярнуць (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Прыбраць колер дакумэнту (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Імпарт/Экспарт з выкарыстаньне розных фарматаў файлаў", - "pad.toolbar.timeslider.title": "Шкала часу", - "pad.toolbar.savedRevision.title": "Захаваць вэрсію", - "pad.toolbar.settings.title": "Налады", - "pad.toolbar.embed.title": "Падзяліцца і ўбудаваць гэты дакумэнт", - "pad.toolbar.showusers.title": "Паказаць карыстальнікаў у гэтым дакумэнце", - "pad.colorpicker.save": "Захаваць", - "pad.colorpicker.cancel": "Скасаваць", - "pad.loading": "Загрузка...", - "pad.noCookie": "Кукі ня знойдзеныя. Калі ласка, дазвольце кукі ў вашым браўзэры!", - "pad.passwordRequired": "Для доступу да гэтага дакумэнта патрэбны пароль", - "pad.permissionDenied": "Вы ня маеце дазволу на доступ да гэтага дакумэнта", - "pad.wrongPassword": "Вы ўвялі няслушны пароль", - "pad.settings.padSettings": "Налады дакумэнта", - "pad.settings.myView": "Мой выгляд", - "pad.settings.stickychat": "Заўсёды паказваць чат", - "pad.settings.chatandusers": "Паказаць чат і ўдзельнікаў", - "pad.settings.colorcheck": "Колеры аўтарства", - "pad.settings.linenocheck": "Нумары радкоў", - "pad.settings.rtlcheck": "Тэкст справа-налева", - "pad.settings.fontType": "Тып шрыфту:", - "pad.settings.fontType.normal": "Звычайны", - "pad.settings.fontType.monospaced": "Монашырынны", - "pad.settings.globalView": "Агульны выгляд", - "pad.settings.language": "Мова:", - "pad.importExport.import_export": "Імпарт/Экспарт", - "pad.importExport.import": "Загрузіжайце любыя тэкставыя файлы або дакумэнты", - "pad.importExport.importSuccessful": "Пасьпяхова!", - "pad.importExport.export": "Экспартаваць бягучы дакумэнт як:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Просты тэкст", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Вы можаце імпартаваць толькі з звычайнага тэксту або HTML. Дзеля больш пашыраных магчымасьцяў імпарту, калі ласка, усталюйце AbiWord.", - "pad.modals.connected": "Падлучыліся.", - "pad.modals.reconnecting": "Перападлучэньне да вашага дакумэнта...", - "pad.modals.forcereconnect": "Прымусовае перападлучэньне", - "pad.modals.reconnecttimer": "Спрабуем перападключыцца праз", - "pad.modals.cancel": "Адмяніць", - "pad.modals.userdup": "Адкрыта ў іншым акне", - "pad.modals.userdup.explanation": "Падобна, дакумэнт адкрыты больш чым у адным акне браўзэра на гэтым кампутары.", - "pad.modals.userdup.advice": "Паўторна падключыць з выкарыстаньнем гэтага акна.", - "pad.modals.unauth": "Не аўтарызаваны", - "pad.modals.unauth.explanation": "Вашыя правы былі зьмененыя ў часе прагляду гэтай старонкі. Паспрабуйце перападключыцца.", - "pad.modals.looping.explanation": "Праблемы далучэньня да сэрвэра сынхранізацыі.", - "pad.modals.looping.cause": "Магчыма, вы падключыліся празь несумяшчальны брандмаўэр або проксі.", - "pad.modals.initsocketfail": "Сэрвэр недаступны.", - "pad.modals.initsocketfail.explanation": "Не атрымалася падлучыцца да сэрвэра сынхранізацыі.", - "pad.modals.initsocketfail.cause": "Імаверна, гэта зьвязана з праблемамі з вашым браўзэрам або інтэрнэт-злучэньнем.", - "pad.modals.slowcommit.explanation": "Сэрвэр не адказвае.", - "pad.modals.slowcommit.cause": "Гэта можа быць выклікана праблемамі зь сеткавым падлучэньнем.", - "pad.modals.badChangeset.explanation": "Сэрвэр сынхранізацыі вызначыў зробленае вамі рэдагаваньне як недапушчальнае.", - "pad.modals.badChangeset.cause": "Гэта можа адбывацца празь няслушную канфігурацыю сэрвэра або празь іншыя нечаканыя дзеяньні. Калі ласка, скантактуйцеся з адміністратарам, калі вы лічыце, што гэта памылка. Паспрабуйце перападлучыцца, каб працягнуць рэдагаваньне.", - "pad.modals.corruptPad.explanation": "Дакумэнт, да якога вы спрабуеце атрымаць доступ, пашкоджаны.", - "pad.modals.corruptPad.cause": "Гэта можа быць выклікана няправільнай канфігурацыяй сэрвэру або іншымі нечаканымі дзеяньнямі. Калі ласка, скантактуйцеся з адміністратарам службы.", - "pad.modals.deleted": "Выдалены.", - "pad.modals.deleted.explanation": "Гэты дакумэнт быў выдалены.", - "pad.modals.disconnected": "Вы былі адключаныя.", - "pad.modals.disconnected.explanation": "Злучэньне з сэрвэрам было страчанае", - "pad.modals.disconnected.cause": "Магчыма, сэрвэр недаступны. Калі ласка, паведаміце адміністратару службы, калі праблема будзе паўтарацца.", - "pad.share": "Падзяліцца дакумэнтам", - "pad.share.readonly": "Толькі для чытаньня", - "pad.share.link": "Спасылка", - "pad.share.emebdcode": "Укласьці URL", - "pad.chat": "Чат", - "pad.chat.title": "Адкрыць чат для гэтага дакумэнту.", - "pad.chat.loadmessages": "Загрузіць болей паведамленьняў", - "timeslider.pageTitle": "Часавая шкала {{appTitle}}", - "timeslider.toolbar.returnbutton": "Вярнуцца да дакумэнту", - "timeslider.toolbar.authors": "Аўтары:", - "timeslider.toolbar.authorsList": "Няма аўтараў", - "timeslider.toolbar.exportlink.title": "Экспарт", - "timeslider.exportCurrent": "Экспартаваць актуальную вэрсію як:", - "timeslider.version": "Вэрсія {{version}}", - "timeslider.saved": "Захавана {{day}}.{{month}}.{{year}}", - "timeslider.playPause": "Прайграць / спыніць зьмест дакумэнту", - "timeslider.backRevision": "Вярнуць рэдагаваньне гэтага дакумэнту", - "timeslider.forwardRevision": "Перайсьці да наступнага рэдагаваньня гэтага дакумэнту", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "студзень", - "timeslider.month.february": "люты", - "timeslider.month.march": "сакавік", - "timeslider.month.april": "красавік", - "timeslider.month.may": "травень", - "timeslider.month.june": "чэрвень", - "timeslider.month.july": "ліпень", - "timeslider.month.august": "жнівень", - "timeslider.month.september": "верасень", - "timeslider.month.october": "кастрычнік", - "timeslider.month.november": "лістапад", - "timeslider.month.december": "сьнежань", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: безыменны аўтар, few: безыменныя аўтары, many: безыменных аўтараў, other: безыменных аўтараў ]}", - "pad.savedrevs.marked": "Гэтая вэрсія цяпер пазначаная як захаваная", - "pad.savedrevs.timeslider": "Вы можаце пабачыць захаваныя вэрсіі з дапамогай шкалы часу", - "pad.userlist.entername": "Увядзіце вашае імя", - "pad.userlist.unnamed": "безыменны", - "pad.userlist.guest": "Госьць", - "pad.userlist.deny": "Адхіліць", - "pad.userlist.approve": "Зацьвердзіць", - "pad.editbar.clearcolors": "Ачысьціць аўтарскія колеры ва ўсім дакумэнце?", - "pad.impexp.importbutton": "Імпартаваць зараз", - "pad.impexp.importing": "Імпартаваньне…", - "pad.impexp.confirmimport": "Імпарт файла перазапіша цяперашні тэкст дакумэнту. Вы ўпэўненыя, што хочаце працягваць?", - "pad.impexp.convertFailed": "Не атрымалася імпартаваць гэты файл. Калі ласка, выкарыстайце іншы фармат дакумэнту або скапіюйце ўручную.", - "pad.impexp.padHasData": "Мы не змаглі імпартаваць гэты файл, бо дакумэнт ужо мае зьмены, калі ласка, імпартуйце ў новы дакумэнт", - "pad.impexp.uploadFailed": "Загрузка не атрымалася, калі ласка, паспрабуйце яшчэ раз", - "pad.impexp.importfailed": "Памылка імпарту", - "pad.impexp.copypaste": "Калі ласка, скапіюйце і ўстаўце", - "pad.impexp.exportdisabled": "Экспарт у фармаце {{type}} адключаны. Калі ласка, зьвярніцеся да вашага сыстэмнага адміністратара па падрабязнасьці." -} diff --git a/sources/src/locales/bg.json b/sources/src/locales/bg.json deleted file mode 100644 index 52e424c..0000000 --- a/sources/src/locales/bg.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Vodnokon4e", - "StanProg" - ] - }, - "index.newPad": "Нов пад", - "index.createOpenPad": "или създаване/отваряне на пад с име:", - "pad.toolbar.bold.title": "Получер (Ctrl+B)", - "pad.toolbar.italic.title": "Наклонен (Ctrl+I)", - "pad.toolbar.underline.title": "Подчертан (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Зачеркнат (Ctrl+5)", - "pad.toolbar.ol.title": "Подреден списък (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Неподреден списък (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Отстъп (TAB)", - "pad.toolbar.unindent.title": "Премахване на отстъпа (Shift+TAB)", - "pad.toolbar.undo.title": "Отмяна (Ctrl+Z)", - "pad.toolbar.redo.title": "Връщане (Ctrl+Y)", - "pad.toolbar.settings.title": "Настройки", - "pad.colorpicker.save": "Съхраняване", - "pad.colorpicker.cancel": "Отказване", - "pad.loading": "Зареждане...", - "pad.wrongPassword": "Неправилна парола", - "pad.settings.language": "Език:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Обикновен текст", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.modals.cancel": "Отказване", - "pad.modals.userdup": "Отворен в друг прозорец", - "pad.modals.userdup.explanation": "Изглежда, че този пад е отворен на повече от един раздел в браузъра на компютъра.", - "pad.modals.looping.explanation": "Има проблеми с комуникацията със сървъра за синхронизация.", - "pad.modals.looping.cause": "Може би сте свързани чрез несъвместима защитна стена или прокси.", - "pad.modals.initsocketfail": "Сървърът е недостъпен.", - "pad.modals.initsocketfail.explanation": "Свързването със сървъра за синхронизация е неуспешно.", - "pad.modals.initsocketfail.cause": "Това вероятно се дължи на проблем с браузъра Ви или връзката Ви с Интернет.", - "pad.modals.slowcommit.explanation": "Сървърът не отговаря.", - "pad.modals.slowcommit.cause": "Това може да се дължи на проблеми с мрежовите връзки.", - "pad.modals.deleted": "Изтрито.", - "pad.share.readonly": "Само за четене", - "pad.share.link": "Препратка", - "pad.share.emebdcode": "Постави URL", - "pad.chat": "Чат", - "pad.chat.title": "Отваряне на чат за този пад.", - "pad.chat.loadmessages": "Зареждане на повече съобщения", - "timeslider.toolbar.returnbutton": "Връщане към пада", - "timeslider.toolbar.authors": "Автори:", - "timeslider.toolbar.authorsList": "Няма автори", - "timeslider.toolbar.exportlink.title": "Изнасяне", - "timeslider.exportCurrent": "Изнасяне на текущата версия като:", - "timeslider.version": "Версия {{version}}", - "timeslider.month.january": "януари", - "timeslider.month.february": "февруари", - "timeslider.month.march": "март", - "timeslider.month.april": "април", - "timeslider.month.may": "май", - "timeslider.month.june": "юни", - "timeslider.month.july": "юли", - "timeslider.month.august": "август", - "timeslider.month.september": "септември", - "timeslider.month.october": "октомври", - "timeslider.month.november": "ноември", - "timeslider.month.december": "декември", - "pad.userlist.entername": "Въведете вашето име", - "pad.userlist.guest": "Гост" -} diff --git a/sources/src/locales/bgn.json b/sources/src/locales/bgn.json deleted file mode 100644 index 00efbf3..0000000 --- a/sources/src/locales/bgn.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Baloch Afghanistan" - ] - }, - "index.newPad": "یاداشتی نوکین کتابچه", - "index.createOpenPad": "یا جوڑ\t کورتین/پاچ کورتین یک کتابچه ئی یاداشتی بی نام:", - "pad.toolbar.bold.title": "پررنگ (Ctrl-B)", - "pad.toolbar.italic.title": "چوّٹ (Ctrl-I)", - "pad.toolbar.underline.title": "جهلگ خط (Ctrl-U)", - "pad.toolbar.strikethrough.title": "خط وارته (Ctrl+5)", - "pad.toolbar.ol.title": "ترتیب بوتگین لر لیست (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "ترتیب نه بوتگین لر لیست (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "بیئتئ بوتگین (TAB)", - "pad.toolbar.unindent.title": "در آتگی (Shift+TAB)", - "pad.toolbar.undo.title": "باطل‌کورتین (Ctrl-Z)", - "pad.toolbar.redo.title": "شه نوک (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "نویسوکئ رنگانی پاک کورتین (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "بی تئ کورتین/دَر کورتین شه/بی رکم رکمین قالیبان", - "pad.toolbar.timeslider.title": "وختئ لَگوشوک", - "pad.toolbar.savedRevision.title": "نسخه ئی ذخیره کورتین", - "pad.toolbar.settings.title": "تنظیمات", - "pad.colorpicker.save": "ذخیره", - "pad.colorpicker.cancel": "کنسیل", - "pad.loading": "لودینگ...", - "pad.wrongPassword": "شمی پاسورد جووان نه اینت", - "pad.settings.padSettings": "یاداشتئ دفترچه ئی تنظیمات", - "pad.settings.myView": "نئ دیست", - "pad.settings.stickychat": "هبر موچین وختا بی دیستئ تاکدیمئ سرا بیئت", - "pad.settings.colorcheck": "نویسوکی رنگ ئان", - "pad.settings.linenocheck": "خط ئانی نمبر", - "pad.settings.rtlcheck": "محتوایی وانتین شه راست بی چپا؟", - "pad.settings.fontType": "قلم رکم:", - "pad.settings.fontType.normal": "ساددگ", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "سراسرین دیست یا نما", - "pad.settings.language": "زبان:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "ساده گین متن", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (پاچین سندئ قالب)", - "pad.importExport.abiword.innerHTML": "شما تا توانیت که شه ساده گین متنی ئین قالب یا اچ‌تی‌ام‌ال بی تئ کنیت . په گیشتیرین کارا ئییان پیشرفته ئین بی تئ کورتینا AbiWord نصب کنیت.", - "pad.modals.connected": "وصل بوت.", - "pad.modals.userdup": "نوکین دروازه گئ پاچ کورتین", - "pad.modals.unauth": "مجاز نه اینت", - "pad.modals.deleted.explanation": "ای یاداشتی دفترچه پاک بوته.", - "pad.share.readonly": "فقط وانتین", - "pad.share.link": "لینک", - "pad.chat": "چت وهبر", - "timeslider.toolbar.exportlink.title": "دَر کورتین", - "timeslider.month.january": "جنوری", - "timeslider.month.february": "فیبروری", - "timeslider.month.march": "مارچ", - "timeslider.month.april": "اپریل", - "timeslider.month.may": "می", - "timeslider.month.june": "جون", - "timeslider.month.july": "جولای", - "timeslider.month.august": "اگوست", - "timeslider.month.september": "سیپٹمبر", - "timeslider.month.october": "اکتوبر", - "timeslider.month.november": "نوامبر", - "timeslider.month.december": "ڈ\tسمبر", - "timeslider.unnamedauthors": "{{num}} بی نامین نویسوک", - "pad.userlist.entername": "وتئ ناما نیویشته بکنیت", - "pad.userlist.unnamed": "بی نام", - "pad.userlist.guest": "مهمان", - "pad.userlist.deny": "رد کورتین", - "pad.userlist.approve": "قبول کورتین", - "pad.impexp.importbutton": "انون بی تئ کن", - "pad.impexp.importing": "بی بی تئ کورتینی حالا...", - "pad.impexp.uploadFailed": "آپلود انجام نه بوت، پدا کوشش کن", - "pad.impexp.copypaste": "کپی پیست کَنیت" -} diff --git a/sources/src/locales/bn.json b/sources/src/locales/bn.json deleted file mode 100644 index 0102720..0000000 --- a/sources/src/locales/bn.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Bellayet", - "Nasir8891", - "Sankarshan", - "Aftab1995", - "Aftabuzzaman" - ] - }, - "index.newPad": "নতুন প্যাড", - "index.createOpenPad": "অথবা নাম লিখে প্যাড খুলুন/তৈরী করুন:", - "pad.toolbar.bold.title": "গাঢ় (Ctrl-B)", - "pad.toolbar.italic.title": "বাঁকা (Ctrl+I)", - "pad.toolbar.underline.title": "নিম্নরেখা (Ctrl+U)", - "pad.toolbar.strikethrough.title": "অবচ্ছেদন (Ctrl+5)", - "pad.toolbar.ol.title": "সারিবদ্ধ তালিকা (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "অসারিবদ্ধ তালিকা (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "প্রান্তিককরণ (TAB)", - "pad.toolbar.unindent.title": "আউটডেন্ট (Shift+TAB)", - "pad.toolbar.undo.title": "বাতিল করুন (Ctrl-Z)", - "pad.toolbar.redo.title": "পুনরায় করুন (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "কৃতি রং পরিষ্কার করুন (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "ভিন্ন ফাইল বিন্যাসে আমদানি/রপ্তানি করুন", - "pad.toolbar.timeslider.title": "টাইমস্লাইডার", - "pad.toolbar.savedRevision.title": "সংস্করণ সংরক্ষণ করুন", - "pad.toolbar.settings.title": "সেটিং", - "pad.toolbar.embed.title": "এই প্যাডটি শেয়ার ও এম্বেড করুন", - "pad.toolbar.showusers.title": "এই প্যাডের ব্যবহারকারীদের দেখান", - "pad.colorpicker.save": "সংরক্ষণ", - "pad.colorpicker.cancel": "বাতিল", - "pad.loading": "লোড হচ্ছে...", - "pad.noCookie": "কুকি পাওয়া যায়নি। দয়া করে আপনার ব্রাউজারে কুকি অনুমতি দিন!", - "pad.passwordRequired": "এই প্যাড-টি দেখার জন্য আপনাকে পাসওয়ার্ড ব্যবহার করতে হবে", - "pad.permissionDenied": "দুঃখিত, এ প্যাড-টি দেখার অধিকার আপনার নেই", - "pad.wrongPassword": "আপনার পাসওয়ার্ড সঠিক নয়", - "pad.settings.padSettings": "প্যাডের স্থাপন", - "pad.settings.myView": "আমার দৃশ্য", - "pad.settings.stickychat": "চ্যাট সক্রীনে প্রদর্শন করা হবে", - "pad.settings.chatandusers": "চ্যাট এবং ব্যবহারকারী দেখান", - "pad.settings.colorcheck": "লেখকদের নিজস্ব নির্বাচিত রং", - "pad.settings.linenocheck": "লাইন নম্বর", - "pad.settings.rtlcheck": "ডান থেকে বামে বিষয়বস্তু পড়বেন?", - "pad.settings.fontType": "ফন্টের প্রকার:", - "pad.settings.fontType.normal": "সাধারণ", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "সর্বব্যাপী দৃশ্য", - "pad.settings.language": "ভাষা:", - "pad.importExport.import_export": "আমদানি/রপ্তানি", - "pad.importExport.import": "কোন টেক্সট ফাইল বা নথি আপলোড করুন", - "pad.importExport.importSuccessful": "সফল!", - "pad.importExport.export": "এই প্যাডটি রপ্তানি করুন:", - "pad.importExport.exportetherpad": "ইথারপ্যাড", - "pad.importExport.exporthtml": "এইচটিএমএল", - "pad.importExport.exportplain": "সাধারণ লেখা", - "pad.importExport.exportword": "মাইক্রোসফট ওয়ার্ড", - "pad.importExport.exportpdf": "পিডিএফ", - "pad.importExport.exportopen": "ওডিএফ (ওপেন ডকুমেন্ট ফরম্যাট)", - "pad.modals.connected": "যোগাযোগ সফল", - "pad.modals.reconnecting": "আপনার প্যাডের সাথে সংযোগস্থাপন করা হচ্ছে..", - "pad.modals.forcereconnect": "পুনরায় সংযোগস্থাপনের চেষ্টা", - "pad.modals.userdup": "অন্য উইন্ডো-তে খোলা হয়েছে", - "pad.modals.unauth": "আপনার অধিকার নেই", - "pad.modals.initsocketfail": "সার্ভারে পৌঁছানো যাচ্ছে না।", - "pad.modals.slowcommit.explanation": "সার্ভার সাড়া দিচ্ছে না।", - "pad.modals.deleted": "অপসারিত।", - "pad.modals.deleted.explanation": "এই প্যাডটি অপসারণ করা হয়েছে।", - "pad.modals.disconnected": "আপনি সংযোগ বিচ্ছিন্ন হয়েছে গেছে।", - "pad.modals.disconnected.explanation": "সার্ভারের সাথে যোগাযোগ করা যাচ্ছে না", - "pad.share": "শেয়ার করুন", - "pad.share.readonly": "শুধু পড়া", - "pad.share.link": "লিংক", - "pad.share.emebdcode": "ইউআরএল সংযোজন", - "pad.chat": "চ্যাট", - "pad.chat.title": "এই প্যাডের জন্য চ্যাট চালু করুন।", - "pad.chat.loadmessages": "আরও বার্তা লোড করুন", - "timeslider.toolbar.returnbutton": "প্যাডে ফিরে যাও", - "timeslider.toolbar.authors": "লেখকগণ:", - "timeslider.toolbar.authorsList": "কোনো লেখক নেই", - "timeslider.toolbar.exportlink.title": "রপ্তানি", - "timeslider.exportCurrent": "বর্তমান সংস্করণটি রপ্তানি করুন:", - "timeslider.version": "সংস্করণ {{version}}", - "timeslider.saved": "সংরক্ষিত হয় {{month}} {{day}}, {{year}}", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "জানুয়ারি", - "timeslider.month.february": "ফেব্রুয়ারি", - "timeslider.month.march": "মার্চ", - "timeslider.month.april": "এপ্রিল", - "timeslider.month.may": "মে", - "timeslider.month.june": "জুন", - "timeslider.month.july": "জুলাই", - "timeslider.month.august": "আগস্ট", - "timeslider.month.september": "সেপ্টেম্বর", - "timeslider.month.october": "অক্টোবর", - "timeslider.month.november": "নভেম্বর", - "timeslider.month.december": "ডিসেম্বর", - "timeslider.unnamedauthors": "নামবিহীন {{num}} জন {[plural(num) one: লেখক, other: লেখক ]}", - "pad.userlist.entername": "আপনার নাম লিখুন", - "pad.userlist.unnamed": "কোন নাম নির্বাচন করা হয়নি", - "pad.userlist.guest": "অতিথি", - "pad.userlist.deny": "প্রত্যাখ্যান", - "pad.userlist.approve": "অনুমোদিত", - "pad.impexp.importbutton": "এখন আমদানি করুন", - "pad.impexp.importing": "আমদানি হচ্ছে...", - "pad.impexp.padHasData": "আমরা এই ফাইলটি আমদানি করতে সক্ষম হয়নি কারণ এই প্যাড ইতিমধ্যে পরিবর্তিত হয়েছে, দয়া করে একটি নতুন প্যাডে অামদানি করুন।", - "pad.impexp.uploadFailed": "আপলোড করতে ব্যর্থ, দয়া করে আবার চেষ্টা করুন", - "pad.impexp.importfailed": "আমদানি ব্যর্থ", - "pad.impexp.copypaste": "দয়া করে অনুলিপি প্রতিলেপন করুন", - "pad.impexp.exportdisabled": "{{type}} হিসেবে রপ্তানি করা নিষ্ক্রিয় আছে। বিস্তারিত জানার জন্য আপনার সিস্টেম প্রশাসকের সাথে যোগাযোগ করুন।" -} diff --git a/sources/src/locales/br.json b/sources/src/locales/br.json deleted file mode 100644 index aa31f7f..0000000 --- a/sources/src/locales/br.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Fohanno", - "Fulup", - "Gwenn-Ael", - "Y-M D" - ] - }, - "index.newPad": "Pad nevez", - "index.createOpenPad": "pe krouiñ/digeriñ ur pad gant an anv :", - "pad.toolbar.bold.title": "Tev (Ctrl-B)", - "pad.toolbar.italic.title": "Italek (Ctrl-I)", - "pad.toolbar.underline.title": "Islinennañ (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Barrennet(Ktrl+5)", - "pad.toolbar.ol.title": "Listenn urzhiet (Ktrl+Pennlizherenn+N)", - "pad.toolbar.ul.title": "Listenn en dizurzh (Ktrl+Pennlizherenn+L)", - "pad.toolbar.indent.title": "Endantañ (TAB)", - "pad.toolbar.unindent.title": "Diendantañ (Shift+TAB)", - "pad.toolbar.undo.title": "Dizober (Ktrl-Z)", - "pad.toolbar.redo.title": "Adober (Ktrl-Y)", - "pad.toolbar.clearAuthorship.title": "Diverkañ al livioù oc'h anaout an aozerien (Ktrl+Pennlizherenn+C)", - "pad.toolbar.import_export.title": "Enporzhiañ/Ezporzhiañ eus/war-zu ur furmad restr disheñvel", - "pad.toolbar.timeslider.title": "Istor dinamek", - "pad.toolbar.savedRevision.title": "Enrollañ an adweladenn", - "pad.toolbar.settings.title": "Arventennoù", - "pad.toolbar.embed.title": "Rannañ hag enframmañ ar pad-mañ", - "pad.toolbar.showusers.title": "Diskwelet implijerien ar Pad", - "pad.colorpicker.save": "Enrollañ", - "pad.colorpicker.cancel": "Nullañ", - "pad.loading": "O kargañ...", - "pad.noCookie": "N'eus ket gallet kavout an toupin. Aotreit an toupinoù en ho merdeer, mar plij !", - "pad.passwordRequired": "Ezhomm ho peus ur ger-tremen evit mont d'ar Pad-se", - "pad.permissionDenied": "\nN'oc'h ket aotreet da vont d'ar pad-mañ", - "pad.wrongPassword": "Fazius e oa ho ker-tremen", - "pad.settings.padSettings": "Arventennoù Pad", - "pad.settings.myView": "Ma diskwel", - "pad.settings.stickychat": "Diskwel ar flap bepred", - "pad.settings.chatandusers": "Diskouez ar gaoz hag an implijerien", - "pad.settings.colorcheck": "Livioù anaout", - "pad.settings.linenocheck": "Niverennoù linennoù", - "pad.settings.rtlcheck": "Lenn an danvez a-zehou da gleiz ?", - "pad.settings.fontType": "Seurt font :", - "pad.settings.fontType.normal": "Reizh", - "pad.settings.fontType.monospaced": "Monospas", - "pad.settings.globalView": "Gwel dre vras", - "pad.settings.language": "Yezh :", - "pad.importExport.import_export": "Enporzhiañ/Ezporzhiañ", - "pad.importExport.import": "Enkargañ un destenn pe ur restr", - "pad.importExport.importSuccessful": "Deuet eo ganeoc'h !", - "pad.importExport.export": "Ezporzhiañ ar pad bremañ evel :", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Testenn blaen", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Ne c'hallit ket emporzjiañ furmadoù testennoù kriz pe html. Evit arc'hwelioù enporzhiañ emdroetoc'h, staliit abiword mar plij.", - "pad.modals.connected": "Kevreet.", - "pad.modals.reconnecting": "Adkevreañ war-zu ho pad...", - "pad.modals.forcereconnect": "Adkevreañ dre heg", - "pad.modals.reconnecttimer": "O klask adkevreañ", - "pad.modals.cancel": "Nullañ", - "pad.modals.userdup": "Digor en ur prenestr all", - "pad.modals.userdup.explanation": "Digor eo ho pad, war a seblant, e meur a brenestr eus ho merdeer en urzhiataer-mañ.", - "pad.modals.userdup.advice": "Kevreañ en ur implijout ar prenestr-mañ.", - "pad.modals.unauth": "N'eo ket aotreet", - "pad.modals.unauth.explanation": "Kemmet e vo hoc'h aotreoù pa vo diskwelet ar bajenn.-mañ Klaskit kevreañ en-dro.", - "pad.modals.looping.explanation": "Kudennoù kehentiñ zo gant ar servijer sinkronelekaat.", - "pad.modals.looping.cause": "Posupl eo e vefe gwarezet ho kevreadur gant ur maltouter diembreget pe ur servijer proksi", - "pad.modals.initsocketfail": "Ne c'haller ket tizhout ar servijer.", - "pad.modals.initsocketfail.explanation": "Ne c'haller ket kevreañ ouzh ar servijer sinkronelaat.", - "pad.modals.initsocketfail.cause": "Gallout a ra ar gudenn dont eus ho merdeer Web pe eus ho kevreadur Internet.", - "pad.modals.slowcommit.explanation": "Ne respont ket ar serveur.", - "pad.modals.slowcommit.cause": "Gallout a ra dont diwar kudennoù kevreañ gant ar rouedad.", - "pad.modals.badChangeset.explanation": "Graet ho peus ur c'hemm met rummet eo bet evel e-maez lezenn gant ar servijer sinkronelaat", - "pad.modals.badChangeset.cause": "Dont a ra marteze eus ur c'hefluniadur fall eus ar servijer pe eus un emzalc'h dic'hortoz all. Kit e darempred, mar plij, gant merour ar servijer, ma soñj deoc'h ez eo ur fazi. Klaskit kevreañ en-dro evit kenderc'hel da gemmañ.", - "pad.modals.corruptPad.explanation": "Breinet eo ar bloc'h emaoc'h o klask tizhout.", - "pad.modals.corruptPad.cause": "Dont a ra marteze eus ur c'hefluniadur fall eus ar servijer pe eus un emzalc'h dic'hortoz all. Kit e darempred, mar plij, gant merour ar servijer.", - "pad.modals.deleted": "Dilamet.", - "pad.modals.deleted.explanation": "Lamet eo bet ar pad-mañ.", - "pad.modals.disconnected": "Digevreet oc'h bet.", - "pad.modals.disconnected.explanation": "Kollet eo bet ar c'hevreadur gant ar servijer", - "pad.modals.disconnected.cause": "Dizimplijadus eo ar servijer marteze. Kelaouit ar servij merañ ma pad ar gudenn.", - "pad.share": "Rannañ ar pad-mañ.", - "pad.share.readonly": "Lenn hepken", - "pad.share.link": "Liamm", - "pad.share.emebdcode": "Enframmañ an URL", - "pad.chat": "Flap", - "pad.chat.title": "Digeriñ ar flap kevelet gant ar pad-mañ.", - "pad.chat.loadmessages": "Kargañ muioc'h a gemennadennoù", - "timeslider.pageTitle": "Istor dinamek eus {{appTitle}}", - "timeslider.toolbar.returnbutton": "Distreiñ d'ar pad-mañ.", - "timeslider.toolbar.authors": "Aozerien :", - "timeslider.toolbar.authorsList": "Aozer ebet", - "timeslider.toolbar.exportlink.title": "Ezporzhiañ", - "timeslider.exportCurrent": "Ezporzhiañ an doare bremañ evel :", - "timeslider.version": "Stumm {{version}}", - "timeslider.saved": "Enrollañ {{day}} {{month}} {{year}}", - "timeslider.playPause": "Lenn / Ehan endalc'hoù ar pad", - "timeslider.backRevision": "Kilit eus un adweladenn er pad-mañ", - "timeslider.forwardRevision": "Araogiñ un adweladenn er pad-mañ", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Genver", - "timeslider.month.february": "C'hwevrer", - "timeslider.month.march": "Meurzh", - "timeslider.month.april": "Ebrel", - "timeslider.month.may": "Mae", - "timeslider.month.june": "Mezheven", - "timeslider.month.july": "Gouere", - "timeslider.month.august": "Eost", - "timeslider.month.september": "Gwengolo", - "timeslider.month.october": "Here", - "timeslider.month.november": "Du", - "timeslider.month.december": "Kerzu", - "timeslider.unnamedauthors": "{{num}} dianav {[plural(num) one: aozer, other: aozerien ]}", - "pad.savedrevs.marked": "Merket eo an adweladenn-mañ evel adweladenn gwiriet", - "pad.savedrevs.timeslider": "Gallout a reot gwelet an adweladurioù enrollet en ur weladenniñ ar bignerez amzerel", - "pad.userlist.entername": "Ebarzhit hoc'h anv", - "pad.userlist.unnamed": "dizanv", - "pad.userlist.guest": "Den pedet", - "pad.userlist.deny": "Nac'h", - "pad.userlist.approve": "Aprouiñ", - "pad.editbar.clearcolors": "Diverkañ al livioù stag ouzh an aozerien en teul a-bezh ?", - "pad.impexp.importbutton": "Enporzhiañ bremañ", - "pad.impexp.importing": "Oc'h enporzhiañ...", - "pad.impexp.confirmimport": "Ma vez enporzhiet ur restr e vo diverket ar pezh zo en teul a-vremañ. Ha sur oc'h e fell deoc'h mont betek penn ?", - "pad.impexp.convertFailed": "N'eus ket bet gallet enporzhiañ ar restr. Ober gant ur furmad teul all pe eilañ/pegañ gant an dorn.", - "pad.impexp.padHasData": "N'hon eus ket gallet enporzhiañ ar restr-mañdre ma'z eus bet degaset kemmoù er bloc'h-se ; enporzhiit anezhi war-zu ur bloc'h nevez, mar plij.", - "pad.impexp.uploadFailed": "C'hwitet eo bet an enporzhiañ. Klaskit en-dro.", - "pad.impexp.importfailed": "C'hwitet eo an enporzhiadenn", - "pad.impexp.copypaste": "Eilit/pegit, mar plij", - "pad.impexp.exportdisabled": "Diweredekaet eo ezporzhiañ d'ar furmad {{type}}. Kit e darempred gant merour ar reizhiad evit gouzout hiroc'h." -} diff --git a/sources/src/locales/bs.json b/sources/src/locales/bs.json deleted file mode 100644 index e4fb574..0000000 --- a/sources/src/locales/bs.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Edinwiki", - "Srdjan m" - ] - }, - "pad.toolbar.bold.title": "Podebljano (Ctrl+B)", - "pad.toolbar.italic.title": "Ukošeno (Ctrl+I)", - "pad.toolbar.underline.title": "Podvučeno (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Precrtano (Ctrl+5)", - "pad.toolbar.ol.title": "Poredani spisak (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Neporedani spisak (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Uvučeno (TAB)", - "pad.toolbar.unindent.title": "Izvučeno (Shift+TAB)", - "pad.toolbar.undo.title": "Poništi (Ctrl+Z)", - "pad.toolbar.redo.title": "Ponovi (Ctrl+Y)", - "pad.toolbar.timeslider.title": "Historijski pregled", - "pad.toolbar.settings.title": "Postavke", - "pad.colorpicker.save": "Sačuvaj", - "pad.colorpicker.cancel": "Otkaži", - "pad.loading": "Učitavam...", - "pad.noCookie": "Kolačić nije pronađen. Dozvolite kolačiće u Vašem pregledniku!", - "pad.wrongPassword": "Pogrešna lozinka", - "pad.settings.myView": "Moj prikaz", - "pad.settings.stickychat": "Ćaskanje uvijek na ekranu", - "pad.settings.chatandusers": "Prikaži ćaskanje i korisnike", - "pad.settings.linenocheck": "Brojevi redova", - "pad.settings.rtlcheck": "Da prikažem sadržaj zdesna ulijevo?", - "pad.settings.fontType": "Vrsta fonta:", - "pad.settings.fontType.normal": "Normalno", - "pad.settings.globalView": "Globalni prikaz", - "pad.settings.language": "Jezik:", - "pad.importExport.import_export": "Uvoz/Izvoz", - "pad.importExport.import": "Postavite bilo koju tekstualnu datoteku ili dokument", - "pad.importExport.importSuccessful": "Uspješno!", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Obični tekst", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.modals.connected": "Spojeno.", - "pad.modals.forcereconnect": "Prisilno se ponovo poveži", - "pad.modals.reconnecttimer": "Pokušavam se ponovo povezati", - "pad.modals.cancel": "Otkaži", - "pad.modals.userdup": "Otvoreno u drugom prozoru", - "pad.modals.userdup.advice": "Ponovo se povežite da biste koristili ovaj prozor.", - "pad.modals.unauth": "Niste ovlašteni", - "pad.modals.initsocketfail": "Server je nedostupan.", - "pad.modals.initsocketfail.explanation": "Ne mogu se povezati sa sinhronizacijskim serverom.", - "pad.modals.slowcommit.explanation": "Server se ne odaziva.", - "pad.modals.deleted": "Obrisano.", - "pad.modals.disconnected": "Veza je prekinuta.", - "pad.modals.disconnected.explanation": "Izgubljena je veza sa serverom", - "pad.modals.disconnected.cause": "Moguće je da server nije dostupan. Obavijestite administratora ako se ovo nastavi dešavati.", - "pad.share.readonly": "Samo za čitanje", - "pad.share.link": "Link", - "pad.share.emebdcode": "URL za ugradnju", - "pad.chat": "Ćaskanje", - "pad.chat.loadmessages": "Učitaj više poruka", - "timeslider.pageTitle": "{{appTitle}} Historijski pregled", - "timeslider.toolbar.authors": "Autori:", - "timeslider.toolbar.authorsList": "Nema autora", - "timeslider.toolbar.exportlink.title": "Izvoz", - "timeslider.exportCurrent": "Izvezi trenutnu verziju kao:", - "timeslider.version": "Verzija {{version}}", - "timeslider.saved": "Sačuvano na datum {{day}}. {{month}} {{year}}", - "timeslider.month.january": "januar", - "timeslider.month.february": "februar", - "timeslider.month.march": "mart", - "timeslider.month.april": "april", - "timeslider.month.may": "maj", - "timeslider.month.june": "juni", - "timeslider.month.july": "juli", - "timeslider.month.august": "august", - "timeslider.month.september": "septembar", - "timeslider.month.october": "oktobar", - "timeslider.month.november": "novembar", - "timeslider.month.december": "decembar", - "pad.userlist.entername": "Upišite svoje ime", - "pad.userlist.unnamed": "bez imena", - "pad.userlist.guest": "Gost", - "pad.userlist.deny": "Odbij", - "pad.userlist.approve": "Odobri", - "pad.impexp.importbutton": "Uvezi odmah", - "pad.impexp.importing": "Uvozim...", - "pad.impexp.uploadFailed": "Postavljanje nije uspjelo. Pokušajte ponovo", - "pad.impexp.importfailed": "Uvoz neuspješan" -} diff --git a/sources/src/locales/ca.json b/sources/src/locales/ca.json deleted file mode 100644 index 7143061..0000000 --- a/sources/src/locales/ca.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Alvaro Vidal-Abarca", - "Pginer", - "Pitort", - "Toniher", - "Macofe", - "Joan manel", - "Eduardo Martinez", - "Jaumeortola", - "Ssola" - ] - }, - "index.newPad": "Nou pad", - "index.createOpenPad": "o crea/obre un pad amb el nom:", - "pad.toolbar.bold.title": "Negreta (Ctrl-B)", - "pad.toolbar.italic.title": "Cursiva (Ctrl-I)", - "pad.toolbar.underline.title": "Subratllat (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Ratllat (Ctrl+5)", - "pad.toolbar.ol.title": "Llista ordenada (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Llista sense ordenar (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Sagnat (TAB)", - "pad.toolbar.unindent.title": "Sagnat invers (Majúsc+TAB)", - "pad.toolbar.undo.title": "Desfés (Ctrl-Z)", - "pad.toolbar.redo.title": "Refés (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Neteja els colors d'autoria (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importa/exporta a partir de diferents formats de fitxer", - "pad.toolbar.timeslider.title": "Línia temporal", - "pad.toolbar.savedRevision.title": "Desa la revisió", - "pad.toolbar.settings.title": "Configuració", - "pad.toolbar.embed.title": "Comparteix i incrusta aquest pad", - "pad.toolbar.showusers.title": "Mostra els usuaris d’aquest pad", - "pad.colorpicker.save": "Desa", - "pad.colorpicker.cancel": "Cancel·la", - "pad.loading": "S'està carregant...", - "pad.noCookie": "No s'ha trobat la galeta. Permeteu les galetes en el navegador!", - "pad.passwordRequired": "Us cal una contrasenya per a accedir a aquest pad", - "pad.permissionDenied": "No teniu permisos per a accedir a aquest pad", - "pad.wrongPassword": "La contrasenya és incorrecta", - "pad.settings.padSettings": "Paràmetres del pad", - "pad.settings.myView": "La meva vista", - "pad.settings.stickychat": "Xateja sempre a la pantalla", - "pad.settings.chatandusers": "Mostra el xat i els usuaris", - "pad.settings.colorcheck": "Colors d'autoria", - "pad.settings.linenocheck": "Números de línia", - "pad.settings.rtlcheck": "Llegir el contingut de dreta a esquerra?", - "pad.settings.fontType": "Tipus de lletra:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "D'amplada fixa", - "pad.settings.globalView": "Vista global", - "pad.settings.language": "Llengua:", - "pad.importExport.import_export": "Importació/exportació", - "pad.importExport.import": "Puja qualsevol fitxer de text o document", - "pad.importExport.importSuccessful": "Hi ha hagut èxit!", - "pad.importExport.export": "Exporta el pad actual com a:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Text net", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Només podeu importar de text net o html. Per a opcions d'importació més avançades instal·leu l'Abiword.", - "pad.modals.connected": "Connectat.", - "pad.modals.reconnecting": "S'està tornant a connectar al vostre pad…", - "pad.modals.forcereconnect": "Força tornar a connectar", - "pad.modals.reconnecttimer": "Intentant reconnectar en", - "pad.modals.cancel": "Cancel·la", - "pad.modals.userdup": "Obert en una altra finestra", - "pad.modals.userdup.explanation": "Aquest pad sembla que està obert en més d'una finestra de navegador de l'ordinador.", - "pad.modals.userdup.advice": "Torneu a connectar-vos per a utilitzar aquesta finestra.", - "pad.modals.unauth": "No autoritzat", - "pad.modals.unauth.explanation": "Els vostres permisos han canviat mentre es visualitzava la pàgina. Proveu de reconnectar-vos.", - "pad.modals.looping.explanation": "Hi ha problemes de comunicació amb el servidor de sincronització.", - "pad.modals.looping.cause": "Potser us heu connectat a través d'un tallafocs o servidor intermediari incompatible.", - "pad.modals.initsocketfail": "El servidor no és accessible.", - "pad.modals.initsocketfail.explanation": "No s'ha pogut connectar amb el servidor de sincronització.", - "pad.modals.initsocketfail.cause": "Això és probablement a causa d'un problema amb el navegador o la connexió a Internet.", - "pad.modals.slowcommit.explanation": "El servidor no respon.", - "pad.modals.slowcommit.cause": "Això podria ser a causa de problemes amb la connectivitat de la xarxa.", - "pad.modals.badChangeset.explanation": "El servidor de sincronització ha classificat com a il·legat una edició que heu fet.", - "pad.modals.badChangeset.cause": "Això pot ser degut a una configuració errònia del servidor o a algun altre comportament inesperat. Si considereu que és un error, contacteu amb l'administrador del servei. Intenteu reconnectar-vos per a continuar editant.", - "pad.modals.corruptPad.explanation": "El pad al qual esteu intentant accedir està corrupte.", - "pad.modals.corruptPad.cause": "Això pot ser degut a una configuració errònia del servidor o a algun altre comportament inesperat. Si us plau, contacteu amb l'administrador del servei.", - "pad.modals.deleted": "Suprimit.", - "pad.modals.deleted.explanation": "S'ha suprimit el pad.", - "pad.modals.disconnected": "Heu estat desconnectat.", - "pad.modals.disconnected.explanation": "S'ha perdut la connexió amb el servidor", - "pad.modals.disconnected.cause": "El servidor sembla que no està disponible. Notifiqueu a l'administrador del servei si continua passant.", - "pad.share": "Comparteix el pad", - "pad.share.readonly": "Només de lectura", - "pad.share.link": "Enllaç", - "pad.share.emebdcode": "Incrusta l'URL", - "pad.chat": "Xat", - "pad.chat.title": "Obre el xat d'aquest pad.", - "pad.chat.loadmessages": "Carrega més missatges", - "timeslider.pageTitle": "Línia temporal — {{appTitle}}", - "timeslider.toolbar.returnbutton": "Torna al pad", - "timeslider.toolbar.authors": "Autors:", - "timeslider.toolbar.authorsList": "No hi ha autors", - "timeslider.toolbar.exportlink.title": "Exporta", - "timeslider.exportCurrent": "Exporta la versió actual com a:", - "timeslider.version": "Versió {{version}}", - "timeslider.saved": "Desat {{month}} {{day}}, {{year}}", - "timeslider.playPause": "Reproducció / Pausa els continguts del pad", - "timeslider.backRevision": "Tornar una revisió enrere en aquest Pad", - "timeslider.forwardRevision": "Anar una revisió endavant en aquest Pad", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Gener", - "timeslider.month.february": "Febrer", - "timeslider.month.march": "Març", - "timeslider.month.april": "Abril", - "timeslider.month.may": "Maig", - "timeslider.month.june": "Juny", - "timeslider.month.july": "Juliol", - "timeslider.month.august": "Agost", - "timeslider.month.september": "Setembre", - "timeslider.month.october": "Octubre", - "timeslider.month.november": "Novembre", - "timeslider.month.december": "Desembre", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor, other: autors ]} sense nom", - "pad.savedrevs.marked": "Aquesta revisió està marcada ara com a revisió desada", - "pad.savedrevs.timeslider": "Les revisions que s'han desat les podeu veure amb la línia de temps", - "pad.userlist.entername": "Introduïu el vostre nom", - "pad.userlist.unnamed": "sense nom", - "pad.userlist.guest": "Convidat", - "pad.userlist.deny": "Refusa", - "pad.userlist.approve": "Aprova", - "pad.editbar.clearcolors": "Voleu netejar els colors d'autor del document sencer?", - "pad.impexp.importbutton": "Importa ara", - "pad.impexp.importing": "Important...", - "pad.impexp.confirmimport": "En importar un fitxer se sobreescriurà el text actual del pad. Esteu segur que voleu continuar?", - "pad.impexp.convertFailed": "No és possible d'importar aquest fitxer. Si us plau, podeu provar d'utilitzar un format diferent o copiar i enganxar manualment.", - "pad.impexp.padHasData": "No vam poder importar el fitxer perquè el pad ja tenia canvis. Importeu-lo a un nou pad", - "pad.impexp.uploadFailed": "Ha fallat la càrrega. Torneu-ho a provar", - "pad.impexp.importfailed": "Ha fallat la importació", - "pad.impexp.copypaste": "Si us plau, copieu i enganxeu", - "pad.impexp.exportdisabled": "Està inhabilitada l'exportació com a {{type}}. Contacteu amb el vostre administrador de sistemes per a més informació." -} diff --git a/sources/src/locales/cs.json b/sources/src/locales/cs.json deleted file mode 100644 index 10fc55e..0000000 --- a/sources/src/locales/cs.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Jakubt", - "Jezevec", - "Juandev", - "Leanes", - "Quinn", - "Aktron", - "Mormegil", - "Dvorapa", - "Clon" - ] - }, - "index.newPad": "Založ nový Pad", - "index.createOpenPad": "nebo vytvoř/otevři Pad s názvem:", - "pad.toolbar.bold.title": "Tučný text (Ctrl-B)", - "pad.toolbar.italic.title": "Kurzíva (Ctrl-I)", - "pad.toolbar.underline.title": "Podtržené písmo (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Přeškrtnuto (Ctrl+5)", - "pad.toolbar.ol.title": "Číslovaný seznam", - "pad.toolbar.ul.title": "Nečíslovaný seznam", - "pad.toolbar.indent.title": "Odsazení (TAB)", - "pad.toolbar.unindent.title": "Předsazení (Shift+TAB)", - "pad.toolbar.undo.title": "Zpět (Ctrl-Z)", - "pad.toolbar.redo.title": "Opakovat (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Vymazat barvy autorů", - "pad.toolbar.import_export.title": "Importovat/Exportovat z/do jiných formátů", - "pad.toolbar.timeslider.title": "Časová osa", - "pad.toolbar.savedRevision.title": "Uložit revizi", - "pad.toolbar.settings.title": "Nastavení", - "pad.toolbar.embed.title": "Sdílet a umístit tento Pad", - "pad.toolbar.showusers.title": "Zobrazit uživatele u tohoto Padu", - "pad.colorpicker.save": "Uložit", - "pad.colorpicker.cancel": "Zrušit", - "pad.loading": "Načítání...", - "pad.noCookie": "Nelze nalézt cookie. Povolte prosím cookie ve Vašem prohlížeči.", - "pad.passwordRequired": "Pro přístup k tomuto Padu je třeba znát heslo", - "pad.permissionDenied": "Nemáte oprávnění pro přístup k tomuto Padu", - "pad.wrongPassword": "Nesprávné heslo", - "pad.settings.padSettings": "Nastavení Padu", - "pad.settings.myView": "Vlastní pohled", - "pad.settings.stickychat": "Chat vždy na obrazovce", - "pad.settings.chatandusers": "Ukázat Chat a Uživatele", - "pad.settings.colorcheck": "Barvy autorů", - "pad.settings.linenocheck": "Čísla řádků", - "pad.settings.rtlcheck": "Číst obsah zprava doleva?", - "pad.settings.fontType": "Typ písma:", - "pad.settings.fontType.normal": "Normální", - "pad.settings.fontType.monospaced": "Neproporční", - "pad.settings.globalView": "Globální pohled", - "pad.settings.language": "Jazyk:", - "pad.importExport.import_export": "Import/Export", - "pad.importExport.import": "Nahrát libovolný textový soubor nebo dokument", - "pad.importExport.importSuccessful": "Úspěšně!", - "pad.importExport.export": "Exportovat stávající Pad jako:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Prostý text", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Importovat můžeš pouze prostý text nebo HTML formátování. Pro pokročilejší funkce importu, prosím, nainstaluj „AbiWord“.", - "pad.modals.connected": "Připojeno.", - "pad.modals.reconnecting": "Znovupřipojování k Padu…", - "pad.modals.forcereconnect": "Vynutit znovupřipojení", - "pad.modals.reconnecttimer": "Zkouším to znovu připojit", - "pad.modals.cancel": "Zrušit", - "pad.modals.userdup": "Otevřeno v jiném okně", - "pad.modals.userdup.explanation": "Zdá se, že tento Pad je na tomto počítači otevřen ve více než jednom okně.", - "pad.modals.userdup.advice": "Pro použití tohoto okna je třeba se znovu připojit.", - "pad.modals.unauth": "Nemáte autorizaci", - "pad.modals.unauth.explanation": "Vaše oprávnění se změnila, zatímco jste si prohlížel/a toto okno. Zkuste se znovu připojit.", - "pad.modals.looping.explanation": "Nastaly problémy při komunikaci se synchronizačním serverem.", - "pad.modals.looping.cause": "Možná jste připojeni přes nekompaktní firewall nebo proxy.", - "pad.modals.initsocketfail": "Server je nedostupný.", - "pad.modals.initsocketfail.explanation": "Nepodařilo se připojit k synchronizačnímu serveru.", - "pad.modals.initsocketfail.cause": "Toto je pravděpodobně způsobeno vaším prohlížečem nebo připojením k internetu.", - "pad.modals.slowcommit.explanation": "Server neodpovídá.", - "pad.modals.slowcommit.cause": "Může to být způsobeno problémy s internetovým připojením.", - "pad.modals.badChangeset.explanation": "Editace, kterou jste učinili byla vyhodnocena jako zakázaná syncronizací serveru.", - "pad.modals.badChangeset.cause": "To může být způsobeno špatnou konfigurací serveru, nebo jiným neočekávaným chováním. Kontaktujte prosím správce služby, pokud i myslíte, že se jedná o chybu. Zkuste se připojit znovu, pokud chcete pokračovat v psaní.", - "pad.modals.corruptPad.explanation": "Pad, ke kterému se snažíte připojit je poškozen.", - "pad.modals.corruptPad.cause": "To může být kvůli špatné konfiguraci serveru, nebo kvůli jinému neočekávanému chování. Kontaktujte prosím správce služby.", - "pad.modals.deleted": "Odstraněno.", - "pad.modals.deleted.explanation": "Tento Pad byl odebrán.", - "pad.modals.disconnected": "Byl jste odpojen.", - "pad.modals.disconnected.explanation": "Připojení k serveru bylo přerušeno", - "pad.modals.disconnected.cause": "Server může být nedostupný. Upozorněte administrátora služby, pokud se to bude opakovat.", - "pad.share": "Sdílet tento Pad", - "pad.share.readonly": "Jen pro čtení", - "pad.share.link": "Odkaz", - "pad.share.emebdcode": "Vložit URL", - "pad.chat": "Chat", - "pad.chat.title": "Otevřít chat tohoto Padu.", - "pad.chat.loadmessages": "Načíst více zpráv", - "timeslider.pageTitle": "Časová osa {{appTitle}}", - "timeslider.toolbar.returnbutton": "Návrat do Padu", - "timeslider.toolbar.authors": "Autoři:", - "timeslider.toolbar.authorsList": "Bez autorů", - "timeslider.toolbar.exportlink.title": "Exportovat", - "timeslider.exportCurrent": "Exportovat nynější verzi jako:", - "timeslider.version": "Verze {{version}}", - "timeslider.saved": "Uloženo {{day}} {{month}} {{year}}", - "timeslider.playPause": "Pustit / pozastavit obsah padu", - "timeslider.backRevision": "Jít v tomto padu o revizi zpět", - "timeslider.forwardRevision": "Jít v tomto padu o revizi vpřed", - "timeslider.dateformat": "{{day}} {{month}} {{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "leden", - "timeslider.month.february": "únor", - "timeslider.month.march": "březen", - "timeslider.month.april": "duben", - "timeslider.month.may": "květen", - "timeslider.month.june": "červen", - "timeslider.month.july": "červenec", - "timeslider.month.august": "srpen", - "timeslider.month.september": "září", - "timeslider.month.october": "říjen", - "timeslider.month.november": "listopad", - "timeslider.month.december": "prosinec", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: nejmenovaný autor, few: nejmenovaní autoři, other: nejmenovaných autorů ]}", - "pad.savedrevs.marked": "Tato revize je nyní označena jako uložená", - "pad.savedrevs.timeslider": "Návštěvou časové osy zobrazíte uložené revize", - "pad.userlist.entername": "Zadejte své jméno", - "pad.userlist.unnamed": "nejmenovaný", - "pad.userlist.guest": "Host", - "pad.userlist.deny": "Zakázat", - "pad.userlist.approve": "Povolit", - "pad.editbar.clearcolors": "Odstranit barvy autorů z celého dokumentu?", - "pad.impexp.importbutton": "Importovat", - "pad.impexp.importing": "Importování…", - "pad.impexp.confirmimport": "Import souboru přepíše aktuální text v padu. Opravdu chcete tuto akci provést?", - "pad.impexp.convertFailed": "Tento soubor nelze importovat. Použijte prosím jiný formát dokumentu nebo nakopírujte text ručně", - "pad.impexp.padHasData": "Tento soubor jsme nebyly schopni importovat, protože tento Pad již obsahoval změny. Importujte ho prosím do nového padu", - "pad.impexp.uploadFailed": "Nahrávání selhalo, zkuste to znovu", - "pad.impexp.importfailed": "Import selhal", - "pad.impexp.copypaste": "Vložte prosím kopii", - "pad.impexp.exportdisabled": "Export do formátu {{type}} je zakázán. Kontaktujte svého administrátora pro zjištění detailů." -} diff --git a/sources/src/locales/da.json b/sources/src/locales/da.json deleted file mode 100644 index 06280b8..0000000 --- a/sources/src/locales/da.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Christian List", - "Peter Alberti", - "Steenth", - "Joedalton" - ] - }, - "index.newPad": "Ny Pad", - "index.createOpenPad": "eller opret/åbn en Pad med navnet:", - "pad.toolbar.bold.title": "Fed (Ctrl-B)", - "pad.toolbar.italic.title": "Kursiv (Ctrl-I)", - "pad.toolbar.underline.title": "Understregning (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Gennemstregning (Ctrl+5)", - "pad.toolbar.ol.title": "Sorteret liste (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Usorteret liste (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Indrykning (TAB)", - "pad.toolbar.unindent.title": "Ryk ud (Shift+TAB)", - "pad.toolbar.undo.title": "Fortryd (Ctrl-Z)", - "pad.toolbar.redo.title": "Annuller Fortryd (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Fjern farver for forfatterskab (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Import/eksport fra/til forskellige filformater", - "pad.toolbar.timeslider.title": "Timeslider", - "pad.toolbar.savedRevision.title": "Gem Revision", - "pad.toolbar.settings.title": "Indstillinger", - "pad.toolbar.embed.title": "Del og integrer denne pad", - "pad.toolbar.showusers.title": "Vis brugere på denne pad", - "pad.colorpicker.save": "Gem", - "pad.colorpicker.cancel": "Afbryd", - "pad.loading": "Indlæser ...", - "pad.noCookie": "Cookie kunne ikke findes. Tillad venligst cookier i din browser!", - "pad.passwordRequired": "Du skal bruge en adgangskode for at få adgang til denne pad", - "pad.permissionDenied": "Du har ikke tilladelse til at få adgang til denne pad.", - "pad.wrongPassword": "Din adgangskode er forkert", - "pad.settings.padSettings": "Pad indstillinger", - "pad.settings.myView": "Min visning", - "pad.settings.stickychat": "Chat altid på skærmen", - "pad.settings.chatandusers": "Vis snak (chat) og brugere", - "pad.settings.colorcheck": "Forfatterskabsfarver", - "pad.settings.linenocheck": "Linjenumre", - "pad.settings.rtlcheck": "Læse indhold fra højre mod venstre?", - "pad.settings.fontType": "Skrifttype:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Fastbredde", - "pad.settings.globalView": "Global visning", - "pad.settings.language": "Sprog:", - "pad.importExport.import_export": "Import/Eksport", - "pad.importExport.import": "Uploade en tekstfil eller dokument", - "pad.importExport.importSuccessful": "Vellykket!", - "pad.importExport.export": "Eksporter aktuelle pad som:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Almindelig tekst", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Du kan kun importere fra almindelig tekst eller HTML-formater. For mere avancerede importfunktioner, installer AbiWord.", - "pad.modals.connected": "Forbundet.", - "pad.modals.reconnecting": "Genopretter forbindelsen til din pad...", - "pad.modals.forcereconnect": "Gennemtving genoprettelse af forbindelsen", - "pad.modals.reconnecttimer": "Prøver at tilkoble igen", - "pad.modals.cancel": "Afbryd", - "pad.modals.userdup": "Åbnet i et andet vindue", - "pad.modals.userdup.explanation": "Denne pad synes at være åbnet i mere end ét browservindue på denne computer.", - "pad.modals.userdup.advice": "Tilslut igen for at bruge dette vindue i stedet.", - "pad.modals.unauth": "Ikke tilladt", - "pad.modals.unauth.explanation": "Dine rettigheder er ændret mens du ser på denne side. Prøv at oprette forbindelsen igen.", - "pad.modals.looping.explanation": "Der er kommunikationsproblemer med synkroniseringsserveren.", - "pad.modals.looping.cause": "Måske tilsluttede du via en inkompatibel firewall eller proxy.", - "pad.modals.initsocketfail": "Serveren er ikke tilgængelig.", - "pad.modals.initsocketfail.explanation": "Kunne ikke oprette forbindelse til synkroniseringsserveren.", - "pad.modals.initsocketfail.cause": "Det skyldes sandsynligvis et problem med din browser eller din internetforbindelse.", - "pad.modals.slowcommit.explanation": "Serveren svarer ikke.", - "pad.modals.slowcommit.cause": "Det kan skyldes problemer med netværksforbindelsen.", - "pad.modals.badChangeset.explanation": "En redigering, du har foretaget, blev klassificeret ulovlig af synkroniseringsserveren.", - "pad.modals.badChangeset.cause": "Dette kan skyldes en forkert konfiguration af serveren eller en anden uventet adfærd. Kontakt venligst service administratoren, hvis du føler, at dette er en fejl. Prøv at oprette forbindelsen igen for at fortsætte med at redigere.", - "pad.modals.corruptPad.explanation": "Den pad du prøver at få adgang til er beskadiget.", - "pad.modals.corruptPad.cause": "Dette kan skyldes en forkert konfiguration af serveren eller en anden uventet adfærd. Kontakt venligst service administratoren.", - "pad.modals.deleted": "Slettet.", - "pad.modals.deleted.explanation": "Denne pad er blevet fjernet.", - "pad.modals.disconnected": "Du har fået afbrudt forbindelsen.", - "pad.modals.disconnected.explanation": "Forbindelsen til serveren blev afbrudt", - "pad.modals.disconnected.cause": "Serveren er muligvis ikke tilgængelig. Informer service administratoren hvis dette fortsætter med at ske.", - "pad.share": "Del denne pad", - "pad.share.readonly": "Skrivebeskyttet", - "pad.share.link": "Link", - "pad.share.emebdcode": "Integrerings URL", - "pad.chat": "Chat", - "pad.chat.title": "Åben chat for denne pad.", - "pad.chat.loadmessages": "Indlæs flere meddelelser", - "timeslider.pageTitle": "{{appTitle}} Timeslider", - "timeslider.toolbar.returnbutton": "Tilbage til pad", - "timeslider.toolbar.authors": "Forfattere:", - "timeslider.toolbar.authorsList": "Ingen forfattere", - "timeslider.toolbar.exportlink.title": "Eksportér", - "timeslider.exportCurrent": "Eksporter aktuelle version som:", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Gemt den {{day}}.{{month}} {{year}}", - "timeslider.playPause": "Afspil eller sæt padindhold på pause", - "timeslider.backRevision": "Gå en revision tilbage i denne pad", - "timeslider.forwardRevision": "Gå en revision fremad i denne pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "januar", - "timeslider.month.february": "februar", - "timeslider.month.march": "marts", - "timeslider.month.april": "april", - "timeslider.month.may": "maj", - "timeslider.month.june": "juni", - "timeslider.month.july": "juli", - "timeslider.month.august": "august", - "timeslider.month.september": "september", - "timeslider.month.october": "oktober", - "timeslider.month.november": "november", - "timeslider.month.december": "december", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: unavngiven forfatter, other: unavngivne forfattere]}", - "pad.savedrevs.marked": "Denne revision er nu markeret som en gemt revision", - "pad.savedrevs.timeslider": "Du kan se gemte revisioner ved at besøge tidslinjen", - "pad.userlist.entername": "Indtast dit navn", - "pad.userlist.unnamed": "ikke-navngivet", - "pad.userlist.guest": "Gæst", - "pad.userlist.deny": "Nægt", - "pad.userlist.approve": "Godkend", - "pad.editbar.clearcolors": "Fjern farver for ophavsmand i hele dokumentet?", - "pad.impexp.importbutton": "Importer nu", - "pad.impexp.importing": "Importerer...", - "pad.impexp.confirmimport": "At importere en fil, vil overskrives den aktuelle pad tekst. Er du sikker på du vil fortsætte?", - "pad.impexp.convertFailed": "Vi var ikke i stand til at importere denne fil. Brug et andet dokument-format eller kopier og sæt ind manuelt", - "pad.impexp.padHasData": "Vi kunne ikke importere denne fil, da denne pad allerede har haft ændringer; lav venligst import til en ny pad", - "pad.impexp.uploadFailed": "Upload mislykkedes, prøv igen", - "pad.impexp.importfailed": "Importen mislykkedes", - "pad.impexp.copypaste": "Venligst kopier og sæt ind", - "pad.impexp.exportdisabled": "Eksportere i {{type}} format er deaktiveret. Kontakt din systemadministrator for mere information." -} diff --git a/sources/src/locales/de.json b/sources/src/locales/de.json deleted file mode 100644 index 85bd3bf..0000000 --- a/sources/src/locales/de.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Metalhead64", - "Mklehr", - "Nipsky", - "Wikinaut", - "Thargon", - "Predatorix", - "Sebastian Wallroth" - ] - }, - "index.newPad": "Neues Pad", - "index.createOpenPad": "oder ein Pad mit folgendem Namen erstellen/öffnen:", - "pad.toolbar.bold.title": "Fett (Strg-B)", - "pad.toolbar.italic.title": "Kursiv (Strg-I)", - "pad.toolbar.underline.title": "Unterstrichen (Strg-U)", - "pad.toolbar.strikethrough.title": "Durchgestrichen (Strg+5)", - "pad.toolbar.ol.title": "Nummerierte Liste (Strg+Shift+N)", - "pad.toolbar.ul.title": "Ungeordnete Liste (Strg+Shift+L)", - "pad.toolbar.indent.title": "Einrücken (TAB)", - "pad.toolbar.unindent.title": "Ausrücken (Shift+TAB)", - "pad.toolbar.undo.title": "Rückgängig (Strg-Z)", - "pad.toolbar.redo.title": "Wiederholen (Strg-Y)", - "pad.toolbar.clearAuthorship.title": "Autorenfarben zurücksetzen (Strg+Shift+C)", - "pad.toolbar.import_export.title": "Import/Export von/zu verschiedenen Dateiformaten", - "pad.toolbar.timeslider.title": "Bearbeitungsverlauf", - "pad.toolbar.savedRevision.title": "Version speichern", - "pad.toolbar.settings.title": "Einstellungen", - "pad.toolbar.embed.title": "Dieses Pad teilen oder einbetten", - "pad.toolbar.showusers.title": "Benutzer dieses Pads anzeigen", - "pad.colorpicker.save": "Speichern", - "pad.colorpicker.cancel": "Abbrechen", - "pad.loading": "Lade …", - "pad.noCookie": "Das Cookie konnte nicht gefunden werden. Bitte erlaube Cookies in deinem Browser!", - "pad.passwordRequired": "Sie benötigen ein Kennwort, um auf dieses Pad zuzugreifen", - "pad.permissionDenied": "Sie haben keine Berechtigung, um auf dieses Pad zuzugreifen", - "pad.wrongPassword": "Ihr eingegebenes Kennwort war falsch", - "pad.settings.padSettings": "Pad-Einstellungen", - "pad.settings.myView": "Eigene Ansicht", - "pad.settings.stickychat": "Unterhaltung immer anzeigen", - "pad.settings.chatandusers": "Unterhaltung und Benutzer anzeigen", - "pad.settings.colorcheck": "Autorenfarben anzeigen", - "pad.settings.linenocheck": "Zeilennummern", - "pad.settings.rtlcheck": "Inhalt von rechts nach links lesen?", - "pad.settings.fontType": "Schriftart:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Gemeinsame Ansicht", - "pad.settings.language": "Sprache:", - "pad.importExport.import_export": "Import/Export", - "pad.importExport.import": "Text-Datei oder Dokument hochladen", - "pad.importExport.importSuccessful": "Erfolgreich!", - "pad.importExport.export": "Aktuelles Pad exportieren als:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Textdatei", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Sie können nur aus reinen Text- oder HTML-Formaten importieren. Für umfangreichere Importfunktionen installieren Sie bitte AbiWord.", - "pad.modals.connected": "Verbunden.", - "pad.modals.reconnecting": "Wiederherstellen der Verbindung …", - "pad.modals.forcereconnect": "Erneutes Verbinden erzwingen", - "pad.modals.reconnecttimer": "Versuche Neuverbindung in", - "pad.modals.cancel": "Abbrechen", - "pad.modals.userdup": "In einem anderen Fenster geöffnet", - "pad.modals.userdup.explanation": "Dieses Pad scheint in mehr als einem Browser-Fenster auf diesem Rechner geöffnet zu sein.", - "pad.modals.userdup.advice": "Um stattdessen dieses Fenster zu verwenden, verbinden Sie sich bitte erneut.", - "pad.modals.unauth": "Nicht berechtigt", - "pad.modals.unauth.explanation": "Ihre Zugriffsberechtigung für dieses Pad hat sich zwischenzeitlich geändert. Versuchen Sie sich erneut zu verbinden.", - "pad.modals.looping.explanation": "Es gibt Verbindungsprobleme mit dem Server.", - "pad.modals.looping.cause": "Möglicherweise sind Sie durch eine inkompatible Firewall oder über einen inkompatiblen Proxy mit dem Server verbunden.", - "pad.modals.initsocketfail": "Der Server ist nicht erreichbar.", - "pad.modals.initsocketfail.explanation": "Es konnte keine Verbindung zum Server hergestellt werden.", - "pad.modals.initsocketfail.cause": "Dies könnte an Ihrem Browser oder Ihrer Internet-Verbindung liegen.", - "pad.modals.slowcommit.explanation": "Der Server antwortet nicht.", - "pad.modals.slowcommit.cause": "Dies könnte ein Netzwerkverbindungsproblem sein oder eine momentane Überlastung des Servers.", - "pad.modals.badChangeset.explanation": "Eine von Ihnen gemachte Änderung wurde vom Server als ungültig eingestuft.", - "pad.modals.badChangeset.cause": "Dies könnte aufgrund einer falschen Serverkonfiguration oder eines anderen unerwarteten Verhaltens passiert sein. Bitte kontaktiere den Diensteadministrator, falls du glaubst, dass es sich um einen Fehler handelt. Versuche dich erneut zu verbinden, um mit dem Bearbeiten fortzufahren.", - "pad.modals.corruptPad.explanation": "Das Pad, auf das Sie versuchen zuzugreifen, ist beschädigt.", - "pad.modals.corruptPad.cause": "Dies könnte an einer falschen Serverkonfiguration oder eines anderen unerwarteten Verhaltens liegen. Bitte kontaktieren Sie den Administrator dieses Dienstes.", - "pad.modals.deleted": "Gelöscht.", - "pad.modals.deleted.explanation": "Dieses Pad wurde entfernt.", - "pad.modals.disconnected": "Ihre Verbindung wurde getrennt.", - "pad.modals.disconnected.explanation": "Die Verbindung zum Server wurde unterbrochen.", - "pad.modals.disconnected.cause": "Möglicherweise ist der Server nicht erreichbar. Bitte benachrichtigen Sie den Dienstadministrator, falls dies weiterhin passiert.", - "pad.share": "Dieses Pad teilen", - "pad.share.readonly": "Eingeschränkter Nur-Lese-Zugriff", - "pad.share.link": "Verknüpfung", - "pad.share.emebdcode": "In Webseite einbetten", - "pad.chat": "Unterhaltung", - "pad.chat.title": "Den Chat für dieses Pad öffnen.", - "pad.chat.loadmessages": "Weitere Nachrichten laden", - "timeslider.pageTitle": "{{appTitle}} Bearbeitungsverlauf", - "timeslider.toolbar.returnbutton": "Zurück zum Pad", - "timeslider.toolbar.authors": "Autoren:", - "timeslider.toolbar.authorsList": "keine Autoren", - "timeslider.toolbar.exportlink.title": "Diese Version exportieren", - "timeslider.exportCurrent": "Exportiere diese Version als:", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Gespeichert am {{day}}. {{month}} {{year}}", - "timeslider.playPause": "Padbearbeitung abspielen/pausieren", - "timeslider.backRevision": "Eine Version in diesem Pad zurück gehen", - "timeslider.forwardRevision": "Eine Version in diesem Pad vorwärts gehen", - "timeslider.dateformat": "{{day}}.{{month}}.{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januar", - "timeslider.month.february": "Februar", - "timeslider.month.march": "März", - "timeslider.month.april": "April", - "timeslider.month.may": "Mai", - "timeslider.month.june": "Juni", - "timeslider.month.july": "Juli", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "Oktober", - "timeslider.month.november": "November", - "timeslider.month.december": "Dezember", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: unbenannter Autor, other: unbenannte Autoren ]}", - "pad.savedrevs.marked": "Diese Version wurde jetzt als gespeicherte Version gekennzeichnet", - "pad.savedrevs.timeslider": "Du kannst gespeicherte Versionen durch den Aufruf des Bearbeitungsverlaufes ansehen", - "pad.userlist.entername": "Geben Sie Ihren Namen ein", - "pad.userlist.unnamed": "unbenannt", - "pad.userlist.guest": "Gast", - "pad.userlist.deny": "Verweigern", - "pad.userlist.approve": "Genehmigen", - "pad.editbar.clearcolors": "Autorenfarben im gesamten Dokument zurücksetzen?", - "pad.impexp.importbutton": "Jetzt importieren", - "pad.impexp.importing": "Importiere …", - "pad.impexp.confirmimport": "Das Importieren einer Datei überschreibt den aktuellen Text des Pads. Wollen Sie wirklich fortfahren?", - "pad.impexp.convertFailed": "Diese Datei konnte nicht importiert werden. Bitte verwenden Sie ein anderes Dokumentformat oder übertragen Sie den Text manuell.", - "pad.impexp.padHasData": "Diese Datei konnte nicht importiert werden, da dieses Pad bereits Änderungen enthält. Bitte importieren Sie die Datei in ein neues Pad.", - "pad.impexp.uploadFailed": "Das Hochladen ist fehlgeschlagen. Bitte versuchen Sie es erneut.", - "pad.impexp.importfailed": "Import fehlgeschlagen", - "pad.impexp.copypaste": "Bitte kopieren und einfügen", - "pad.impexp.exportdisabled": "Der Export im {{type}}-Format ist deaktiviert. Für Einzelheiten kontaktieren Sie bitte Ihren Systemadministrator." -} diff --git a/sources/src/locales/diq.json b/sources/src/locales/diq.json deleted file mode 100644 index a823232..0000000 --- a/sources/src/locales/diq.json +++ /dev/null @@ -1,136 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Erdemaslancan", - "Gorizon", - "Mirzali", - "Kumkumuk", - "1917 Ekim Devrimi", - "Gırd" - ] - }, - "index.newPad": "Pedo newe", - "index.createOpenPad": "Yana eno bamaeya bloknot vıraz/ak:", - "pad.toolbar.bold.title": "Qalın (Ctrl-B)", - "pad.toolbar.italic.title": "Namıte (Ctrl-I)", - "pad.toolbar.underline.title": "Bınxetın (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Serxetın (Ctrl+5)", - "pad.toolbar.ol.title": "Lista rêzkerdiye (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Lista rêznêkerdiye (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Serrêze (TAB)", - "pad.toolbar.unindent.title": "Teberdayış (Shift+TAB)", - "pad.toolbar.undo.title": "Meke (Ctrl-Z)", - "pad.toolbar.redo.title": "Fına bıke (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Rengê Nuştoğiê Arıstey (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Babaetna tewranê dosyaya azere/ateber ke", - "pad.toolbar.timeslider.title": "Ğızagê zemani", - "pad.toolbar.savedRevision.title": "Çımraviyarnayışi qeyd ke", - "pad.toolbar.settings.title": "Sazkerdışi", - "pad.toolbar.embed.title": "Na bloknot degusn u bıhesrne", - "pad.toolbar.showusers.title": "Karbera ena bloknot dı bımotné", - "pad.colorpicker.save": "Qeyd ke", - "pad.colorpicker.cancel": "Bıtexelne", - "pad.loading": "Bar beno...", - "pad.noCookie": "Çerez nêvibeya. Rovıter de çereza aktiv kerê", - "pad.passwordRequired": "Ena bloknot resayışi rê parola icab krna", - "pad.permissionDenied": "Ena bloknot resayışi rê icazeta şıma çıni ya", - "pad.wrongPassword": "Parola şıma ğeleta", - "pad.settings.padSettings": "Sazkerdışê Pedi", - "pad.settings.myView": "Asayışê mı", - "pad.settings.stickychat": "Ekran de tım mıhebet bıkerê", - "pad.settings.chatandusers": "Werênayış û Karberan bımocne", - "pad.settings.colorcheck": "Rengê nuştekariye", - "pad.settings.linenocheck": "Nımreyê xeter", - "pad.settings.rtlcheck": "Zerrek heto raşt ra be heto çep bıwaniyo?", - "pad.settings.fontType": "Babeta nuşti:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Yewca", - "pad.settings.globalView": "Asayışo Global", - "pad.settings.language": "Zıwan:", - "pad.importExport.import_export": "Zerredayış/Teberdayış", - "pad.importExport.import": "Dosya ya zi dokumanê meqaleyê de tesadufi bar ke", - "pad.importExport.importSuccessful": "Mıwafaq biye", - "pad.importExport.export": "Mewcud bloknoti ateberd:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Metno pan", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Şıma şenê tenya metınanê zelalan ya zi formatanê HTML-i biyarê. Seba vêşi xısusiyetanê arezekerdışi ra gırey AbiWord-i bar kerên.", - "pad.modals.connected": "Gırediya.", - "pad.modals.reconnecting": "Bloknot da şıma rê fına irtibat kewê no", - "pad.modals.forcereconnect": "Mecbur anciya gırê de", - "pad.modals.reconnecttimer": "Anciya gırê beno", - "pad.modals.cancel": "Bıtexelne", - "pad.modals.userdup": "Zewbina pençere de bi a", - "pad.modals.userdup.explanation": "Ena bloknot ena komputer de yew ra zeder penceran dı akerde asena", - "pad.modals.userdup.advice": "Ena pencera ra kar finayışi rê fına irtibat kewê", - "pad.modals.unauth": "Selahiyetdar niyo", - "pad.modals.unauth.explanation": "Ena pela asenayış de mısadey şıma vuriyay. Fına irtibat kewtışi bıcerebne", - "pad.modals.looping.explanation": "Bahdê takêş kerdışi problemê irtibati esta", - "pad.modals.looping.cause": "Belki zi dêsê emeley hewl niyo yana şımayê proksi ya kenê dekewê de", - "pad.modals.initsocketfail": "Nêresneyêno ciyageyroği.", - "pad.modals.initsocketfail.explanation": "Rovıterê takêş kerdışi ya irtibato nêbeno.", - "pad.modals.initsocketfail.cause": "Ena probleme muhtemelen komputer yana grebıyayışa ibter da şıma ra bıya", - "pad.modals.slowcommit.explanation": "Server cewab nêdano.", - "pad.modals.slowcommit.cause": "Ena xeta gındık ta greyan de şıma ameya meydan", - "pad.modals.badChangeset.explanation": "Ena vurriyayışa şıma tereftê rovıterê tekêş kerdışi ra bêkaide deyne liste biya", - "pad.modals.badChangeset.cause": "Eno, xırab vıraziyena rovıteri yana nezanaye xırab yew faktori ra amrya meydan. Ena şıma çımdı xeta yena se idarekaran de sisteniya irtibat kewê. Dewam kerdışi re fına grebıyayışi bıcerebne", - "pad.modals.corruptPad.explanation": "Bloknota ke şımayê kenê cıresê xerpiyayi ya", - "pad.modals.corruptPad.cause": "Eno, xırab vıraziyena rovıteri yana nezanaye xırab yew faktori ra amrya meydan. Ena şıma çımdı xeta yena se idarekaran de sisteniya irtibat kewê", - "pad.modals.deleted": "Esteriya.", - "pad.modals.deleted.explanation": "Ena ped wedariye", - "pad.modals.disconnected": "İrtibata şıma reyê", - "pad.modals.disconnected.explanation": "Rovıteri ya irtibata şıma reyyê", - "pad.modals.disconnected.cause": "Qay rovıtero nêkarên o. Ena xerpey deqam kena se idarekaranê sistemiya irtibat kewê", - "pad.share": "Na ped vıla ke", - "pad.share.readonly": "Tenya bıwane", - "pad.share.link": "Gıre", - "pad.share.emebdcode": "Degusnaye URL", - "pad.chat": "Mıhebet", - "pad.chat.title": "Qandê ena ped mıhebet ake.", - "pad.chat.loadmessages": "Dehana zaf mesaci bar keri", - "timeslider.pageTitle": "Ğızagê zemani {{appTitle}}", - "timeslider.toolbar.returnbutton": "Peyser şo ped", - "timeslider.toolbar.authors": "Nuştoği:", - "timeslider.toolbar.authorsList": "Nuştoği çıniyê", - "timeslider.toolbar.exportlink.title": "Teberdayış", - "timeslider.exportCurrent": "Versiyonê enewki teber de:", - "timeslider.version": "Versiyonê {{version}}", - "timeslider.saved": "{{day}} {{month}}, {{year}} de biyo qeyd", - "timeslider.playPause": "Zerrekê bloknoti kayfi/vındarn", - "timeslider.backRevision": "Peyser şo revizyona ena bloknoter", - "timeslider.forwardRevision": "Ena bloknot de şo revizyonê bini", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Çele", - "timeslider.month.february": "Zemherı", - "timeslider.month.march": "Adar", - "timeslider.month.april": "Nisane", - "timeslider.month.may": "Gúlan", - "timeslider.month.june": "Heziran", - "timeslider.month.july": "Temuz", - "timeslider.month.august": "Tebaxe", - "timeslider.month.september": "Keşkelun", - "timeslider.month.october": "Tışrino Verên", - "timeslider.month.november": "Tışrino Peyên", - "timeslider.month.december": "Kanun", - "timeslider.unnamedauthors": "{{num}} unnamed {[plural(num) zu: nuştoğ, zewbi: nustoği ]}", - "pad.savedrevs.marked": "Eno vurriyayış henda qeyd bıyaye yew vurriyayış deyne nışan bıyo", - "pad.savedrevs.timeslider": "Xızberê zemani ziyer kerdış ra şıma şenê revizyonanê qeyd bıyayan bıvinê", - "pad.userlist.entername": "Namey xo cıkewe", - "pad.userlist.unnamed": "Name nébıyo", - "pad.userlist.guest": "Meyman", - "pad.userlist.deny": "Red ke", - "pad.userlist.approve": "Tesdiq ke", - "pad.editbar.clearcolors": "Wesiqa de renge nuştoğey bıesterneye?", - "pad.impexp.importbutton": "Nıka miyan ke", - "pad.impexp.importing": "Deyeno azere...", - "pad.impexp.confirmimport": "Yu dosya azere kerdış de mewcud bloknoti sero nuşiye no. Şıma qayılê dewam bıkerê?", - "pad.impexp.convertFailed": "Ena dosya azere kerdış mıkum niyo. Babetna namey dokumani weçinê yana xo desti kopya kerê u pronê.", - "pad.impexp.padHasData": "Ma nêşa dosya azere kem, çıkı ena bloknot xora vurriya ya. Xorê yewna bloknot azere kerê", - "pad.impexp.uploadFailed": "Barkerdış nêbi, kerem ke anciya bıcerebne", - "pad.impexp.importfailed": "Zer kerdış mıwafaq nebı", - "pad.impexp.copypaste": "Reca keme kopya pronayış bıkeri", - "pad.impexp.exportdisabled": "Formatta {{type}} ya ateber kerdış dewra vıciya yo. Qandé teferruati idarekarana irtibat kewê" -} diff --git a/sources/src/locales/dsb.json b/sources/src/locales/dsb.json deleted file mode 100644 index 0600be9..0000000 --- a/sources/src/locales/dsb.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Michawiki" - ] - }, - "index.newPad": "Nowy zapisnik", - "index.createOpenPad": "abo napóraj/wócyń zapisnik z mjenim:", - "pad.toolbar.bold.title": "Tucny (Strg-B)", - "pad.toolbar.italic.title": "Kursiwny (Strg-I)", - "pad.toolbar.underline.title": "Pódšmarnuś (Strg-U)", - "pad.toolbar.strikethrough.title": "Pśešmarnuś", - "pad.toolbar.ol.title": "Numerěrowana lisćina", - "pad.toolbar.ul.title": "Nalicenje", - "pad.toolbar.indent.title": "Zasunuś (TAB)", - "pad.toolbar.unindent.title": "Wusunuś (Umsch+TAB)", - "pad.toolbar.undo.title": "Anulěrowaś (Strg-Z)", - "pad.toolbar.redo.title": "Wóspjetowaś (Strg-Y)", - "pad.toolbar.clearAuthorship.title": "Awtorowe barwy lašowaś", - "pad.toolbar.import_export.title": "Import/Eksport z/do drugich datajowych formatow", - "pad.toolbar.timeslider.title": "Wersijowa historija", - "pad.toolbar.savedRevision.title": "Wersiju składowaś", - "pad.toolbar.settings.title": "Nastajenja", - "pad.toolbar.embed.title": "Toś ten zapisnik źěliś a zasajźiś", - "pad.toolbar.showusers.title": "Wužywarje na toś tom zapisniku pokazaś", - "pad.colorpicker.save": "Składowaś", - "pad.colorpicker.cancel": "Pśetergnuś", - "pad.loading": "Zacytujo se...", - "pad.passwordRequired": "Trjebaš gronidło, aby na toś ten zapisnik pśistup měł", - "pad.permissionDenied": "Njamaš pśistupne pšawo za toś ten zapisnik.", - "pad.wrongPassword": "Twójo gronidło jo wopaki było", - "pad.settings.padSettings": "Nastajenja zapisnika", - "pad.settings.myView": "Mój naglěd", - "pad.settings.stickychat": "Chat pśecej na wobrazowce pokazaś", - "pad.settings.colorcheck": "Awtorowe barwy", - "pad.settings.linenocheck": "Smužkowe numery", - "pad.settings.rtlcheck": "Wopśimjeśe wótpšawa nalěwo cytaś?", - "pad.settings.fontType": "Pismowa družyna:", - "pad.settings.fontType.normal": "Normalny", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Globalny naglěd", - "pad.settings.language": "Rěc:", - "pad.importExport.import_export": "Import/Eksport", - "pad.importExport.import": "Tekstowu dataju abo dokument nagraś", - "pad.importExport.importSuccessful": "Wuspěšny!", - "pad.importExport.export": "Aktualny zapisnik eksportěrowaś ako:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Lutny tekst", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Móžoš jano z fprmatow lutnego teksta abo z HTML-formata importěrowaś. Za wěcej rozšyrjone importěrowańske funkcije instalěruj pšosym Abiword.", - "pad.modals.connected": "Zwězany.", - "pad.modals.reconnecting": "Zwězujo se znowego z twójim zapisnikom...", - "pad.modals.forcereconnect": "Znowego zwězaś", - "pad.modals.userdup": "W drugem woknje wócynjony", - "pad.modals.userdup.explanation": "Zda se, až toś ten zapisnik jo se we wěcej ako jadnem woknje wobglědowaka na toś tom licadłu wócynił.", - "pad.modals.userdup.advice": "Zwězaj znowego, aby toś to wokno město togo wužywał.", - "pad.modals.unauth": "Njeawtorizěrowany", - "pad.modals.unauth.explanation": "Pśi wobglědowanju toś togo boka su se twóje pšawa změnili. Wopytaj se znowego zwězaś.", - "pad.modals.looping.explanation": "Su komunikaciske problemy ze synchronizěrowańskim serwerom.", - "pad.modals.looping.cause": "Snaź sy pśez njekompatibelnu wognjowu murju abo proksy zwězany.", - "pad.modals.initsocketfail": "Serwer njejo dojśpiwajobny.", - "pad.modals.initsocketfail.explanation": "Zwisk ze synchronizěrowańskim serwerom njejo móžno.", - "pad.modals.initsocketfail.cause": "To jo nejskerjej problem z twójim wobglědowakom abo twójim internetnym zwiskom.", - "pad.modals.slowcommit.explanation": "Serwer njewótegranja.", - "pad.modals.slowcommit.cause": "To by mógło problem seśowego zwiska byś.", - "pad.modals.badChangeset.explanation": "Změna, kótaruž sy pśewjadł, jo se pśez synchronizěrowański serwer ako njedowólonu markěrowała.", - "pad.modals.badChangeset.cause": "To jo se snaź wopacneje serweroweje konfiguracije dla abo drugego njewócakanego zaźaeržanja dla stało. Pšosym staj se ze słužbowym administratorom do zwiska, jolic se mysliš, až to jo zmólka. Wopytaj hyšći raz zwězaś, aby z wobźěłowanim pókšacował.", - "pad.modals.corruptPad.explanation": "Zapisnik, na kótaryž coš pśistup měś, jo wobškóźony.", - "pad.modals.corruptPad.cause": "To jo se snaź wopacneje serweroweje konfiguracije dla abo drugego njewócakanego zaźaržanja dla stało. Pšosym staj se ze słužbowym administratorom do zwiska.", - "pad.modals.deleted": "Wulašowany.", - "pad.modals.deleted.explanation": "Toś ten zapisnik jo se wótpórał.", - "pad.modals.disconnected": "Zwisk jo pśetergnjony.", - "pad.modals.disconnected.explanation": "Zwisk ze serwerom jo se zgubił", - "pad.modals.disconnected.cause": "Serwer njestoj k dispoziciji. Pšosym informěruj słužbowego administratora, jolic to se dalej stawa.", - "pad.share": "Toś ten zapisnik źěliś", - "pad.share.readonly": "Jano cytajobny", - "pad.share.link": "Wótkaz", - "pad.share.emebdcode": "URL zasajźiś", - "pad.chat": "Chat", - "pad.chat.title": "Chat za toś ten zapisnik wócyniś", - "pad.chat.loadmessages": "Dalšne powěsći zacytaś", - "timeslider.pageTitle": "{{appTitle}} - wersijowa historija", - "timeslider.toolbar.returnbutton": "Slědk k zapisnikoju", - "timeslider.toolbar.authors": "Awtory:", - "timeslider.toolbar.authorsList": "Žedne awtory", - "timeslider.toolbar.exportlink.title": "Eksportěrowaś", - "timeslider.exportCurrent": "Aktualnu wersiju eksportěrowaś ako:", - "timeslider.version": "Wersija {{version}}", - "timeslider.saved": "Składowany {{day}}. {{month}} {{year}}", - "timeslider.dateformat": "{{day}}. {{month}} {{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "januara", - "timeslider.month.february": "februara", - "timeslider.month.march": "měrca", - "timeslider.month.april": "apryla", - "timeslider.month.may": "maja", - "timeslider.month.june": "junija", - "timeslider.month.july": "julija", - "timeslider.month.august": "awgusta", - "timeslider.month.september": "septembra", - "timeslider.month.october": "oktobra", - "timeslider.month.november": "nowembra", - "timeslider.month.december": "decembra", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: awtor, two: awtora, few: awtory, other: awtorow ]} bźez mjenja", - "pad.savedrevs.marked": "Toś ta wersija jo se něnto ako składowana wersija markěrowała", - "pad.userlist.entername": "Zapódaj swójo mě", - "pad.userlist.unnamed": "bźez mjenja", - "pad.userlist.guest": "Gósć", - "pad.userlist.deny": "Wótpokazaś", - "pad.userlist.approve": "Pśizwóliś", - "pad.editbar.clearcolors": "Awtorowe barwy w cełem dokumenśe lašowaś?", - "pad.impexp.importbutton": "Něnto importěrowaś", - "pad.impexp.importing": "Importěrujo se...", - "pad.impexp.confirmimport": "Importowanje dataje pśepišo aktualny tekst zapisnika. Coš napšawdu pókšacowaś?", - "pad.impexp.convertFailed": "Njejsmy mógli toś tu dataju importěrowaś. Pšosym wužyj drugi dokumentowy format abo kopěruj manuelnje", - "pad.impexp.uploadFailed": "Nagraśe njejo se raźiło, pšosym wopytaj hyšći raz", - "pad.impexp.importfailed": "Import njejo se raził", - "pad.impexp.copypaste": "Pšosym kopěrowaś a zasajźiś", - "pad.impexp.exportdisabled": "Eksport ako format {{type}} jo znjemóžnjony. Pšosym staj se ze swójim systemowym administratorom za drobnostki do zwiska." -} diff --git a/sources/src/locales/dty.json b/sources/src/locales/dty.json deleted file mode 100644 index 0682da6..0000000 --- a/sources/src/locales/dty.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "@metadata": { - "authors": [ - "रमेश सिंह बोहरा", - "राम प्रसाद जोशी", - "Nirajan pant" - ] - }, - "index.newPad": "नौलो प्याड", - "index.createOpenPad": "नाउँ सहितको नौलो प्याड सिर्जना गद्य्या / खोल्ल्या :", - "pad.toolbar.bold.title": "मोटो (Ctrl-B)", - "pad.toolbar.italic.title": "ढल्के (Ctrl-I)", - "pad.toolbar.underline.title": "इसो रेखाङ्कन (Ctrl-U)", - "pad.toolbar.strikethrough.title": "बीचको धड्को (Ctrl+5)", - "pad.toolbar.ol.title": "एकनासको सूची (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "अक्रमाङ्कित सूची (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "इन्डेन्ट (TAB)", - "pad.toolbar.unindent.title": "आउटडेन्ट (Shift+TAB)", - "pad.toolbar.undo.title": "अण्डू (Ctrl-Z)", - "pad.toolbar.redo.title": "दोसर्या:लागु (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "लेखकीय रङ्ग हटाउन्या (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "विविध फाइल फर्म्याटअन बठेइ/मी आयात/निर्यात", - "pad.toolbar.timeslider.title": "टाइमस्लाइडर", - "pad.toolbar.savedRevision.title": "पुनरावलोकन संग्रह गद्य्या", - "pad.toolbar.settings.title": "सेटिङ्गअन", - "pad.toolbar.embed.title": "यै प्याडलाई बाड्न्या यात इम्बेड गद्य्या", - "pad.toolbar.showusers.title": "यै प्याडमि रयाका प्रयोगकर्ता देखाउन्या", - "pad.colorpicker.save": "सङ्ग्रह गद्या", - "pad.colorpicker.cancel": "खारेजी", - "pad.loading": "लोड हुन्नाछ़....", - "pad.noCookie": "कुकी पाउन नाइ सकियो। तमरा ब्राउजरमी कुकी राख्दाइ अनुमति दिय!", - "pad.passwordRequired": "यो प्याड खोल्लाकी पासवर्ड चाहिन्छ", - "pad.permissionDenied": "तमलाईँ यै प्याड खोल्लाकी अनुमति नाइथिन", - "pad.wrongPassword": "तमरो पासवर्ड गलत थ्यो", - "pad.settings.padSettings": "प्याड सेटिङ्गअन", - "pad.settings.myView": "मेरि हेराइ", - "pad.settings.stickychat": "जबलई पर्दामी कुरडी गद्य्या", - "pad.settings.chatandusers": "वार्ता और प्रयोगकर्ताअन देखाउन्या", - "pad.settings.colorcheck": "लेखकीय रङ्ग", - "pad.settings.linenocheck": "हरफ संख्या", - "pad.settings.rtlcheck": "सामग्री दाहिना बठे देब्रे पढ्न्या हो कि?", - "pad.settings.fontType": "फन्ट प्रकार:", - "pad.settings.globalView": "विश्वव्यापी दृष्य", - "pad.settings.language": "भाषा:", - "pad.importExport.import_export": "आयात/निर्यात", - "pad.importExport.import": "कोइलै पाठ फाइल और कागजात अपलोड अरऽ", - "pad.importExport.importSuccessful": "सफल भयो!", - "pad.importExport.export": "निम्न रुपमि प्याड निर्यात:", - "pad.importExport.exportetherpad": "इथरप्याड", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "सादा पाठ", - "pad.importExport.exportword": "माइक्रोसफ्ट वर्ड", - "pad.importExport.exportpdf": "पिडिएफ", - "pad.importExport.exportopen": "ओडिएफ (खुल्ला कागजात ढाँचा)", - "pad.importExport.abiword.innerHTML": "तम सादा पाठ या HTML ढाँचा बठेइ मात्तरी आयात अरीसकन्छऽ। विस्तारित आयात विशेषता खिलाई कृपया abiword स्थापना अरऽ।", - "pad.modals.connected": "जोडीयाको।", - "pad.modals.reconnecting": "तमरा प्याडमि दोबरा जडान अद्‍दाछ़..", - "pad.modals.forcereconnect": "बलात् पुन:जडान", - "pad.modals.reconnecttimer": "दोबरा जोड्‍डाइ प्रयास अद्‍दाछ़", - "pad.modals.cancel": "रद्द", - "pad.modals.userdup": "अर्खा विण्डोमी खुलिरैछ", - "pad.modals.userdup.explanation": "यो प्याड येइ कम्प्युटरमी एक़ है बर्ता ब्राउजर सञ्झ्यालमी खोल्याऽ धेकीँछ।", - "pad.modals.userdup.advice": "बरु यो विण्डो प्रयोग अद्दाइ दोसर्‍याँ जोणिय।", - "pad.modals.unauth": "अनुमति नदियीयाऽ", - "pad.modals.unauth.explanation": "येइ पन्ना हेरनज्याँ तमरा अधिकार बदेलिया। दोसर्‍याँ जोणिन्या प्रयास अरऽ।", - "pad.modals.looping.explanation": "सिक्रोनाइजेसन सर्भर सित सञ्चार समस्या धेकिन्नाछ़।", - "pad.modals.looping.cause": "शायद तम यक असंगत फायरवाल या प्रोक्सी का माध्यम बठेइ जोणीरैछऽ।", - "pad.modals.initsocketfail": "सर्भरमी पहुँच पुर्‍याउन नाइसकियो।", - "pad.modals.initsocketfail.explanation": "सिङ्क्रोनाइजेसन सर्भर सित जोणीन नाइ सकियो।", - "pad.modals.initsocketfail.cause": "यो शायद तमरा ब्राउजर या इन्टरनेट जडान सित सम्बन्धित समस्याऽ कारणले होइ सकन्छ़।", - "pad.modals.slowcommit.explanation": "सर्भर प्रत्युत्तर दिन्नारेन।", - "pad.modals.slowcommit.cause": "यो नेटवर्क कनेक्टिविटी सङ्ङ सम्बन्धित समस्याऽ कारण ले होइसकन्छ।", - "pad.modals.badChangeset.explanation": "तमले अर्‍याऽ यक सम्पादन समक्रमण सर्भर हताँ अवैध वर्गीकृत अरियाऽ थ्यो।", - "pad.modals.badChangeset.cause": "यो यक गलत सर्भर विन्यास या केइ और अप्रत्याशित चालचलनाऽ कारण़ ले होइसकन्छ। यदि तमलाई यो गल्ती हो भण्ण्या लागन्छ भँण्या, कृपया सेवा व्यवस्थापकलाई सम्पर्क अरऽ। सम्पादन चालु राख्दाइ दोसर्‍याँ जोणिन्या प्रयास अरऽ।", - "pad.modals.corruptPad.explanation": "तमले उपयोग अद्द़ खोज्याऽ प्याड बिगण्योऽ छ।", - "pad.modals.corruptPad.cause": "यो गलत सर्भर विन्यास या केइ और नसोच्याऽ चालचलनले होइसकन्छ। कृपया सेवा व्यवस्थापकलाई सम्पर्क अरऽ।", - "pad.modals.deleted": "मेटियाको।", - "pad.modals.deleted.explanation": "यो प्याड हटाइसकीरैछ।", - "pad.modals.disconnected": "तमरो जडान अवरुद्ध भयो।", - "pad.modals.disconnected.explanation": "तमरो सर्भरसितको जडान अवरुद्ध भयो", - "pad.modals.disconnected.cause": "सर्भर अनुपलब्ध होइसकन्छ। यदि यो हुनोइ रयाबर कृपया सेवा व्यवस्थापकलाई सूचित अरऽ।", - "pad.share": "यस प्याडलाई बाड्न्या", - "pad.share.readonly": "पड्‍ड्या मात्तरै", - "pad.share.link": "लिङ्क", - "pad.share.emebdcode": "URL थप्प्या", - "pad.chat": "कुरणिकानी", - "pad.chat.title": "येइ प्याड खिलाइ गफ खोलऽ", - "pad.chat.loadmessages": "जेदा सन्देश लोड अरऽ", - "timeslider.pageTitle": "{{appTitle}} समय स्लाइडर", - "timeslider.toolbar.returnbutton": "प्याडमी फर्कऽ", - "timeslider.toolbar.authors": "लेखकअन:", - "timeslider.toolbar.authorsList": "लेखकअन आथीनन", - "timeslider.toolbar.exportlink.title": "निर्यात", - "timeslider.exportCurrent": "हालआ शंसोधनलाई इस्याँ निर्यात अरऽ:", - "timeslider.version": "संस्करण {{version}}", - "timeslider.saved": "भँणार अरीयाऽ {{month}} {{day}}, {{year}}", - "timeslider.playPause": "प्याडआ सामाग्रीइनलाई प्लेब्याक/पउज अरऽ", - "timeslider.backRevision": "येइ प्याडमी यक शंसोधन पछा जाऽ", - "timeslider.forwardRevision": "येइ शंसोधनमी यक शंसोधन अघा जाऽ", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "जनवरी", - "timeslider.month.february": "फेब्रुअरी", - "timeslider.month.march": "मार्च", - "timeslider.month.april": "अप्रिल", - "timeslider.month.may": "मे", - "timeslider.month.june": "जुन", - "timeslider.month.july": "जुलाई", - "timeslider.month.august": "अगस्ट", - "timeslider.month.september": "सेप्टेम्बर", - "timeslider.month.october": "अक्टोबर", - "timeslider.month.november": "नोभेम्बर", - "timeslider.month.december": "डिसेम्बर", - "timeslider.unnamedauthors": "{{num}} बिननाउँइको {[plural(num) one: author, other: authors ]}", - "pad.savedrevs.marked": "आब येइ संशोधनलाई सङ्ग्रहित संशोधनआ रूपमी चिनो लायियो", - "pad.savedrevs.timeslider": "समयस्लाइडर भेटिबर तम भँणार अरीयाऽ शंसोधनअनलाई हेरि सकन्छऽ", - "pad.userlist.entername": "तमरो नाउँ हाल", - "pad.userlist.unnamed": "बिननाउँइको", - "pad.userlist.guest": "पाउनो", - "pad.userlist.deny": "अस्वीकार", - "pad.userlist.approve": "अनुमोदन", - "pad.editbar.clearcolors": "सङताइ कागताजमी है लेखक रङ्ङअन साप अद्द्या?", - "pad.impexp.importbutton": "ऐलै आयात अरऽ", - "pad.impexp.importing": "आयात अद्दाछ़...", - "pad.impexp.confirmimport": "फाइल आयात़ ले प्याडओ अइलओ पाठ बदेलिन्या हो। तम ऐतिऱ बड्ड चाहन्छ भणिबर पक्का छऽ?", - "pad.impexp.convertFailed": "एइ फाइललाई आयात अद्द नाइसक्यो। कृपया जुदोइ कागजात फर्याट प्रयोग अरऽ या नकल पेस्ट अरऽ", - "pad.impexp.padHasData": "हम एइ फाइलाई आयात अद्दाइ असमर्थ छौँ क्याइकि एइ प्याडमी पैली अरीयाऽ फेलबदेल छन्, कृपया नयाँ प्याडमी आयात अरऽ", - "pad.impexp.uploadFailed": "अपलोड असफल, कृपया दोसर्‍याँ प्रयास अरऽ", - "pad.impexp.importfailed": "आयात असफल", - "pad.impexp.copypaste": "कृपया नकल सार अरऽ", - "pad.impexp.exportdisabled": "{{type}} फर्म्याटमी निर्यात अक्षम अरीरैछ। विवरण खिलाइ कृपया तमरा संयन्त्र प्रशासकलाई सम्पर्क अर:।" -} diff --git a/sources/src/locales/el.json b/sources/src/locales/el.json deleted file mode 100644 index 2fff2e4..0000000 --- a/sources/src/locales/el.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Evropi", - "Geraki", - "Glavkos", - "Monopatis", - "Protnet" - ] - }, - "index.newPad": "Νέο Pad", - "index.createOpenPad": "ή δημιουργία/άνοιγμα ενός Pad με όνομα:", - "pad.toolbar.bold.title": "Έντονη (Ctrl-B)", - "pad.toolbar.italic.title": "Πλάγια (Ctrl-I)", - "pad.toolbar.underline.title": "Υπογράμμιση (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Διακριτή διαγραφή (Ctrl+5)", - "pad.toolbar.ol.title": "Ταξινομημένη λίστα (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Λίστα χωρίς σειρά (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Αριστερά εσοχή (TAB)", - "pad.toolbar.unindent.title": "Δεξιά εσοχή (Shift+TAB)", - "pad.toolbar.undo.title": "Αναίρεση (Ctrl-Z)", - "pad.toolbar.redo.title": "Επανάληψη (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Εκκαθάριση των χρωμάτων των συντακτών (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Εισαγωγή/Εξαγωγή από/σε διαφορετικούς τύπους αρχείων", - "pad.toolbar.timeslider.title": "Χρονοδιάγραμμα", - "pad.toolbar.savedRevision.title": "Αποθήκευση Αναθεώρησης", - "pad.toolbar.settings.title": "Ρυθμίσεις", - "pad.toolbar.embed.title": "Διαμοίραση και Ενσωμάτωση αυτού του pad", - "pad.toolbar.showusers.title": "Εμφάνιση των χρηστών αυτού του pad", - "pad.colorpicker.save": "Αποθήκευση", - "pad.colorpicker.cancel": "Άκυρο", - "pad.loading": "Φόρτωση...", - "pad.noCookie": "Το cookie δεν βρέθηκε. Παρακαλώ επιτρέψτε τα cookies στον περιηγητή σας!", - "pad.passwordRequired": "Χρειάζεστε κωδικό πρόσβασης για πρόσβαση σε αυτό το pad", - "pad.permissionDenied": "Δεν έχετε δικαίωμα πρόσβασης σε αυτό το pad", - "pad.wrongPassword": "Ο κωδικός σας ήταν λανθασμένος", - "pad.settings.padSettings": "Ρυθμίσεις Pad", - "pad.settings.myView": "Η προβολή μου", - "pad.settings.stickychat": "Να είναι πάντα ορατή η συνομιλία", - "pad.settings.chatandusers": "Εμφάνιση Συνομιλίας και Χρηστών", - "pad.settings.colorcheck": "Χρώματα συντάκτη", - "pad.settings.linenocheck": "Αριθμοί γραμμών", - "pad.settings.rtlcheck": "Διαβάζεται το περιεχόμενο από δεξιά προς τα αριστερά;", - "pad.settings.fontType": "Τύπος γραμματοσειράς:", - "pad.settings.fontType.normal": "Κανονική", - "pad.settings.fontType.monospaced": "Καθορισμένου πλάτους", - "pad.settings.globalView": "Καθολική Προβολή", - "pad.settings.language": "Γλώσσα:", - "pad.importExport.import_export": "Εισαγωγή/Εξαγωγή", - "pad.importExport.import": "Αποστολή οποιουδήποτε αρχείου κειμένου ή εγγράφου", - "pad.importExport.importSuccessful": "Επιτυχής!", - "pad.importExport.export": "Εξαγωγή τρέχοντος pad ως:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Απλό κείμενο", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Μορφή Open Document)", - "pad.importExport.abiword.innerHTML": "Μπορείτε να κάνετε εισαγωγή απλού κειμένου ή μορφής html. Για πιο προηγμένες δυνατότητες εισαγωγής παρακαλώ εγκαταστήστε το abiword.", - "pad.modals.connected": "Συνδεμένοι.", - "pad.modals.reconnecting": "Επανασύνδεση στο pad σας...", - "pad.modals.forcereconnect": "Επιβολή επανασύνδεσης", - "pad.modals.reconnecttimer": "Επαναπροσπάθεια σε", - "pad.modals.cancel": "Ακύρωση", - "pad.modals.userdup": "Ανοιγμένο σε άλλο παράθυρο", - "pad.modals.userdup.explanation": "Αυτό το pad φαίνεται να είναι ανοιχτό σε περισσότερα από ένα παράθυρο του προγράμματος περιήγησης σε αυτόν τον υπολογιστή.", - "pad.modals.userdup.advice": "Επανασυνδεθείτε για να χρησιμοποιήσετε αυτό το παράθυρο.", - "pad.modals.unauth": "Δεν επιτρέπεται", - "pad.modals.unauth.explanation": "Τα δικαιώματά σας άλλαξαν όσο βλέπατε αυτήν τη σελίδα. Δοκιμάστε να επανασυνδεθείτε.", - "pad.modals.looping.explanation": "Υπάρχουν προβλήματα επικοινωνίας με τον διακομιστή συγχρονισμού.", - "pad.modals.looping.cause": "Ίσως συνδεθήκατε μέσω ενός μη συμβατού τείχους προστασίας ή διακομιστή μεσολάβησης.", - "pad.modals.initsocketfail": "Αδύνατη ή επικοινωνία με τον διακομιστή.", - "pad.modals.initsocketfail.explanation": "Δεν ήταν δυνατή η σύνδεση με τον διακομιστή συγχρονισμού.", - "pad.modals.initsocketfail.cause": "Αυτό οφείλεται πιθανώς σε πρόβλημα με το πρόγραμμα περιήγησης ή της σύνδεσής σας στο διαδίκτυο.", - "pad.modals.slowcommit.explanation": "Ο διακομιστής δεν αποκρίνεται.", - "pad.modals.slowcommit.cause": "Αυτό μπορεί να οφείλεται σε προβλήματα σύνδεσης δικτύου.", - "pad.modals.badChangeset.explanation": "Μια επεξεργασία που κάνατε χαρακτηρίστηκε ως παράνομη από τον διακομιστή συγχρονισμού.", - "pad.modals.badChangeset.cause": "Αυτό μπορεί να οφείλεται σε ένα λάθος στη ρύθμιση του διακομιστή ή κάποια άλλη απρόβλεπτη συμπεριφορά. Παρακαλώ επικοινωνήστε με τον διαχειριστή της υπηρεσίας, εάν πιστεύετε πως αυτό οφείλεται σε σφάλμα. Δοκιμάστε να επανασυνδεθείτε για να συνεχίσετε την επεξεργασία.", - "pad.modals.corruptPad.explanation": "Το pad που προσπαθείτε να επισκεφτείτε είναι κατεστραμμένο.", - "pad.modals.corruptPad.cause": "Αυτό μπορεί να οφείλεται σε ένα λάθος στη ρύθμιση του διακομιστή ή κάποια άλλη απρόβλεπτη συμπεριφορά. Παρακαλώ επικοινωνήστε με τον διαχειριστή της υπηρεσίας.", - "pad.modals.deleted": "Διεγράφη.", - "pad.modals.deleted.explanation": "Αυτό το pad έχει καταργηθεί.", - "pad.modals.disconnected": "Είστε αποσυνδεδεμένοι.", - "pad.modals.disconnected.explanation": "Χάθηκε η σύνδεση με τον διακομιστή", - "pad.modals.disconnected.cause": "Ο διακομιστής μπορεί να μην είναι διαθέσιμος. Παρακαλούμε ειδοποιήστε τον διαχειριστή της υπηρεσίας εάν εξακολουθεί να συμβαίνει αυτό.", - "pad.share": "Μοιραστείτε αυτό το pad", - "pad.share.readonly": "Μόνο για ανάγνωση", - "pad.share.link": "Σύνδεσμος", - "pad.share.emebdcode": "URL ενσωμάτωσης", - "pad.chat": "Συνομιλία", - "pad.chat.title": "Άνοιγμα της συνομιλίας για αυτό το pad.", - "pad.chat.loadmessages": "Φόρτωση περισσότερων μηνυμάτων", - "timeslider.pageTitle": "{{appTitle}} Χρονοδιάγραμμα", - "timeslider.toolbar.returnbutton": "Επιστροφή στο pad", - "timeslider.toolbar.authors": "Συντάκτες:", - "timeslider.toolbar.authorsList": "Κανένας Συντάκτης", - "timeslider.toolbar.exportlink.title": "Εξαγωγή", - "timeslider.exportCurrent": "Εξαγωγή τρέχουσας έκδοσης ως:", - "timeslider.version": "Έκδοση {{version}}", - "timeslider.saved": "Αποθηκεύτηκε στις {{day}} {{month}} {{year}}", - "timeslider.playPause": "Αναπαραγωγή / Παύση των περιεχομένων αυτού του Pad", - "timeslider.backRevision": "Επιστροφή σε μια έκδοση αυτού του Pad", - "timeslider.forwardRevision": "Μια έκδοση μπροστά αυτού του Pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Ιανουαρίου", - "timeslider.month.february": "Φεβρουαρίου", - "timeslider.month.march": "Μαρτίου", - "timeslider.month.april": "Απριλίου", - "timeslider.month.may": "Μαΐου", - "timeslider.month.june": "Ιουνίου", - "timeslider.month.july": "Ιουλίου", - "timeslider.month.august": "Αυγούστου", - "timeslider.month.september": "Σεπτεμβρίου", - "timeslider.month.october": "Οκτωβρίου", - "timeslider.month.november": "Νοεμβρίου", - "timeslider.month.december": "Δεκεμβρίου", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: ανώνυμος συντάκτης, other: ανώνυμοι συντάκτες]}", - "pad.savedrevs.marked": "Αυτή η έκδοση επισημάνθηκε ως αποθηκευμένη έκδοση", - "pad.savedrevs.timeslider": "Μπορείτε να δείτε αποθηκευμένες αναθεωρήσεις στο χρονοδιάγραμμα", - "pad.userlist.entername": "Εισάγετε το όνομά σας", - "pad.userlist.unnamed": "ανώνυμος", - "pad.userlist.guest": "Επισκέπτης", - "pad.userlist.deny": "Άρνηση", - "pad.userlist.approve": "Έγκριση", - "pad.editbar.clearcolors": "Να γίνει εκκαθάριση χρωμάτων σύνταξης σε ολόκληρο το έγγραφο;", - "pad.impexp.importbutton": "Εισαγωγή Τώρα", - "pad.impexp.importing": "Εισάγεται...", - "pad.impexp.confirmimport": "Η εισαγωγή ενός αρχείου θα αντικαταστήσει το κείμενο του pad. Είστε βέβαιοι ότι θέλετε να συνεχίσετε;", - "pad.impexp.convertFailed": "Δεν καταφέραμε να εισάγουμε αυτό το αρχείο. Παρακαλώ χρησιμοποιήστε διαφορετικό τύπο αρχείου ή αντιγράψτε και επικολλήστε χειροκίνητα", - "pad.impexp.padHasData": "Δεν μπορέσαμε να εισάγουμε το αρχείο επειδή το Pad είχε ήδη αλλαγές. Παρακαλούμε εισαγάγετε το αρχείο σε νέο pad", - "pad.impexp.uploadFailed": "Η αποστολή απέτυχε, παρακαλώ προσπαθήστε ξανά", - "pad.impexp.importfailed": "Η εισαγωγή απέτυχε", - "pad.impexp.copypaste": "Παρακαλώ αντιγράψτε και επικολλήστε", - "pad.impexp.exportdisabled": "Η εξαγωγή σε μορφή {{type}} έχει απενεργοποιηθεί. Επικοινωνήστε με τον διαχειριστή του συστήματός σας για λεπτομέρειες." -} diff --git a/sources/src/locales/en-gb.json b/sources/src/locales/en-gb.json deleted file mode 100644 index 6206f77..0000000 --- a/sources/src/locales/en-gb.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Chase me ladies, I'm the Cavalry", - "Shirayuki", - "Andibing", - "HairyFotr" - ] - }, - "index.newPad": "New Pad", - "index.createOpenPad": "or create/open a Pad with the name:", - "pad.toolbar.bold.title": "Bold (Ctrl+B)", - "pad.toolbar.italic.title": "Italic (Ctrl+I)", - "pad.toolbar.underline.title": "Underline (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Strikethrough (Ctrl+5)", - "pad.toolbar.ol.title": "Ordered list (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Unordered List (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Indent (Tab)", - "pad.toolbar.unindent.title": "Outdent (Shift+Tab)", - "pad.toolbar.undo.title": "Undo (Ctrl+Z)", - "pad.toolbar.redo.title": "Redo (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Clear Authorship Colours (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Import/Export from/to different file formats", - "pad.toolbar.timeslider.title": "Timeslider", - "pad.toolbar.savedRevision.title": "Save Revision", - "pad.toolbar.settings.title": "Settings", - "pad.toolbar.embed.title": "Share and Embed this pad", - "pad.toolbar.showusers.title": "Show the users on this pad", - "pad.colorpicker.save": "Save", - "pad.colorpicker.cancel": "Cancel", - "pad.loading": "Loading...", - "pad.noCookie": "Cookie could not be found. Please allow cookies in your browser!", - "pad.passwordRequired": "You need a password to access this pad", - "pad.permissionDenied": "You do not have permission to access this pad", - "pad.wrongPassword": "Your password was wrong", - "pad.settings.padSettings": "Pad Settings", - "pad.settings.myView": "My View", - "pad.settings.stickychat": "Chat always on screen", - "pad.settings.chatandusers": "Show Chat and Users", - "pad.settings.colorcheck": "Authorship colours", - "pad.settings.linenocheck": "Line numbers", - "pad.settings.rtlcheck": "Read content from right to left?", - "pad.settings.fontType": "Font type:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Global View", - "pad.settings.language": "Language:", - "pad.importExport.import_export": "Import/Export", - "pad.importExport.import": "Upload any text file or document", - "pad.importExport.importSuccessful": "Successful!", - "pad.importExport.export": "Export current pad as:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Plain text", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please install AbiWord.", - "pad.modals.connected": "Connected.", - "pad.modals.reconnecting": "Reconnecting to your pad..", - "pad.modals.forcereconnect": "Force reconnect", - "pad.modals.reconnecttimer": "Trying to reconnect in", - "pad.modals.cancel": "Cancel", - "pad.modals.userdup": "Opened in another window", - "pad.modals.userdup.explanation": "This pad seems to be opened in more than one browser window on this computer.", - "pad.modals.userdup.advice": "Reconnect to use this window instead.", - "pad.modals.unauth": "Not authorised", - "pad.modals.unauth.explanation": "Your permissions have changed while viewing this page. Try to reconnect.", - "pad.modals.looping.explanation": "There are communication problems with the synchronisation server.", - "pad.modals.looping.cause": "Perhaps you connected through an incompatible firewall or proxy.", - "pad.modals.initsocketfail": "Server is unreachable.", - "pad.modals.initsocketfail.explanation": "Couldn't connect to the synchronisation server.", - "pad.modals.initsocketfail.cause": "This is probably due to a problem with your browser or your internet connection.", - "pad.modals.slowcommit.explanation": "The server is not responding.", - "pad.modals.slowcommit.cause": "This could be due to problems with network connectivity.", - "pad.modals.badChangeset.explanation": "An edit you have made was classified illegal by the synchronisation server.", - "pad.modals.badChangeset.cause": "This could be due to a wrong server configuration or some other unexpected behaviour. Please contact the service administrator, if you feel this is an error. Try to reconnect in order to continue editing.", - "pad.modals.corruptPad.explanation": "The pad you are trying to access is corrupt.", - "pad.modals.corruptPad.cause": "This may be due to a wrong server configuration or some other unexpected behaviour. Please contact the service administrator.", - "pad.modals.deleted": "Deleted.", - "pad.modals.deleted.explanation": "This pad has been removed.", - "pad.modals.disconnected": "You have been disconnected.", - "pad.modals.disconnected.explanation": "The connection to the server was lost", - "pad.modals.disconnected.cause": "The server may be unavailable. Please notify the service administrator if this continues to happen.", - "pad.share": "Share this pad", - "pad.share.readonly": "Read only", - "pad.share.link": "Link", - "pad.share.emebdcode": "Embed URL", - "pad.chat": "Chat", - "pad.chat.title": "Open the chat for this pad.", - "pad.chat.loadmessages": "Load more messages", - "timeslider.pageTitle": "{{appTitle}} Timeslider", - "timeslider.toolbar.returnbutton": "Return to pad", - "timeslider.toolbar.authors": "Authors:", - "timeslider.toolbar.authorsList": "No Authors", - "timeslider.toolbar.exportlink.title": "Export", - "timeslider.exportCurrent": "Export current version as:", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Saved {{month}} {{day}}, {{year}}", - "timeslider.playPause": "Playback/Pause Pad Contents", - "timeslider.backRevision": "Go back a revision in this Pad", - "timeslider.forwardRevision": "Go forward a revision in this Pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "January", - "timeslider.month.february": "February", - "timeslider.month.march": "March", - "timeslider.month.april": "April", - "timeslider.month.may": "May", - "timeslider.month.june": "June", - "timeslider.month.july": "July", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "October", - "timeslider.month.november": "November", - "timeslider.month.december": "December", - "timeslider.unnamedauthors": "{{num}} unnamed {[plural(num) one: author, other: authors ]}", - "pad.savedrevs.marked": "This revision is now marked as a saved revision", - "pad.savedrevs.timeslider": "You can see saved revisions by visiting the timeslider", - "pad.userlist.entername": "Enter your name", - "pad.userlist.unnamed": "unnamed", - "pad.userlist.guest": "Guest", - "pad.userlist.deny": "Deny", - "pad.userlist.approve": "Approve", - "pad.editbar.clearcolors": "Clear authorship colours on entire document?", - "pad.impexp.importbutton": "Import Now", - "pad.impexp.importing": "Importing...", - "pad.impexp.confirmimport": "Importing a file will overwrite the current text of the pad. Are you sure you want to proceed?", - "pad.impexp.convertFailed": "We were not able to import this file. Please use a different document format or copy & paste manually", - "pad.impexp.padHasData": "We were not able to import this file because this Pad has already had changes, please import to a new pad", - "pad.impexp.uploadFailed": "The upload failed, please try again", - "pad.impexp.importfailed": "Import failed", - "pad.impexp.copypaste": "Please copy & paste", - "pad.impexp.exportdisabled": "Exporting as {{type}} format is disabled. Please contact your system administrator for details." -} diff --git a/sources/src/locales/en.json b/sources/src/locales/en.json deleted file mode 100644 index e438fa1..0000000 --- a/sources/src/locales/en.json +++ /dev/null @@ -1,166 +0,0 @@ -{ - "index.newPad": "New Pad", - "index.createOpenPad": "or create/open a Pad with the name:", - - "pad.toolbar.bold.title": "Bold (Ctrl+B)", - "pad.toolbar.italic.title": "Italic (Ctrl+I)", - "pad.toolbar.underline.title": "Underline (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Strikethrough (Ctrl+5)", - "pad.toolbar.ol.title": "Ordered list (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Unordered List (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Indent (TAB)", - "pad.toolbar.unindent.title": "Outdent (Shift+TAB)", - "pad.toolbar.undo.title": "Undo (Ctrl+Z)", - "pad.toolbar.redo.title": "Redo (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Clear Authorship Colors (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Import/Export from/to different file formats", - "pad.toolbar.timeslider.title": "Timeslider", - "pad.toolbar.savedRevision.title": "Save Revision", - "pad.toolbar.settings.title": "Settings", - "pad.toolbar.embed.title": "Share and Embed this pad", - "pad.toolbar.showusers.title": "Show the users on this pad", - - "pad.colorpicker.save": "Save", - "pad.colorpicker.cancel": "Cancel", - - "pad.loading": "Loading...", - "pad.noCookie": "Cookie could not be found. Please allow cookies in your browser!", - "pad.passwordRequired": "You need a password to access this pad", - "pad.permissionDenied": "You do not have permission to access this pad", - "pad.wrongPassword": "Your password was wrong", - - "pad.settings.padSettings": "Pad Settings", - "pad.settings.myView": "My View", - "pad.settings.stickychat": "Chat always on screen", - "pad.settings.chatandusers": "Show Chat and Users", - "pad.settings.colorcheck": "Authorship colors", - "pad.settings.linenocheck": "Line numbers", - "pad.settings.rtlcheck": "Read content from right to left?", - "pad.settings.fontType": "Font type:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.opendyslexic": "Open Dyslexic", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.fontType.montserrat": "Montserrat", - "pad.settings.fontType.comicsans": "Comic Sans", - "pad.settings.fontType.couriernew": "Courier New", - "pad.settings.fontType.georgia": "Georgia", - "pad.settings.fontType.impact": "Impact", - "pad.settings.fontType.lucida": "Lucida", - "pad.settings.fontType.lucidasans": "Lucida Sans", - "pad.settings.fontType.palatino": "Palatino", - "pad.settings.fontType.robotomono": "RobotoMono", - "pad.settings.fontType.tahoma": "Tahoma", - "pad.settings.fontType.timesnewroman": "Times New Roman", - "pad.settings.fontType.trebuchet": "Trebuchet", - "pad.settings.fontType.verdana": "Verdana", - "pad.settings.fontType.symbol": "Symbol", - "pad.settings.fontType.webdings": "Webdings", - "pad.settings.fontType.wingdings": "Wingdings", - "pad.settings.fontType.sansserif": "Sans Serif", - "pad.settings.fontType.serif": "Serif", - "pad.settings.globalView": "Global View", - "pad.settings.language": "Language:", - - "pad.importExport.import_export": "Import/Export", - "pad.importExport.import": "Upload any text file or document", - "pad.importExport.importSuccessful": "Successful!", - "pad.importExport.export": "Export current pad as:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Plain text", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please install AbiWord.", - - "pad.modals.connected": "Connected.", - "pad.modals.reconnecting": "Reconnecting to your pad..", - "pad.modals.forcereconnect": "Force reconnect", - "pad.modals.reconnecttimer": "Trying to reconnect in ", - "pad.modals.cancel": "Cancel", - - "pad.modals.userdup": "Opened in another window", - "pad.modals.userdup.explanation": "This pad seems to be opened in more than one browser window on this computer.", - "pad.modals.userdup.advice": "Reconnect to use this window instead.", - - "pad.modals.unauth": "Not authorized", - "pad.modals.unauth.explanation": "Your permissions have changed while viewing this page. Try to reconnect.", - - "pad.modals.looping.explanation": "There are communication problems with the synchronization server.", - "pad.modals.looping.cause": "Perhaps you connected through an incompatible firewall or proxy.", - - "pad.modals.initsocketfail": "Server is unreachable.", - "pad.modals.initsocketfail.explanation": "Couldn't connect to the synchronization server.", - "pad.modals.initsocketfail.cause": "This is probably due to a problem with your browser or your internet connection.", - - "pad.modals.slowcommit.explanation": "The server is not responding.", - "pad.modals.slowcommit.cause": "This could be due to problems with network connectivity.", - - "pad.modals.badChangeset.explanation": "An edit you have made was classified illegal by the synchronization server.", - "pad.modals.badChangeset.cause": "This could be due to a wrong server configuration or some other unexpected behavior. Please contact the service administrator, if you feel this is an error. Try to reconnect in order to continue editing.", - - "pad.modals.corruptPad.explanation": "The pad you are trying to access is corrupt.", - "pad.modals.corruptPad.cause": "This may be due to a wrong server configuration or some other unexpected behavior. Please contact the service administrator.", - - "pad.modals.deleted": "Deleted.", - "pad.modals.deleted.explanation": "This pad has been removed.", - - "pad.modals.disconnected": "You have been disconnected.", - "pad.modals.disconnected.explanation": "The connection to the server was lost", - "pad.modals.disconnected.cause": "The server may be unavailable. Please notify the service administrator if this continues to happen.", - - "pad.share": "Share this pad", - "pad.share.readonly": "Read only", - "pad.share.link": "Link", - "pad.share.emebdcode": "Embed URL", - "pad.chat": "Chat", - "pad.chat.title": "Open the chat for this pad.", - "pad.chat.loadmessages": "Load more messages", - - "timeslider.pageTitle": "{{appTitle}} Timeslider", - "timeslider.toolbar.returnbutton": "Return to pad", - "timeslider.toolbar.authors": "Authors:", - "timeslider.toolbar.authorsList": "No Authors", - "timeslider.toolbar.exportlink.title": "Export", - "timeslider.exportCurrent": "Export current version as:", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Saved {{month}} {{day}}, {{year}}", - - "timeslider.playPause": "Playback / Pause Pad Contents", - "timeslider.backRevision":"Go back a revision in this Pad", - "timeslider.forwardRevision":"Go forward a revision in this Pad", - - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "January", - "timeslider.month.february": "February", - "timeslider.month.march": "March", - "timeslider.month.april": "April", - "timeslider.month.may": "May", - "timeslider.month.june": "June", - "timeslider.month.july": "July", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "October", - "timeslider.month.november": "November", - "timeslider.month.december": "December", - - "timeslider.unnamedauthors": "{{num}} unnamed {[plural(num) one: author, other: authors ]}", - "pad.savedrevs.marked": "This revision is now marked as a saved revision", - "pad.savedrevs.timeslider": "You can see saved revisions by visiting the timeslider", - "pad.userlist.entername": "Enter your name", - "pad.userlist.unnamed": "unnamed", - "pad.userlist.guest": "Guest", - "pad.userlist.deny": "Deny", - "pad.userlist.approve": "Approve", - "pad.editbar.clearcolors": "Clear authorship colors on entire document?", - - "pad.impexp.importbutton": "Import Now", - "pad.impexp.importing": "Importing...", - "pad.impexp.confirmimport": "Importing a file will overwrite the current text of the pad. Are you sure you want to proceed?", - "pad.impexp.convertFailed": "We were not able to import this file. Please use a different document format or copy paste manually", - "pad.impexp.padHasData": "We were not able to import this file because this Pad has already had changes, please import to a new pad", - "pad.impexp.uploadFailed": "The upload failed, please try again", - "pad.impexp.importfailed": "Import failed", - "pad.impexp.copypaste": "Please copy paste", - "pad.impexp.exportdisabled": "Exporting as {{type}} format is disabled. Please contact your system administrator for details." -} diff --git a/sources/src/locales/eo.json b/sources/src/locales/eo.json deleted file mode 100644 index 2754eaf..0000000 --- a/sources/src/locales/eo.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Eliovir", - "Mschmitt", - "Objectivesea", - "Robin van der Vliet" - ] - }, - "index.newPad": "Nova Teksto", - "index.createOpenPad": "aŭ krei/malfermi novan tekston kun la nomo:", - "pad.toolbar.bold.title": "Grasa (Ctrl+B)", - "pad.toolbar.italic.title": "Kursiva (Ctrl+I)", - "pad.toolbar.underline.title": "Substrekita (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Trastrekita (Ctrl+5)", - "pad.toolbar.ol.title": "Ordigita listo (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Neordigita Listo (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Enŝovi (TAB)", - "pad.toolbar.unindent.title": "Elŝovi (Shift+TAB)", - "pad.toolbar.undo.title": "Malfari (Ctrl+Z)", - "pad.toolbar.redo.title": "Refari (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Forigi kolorojn de aŭtoreco (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Enporti/elporti de/al aliaj dosierformatoj", - "pad.toolbar.timeslider.title": "Tempoŝovilo", - "pad.toolbar.savedRevision.title": "Konservi version", - "pad.toolbar.settings.title": "Agordoj", - "pad.toolbar.embed.title": "Kunhavigi kaj enigi ĉi tiun tekston", - "pad.toolbar.showusers.title": "Montri la redaktantojn sur ĉi tiu teksto", - "pad.colorpicker.save": "Konservi", - "pad.colorpicker.cancel": "Nuligi", - "pad.loading": "Ŝargante...", - "pad.noCookie": "Kuketo ne estis trovigebla. Bonvolu permesi kuketojn en via retumilo!", - "pad.passwordRequired": "Vi bezonas pasvorton por aliri ĉi tiun tekston", - "pad.permissionDenied": "Vi ne havas permeson por aliri ĉi tiun tekston", - "pad.wrongPassword": "Via pasvorto estis malĝusta", - "pad.settings.padSettings": "Redaktilaj Agordoj", - "pad.settings.myView": "Mia vido", - "pad.settings.stickychat": "Babilejo ĉiam videbla", - "pad.settings.chatandusers": "Montri babilejon kaj uzantojn", - "pad.settings.colorcheck": "Koloroj de aŭtoreco", - "pad.settings.linenocheck": "Liniaj nombroj", - "pad.settings.rtlcheck": "Legi dekstre-maldekstren?", - "pad.settings.fontType": "Tiparo:", - "pad.settings.fontType.normal": "Normala", - "pad.settings.fontType.monospaced": "Egallarĝa", - "pad.settings.globalView": "Ĉiea Vido", - "pad.settings.language": "Lingvo:", - "pad.importExport.import_export": "Enporti/Elporti", - "pad.importExport.import": "Alŝuti ajnan dosieron aŭ dokumenton", - "pad.importExport.importSuccessful": "Sukceso!", - "pad.importExport.export": "Elporti la nunan tekston kiel:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Plata teksto", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Formato “OpenDocument”)", - "pad.importExport.abiword.innerHTML": "Nur kapablas enporti de plata teksto aŭ HTML. Por pli speciala importkapablo, bonvolu instalu la programon, Abiword.", - "pad.modals.connected": "Konektita.", - "pad.modals.reconnecting": "Rekonektanta al via redaktilo..", - "pad.modals.forcereconnect": "Perforte rekonekti", - "pad.modals.reconnecttimer": "Provos rekonekti post", - "pad.modals.cancel": "Nuligi", - "pad.modals.userdup": "Malfermita en alia fenestro", - "pad.modals.userdup.explanation": "Ĉi tiu teksto ŝajne estas malferma en pli ol unu retumilo sur ĉi tiu komputilo.", - "pad.modals.userdup.advice": "Rekonekti por anstataŭe uzi ĉi tiun fenestron.", - "pad.modals.unauth": "Ne permesita", - "pad.modals.unauth.explanation": "Viaj permesoj ŝanĝis dum kiam vi rigardis ĉi tiun paĝon. Provu rekonekti.", - "pad.modals.looping.explanation": "Okazas problemoj dum komunikado kun la sinkronigservilo.", - "pad.modals.looping.cause": "Eble vi konektis per malkongrua fajroŝirmilo aŭ retperanto.", - "pad.modals.initsocketfail": "Servilo ne estas atingebla.", - "pad.modals.initsocketfail.explanation": "Ne kapablis konekti al la sinkronigservilo.", - "pad.modals.initsocketfail.cause": "Tio verŝajne okazas pro problemo kun via retumilo aŭ via retkonekto.", - "pad.modals.slowcommit.explanation": "La servilo ne respondas.", - "pad.modals.slowcommit.cause": "Tio eble estas pro problemoj kun retkonekto.", - "pad.modals.badChangeset.explanation": "La sinkronigservilo decidis ke redakto de vi estas malpermesita.", - "pad.modals.badChangeset.cause": "Tio eble okazis pro malĝustaj agordoj aŭ alia neatendita teniĝo sur la servilo. Se vi pensas ke estas eraro, bonvolu kontakti la servoadminstranton. Provu rekonekti por denove redakti.", - "pad.modals.corruptPad.explanation": "La teksto kiun vi provas atingi estas difekta.", - "pad.modals.corruptPad.cause": "Tio eble okazis pro malĝustaj agordoj aŭ alia neatendita teniĝo sur la servilo. Bonvolu kontakti la servoadminstranton.", - "pad.modals.deleted": "Forigita.", - "pad.modals.deleted.explanation": "Ĉi tiu teksto estis forigita.", - "pad.modals.disconnected": "Vi estas malkonektita.", - "pad.modals.disconnected.explanation": "La konekto al la servilo perdiĝis", - "pad.modals.disconnected.cause": "Eble la servilo ne estas disponebla. Bonvolu kontakti la servoadministranton se tio daŭre okazas.", - "pad.share": "Kunhavigi ĉi tiun tekston", - "pad.share.readonly": "Nur legebla", - "pad.share.link": "Ligilo", - "pad.share.emebdcode": "Enfiksi URL-on", - "pad.chat": "Babilejo", - "pad.chat.title": "Malfermi la babilejon por ĉi tiu teksto.", - "pad.chat.loadmessages": "Ŝargi pliajn mesaĝojn", - "timeslider.pageTitle": "{{appTitle}} Tempoŝovilo", - "timeslider.toolbar.returnbutton": "Reiri al teksto", - "timeslider.toolbar.authors": "Aŭtoroj:", - "timeslider.toolbar.authorsList": "Neniu aŭtoro", - "timeslider.toolbar.exportlink.title": "Elporti", - "timeslider.exportCurrent": "Elporti la nunan version kiel:", - "timeslider.version": "Versio {{version}}", - "timeslider.saved": "Konservita la {{day}}an de {{month}}, {{year}}", - "timeslider.playPause": "Ludi / paŭzi la enhavojn de la teksto", - "timeslider.backRevision": "Reiri unu version en ĉi tiu teksto", - "timeslider.forwardRevision": "Antaŭeniri unu version en ĉi tiu teksto", - "timeslider.dateformat": "{{day}}-{{month}}-{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "januaro", - "timeslider.month.february": "februaro", - "timeslider.month.march": "marto", - "timeslider.month.april": "aprilo", - "timeslider.month.may": "majo", - "timeslider.month.june": "junio", - "timeslider.month.july": "julio", - "timeslider.month.august": "aŭgusto", - "timeslider.month.september": "septembro", - "timeslider.month.october": "oktobro", - "timeslider.month.november": "novembro", - "timeslider.month.december": "decembro", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: sennoma aŭtoro, other: sennomaj aŭtoroj ]}", - "pad.savedrevs.marked": "Ĉi tiu versio nun estas markita kiel konservita versio", - "pad.savedrevs.timeslider": "Vi povas rigardi konservitajn versiojn per la tempoŝovilo", - "pad.userlist.entername": "Entajpu vian nomon", - "pad.userlist.unnamed": "sennoma", - "pad.userlist.guest": "Gasto", - "pad.userlist.deny": "Malaprobi", - "pad.userlist.approve": "Aprobi", - "pad.editbar.clearcolors": "Forigi kolorojn de aŭtoreco en la tuta dokumento?", - "pad.impexp.importbutton": "Enporti Nun", - "pad.impexp.importing": "Enportante...", - "pad.impexp.confirmimport": "Enporti dosieron superskribos la nunan tekston en la redaktilo. Ĉu vi certe volas daŭrigi?", - "pad.impexp.convertFailed": "Ni ne kapablis enporti tiun dosieron. Bonvolu uzi alian dokumentformaton aŭ permane kopii kaj alglui.", - "pad.impexp.padHasData": "Ni ne kapablis enporti tiun dosieron ĉar la teksto jam estas ŝanĝita. Bonvolu enporti en novan tekston.", - "pad.impexp.uploadFailed": "La alŝuto malsukcesis, bonvolu provi denove.", - "pad.impexp.importfailed": "Enporti malsukcesis.", - "pad.impexp.copypaste": "Bonvolu kopii kaj alglui", - "pad.impexp.exportdisabled": "Elporti en {{type}} formato estas malŝalta. Bonvolu kontakti la sistremadministranton pro pliaj informoj." -} diff --git a/sources/src/locales/es.json b/sources/src/locales/es.json deleted file mode 100644 index d271b61..0000000 --- a/sources/src/locales/es.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Armando-Martin", - "Jacobo", - "Joker", - "Larjona", - "Mklehr", - "Rubenwap", - "VegaDark", - "Vivaelcelta", - "Xuacu", - "Macofe", - "Fitoschido", - "Dgstranz", - "Luzcaru" - ] - }, - "index.newPad": "Nuevo pad", - "index.createOpenPad": "o crea/abre un pad con el nombre:", - "pad.toolbar.bold.title": "Negrita (Ctrl-B)", - "pad.toolbar.italic.title": "Cursiva (Ctrl-I)", - "pad.toolbar.underline.title": "Subrayado (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Tachado (Ctrl+5)", - "pad.toolbar.ol.title": "Lista ordenada (Ctrl+Mayús+N)", - "pad.toolbar.ul.title": "Lista desordenada (Ctrl+Mayús+L)", - "pad.toolbar.indent.title": "Sangría (TAB)", - "pad.toolbar.unindent.title": "Eliminar sangría (Shift+TAB)", - "pad.toolbar.undo.title": "Deshacer (Ctrl-Z)", - "pad.toolbar.redo.title": "Rehacer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Eliminar los colores de autoría (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importar/Exportar a diferentes formatos de archivos", - "pad.toolbar.timeslider.title": "Línea de tiempo", - "pad.toolbar.savedRevision.title": "Guardar revisión", - "pad.toolbar.settings.title": "Configuración", - "pad.toolbar.embed.title": "Compartir e incrustar este pad", - "pad.toolbar.showusers.title": "Mostrar los usuarios de este pad", - "pad.colorpicker.save": "Guardar", - "pad.colorpicker.cancel": "Cancelar", - "pad.loading": "Cargando...", - "pad.noCookie": "No se pudo encontrar la «cookie». Permite la utilización de «cookies» en el navegador.", - "pad.passwordRequired": "Necesitas una contraseña para acceder a este pad", - "pad.permissionDenied": "No tienes permiso para acceder a este pad", - "pad.wrongPassword": "La contraseña era incorrecta", - "pad.settings.padSettings": "Configuración del pad", - "pad.settings.myView": "Preferencias personales", - "pad.settings.stickychat": "Chat siempre en pantalla", - "pad.settings.chatandusers": "Mostrar el chat y los usuarios", - "pad.settings.colorcheck": "Colores de autoría", - "pad.settings.linenocheck": "Números de línea", - "pad.settings.rtlcheck": "¿Leer contenido de derecha a izquierda?", - "pad.settings.fontType": "Tipografía:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespacio", - "pad.settings.globalView": "Preferencias globales", - "pad.settings.language": "Idioma:", - "pad.importExport.import_export": "Importar/Exportar", - "pad.importExport.import": "Subir cualquier texto o documento", - "pad.importExport.importSuccessful": "¡Éxito!", - "pad.importExport.export": "Exporta el pad actual como:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Texto sin formato", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Solo es posible importar texto sin formato o en HTML. Para obtener funciones de importación más avanzadas es necesario instalar AbiWord.", - "pad.modals.connected": "Conectado.", - "pad.modals.reconnecting": "Reconectando a tu pad..", - "pad.modals.forcereconnect": "Forzar reconexión", - "pad.modals.reconnecttimer": "Se intentará reconectar en", - "pad.modals.cancel": "Cancelar", - "pad.modals.userdup": "Abierto en otra ventana", - "pad.modals.userdup.explanation": "Este pad parece estar abierto en más de una ventana de tu navegador.", - "pad.modals.userdup.advice": "Reconectar para usar esta ventana.", - "pad.modals.unauth": "No autorizado.", - "pad.modals.unauth.explanation": "Tus permisos han cambiado mientras estabas viendo esta página. Intenta reconectarte.", - "pad.modals.looping.explanation": "Hay problemas con el servidor de sincronización.", - "pad.modals.looping.cause": "Puede deberse a que te conectes a través de un proxy o un cortafuegos incompatible.", - "pad.modals.initsocketfail": "Servidor incalcanzable.", - "pad.modals.initsocketfail.explanation": "No se pudo conectar con el servidor de sincronización.", - "pad.modals.initsocketfail.cause": "Probablemente debido a un problema en tu navegador o en tu conexión a Internet.", - "pad.modals.slowcommit.explanation": "El servidor no responde.", - "pad.modals.slowcommit.cause": "Puede deberse a problemas con tu conexión de red.", - "pad.modals.badChangeset.explanation": "Has hecho una edición clasificada como ilegal por el servidor de sincronización.", - "pad.modals.badChangeset.cause": "Esto podría deberse a una mala configuración del servidor o algún otro comportamiento inesperado. Contacta al administrador del servicio, si piensas que esto es un error. Intenta reconectarte con el fin de seguir editando.", - "pad.modals.corruptPad.explanation": "El pad que intentas acceder está dañado.", - "pad.modals.corruptPad.cause": "Esto puede deberse a una mala configuración del servidor o algún otro comportamiento inesperado. Contacta al administrador del servicio.", - "pad.modals.deleted": "Borrado.", - "pad.modals.deleted.explanation": "Este pad ha sido borrado.", - "pad.modals.disconnected": "Te has desconectado.", - "pad.modals.disconnected.explanation": "Se perdió la conexión con el servidor", - "pad.modals.disconnected.cause": "El servidor podría no estar disponible. Contacta al administrador del servicio si esto continúa sucediendo.", - "pad.share": "Compatir este pad", - "pad.share.readonly": "Solo lectura", - "pad.share.link": "Enlace", - "pad.share.emebdcode": "Incrustar URL", - "pad.chat": "Chat", - "pad.chat.title": "Abrir el chat para este pad.", - "pad.chat.loadmessages": "Cargar más mensajes", - "timeslider.pageTitle": "{{appTitle}} Línea de tiempo", - "timeslider.toolbar.returnbutton": "Volver al pad", - "timeslider.toolbar.authors": "Autores:", - "timeslider.toolbar.authorsList": "Sin autores", - "timeslider.toolbar.exportlink.title": "Exportar", - "timeslider.exportCurrent": "Exportar la versión actual como:", - "timeslider.version": "Versión {{version}}", - "timeslider.saved": "Guardado el {{day}} de {{month}} de {{year}}", - "timeslider.playPause": "Reproducir/pausar los contenidos del pad", - "timeslider.backRevision": "Ir a la revisión anterior en este pad", - "timeslider.forwardRevision": "Ir a la revisión posterior en este pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "enero", - "timeslider.month.february": "febrero", - "timeslider.month.march": "marzo", - "timeslider.month.april": "abril", - "timeslider.month.may": "mayo", - "timeslider.month.june": "junio", - "timeslider.month.july": "julio", - "timeslider.month.august": "agosto", - "timeslider.month.september": "septiembre", - "timeslider.month.october": "octubre", - "timeslider.month.november": "noviembre", - "timeslider.month.december": "diciembre", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor desconocido, other: autores desconocidos]}", - "pad.savedrevs.marked": "Revisión guardada", - "pad.savedrevs.timeslider": "Puedes ver revisiones guardadas visitando la línea de tiempo", - "pad.userlist.entername": "Escribe tu nombre", - "pad.userlist.unnamed": "anónimo", - "pad.userlist.guest": "Invitado", - "pad.userlist.deny": "Denegar", - "pad.userlist.approve": "Aprobar", - "pad.editbar.clearcolors": "¿Quieres borrar los colores de autoría en todo el documento?", - "pad.impexp.importbutton": "Importar ahora", - "pad.impexp.importing": "Importando...", - "pad.impexp.confirmimport": "Al importar un archivo se borrará el contenido actual del pad. ¿Estás seguro de que quieres continuar?", - "pad.impexp.convertFailed": "No pudimos importar este archivo. Inténtalo con un formato diferente o copia y pega manualmente.", - "pad.impexp.padHasData": "No hemos podido importar este archivo porque este pad ya ha tenido cambios. Importa a un nuevo pad.", - "pad.impexp.uploadFailed": "El envío falló. Inténtalo de nuevo.", - "pad.impexp.importfailed": "Fallo al importar", - "pad.impexp.copypaste": "Intenta copiar y pegar", - "pad.impexp.exportdisabled": "La exportación al formato {{type}} está desactivada. Contacta a tu administrador de sistemas." -} diff --git a/sources/src/locales/et.json b/sources/src/locales/et.json deleted file mode 100644 index 3ea8b3e..0000000 --- a/sources/src/locales/et.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Kristian.kankainen" - ] - }, - "index.newPad": "Uus klade", - "index.createOpenPad": "loo või rööptoimeta kladet nimega:", - "pad.toolbar.bold.title": "Rasvane (Ctrl + B)", - "pad.toolbar.italic.title": "Kaldkiri (Ctrl + I)", - "pad.toolbar.underline.title": "Allakriipsutus (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Läbikriipsutus", - "pad.toolbar.ol.title": "Nummerdatud loend", - "pad.toolbar.ul.title": "Täppidega loend", - "pad.toolbar.indent.title": "Suurenda taanet (TAB)", - "pad.toolbar.unindent.title": "Vähenda taanet (Shift+TAB)", - "pad.toolbar.undo.title": "Võta tagasi (Ctrl-Z)", - "pad.toolbar.redo.title": "Tee uuesti (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Kustuta eri autorite värvid", - "pad.toolbar.import_export.title": "Impordi-ekspordi eri failivormingutesse", - "pad.toolbar.timeslider.title": "Ajajoon", - "pad.toolbar.savedRevision.title": "Salvesta versioon", - "pad.toolbar.settings.title": "Seaded", - "pad.toolbar.embed.title": "Jaga ja põimi seda kladet", - "pad.toolbar.showusers.title": "Näita klade kasutajaid", - "pad.colorpicker.save": "Salvesta", - "pad.colorpicker.cancel": "Loobu", - "pad.loading": "Laadimine...", - "pad.passwordRequired": "Sul peab olema parool selle klade rööptoimetamiseks", - "pad.permissionDenied": "Sul puuduvad ligipääsuõigused selle klade rööptoimetamiseks", - "pad.wrongPassword": "Vigane parool", - "pad.settings.padSettings": "Klade seadistused", - "pad.settings.myView": "Minu vaade", - "pad.settings.stickychat": "Näita vestlust alatiselt ekraanil", - "pad.settings.colorcheck": "Autorite värvid", - "pad.settings.linenocheck": "Reanumbrid", - "pad.settings.rtlcheck": "Näita sisu paremalt vasakule?", - "pad.settings.fontType": "Šrifti tüüp:", - "pad.settings.fontType.normal": "Normaalne", - "pad.settings.fontType.monospaced": "Ühelaiuste märkidega", - "pad.settings.globalView": "Koguvaade", - "pad.settings.language": "Keel:", - "pad.importExport.import_export": "Import-eksport", - "pad.importExport.import": "Laadi üles mistahes tekstifail või dokument", - "pad.importExport.importSuccessful": "Edukalt laaditud!", - "pad.importExport.export": "Ekspordi käesolev klade kui:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Lihttekst", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Paraku on ainult lihttekstis voi HTML-vormingus dokumentide importimine võimaldatud. Rohkem võimaluste jaoks peab paigaldama abiword.", - "pad.modals.connected": "Ühendatud.", - "pad.modals.reconnecting": "Proovitakse luua ühendus klade juurde...", - "pad.modals.forcereconnect": "Sunni ühenduse taasloomist", - "pad.modals.userdup": "Käesolev klade on avatud teises aknas", - "pad.modals.userdup.explanation": "Käesolev klade paistab olevat avatud rohkem kui ühes brauseriaknas selles arvutis.", - "pad.modals.userdup.advice": "Kasuta käesolevat akent teiste asemel.", - "pad.modals.unauth": "Pole lubatud", - "pad.modals.unauth.explanation": "Sinu ligipääsuõigused on muutunud. Proovi ühendada uuesti.", - "pad.modals.looping.explanation": "Serveriga sünkroniseerimine tundub olevat takistatud.", - "pad.modals.looping.cause": "Äkki oled ühendatud tulemüüri või puhverserveri kaudu?", - "pad.modals.initsocketfail": "Server pole kättesaadaval.", - "pad.modals.initsocketfail.explanation": "Ei saadud ühendust sünkroniseerimisserveriga.", - "pad.modals.initsocketfail.cause": "See on tõenäoliselt su brauserist või internetiühendusest tingitud.", - "pad.modals.slowcommit.explanation": "Server ei vasta.", - "pad.modals.slowcommit.cause": "See on tõenäoliselt võrguühendusest tingitud.", - "pad.modals.badChangeset.explanation": "Sünkroniseerimisserver keeldus vastuvõtmast tehtud muudatuse.", - "pad.modals.badChangeset.cause": "See võib sõltuda serveri valest seadistusest või mõnest muust tõrkest. Palun kontakteeru teenuse haldajaga või proovi uuesti.", - "pad.modals.corruptPad.explanation": "Klade, millele püüad ligi pääseda, on rikkis.", - "pad.modals.corruptPad.cause": "See võib sõltuda serveri valest seadistusest või mõnest muust tõrkest. Palun kontakteeru teenuse haldajaga või proovi uuesti.", - "pad.modals.deleted": "Kustutatud.", - "pad.modals.deleted.explanation": "Klade on kustutatud.", - "pad.modals.disconnected": "Sa ei ole ühendatud.", - "pad.modals.disconnected.explanation": "Ühendus serveriga katkes", - "pad.modals.disconnected.cause": "Server ei ole saadaval. Palun kontakteeru teenuse haldajaga või proovi uuesti.", - "pad.share": "Jaga kladet", - "pad.share.readonly": "Kirjutuskaitstud", - "pad.share.link": "Link", - "pad.share.emebdcode": "Põimi URL", - "pad.chat": "Vestle", - "pad.chat.title": "Ava klade vestlusaken.", - "pad.chat.loadmessages": "Laadi rohkem sõnumeid", - "timeslider.pageTitle": "{{appTitle}} ajajoon", - "timeslider.toolbar.returnbutton": "Tagasi kladele", - "timeslider.toolbar.authors": "Autoridː", - "timeslider.toolbar.authorsList": "Autor puudub", - "timeslider.toolbar.exportlink.title": "Eksport", - "timeslider.exportCurrent": "Ekspordi käesolev versioon kuiː", - "timeslider.version": "Versioon {{version}}", - "timeslider.saved": "Salvestatud {{day}}. {{month}}il {{year}}. aastal", - "timeslider.dateformat": "{{day}}.{{month}}.{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Jaanuar", - "timeslider.month.february": "Veebruar", - "timeslider.month.march": "Märts", - "timeslider.month.april": "Aprill", - "timeslider.month.may": "Mai", - "timeslider.month.june": "Juuni", - "timeslider.month.july": "Juuli", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "Oktoober", - "timeslider.month.november": "November", - "timeslider.month.december": "Detsember", - "timeslider.unnamedauthors": "{{num}} nimetamata {[plural(num) one: autor, other: autorit ]}", - "pad.savedrevs.marked": "Versioon märgiti salvestatuna", - "pad.userlist.entername": "Sisesta oma nimi", - "pad.userlist.unnamed": "Nimetu", - "pad.userlist.guest": "Külaline", - "pad.userlist.deny": "Eira", - "pad.userlist.approve": "Nõustu", - "pad.editbar.clearcolors": "Kas soovid kustutada autorite värvid dokumendist?", - "pad.impexp.importbutton": "Impordi", - "pad.impexp.importing": "Importimine...", - "pad.impexp.confirmimport": "Faili importimine kustutab praeguse versiooni. Kas kindlasti importida?", - "pad.impexp.convertFailed": "Antud faili pole võimalik importida. Palun kasuta teist vormingut või kopeeri-kleebi käsitsi", - "pad.impexp.uploadFailed": "Üleslaadimine nurjus, proovi uuesti", - "pad.impexp.importfailed": "Importimine nurjus", - "pad.impexp.copypaste": "Palun kopeeri ja kleebi", - "pad.impexp.exportdisabled": "Eksportimine vormingusse {{type}} on hetkel keelatud. Üksikasjade saamiseks pöördu oma süsteemiadministraatori poole." -} diff --git a/sources/src/locales/eu.json b/sources/src/locales/eu.json deleted file mode 100644 index fd6c395..0000000 --- a/sources/src/locales/eu.json +++ /dev/null @@ -1,136 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Theklan", - "Subi", - "Xabier Armendaritz", - "An13sa", - "Mikel Ibaiba", - "HairyFotr" - ] - }, - "index.newPad": "Pad berria", - "index.createOpenPad": "edo sortu/ireki Pad bat honako izenarekin:", - "pad.toolbar.bold.title": "Lodia (Ctrl-B)", - "pad.toolbar.italic.title": "Etzana (Ctrl-I)", - "pad.toolbar.underline.title": "Azpimarratua (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Ezabatua (Ctrl+5)", - "pad.toolbar.ol.title": "Zerrenda ordenatua (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Zerrenda ez-ordenatua (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Koska (TAB)", - "pad.toolbar.unindent.title": "Koska kendu (Shift+TAB)", - "pad.toolbar.undo.title": "Desegin (Ctrl-Z)", - "pad.toolbar.redo.title": "Berregin (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Ezabatu Egiletza Koloreak (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Inportatu/Esportatu fitxategi formatu ezberdinetara/ezberdinetatik", - "pad.toolbar.timeslider.title": "Denbora lerroa", - "pad.toolbar.savedRevision.title": "Gorde berrikuspena", - "pad.toolbar.settings.title": "Hobespenak", - "pad.toolbar.embed.title": "Partekatu eta Txertatu pad hau", - "pad.toolbar.showusers.title": "Erakutsi pad honetako erabiltzaileak", - "pad.colorpicker.save": "Gorde", - "pad.colorpicker.cancel": "Utzi", - "pad.loading": "Kargatzen...", - "pad.noCookie": "Cookiea ez da aurkitu. Mesedez, gaitu cookieak zure nabigatzailean!", - "pad.passwordRequired": "Pasahitza behar duzu pad honetara sartzeko", - "pad.permissionDenied": "Ez duzu bamienik pad honetara sartzeko", - "pad.wrongPassword": "Zure pasahitza oker zegoen", - "pad.settings.padSettings": "Pad hobespenak", - "pad.settings.myView": "Nire ikusmoldea", - "pad.settings.stickychat": "Txata beti pantailan", - "pad.settings.chatandusers": "Erakutsi txata eta erabiltzaileak", - "pad.settings.colorcheck": "Egiletzaren koloreak", - "pad.settings.linenocheck": "Lerro zenbakiak", - "pad.settings.rtlcheck": "Edukia eskubitik ezkerrera irakurri?", - "pad.settings.fontType": "Tipografia:", - "pad.settings.fontType.normal": "Arrunta", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Ikuspegi Globala", - "pad.settings.language": "Hizkuntza:", - "pad.importExport.import_export": "Inportatu/Esportatu", - "pad.importExport.import": "Igo edozein testu fitxategi edo dokumentu", - "pad.importExport.importSuccessful": "Arrakastatsua!", - "pad.importExport.export": "Oraingo pad hau honela esportatu:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Testu laua", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Testu laua edo HTML formatudun testuak bakarrik inporta ditzakezu. Aurreratuagoak diren inportazio aukerak izateko AbiWord instala ezazu.", - "pad.modals.connected": "Konektatuta.", - "pad.modals.reconnecting": "Zure pad-era birkonektatu...", - "pad.modals.forcereconnect": "Berkonexioa fortzatu", - "pad.modals.reconnecttimer": "Berriz konektatzen saiatzen", - "pad.modals.cancel": "Deuseztatu", - "pad.modals.userdup": "Beste leiho batean ireki da", - "pad.modals.userdup.explanation": "Pad hau zure nabigatzailearen beste leiho batean irekita dagoela ematen du.", - "pad.modals.userdup.advice": "Berriro konektatu beste leiho hau erabiltzeko.", - "pad.modals.unauth": "Baimenik gabe", - "pad.modals.unauth.explanation": "Orrialdea ikusten ari zinela zure baimenak aldatu dira. Saia zaitez berriro konektatzen.", - "pad.modals.looping.explanation": "Sinkronizazio zerbitzariarekin komunikazioa arazoak daude.", - "pad.modals.looping.cause": "Agian firewall edo proxy ez-bateragarri baten bidez konektatu zara.", - "pad.modals.initsocketfail": "Zerbitzarira ezin da iritsi.", - "pad.modals.initsocketfail.explanation": "Ezin izan da konektatu sinkronizazio zerbitzarira.", - "pad.modals.initsocketfail.cause": "Ziurrenik hau zure nabigatzailea edo internet konexioaren arazo bat dela eta izango da.", - "pad.modals.slowcommit.explanation": "Zerbitzariak ez du erantzuten.", - "pad.modals.slowcommit.cause": "Baliteke hau sarearen konexio arazoak direla eta izatea.", - "pad.modals.badChangeset.explanation": "Sinkronizazio zerbitzariak, zuk egindako aldaketa bat legez kanpokotzat jo du.", - "pad.modals.badChangeset.cause": "Honek zerbitzariaren konfigurazio okerra edo ustekabeko beste jokabidearen baten ondorio izan liteke. Jarri harremanetan zerbitzu-administratzailearekin, errore bat dela uste baduzu. Saiatu berriro konektatzen edizioarekin jarraitzeko.", - "pad.modals.corruptPad.explanation": "Sartzen saiatzen ari zaren Pad-a hondatuta dago.", - "pad.modals.corruptPad.cause": "Baliteke zerbitzari okerreko konfigurazioa edo beste ustekabeko portaera batzuk izatea. Jarri harremanetan zerbitzu-administratzailearekin.", - "pad.modals.deleted": "Ezabatua.", - "pad.modals.deleted.explanation": "Pad hau ezabatua izan da.", - "pad.modals.disconnected": "Deskonektatua izan zara.", - "pad.modals.disconnected.explanation": "Zerbitzariaren konexioa galdu da", - "pad.modals.disconnected.cause": "Baliteke zerbitzaria eskuragarri ez egotea. Mesedez, jakinarazi zerbitzuko administrariari honek gertatzen jarraitzen badu.", - "pad.share": "Pad hau partekatu", - "pad.share.readonly": "Irakurtzeko bakarrik", - "pad.share.link": "Lotura", - "pad.share.emebdcode": "URLa txertatu", - "pad.chat": "Txata", - "pad.chat.title": "Pad honetarako txata ireki.", - "pad.chat.loadmessages": "Mezu gehiago kargatu", - "timeslider.pageTitle": "{{appTitle}} denbora lerroa", - "timeslider.toolbar.returnbutton": "Padera itzuli", - "timeslider.toolbar.authors": "Egileak:", - "timeslider.toolbar.authorsList": "Egilerik gabe", - "timeslider.toolbar.exportlink.title": "Esportatu", - "timeslider.exportCurrent": "Gorde bertsio hau honela:", - "timeslider.version": "Bertsioa {{version}}", - "timeslider.saved": "{{year}}ko {{month}}ren {{day}}an gordeta", - "timeslider.playPause": "Berriro erreproduzitu / gelditu Pad edukiak", - "timeslider.backRevision": "Berrikusketa bat atzerago joan Pad honetan", - "timeslider.forwardRevision": "Berrikusketa bat aurrerago joan Pad honetan", - "timeslider.dateformat": "{{year}}-{{month}}-{{day}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Urtarrila", - "timeslider.month.february": "Otsaila", - "timeslider.month.march": "Martxoa", - "timeslider.month.april": "Apirila", - "timeslider.month.may": "Maiatza", - "timeslider.month.june": "Ekaina", - "timeslider.month.july": "Uztaila", - "timeslider.month.august": "Abuztua", - "timeslider.month.september": "Iraila", - "timeslider.month.october": "Urria", - "timeslider.month.november": "Azaroa", - "timeslider.month.december": "Abendua", - "timeslider.unnamedauthors": "{{num}} izenik gabeko {[plural(num) one: egilea, other: egileak]}", - "pad.savedrevs.marked": "Berrikuspen hau markatua dago gordetako berrikuspen gisa", - "pad.savedrevs.timeslider": "Gordetako berrikusketak ikus ditzakezu denbora-graduatzailea bisitatuz", - "pad.userlist.entername": "Sartu zure erabiltzaile izena", - "pad.userlist.unnamed": "izenik gabe", - "pad.userlist.guest": "Gonbidatua", - "pad.userlist.deny": "Ukatu", - "pad.userlist.approve": "Onartu", - "pad.editbar.clearcolors": "Ezabatu egile koloreak dokumentu osoan?", - "pad.impexp.importbutton": "Inportatu orain", - "pad.impexp.importing": "Inportatzen...", - "pad.impexp.confirmimport": "Fitxategi bat inportatzen baduzu oraingo pad honen testua ezabatuko da. Ziur zaude jarraitu nahi duzula?", - "pad.impexp.convertFailed": "Ez gara gai fitxategi hau inportatzeko. Erabil ezazu, mesedez, beste dokumentu formatu bat edo kopiatu eta itsasi eskuz.", - "pad.impexp.padHasData": "Artxibo hau ezin izan dugu inportatu Pad hau aldaketak izan dituelako jada, Pad berria inportatu mesedez.", - "pad.impexp.uploadFailed": "Igotzean akatsa egon da, saia zaitez berriro", - "pad.impexp.importfailed": "Inportazioak akatsa egin du", - "pad.impexp.copypaste": "Mesedez kopiatu eta pegatu", - "pad.impexp.exportdisabled": "{{type}} formatuarekin esportatzea desgaituta dago. Kontakta ezazu administratzailea detaile gehiagorako." -} diff --git a/sources/src/locales/fa.json b/sources/src/locales/fa.json deleted file mode 100644 index 4b29669..0000000 --- a/sources/src/locales/fa.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "@metadata": { - "authors": [ - "BMRG14", - "Dalba", - "Ebraminio", - "Reza1615", - "ZxxZxxZ", - "الناز", - "Omid.koli" - ] - }, - "index.newPad": "دفترچه یادداشت تازه", - "index.createOpenPad": "یا ایجاد/بازکردن یک دفترچه یادداشت با نام:", - "pad.toolbar.bold.title": "پررنگ (Ctrl-B)", - "pad.toolbar.italic.title": "کج (Ctrl-I)", - "pad.toolbar.underline.title": "زیرخط (Ctrl-U)", - "pad.toolbar.strikethrough.title": "خط خورده (Ctrl+5)", - "pad.toolbar.ol.title": "فهرست مرتب شده (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "فهرست مرتب نشده (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "تورفتگی (TAB)", - "pad.toolbar.unindent.title": "بیرون رفتگی (Shift+TAB)", - "pad.toolbar.undo.title": "باطل‌کردن (Ctrl-Z)", - "pad.toolbar.redo.title": "از نو (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "پاک‌کردن رنگ‌های نویسندگی (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "درون‌ریزی/برون‌ریزی از/به قالب‌های مختلف", - "pad.toolbar.timeslider.title": "لغزندهٔ زمان", - "pad.toolbar.savedRevision.title": "ذخیره‌سازی نسخه", - "pad.toolbar.settings.title": "تنظیمات", - "pad.toolbar.embed.title": "اشتراک و جاسازی این دفترچه یادداشت", - "pad.toolbar.showusers.title": "نمایش کاربران در این دفترچه یادداشت", - "pad.colorpicker.save": "ذخیره", - "pad.colorpicker.cancel": "لغو", - "pad.loading": "در حال بارگذاری...", - "pad.noCookie": "کوکی یافت نشد. لطفاً اجازهٔ اجرای کوکی در مروگرتان را بدهید!", - "pad.passwordRequired": "برای دسترسی به این دفترچه یادداشت نیاز به یک گذرواژه دارید", - "pad.permissionDenied": "شما اجازه‌ی دسترسی به این دفترچه یادداشت را ندارید", - "pad.wrongPassword": "گذرواژه‌ی شما درست نیست", - "pad.settings.padSettings": "تنظیمات دفترچه یادداشت", - "pad.settings.myView": "نمای من", - "pad.settings.stickychat": "گفتگو همیشه روی صفحه نمایش باشد", - "pad.settings.chatandusers": "نمایش چت و کاربران", - "pad.settings.colorcheck": "رنگ‌های نویسندگی", - "pad.settings.linenocheck": "شماره‌ی خطوط", - "pad.settings.rtlcheck": "خواندن محتوا از راست به چپ؟", - "pad.settings.fontType": "نوع قلم:", - "pad.settings.fontType.normal": "ساده", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "نمای سراسری", - "pad.settings.language": "زبان:", - "pad.importExport.import_export": "درون‌ریزی/برون‌ریزی", - "pad.importExport.import": "بارگذاری پرونده‌ی متنی یا سند", - "pad.importExport.importSuccessful": "موفقیت آمیز بود!", - "pad.importExport.export": "برون‌ریزی این دفترچه یادداشت با قالب:", - "pad.importExport.exportetherpad": "اترپد", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "متن ساده", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (قالب سند باز)", - "pad.importExport.abiword.innerHTML": "شما تنها می‌توانید از قالب متن ساده یا اچ‌تی‌ام‌ال درون‌ریزی کنید. برای بیشتر شدن ویژگی‌های درون‌ریزی پیشرفته AbiWord را نصب کنید.", - "pad.modals.connected": "متصل شد.", - "pad.modals.reconnecting": "در حال اتصال دوباره به دفترچه یادداشت شما..", - "pad.modals.forcereconnect": "واداشتن به اتصال دوباره", - "pad.modals.reconnecttimer": "تلاش برای اتصال مجدد", - "pad.modals.cancel": "لغو", - "pad.modals.userdup": "در پنجره‌ای دیگر باز شد", - "pad.modals.userdup.explanation": "گمان می‌رود این دفترچه یادداشت در بیش از یک پنجره‌ی مرورگر باز شده‌است.", - "pad.modals.userdup.advice": "برای استفاده از این پنجره دوباره وصل شوید.", - "pad.modals.unauth": "مجاز نیست", - "pad.modals.unauth.explanation": "دسترسی شما در حین مشاهده‌ی این برگه تغییر یافته‌است. دوباره متصل شوید.", - "pad.modals.looping.explanation": "مشکلاتی ارتباطی با سرور همگام‌سازی وجود دارد.", - "pad.modals.looping.cause": "شاید شما از طریق یک فایروال یا پروکسی ناسازگار متصل شده‌اید.", - "pad.modals.initsocketfail": "سرور در دسترس نیست.", - "pad.modals.initsocketfail.explanation": "نمی‌توان به سرور همگام سازی وصل شد.", - "pad.modals.initsocketfail.cause": "شاید این به خاطر مشکلی در مرورگر یا اتصال اینترنتی شما باشد.", - "pad.modals.slowcommit.explanation": "سرور پاسخ نمی‌دهد.", - "pad.modals.slowcommit.cause": "این می‌تواند به خاطر مشکلاتی در اتصال به شبکه باشد.", - "pad.modals.badChangeset.explanation": "ویرایشی که شما انجام داده‌اید توسط سرور همگام‌سازی نادرست طیقه‌بندی شده است.", - "pad.modals.badChangeset.cause": "این می‌تواند به دلیل پیکربندی اشتباه یا سایر رفتارهای غیرمنتظره باشد. اگر فکر می‌کنید این یک خطا است لطفاً با مدیر خدمت تماس بگیرید. برای ادامهٔ ویرایش سعی کنید که دوباره متصل شوید.", - "pad.modals.corruptPad.explanation": "پدی که شما سعی دارید دسترسی پیدا کنید خراب است.", - "pad.modals.corruptPad.cause": "این احتمالاً به دلیل تنظیمات اشتباه کارساز یا سایر رفتارهای غیرمنتظره است. لطفاً با مدیر خدمت تماس حاصل کنید.", - "pad.modals.deleted": "پاک شد.", - "pad.modals.deleted.explanation": "این دفترچه یادداشت پاک شده‌است.", - "pad.modals.disconnected": "اتصال شما قطع شده‌است.", - "pad.modals.disconnected.explanation": "اتصال به سرور قطع شده‌است.", - "pad.modals.disconnected.cause": "ممکن است سرور در دسترس نباشد. اگر این مشکل باز هم رخ داد مدیر حدمت را آگاه کنید.", - "pad.share": "به اشتراک‌گذاری این دفترچه یادداشت", - "pad.share.readonly": "فقط خواندنی", - "pad.share.link": "پیوند", - "pad.share.emebdcode": "جاسازی نشانی", - "pad.chat": "گفتگو", - "pad.chat.title": "بازکردن گفتگو برای این دفترچه یادداشت", - "pad.chat.loadmessages": "بارگیری پیام‌های بیشتر", - "timeslider.pageTitle": "لغزندهٔ زمان {{appTitle}}", - "timeslider.toolbar.returnbutton": "بازگشت به دفترچه یادداشت", - "timeslider.toolbar.authors": "نویسندگان:", - "timeslider.toolbar.authorsList": "بدون نویسنده", - "timeslider.toolbar.exportlink.title": "برون‌ریزی", - "timeslider.exportCurrent": "برون‌ریزی نگارش کنونی به عنوان:", - "timeslider.version": "نگارش {{version}}", - "timeslider.saved": "{{month}} {{day}}، {{year}} ذخیره شد", - "timeslider.playPause": "اجرای مجدد/متوقف کردن پخش", - "timeslider.backRevision": "رفتن به نسخهٔ پیشین در این دفترچه", - "timeslider.forwardRevision": "رفتن به نسخهٔ بعدی در این دفترچه", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "ژانویه", - "timeslider.month.february": "فوریه", - "timeslider.month.march": "مارس", - "timeslider.month.april": "آوریل", - "timeslider.month.may": "مه", - "timeslider.month.june": "ژوئن", - "timeslider.month.july": "ژوئیه", - "timeslider.month.august": "اوت", - "timeslider.month.september": "سپتامبر", - "timeslider.month.october": "اکتبر", - "timeslider.month.november": "نوامبر", - "timeslider.month.december": "دسامبر", - "timeslider.unnamedauthors": "{{num}} نویسندهٔ بی‌نام", - "pad.savedrevs.marked": "این بازنویسی هم اکنون به عنوان ذخیره شده علامت‌گذاری شد", - "pad.savedrevs.timeslider": "شما می‌توانید نسخه‌های ذخیره شده را با دیدن نوار زمان ببنید", - "pad.userlist.entername": "نام خود را بنویسید", - "pad.userlist.unnamed": "بدون نام", - "pad.userlist.guest": "مهمان", - "pad.userlist.deny": "رد کردن", - "pad.userlist.approve": "پذیرفتن", - "pad.editbar.clearcolors": "رنگ نویسندگی از همه‌ی سند پاک شود؟", - "pad.impexp.importbutton": "هم اکنون درون‌ریزی کن", - "pad.impexp.importing": "در حال درون‌ریزی...", - "pad.impexp.confirmimport": "با درون‌ریزی یک پرونده نوشتهٔ کنونی دفترچه پاک می‌شود. آیا می‌خواهید ادامه دهید؟", - "pad.impexp.convertFailed": "ما نمی‌توانیم این پرونده را درون‌ریزی کنیم. خواهشمندیم قالب دیگری برای سندتان انتخاب کرده یا بصورت دستی آنرا کپی کنید", - "pad.impexp.padHasData": "امکان درون‌ریز این پرونده نیست زیرا این پد تغییر کرده‌است. لطفاً در پد جدید درون‌ریزی کنید.", - "pad.impexp.uploadFailed": "آپلود انجام نشد، دوباره تلاش کنید", - "pad.impexp.importfailed": "درون‌ریزی انجام نشد", - "pad.impexp.copypaste": "کپی پیست کنید", - "pad.impexp.exportdisabled": "برون‌ریزی با قالب {{type}} از کار افتاده است. برای جزئیات بیشتر با مدیر سیستمتان تماس بگیرید." -} diff --git a/sources/src/locales/fi.json b/sources/src/locales/fi.json deleted file mode 100644 index 0a8e43f..0000000 --- a/sources/src/locales/fi.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Artnay", - "Jl", - "Lliehu", - "Nedergard", - "Nike", - "Stryn", - "Tomi Toivio", - "Veikk0.ma", - "VezonThunder", - "Macofe", - "MrTapsa", - "Silvonen", - "Espeox", - "Pyscowicz" - ] - }, - "index.newPad": "Uusi muistio", - "index.createOpenPad": "tai luo tai avaa muistio nimellä:", - "pad.toolbar.bold.title": "Lihavointi (Ctrl-B)", - "pad.toolbar.italic.title": "Kursivointi (Ctrl-I)", - "pad.toolbar.underline.title": "Alleviivaus (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Yliviivaus (Ctrl+5)", - "pad.toolbar.ol.title": "Numeroitu lista (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Numeroimaton lista (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Sisennä (TAB)", - "pad.toolbar.unindent.title": "Ulonna (Shift+TAB)", - "pad.toolbar.undo.title": "Kumoa (Ctrl-Z)", - "pad.toolbar.redo.title": "Tee uudelleen (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Poista kirjoittajavärit (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Tuo tai vie eri tiedostomuodoista tai -muotoihin", - "pad.toolbar.timeslider.title": "Aikajana", - "pad.toolbar.savedRevision.title": "Tallenna muutos", - "pad.toolbar.settings.title": "Asetukset", - "pad.toolbar.embed.title": "Jaa ja upota muistio", - "pad.toolbar.showusers.title": "Näytä muistion käyttäjät", - "pad.colorpicker.save": "Tallenna", - "pad.colorpicker.cancel": "Peru", - "pad.loading": "Ladataan…", - "pad.noCookie": "Evästettä ei löytynyt. Ole hyvä, ja salli evästeet selaimessasi!", - "pad.passwordRequired": "Tämä muistio on suojattu salasanalla.", - "pad.permissionDenied": "Käyttöoikeutesi eivät riitä tämän muistion käyttämiseen.", - "pad.wrongPassword": "Väärä salasana", - "pad.settings.padSettings": "Muistion asetukset", - "pad.settings.myView": "Oma näkymä", - "pad.settings.stickychat": "Keskustelu aina näkyvissä", - "pad.settings.chatandusers": "Näytä keskustelu ja käyttäjät", - "pad.settings.colorcheck": "Kirjoittajavärit", - "pad.settings.linenocheck": "Rivinumerot", - "pad.settings.rtlcheck": "Luetaanko sisältö oikealta vasemmalle?", - "pad.settings.fontType": "Fonttityyppi:", - "pad.settings.fontType.normal": "normaali", - "pad.settings.fontType.monospaced": "tasalevyinen", - "pad.settings.globalView": "Yleisnäkymä", - "pad.settings.language": "Kieli:", - "pad.importExport.import_export": "Tuonti/vienti", - "pad.importExport.import": "Lähetä mikä tahansa tekstitiedosto tai asiakirja", - "pad.importExport.importSuccessful": "Onnistui!", - "pad.importExport.export": "Vie muistio muodossa:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Muotoilematon teksti", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Tuonti on tuettu vain HTML- ja raakatekstitiedostoista. Monipuoliset tuontiominaisuudet ovat käytettävissä asentamalla AbiWord.", - "pad.modals.connected": "Yhdistetty.", - "pad.modals.reconnecting": "Muodostetaan yhteyttä muistioon uudelleen...", - "pad.modals.forcereconnect": "Pakota yhdistämään uudelleen", - "pad.modals.reconnecttimer": "Yritetään yhdistää uudelleen", - "pad.modals.cancel": "Peruuta", - "pad.modals.userdup": "Avattu toisessa ikkunassa", - "pad.modals.userdup.explanation": "Tämä muistio vaikuttaa olevan avoinna useammassa eri selainikkunassa tällä koneella.", - "pad.modals.userdup.advice": "Yhdistä uudelleen, jos haluat käyttää tätä ikkunaa.", - "pad.modals.unauth": "Oikeudet eivät riitä", - "pad.modals.unauth.explanation": "Käyttöoikeutesi ovat muuttuneet katsellessasi tätä sivua. Yritä yhdistää uudelleen.", - "pad.modals.looping.explanation": "Synkronointipalvelimen kanssa on yhteysongelmia.", - "pad.modals.looping.cause": "Yhteytesi on mahdollisesti muodostettu yhteensopimattoman palomuurin tai välityspalvelimen kautta.", - "pad.modals.initsocketfail": "Palvelimeen ei saada yhteyttä.", - "pad.modals.initsocketfail.explanation": "Synkronointipalvelimeen ei saatu yhteyttä.", - "pad.modals.initsocketfail.cause": "Tämä johtuu mitä luultavimmin selaimestasi tai verkkoyhteydestäsi.", - "pad.modals.slowcommit.explanation": "Palvelin ei vastaa.", - "pad.modals.slowcommit.cause": "Tämä saattaa johtua verkkoyhteyden ongelmista.", - "pad.modals.badChangeset.explanation": "Tekemäsi muutos määritettiin sääntöjen vastaiseksi synkronointipalvelimen toimesta.", - "pad.modals.badChangeset.cause": "Tämä saattaa johtua virheellisistä palvelinmäärityksistä tai muusta odottamattomasta toiminnasta. Ota yhteys palvelun ylläpitäjään, jos kyseessä on mielestäsi virhe. Yritä jatkaa muokkausta yhdistämällä uudelleen.", - "pad.modals.corruptPad.explanation": "Muistio jota yrität avata on vioittunut.", - "pad.modals.corruptPad.cause": "Tämä saattaa johtua virheellisistä palvelinmäärityksistä tai muusta odottamattomasta toiminnasta. Ota yhteys palvelun ylläpitäjään.", - "pad.modals.deleted": "Poistettu.", - "pad.modals.deleted.explanation": "Tämä muistio on poistettu.", - "pad.modals.disconnected": "Yhteytesi on katkaistu.", - "pad.modals.disconnected.explanation": "Yhteys palvelimeen katkesi", - "pad.modals.disconnected.cause": "Palvelin saattaa olla tavoittamattomissa. Ilmoita palvelun ylläpitäjälle, jos tilanne toistuu usein.", - "pad.share": "Jaa muistio", - "pad.share.readonly": "Vain luku", - "pad.share.link": "Linkki", - "pad.share.emebdcode": "Upotusosoite", - "pad.chat": "Keskustelu", - "pad.chat.title": "Avaa keskustelu nykyisestä muistiosta.", - "pad.chat.loadmessages": "Lataa lisää viestejä", - "timeslider.pageTitle": "{{appTitle}} -aikajana", - "timeslider.toolbar.returnbutton": "Palaa muistioon", - "timeslider.toolbar.authors": "Tekijät:", - "timeslider.toolbar.authorsList": "Ei tekijöitä", - "timeslider.toolbar.exportlink.title": "Vie", - "timeslider.exportCurrent": "Vie nykyinen versio muodossa:", - "timeslider.version": "Versio {{version}}", - "timeslider.saved": "Tallennettu {{day}}. {{month}}ta {{year}}", - "timeslider.playPause": "Toista / pysäytä muistion sisältö", - "timeslider.backRevision": "Palaa edelliseen muutokseen taaksepäin tässä muistiossa", - "timeslider.forwardRevision": "Siirry seuraavaan muutokseen tässä muistiossa", - "timeslider.dateformat": "{{day}}.{{month}}.{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "tammikuu", - "timeslider.month.february": "helmikuu", - "timeslider.month.march": "maaliskuu", - "timeslider.month.april": "huhtikuu", - "timeslider.month.may": "toukokuu", - "timeslider.month.june": "kesäkuu", - "timeslider.month.july": "heinäkuu", - "timeslider.month.august": "elokuu", - "timeslider.month.september": "syyskuu", - "timeslider.month.october": "lokakuu", - "timeslider.month.november": "marraskuu", - "timeslider.month.december": "joulukuu", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: nimetön tekijä, other: nimetöntä tekijää ]}", - "pad.savedrevs.marked": "Tämä versio on nyt merkitty tallennetuksi versioksi", - "pad.savedrevs.timeslider": "Voit tarkastella tallennettuja versioita avaamalla aikajanan", - "pad.userlist.entername": "Kirjoita nimesi", - "pad.userlist.unnamed": "nimetön", - "pad.userlist.guest": "Vieras", - "pad.userlist.deny": "Estä", - "pad.userlist.approve": "Hyväksy", - "pad.editbar.clearcolors": "Poistetaanko asiakirjasta tekijävärit?", - "pad.impexp.importbutton": "Tuo nyt", - "pad.impexp.importing": "Tuodaan...", - "pad.impexp.confirmimport": "Tiedoston tuonti korvaa kaiken muistiossa olevan tekstin. Haluatko varmasti jatkaa?", - "pad.impexp.convertFailed": "TIedoston tuonti epäonnistui. Käytä eri tiedostomuotoa tai kopioi ja liitä käsin.", - "pad.impexp.padHasData": "Tiedostoa ei voitu lisätä lehtiöön, koska lehtiötä on jo muokattu – ole hyvä ja lisää tiedosto uuteen lehtiöön", - "pad.impexp.uploadFailed": "Lähetys epäonnistui. Yritä uudelleen.", - "pad.impexp.importfailed": "Tuonti epäonnistui", - "pad.impexp.copypaste": "Kopioi ja liitä", - "pad.impexp.exportdisabled": "Vienti muotoon \"{{type}}\" ei ole käytössä. Ota yhteys ylläpitäjään saadaksesi lisätietoja." -} diff --git a/sources/src/locales/fo.json b/sources/src/locales/fo.json deleted file mode 100644 index 43e9d9f..0000000 --- a/sources/src/locales/fo.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "@metadata": { - "authors": [ - "EileenSanda" - ] - }, - "index.newPad": "Nýggjur teldil", - "pad.toolbar.bold.title": "Við feitum (Ctrl-B)", - "pad.toolbar.italic.title": "Skráskrift (Ctrl-I)", - "pad.toolbar.underline.title": "Undirstrikað (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Gjøgnumstrikað", - "pad.toolbar.ol.title": "Bíleggingarlisti", - "pad.toolbar.undo.title": "Angra (Ctrl-Z)", - "pad.toolbar.redo.title": "Ger umaftur (Ctrl-Y)", - "pad.toolbar.import_export.title": "Innflyt/Útflyt frá/til ymiskar fílustøddir", - "pad.toolbar.savedRevision.title": "Goym Endurskoðan", - "pad.toolbar.settings.title": "Innstillingar", - "pad.toolbar.embed.title": "Deil og Innset henda pad'in", - "pad.toolbar.showusers.title": "Vís brúkarar á hesum paddi", - "pad.colorpicker.save": "Goym", - "pad.colorpicker.cancel": "Ógilda", - "pad.loading": "Løðir...", - "pad.passwordRequired": "Tú hevur brúk fyri einum loyniorði fyri at fáa atgongd til henda paddin", - "pad.permissionDenied": "Tú hevur ikki loyvi til at fáa atgongd til henda paddin", - "pad.wrongPassword": "Títt loyniorð var skeivt", - "pad.settings.padSettings": "Pad innstillingar", - "pad.settings.myView": "Mín sýning", - "pad.settings.stickychat": "Kjatta altíð á skerminum", - "pad.settings.colorcheck": "Litir hjá rithøvundaskapinum", - "pad.settings.linenocheck": "Linjunummur", - "pad.settings.rtlcheck": "Vil tú lesa innihaldið frá høgru til vinstu?", - "pad.settings.fontType": "Skriftslag:", - "pad.settings.fontType.normal": "Vanligt", - "pad.settings.fontType.monospaced": "Føst breidd", - "pad.settings.globalView": "Global sýning", - "pad.settings.language": "Mál:", - "pad.importExport.import_export": "Innflyt/Útflyt", - "pad.importExport.import": "Legg út onkra tekstfílu ella dokument", - "pad.importExport.importSuccessful": "Tað eydnaðist!", - "pad.importExport.export": "Útflyt verandi pad sum:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Einfaldur tekstur", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Opið Dokument Format)", - "pad.importExport.abiword.innerHTML": "Tú kanst bert innflyta frá einføldum teksti ella html formatum. Fyri funksjónir til innflytan fyri víðarikomin vinarliga installera abiword.", - "pad.modals.connected": "Tú hevur samband.", - "pad.modals.reconnecting": "Roynir aftur at fáa samband við tín pad..", - "pad.modals.forcereconnect": "Tvinga endurstovnan av sambandi.", - "pad.modals.userdup": "Er latið upp í øðrum vindeyga", - "pad.modals.userdup.explanation": "Tað sær út til at hesin paddurin er latin upp í meira enn einum brovsara vindeyga á hesari telduni.", - "pad.modals.userdup.advice": "Endurstovna sambandi fyri at nýta hetta vindeyga í staðin.", - "pad.modals.unauth": "Er ikki loyvt", - "pad.modals.unauth.explanation": "Tíni loyvi eru broytt, meðan tú hevur hugt at hesi síðuni. Royn og endurstovna sambandi.", - "pad.modals.initsocketfail": "Ambætarin er óatkomuligur.", - "pad.modals.initsocketfail.cause": "Hetta skyldast mest sannlíkt ein trupulleika við tínum kaga/brovsara ella við tínum internetsambandi.", - "pad.modals.slowcommit.explanation": "Ambætarin (servarin) svarar ikki.", - "pad.modals.slowcommit.cause": "Hetta kann skyldast trupulleikar við netverkssambandinum.", - "pad.modals.deleted": "Er strikað.", - "pad.modals.deleted.explanation": "Hesin paddurin er fluttur.", - "pad.modals.disconnected": "Tú hevur mist sambandi.", - "pad.modals.disconnected.explanation": "Sambandið til ambætarin er avbrotið", - "pad.share": "Deil henda paddin", - "pad.share.readonly": "Vart fyri skriving", - "pad.share.link": "Slóð", - "timeslider.toolbar.returnbutton": "Vend aftur til pad'in", - "timeslider.toolbar.authors": "Høvundar:", - "timeslider.toolbar.authorsList": "Ongir høvundar", - "timeslider.toolbar.exportlink.title": "Útflyt", - "timeslider.exportCurrent": "Útflyt hesa versjóna sum:", - "timeslider.version": "Versjón {{version}}", - "timeslider.saved": "Goymt {{month}} {{day}}, {{year}}", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januar", - "timeslider.month.february": "Februar", - "timeslider.month.march": "Mars", - "timeslider.month.april": "Apríl", - "timeslider.month.may": "Mai", - "timeslider.month.june": "Juni", - "timeslider.month.july": "Juli", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "October", - "timeslider.month.november": "November", - "timeslider.month.december": "Desember", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: ónevndur rithøvundur, other: ónevndir rithøvundar ]}", - "pad.savedrevs.marked": "Henda endurskoðanin er nú merkt sum ein goymd endurskoðan", - "pad.userlist.entername": "Skriva títt navn", - "pad.userlist.unnamed": "ikki-navngivið", - "pad.userlist.guest": "Gestur", - "pad.userlist.deny": "Nokta", - "pad.userlist.approve": "Góðkenn" -} diff --git a/sources/src/locales/fr.json b/sources/src/locales/fr.json deleted file mode 100644 index 29583d0..0000000 --- a/sources/src/locales/fr.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Cquoi", - "Crochet.david", - "Gomoko", - "Goofy", - "Goofy-bz", - "Jean-Frédéric", - "Leviathan", - "McDutchie", - "Metroitendo", - "Od1n", - "Peter17", - "Quenenni", - "Rastus Vernon", - "Stephane Cottin", - "Tux-tn", - "Maxim21", - "Boniface", - "Macofe", - "Framafan", - "Fylip22", - "C13m3n7", - "Wladek92", - "Urhixidur", - "Envlh" - ] - }, - "index.newPad": "Nouveau pad", - "index.createOpenPad": "ou créer/ouvrir un pad intitulé :", - "pad.toolbar.bold.title": "Gras (Ctrl+B)", - "pad.toolbar.italic.title": "Italique (Ctrl+I)", - "pad.toolbar.underline.title": "Souligné (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Barré (Ctrl+5)", - "pad.toolbar.ol.title": "Liste ordonnée (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Liste non ordonnée (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Indenter (TAB)", - "pad.toolbar.unindent.title": "Désindenter (Maj+TAB)", - "pad.toolbar.undo.title": "Annuler (Ctrl+Z)", - "pad.toolbar.redo.title": "Rétablir (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Effacer les couleurs identifiant les auteurs (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importer/Exporter de/vers un format de fichier différent", - "pad.toolbar.timeslider.title": "Historique dynamique", - "pad.toolbar.savedRevision.title": "Enregistrer la révision", - "pad.toolbar.settings.title": "Paramètres", - "pad.toolbar.embed.title": "Partager et intégrer ce pad", - "pad.toolbar.showusers.title": "Afficher les utilisateurs du pad", - "pad.colorpicker.save": "Enregistrer", - "pad.colorpicker.cancel": "Annuler", - "pad.loading": "Chargement…", - "pad.noCookie": "Le cookie n’a pas pu être trouvé. Veuillez autoriser les cookies dans votre navigateur !", - "pad.passwordRequired": "Vous avez besoin d'un mot de passe pour accéder à ce pad", - "pad.permissionDenied": "Vous n'avez pas la permission d’accéder à ce pad", - "pad.wrongPassword": "Votre mot de passe est incorrect", - "pad.settings.padSettings": "Paramètres du pad", - "pad.settings.myView": "Ma vue", - "pad.settings.stickychat": "Toujours afficher le clavardage", - "pad.settings.chatandusers": "Afficher la discussion et les utilisateurs", - "pad.settings.colorcheck": "Couleurs d’identification", - "pad.settings.linenocheck": "Numéros de lignes", - "pad.settings.rtlcheck": "Le contenu doit-il être lu de droite à gauche ?", - "pad.settings.fontType": "Police :", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Vue d’ensemble", - "pad.settings.language": "Langue :", - "pad.importExport.import_export": "Importer/Exporter", - "pad.importExport.import": "Charger un texte ou un document", - "pad.importExport.importSuccessful": "Réussi !", - "pad.importExport.export": "Exporter le pad actuel comme :", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Texte brut", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Vous ne pouvez importer que des formats texte brut ou HTML. Pour des fonctionnalités d'importation plus évoluées, veuillez installer AbiWord.", - "pad.modals.connected": "Connecté.", - "pad.modals.reconnecting": "Reconnexion vers votre pad...", - "pad.modals.forcereconnect": "Forcer la reconnexion", - "pad.modals.reconnecttimer": "Essai de reconnexion", - "pad.modals.cancel": "Annuler", - "pad.modals.userdup": "Ouvert dans une autre fenêtre", - "pad.modals.userdup.explanation": "Ce pad semble être ouvert dans plusieurs fenêtres sur cet ordinateur.", - "pad.modals.userdup.advice": "Se reconnecter en utilisant cette fenêtre.", - "pad.modals.unauth": "Non autorisé", - "pad.modals.unauth.explanation": "Vos permissions ont été changées lors de l'affichage de cette page. Essayez de vous reconnecter.", - "pad.modals.looping.explanation": "Nous éprouvons un problème de communication au serveur de synchronisation.", - "pad.modals.looping.cause": "Il est possible que vous soyez connecté avec un pare-feu ou un mandataire incompatible.", - "pad.modals.initsocketfail": "Le serveur est introuvable.", - "pad.modals.initsocketfail.explanation": "Impossible de se connecter au serveur de synchronisation.", - "pad.modals.initsocketfail.cause": "Ceci est probablement dû à un problème avec votre navigateur ou votre connexion internet.", - "pad.modals.slowcommit.explanation": "Le serveur ne répond pas.", - "pad.modals.slowcommit.cause": "Ce problème peut venir d'une mauvaise connectivité au réseau.", - "pad.modals.badChangeset.explanation": "Une modification que vous avez effectuée a été classée comme impossible par le serveur de synchronisation.", - "pad.modals.badChangeset.cause": "Cela peut être dû à une mauvaise configuration du serveur ou à un autre comportement inattendu. Veuillez contacter l’administrateur du service si vous pensez que c’est une erreur. Essayez de vous reconnecter pour continuer à modifier.", - "pad.modals.corruptPad.explanation": "Le pad auquel vous essayez d’accéder est corrompu.", - "pad.modals.corruptPad.cause": "Cela peut être dû à une mauvaise configuration du serveur ou à un autre comportement inattendu. Veuillez contacter l’administrateur du service.", - "pad.modals.deleted": "Supprimé.", - "pad.modals.deleted.explanation": "Ce pad a été supprimé.", - "pad.modals.disconnected": "Vous avez été déconnecté.", - "pad.modals.disconnected.explanation": "La connexion au serveur a échoué.", - "pad.modals.disconnected.cause": "Il se peut que le serveur soit indisponible. Si le problème persiste, veuillez en informer l’administrateur du service.", - "pad.share": "Partager ce pad", - "pad.share.readonly": "Lecture seule", - "pad.share.link": "Lien", - "pad.share.emebdcode": "Incorporer un lien", - "pad.chat": "Clavardage", - "pad.chat.title": "Ouvrir le clavardoir de ce pad.", - "pad.chat.loadmessages": "Charger davantage de messages", - "timeslider.pageTitle": "Historique dynamique de {{appTitle}}", - "timeslider.toolbar.returnbutton": "Retourner au pad", - "timeslider.toolbar.authors": "Auteurs :", - "timeslider.toolbar.authorsList": "Aucun auteur", - "timeslider.toolbar.exportlink.title": "Exporter", - "timeslider.exportCurrent": "Exporter la version actuelle sous :", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Enregistré le {{day}} {{month}} {{year}}", - "timeslider.playPause": "Lecture / Pause des contenus du pad", - "timeslider.backRevision": "Reculer d’une révision dans ce pad", - "timeslider.forwardRevision": "Avancer d’une révision dans ce pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{seconds}}:{{minutes}}:{{hours}}", - "timeslider.month.january": "janvier", - "timeslider.month.february": "février", - "timeslider.month.march": "mars", - "timeslider.month.april": "avril", - "timeslider.month.may": "mai", - "timeslider.month.june": "juin", - "timeslider.month.july": "juillet", - "timeslider.month.august": "août", - "timeslider.month.september": "septembre", - "timeslider.month.october": "octobre", - "timeslider.month.november": "novembre", - "timeslider.month.december": "décembre", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: auteur anonyme, other: auteurs anonymes ]}", - "pad.savedrevs.marked": "Cette révision est maintenant marquée comme révision enregistrée", - "pad.savedrevs.timeslider": "Vous pouvez voir les révisions enregistrées en ouvrant l'historique", - "pad.userlist.entername": "Entrez votre nom", - "pad.userlist.unnamed": "anonyme", - "pad.userlist.guest": "Invité", - "pad.userlist.deny": "Refuser", - "pad.userlist.approve": "Approuver", - "pad.editbar.clearcolors": "Effacer les couleurs de paternité des auteurs dans tout le document ?", - "pad.impexp.importbutton": "Importer maintenant", - "pad.impexp.importing": "Import en cours...", - "pad.impexp.confirmimport": "Importer un fichier écrasera le contenu actuel du pad. Êtes-vous sûr de vouloir le faire ?", - "pad.impexp.convertFailed": "Nous ne pouvons pas importer ce fichier. Veuillez utiliser un autre format de document ou faire manuellement un copier/coller du texte brut", - "pad.impexp.padHasData": "Nous n’avons pas pu importer ce fichier parce que ce pad a déjà eu des modifications ; veuillez donc créer un nouveau pad", - "pad.impexp.uploadFailed": "Le téléversement a échoué, veuillez réessayer", - "pad.impexp.importfailed": "Échec de l'importation", - "pad.impexp.copypaste": "Veuillez copier/coller", - "pad.impexp.exportdisabled": "L'option d'export au format {{type}} est désactivée. Veuillez contacter votre administrateur système pour plus de détails." -} diff --git a/sources/src/locales/fy.json b/sources/src/locales/fy.json deleted file mode 100644 index 540061d..0000000 --- a/sources/src/locales/fy.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Robin van der Vliet" - ] - }, - "pad.toolbar.bold.title": "Fet (Ctrl+B)", - "pad.toolbar.italic.title": "Kursyf (Ctrl+I)", - "pad.toolbar.underline.title": "Understreekje (Ctrl+U)", - "pad.toolbar.settings.title": "Ynstellingen", - "pad.colorpicker.save": "Bewarje", - "pad.colorpicker.cancel": "Annulearje", - "pad.settings.fontType.normal": "Normaal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.language": "Taal:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.modals.connected": "Ferbûn.", - "pad.modals.deleted": "Fuortsmiten.", - "pad.share.link": "Keppeling", - "timeslider.toolbar.authors": "Auteurs:", - "timeslider.toolbar.authorsList": "Gjin auteurs", - "timeslider.toolbar.exportlink.title": "Eksportearje", - "timeslider.version": "Ferzje {{version}}", - "timeslider.dateformat": "{{day}}-{{month}}-{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "jannewaris", - "timeslider.month.february": "febrewaris", - "timeslider.month.march": "maart", - "timeslider.month.april": "april", - "timeslider.month.may": "maaie", - "timeslider.month.june": "juny", - "timeslider.month.july": "july", - "timeslider.month.august": "augustus", - "timeslider.month.september": "septimber", - "timeslider.month.october": "oktober", - "timeslider.month.november": "novimber", - "timeslider.month.december": "desimber", - "pad.userlist.unnamed": "sûnder namme", - "pad.userlist.guest": "Gast", - "pad.userlist.deny": "Wegerje", - "pad.userlist.approve": "Goedkarre" -} diff --git a/sources/src/locales/gl.json b/sources/src/locales/gl.json deleted file mode 100644 index 6749176..0000000 --- a/sources/src/locales/gl.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Toliño", - "Elisardojm" - ] - }, - "index.newPad": "Novo documento", - "index.createOpenPad": "ou cree/abra un documento co nome:", - "pad.toolbar.bold.title": "Negra (Ctrl-B)", - "pad.toolbar.italic.title": "Cursiva (Ctrl-I)", - "pad.toolbar.underline.title": "Subliñar (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Riscar (Ctrl+5)", - "pad.toolbar.ol.title": "Lista ordenada (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Lista sen ordenar (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Sangría (TAB)", - "pad.toolbar.unindent.title": "Sen sangría (Maiús.+TAB)", - "pad.toolbar.undo.title": "Desfacer (Ctrl-Z)", - "pad.toolbar.redo.title": "Refacer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Limpar as cores de identificación dos autores (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importar/Exportar desde/a diferentes formatos de ficheiro", - "pad.toolbar.timeslider.title": "Liña do tempo", - "pad.toolbar.savedRevision.title": "Gardar a revisión", - "pad.toolbar.settings.title": "Configuracións", - "pad.toolbar.embed.title": "Compartir e incorporar este documento", - "pad.toolbar.showusers.title": "Mostrar os usuarios deste documento", - "pad.colorpicker.save": "Gardar", - "pad.colorpicker.cancel": "Cancelar", - "pad.loading": "Cargando...", - "pad.noCookie": "Non se puido atopar a cookie. Por favor, habilite as cookies no seu navegador!", - "pad.passwordRequired": "Cómpre un contrasinal para acceder a este documento", - "pad.permissionDenied": "Non ten permiso para acceder a este documento", - "pad.wrongPassword": "O contrasinal era incorrecto", - "pad.settings.padSettings": "Configuracións do documento", - "pad.settings.myView": "A miña vista", - "pad.settings.stickychat": "Chat sempre visible", - "pad.settings.chatandusers": "Mostrar o chat e os usuarios", - "pad.settings.colorcheck": "Cores de identificación", - "pad.settings.linenocheck": "Números de liña", - "pad.settings.rtlcheck": "Quere ler o contido da dereita á esquerda?", - "pad.settings.fontType": "Tipo de letra:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespazada", - "pad.settings.globalView": "Vista global", - "pad.settings.language": "Lingua:", - "pad.importExport.import_export": "Importar/Exportar", - "pad.importExport.import": "Cargar un ficheiro de texto ou documento", - "pad.importExport.importSuccessful": "Correcto!", - "pad.importExport.export": "Exportar o documento actual en formato:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Texto simple", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Só pode importar texto simple ou formatos HTML. Para obter máis información sobre as características de importación avanzadas instale abiword.", - "pad.modals.connected": "Conectado.", - "pad.modals.reconnecting": "Reconectando co seu documento...", - "pad.modals.forcereconnect": "Forzar a reconexión", - "pad.modals.reconnecttimer": "Intentarase reconectar en", - "pad.modals.cancel": "Cancelar", - "pad.modals.userdup": "Aberto noutra ventá", - "pad.modals.userdup.explanation": "Semella que este documento está aberto en varias ventás do navegador neste ordenador.", - "pad.modals.userdup.advice": "Reconectar para usar esta ventá.", - "pad.modals.unauth": "Non autorizado", - "pad.modals.unauth.explanation": "Os seus permisos cambiaron mentres estaba nesta páxina. Intente a reconexión.", - "pad.modals.looping.explanation": "Hai un problema de comunicación co servidor de sincronización.", - "pad.modals.looping.cause": "Seica a súa conexión pasa a través dun firewall ou proxy incompatible.", - "pad.modals.initsocketfail": "Non se pode alcanzar o servidor.", - "pad.modals.initsocketfail.explanation": "Non se pode conectar co servidor de sincronización.", - "pad.modals.initsocketfail.cause": "Isto acontece probablemente debido a un problema co navegador ou coa conexión á internet.", - "pad.modals.slowcommit.explanation": "O servidor non responde.", - "pad.modals.slowcommit.cause": "Isto pode deberse a un problema de conexión á rede.", - "pad.modals.badChangeset.explanation": "O servidor de sincronización clasificou como ilegal unha das súas edicións.", - "pad.modals.badChangeset.cause": "Isto pode deberse a unha cofiguración errónea do servidor ou algún outro comportamento inesperado. Póñase en contacto co administrador do servizo, se pensa que isto é un erro. Intente reconectar para continuar editando.", - "pad.modals.corruptPad.explanation": "O documento ao que intenta acceder está corrompido.", - "pad.modals.corruptPad.cause": "Isto pode deberse a unha cofiguración errónea do servidor ou algún outro comportamento inesperado. Póñase en contacto co administrador do servizo.", - "pad.modals.deleted": "Borrado.", - "pad.modals.deleted.explanation": "Este documento foi eliminado.", - "pad.modals.disconnected": "Foi desconectado.", - "pad.modals.disconnected.explanation": "Perdeuse a conexión co servidor", - "pad.modals.disconnected.cause": "O servidor non está dispoñible. Póñase en contacto co administrador do servizo se o problema continúa.", - "pad.share": "Compartir este documento", - "pad.share.readonly": "Lectura só", - "pad.share.link": "Ligazón", - "pad.share.emebdcode": "Incorporar o URL", - "pad.chat": "Chat", - "pad.chat.title": "Abrir o chat deste documento.", - "pad.chat.loadmessages": "Cargar máis mensaxes", - "timeslider.pageTitle": "Liña do tempo de {{appTitle}}", - "timeslider.toolbar.returnbutton": "Volver ao documento", - "timeslider.toolbar.authors": "Autores:", - "timeslider.toolbar.authorsList": "Ningún autor", - "timeslider.toolbar.exportlink.title": "Exportar", - "timeslider.exportCurrent": "Exportar a versión actual en formato:", - "timeslider.version": "Versión {{version}}", - "timeslider.saved": "Gardado o {{day}} de {{month}} de {{year}}", - "timeslider.playPause": "Reproducir/pausar os contidos do pad", - "timeslider.backRevision": "Ir á revisión anterior neste pad", - "timeslider.forwardRevision": "Ir á revisión posterior neste pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "xaneiro", - "timeslider.month.february": "febreiro", - "timeslider.month.march": "marzo", - "timeslider.month.april": "abril", - "timeslider.month.may": "maio", - "timeslider.month.june": "xuño", - "timeslider.month.july": "xullo", - "timeslider.month.august": "agosto", - "timeslider.month.september": "setembro", - "timeslider.month.october": "outubro", - "timeslider.month.november": "novembro", - "timeslider.month.december": "decembro", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor anónimo, other: autores anónimos ]}", - "pad.savedrevs.marked": "Esta revisión está agora marcada como revisión gardada", - "pad.savedrevs.timeslider": "Pode consultar as revisións gardadas visitando a liña do tempo", - "pad.userlist.entername": "Insira o seu nome", - "pad.userlist.unnamed": "anónimo", - "pad.userlist.guest": "Convidado", - "pad.userlist.deny": "Rexeitar", - "pad.userlist.approve": "Aprobar", - "pad.editbar.clearcolors": "Quere limpar as cores de identificación dos autores en todo o documento?", - "pad.impexp.importbutton": "Importar agora", - "pad.impexp.importing": "Importando...", - "pad.impexp.confirmimport": "A importación dun ficheiro ha sobrescribir o texto actual do documento. Está seguro de querer continuar?", - "pad.impexp.convertFailed": "Non somos capaces de importar o ficheiro. Utilice un formato de documento diferente ou copie e pegue manualmente", - "pad.impexp.padHasData": "Non puidemos importar este ficheiro porque este documento xa sufriu cambios; importe a un novo documento.", - "pad.impexp.uploadFailed": "Houbo un erro ao cargar o ficheiro; inténteo de novo", - "pad.impexp.importfailed": "Fallou a importación", - "pad.impexp.copypaste": "Copie e pegue", - "pad.impexp.exportdisabled": "A exportación en formato {{type}} está desactivada. Póñase en contacto co administrador do sistema se quere máis detalles." -} diff --git a/sources/src/locales/gu.json b/sources/src/locales/gu.json deleted file mode 100644 index 00a1a5f..0000000 --- a/sources/src/locales/gu.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Bhatakati aatma", - "Harsh4101991", - "KartikMistry" - ] - }, - "index.newPad": "નવું પેડ", - "pad.toolbar.bold.title": "બોલ્ડ", - "pad.toolbar.settings.title": "ગોઠવણીઓ", - "pad.colorpicker.save": "સાચવો", - "pad.colorpicker.cancel": "રદ્દ કરો", - "pad.loading": "લાવે છે...", - "pad.noCookie": "કુકી મળી નહી. આપના બ્રાઉઝર સેટિંગમાં જઇ કુકી સક્રિય કરો!", - "pad.passwordRequired": "તમારે આ પેડના ઉપયોગ માટે ગુપ્તસંજ્ઞાની જરુર પડશે", - "pad.permissionDenied": "આ પેડના ઉપયોગની આપને પરવાનગી નથી", - "pad.wrongPassword": "આપની ગુપ્તસંજ્ઞા ખોટી છે", - "pad.settings.padSettings": "પેડ ગોઠવણીઓ", - "pad.settings.myView": "મારા મતે", - "pad.settings.fontType.normal": "સામાન્ય", - "pad.settings.fontType.monospaced": "મોનોસ્પેસ", - "pad.settings.language": "ભાષા:", - "pad.importExport.import_export": "આયાત/નિકાસ", - "pad.importExport.importSuccessful": "સફળ!", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "સાદું લખાણ", - "pad.importExport.exportword": "માઇક્રોસોફ્ટ વર્ડ", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (ઓપન ડોક્યુમેન્ટ ફોરમેટ)", - "pad.importExport.abiword.innerHTML": "આપ માત્ર સાદુ લખાણ અથવા HTML આયાત કરી શકો છો. વધુ અધ્યતન આયાત સુવિધા માટે abiword ઇન્સ્ટોલ કરો.", - "pad.modals.connected": "જોડાયેલું", - "pad.chat": "વાતચીત", - "pad.chat.title": "આ પેડ માટે વાતચીત ખોલો.", - "pad.chat.loadmessages": "વધુ સંદેશાઓ લાવો", - "timeslider.toolbar.authors": "લેખકો:", - "timeslider.month.january": "જાન્યુઆરી", - "timeslider.month.february": "ફેબ્રુઆરી", - "timeslider.month.march": "માર્ચ", - "timeslider.month.april": "એપ્રિલ", - "timeslider.month.may": "મે", - "timeslider.month.june": "જૂન", - "timeslider.month.july": "જુલાઇ", - "timeslider.month.august": "ઓગસ્ટ", - "timeslider.month.september": "સપ્ટેમ્બર", - "timeslider.month.october": "ઓક્ટોબર", - "timeslider.month.november": "નવેમ્બર", - "timeslider.month.december": "ડિસેમ્બર", - "pad.userlist.entername": "તમારું નામ દાખલ કરો", - "pad.userlist.unnamed": "અનામી", - "pad.userlist.guest": "મહેમાન", - "pad.userlist.deny": "નકારો", - "pad.userlist.approve": "મંજૂર", - "pad.impexp.importbutton": "આયાત કરો", - "pad.impexp.importing": "આયાત કરે છે..." -} diff --git a/sources/src/locales/he.json b/sources/src/locales/he.json deleted file mode 100644 index a857671..0000000 --- a/sources/src/locales/he.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Amire80", - "Ofrahod", - "YaronSh", - "תומר ט" - ] - }, - "index.newPad": "פנקס חדש", - "index.createOpenPad": "ליצור או לפתוח פנקס בשם:", - "pad.toolbar.bold.title": "בולט (Ctrl-B)", - "pad.toolbar.italic.title": "נטוי (Ctrl-I)", - "pad.toolbar.underline.title": "קו תחתי (Ctrl-U)", - "pad.toolbar.strikethrough.title": "קו מוחק (Ctrl+5)", - "pad.toolbar.ol.title": "רשימה ממוספרת (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "רשימת תבליטים (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "הזחה (טאב)", - "pad.toolbar.unindent.title": "צמצום הזחה (שיפט–טאב)", - "pad.toolbar.undo.title": "ביטול (Ctrl-Z)", - "pad.toolbar.redo.title": "ביצוע מחדש", - "pad.toolbar.clearAuthorship.title": "ניקוי צבעי כותבים (Ctrl-Shift-C)", - "pad.toolbar.import_export.title": "ייבוא/ייצוא בתסדירי קבצים שונים", - "pad.toolbar.timeslider.title": "גולל זמן", - "pad.toolbar.savedRevision.title": "שמירת גרסה", - "pad.toolbar.settings.title": "הגדרות", - "pad.toolbar.embed.title": "שיתוף והטמעה של הפנקס הזה", - "pad.toolbar.showusers.title": "הצגת המשתמשים בפנקס הזה", - "pad.colorpicker.save": "שמירה", - "pad.colorpicker.cancel": "ביטול", - "pad.loading": "טעינה...", - "pad.noCookie": "העוגייה לא נמצאה. נא לאפשר עוגיות בדפדפן שלך!", - "pad.passwordRequired": "דרושה ססמה כדי לגשת לפנקס הזה", - "pad.permissionDenied": "אין לך הרשאה לגשת לפנקס הזה", - "pad.wrongPassword": "ססמתך הייתה שגויה", - "pad.settings.padSettings": "הגדרות פנקס", - "pad.settings.myView": "התצוגה שלי", - "pad.settings.stickychat": "השיחה תמיד על המסך", - "pad.settings.chatandusers": "הצגת צ'אט ומשתמשים", - "pad.settings.colorcheck": "צביעה לפי מחבר", - "pad.settings.linenocheck": "מספרי שורות", - "pad.settings.rtlcheck": "לקרוא את התוכן מימין לשמאל?", - "pad.settings.fontType": "סוג גופן:", - "pad.settings.fontType.normal": "רגיל", - "pad.settings.fontType.monospaced": "ברוחב קבוע", - "pad.settings.globalView": "תצוגה לכל המשתמשים", - "pad.settings.language": "שפה:", - "pad.importExport.import_export": "ייבוא/ייצוא", - "pad.importExport.import": "העלאת כל קובץ טקסט או מסמך", - "pad.importExport.importSuccessful": "זה עבד!", - "pad.importExport.export": "ייצוא הפנקס הנוכחי בתור:", - "pad.importExport.exportetherpad": "את'רפד", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "טקסט רגיל", - "pad.importExport.exportword": "מיקרוסופט וורד", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "באפשרותך לייבא מטקסט פשוט או מ־HTML. לאפשרויות ייבוא מתקדמות יותר יש להתקין AbiWord.", - "pad.modals.connected": "מחובר.", - "pad.modals.reconnecting": "מתבצע חיבור מחדש...", - "pad.modals.forcereconnect": "לכפות חיבור מחדש", - "pad.modals.reconnecttimer": "מנסה להתחבר מחדש בעוד", - "pad.modals.cancel": "ביטול", - "pad.modals.userdup": "פתוח בחלון אחר", - "pad.modals.userdup.explanation": "נראה שהפנקס הזה פתוח ביותר מחלון דפדפן אחד במחשב הזה.", - "pad.modals.userdup.advice": "להתחבר מחדש באמצעות החלון הזה.", - "pad.modals.unauth": "אין הרשאה", - "pad.modals.unauth.explanation": "ההרשאות שלך השתנו בזמן שניסית להתחבר. נא לנסות להתחבר מחדש.", - "pad.modals.looping.explanation": "יש בעיות חיבור עם השרת המתאם.", - "pad.modals.looping.cause": "ייתכן שהתחברת דרך חומת־אש או שרת מתווך בלתי־תואמים.", - "pad.modals.initsocketfail": "אין תקשורות לשרת.", - "pad.modals.initsocketfail.explanation": "התחברות לשרת המתאם לא הצליחה.", - "pad.modals.initsocketfail.cause": "אולי זה בגלל הדפדפן שלך או חיבור האינטרנט שלך.", - "pad.modals.slowcommit.explanation": "השרת אינו מגיב.", - "pad.modals.slowcommit.cause": "אולי זה בגלל בעיות עם תקשורת לרשת.", - "pad.modals.badChangeset.explanation": "עריכה שעשית סווגה כבלתי־תקינה על־ידי שרת הסנכרון.", - "pad.modals.badChangeset.cause": "ייתכן שזה קרה בגלל הגדרות שרת שגויות או התנהגות בלתי־צפויה כלשהי. נא ליצור קשר עם המנהל של השירות אם נראה לך שזאת שגיאה. כדי להמשיך לערוך יש לנסות להתחבר מחדש.", - "pad.modals.corruptPad.explanation": "הנתונים בפנקס שניסית לגשת אליו התקלקלו.", - "pad.modals.corruptPad.cause": "ייתכן שזה קרה בגלל הגדרות שרת שגויות או התנהגות בלתי־צפויה כלשהי. נא ליצור קשר עם המנהל של השירות אם נראה לך שזאת שגיאה.", - "pad.modals.deleted": "נמחק.", - "pad.modals.deleted.explanation": "הפנקס הזה הוסר.", - "pad.modals.disconnected": "נותקת.", - "pad.modals.disconnected.explanation": "התקשורת לשרת אבדה", - "pad.modals.disconnected.cause": "ייתכן שהשרת אינו זמין. נא להודיע למנהל השירות אם זה ממשיך לקרות.", - "pad.share": "שיתוף הפנקס הזה", - "pad.share.readonly": "קישור", - "pad.share.link": "קישור", - "pad.share.emebdcode": "הטמעת קישור", - "pad.chat": "שיחה", - "pad.chat.title": "פתיחת השיחה של הפנקס הזה.", - "pad.chat.loadmessages": "טעינת הודעות נוספות", - "timeslider.pageTitle": "גולל זמן של {{appTitle}}", - "timeslider.toolbar.returnbutton": "חזרה אל הפנקס", - "timeslider.toolbar.authors": "כותבים:", - "timeslider.toolbar.authorsList": "אין כותבים", - "timeslider.toolbar.exportlink.title": "ייצוא", - "timeslider.exportCurrent": "ייצוא הגרסה הנוכחית בתור:", - "timeslider.version": "גרסה {{version}}", - "timeslider.saved": "נשמרה ב־{{day}} ב{{month}} {{year}}", - "timeslider.playPause": "לנגן / לעצור את תוכן הפנקס", - "timeslider.backRevision": "לחזור לגרסה של הפנקס הזה", - "timeslider.forwardRevision": "ללכת לגרסה חדשה יותר בפנקס הזה", - "timeslider.dateformat": "{{year}}-{{month}}-{{day}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "ינואר", - "timeslider.month.february": "פברואר", - "timeslider.month.march": "מרץ", - "timeslider.month.april": "אפריל", - "timeslider.month.may": "מאי", - "timeslider.month.june": "יוני", - "timeslider.month.july": "יולי", - "timeslider.month.august": "אוגוסט", - "timeslider.month.september": "ספטמבר", - "timeslider.month.october": "אוקטובר", - "timeslider.month.november": "נובמבר", - "timeslider.month.december": "דצמבר", - "timeslider.unnamedauthors": "{[plural(num) one: יוצר אחד, other: {{num}} יוצרים ]} ללא שם", - "pad.savedrevs.marked": "גרסה זו מסומנת כגרסה שמורה", - "pad.savedrevs.timeslider": "אפשר להציג גרסאות שמורות באמצעות ביקור בגולל הזמן", - "pad.userlist.entername": "נא להזין את שמך", - "pad.userlist.unnamed": "ללא שם", - "pad.userlist.guest": "אורח", - "pad.userlist.deny": "לדחות", - "pad.userlist.approve": "לאשר", - "pad.editbar.clearcolors": "לנקות צבעים לסימון כותבים בכל המסמך?", - "pad.impexp.importbutton": "לייבא כעת", - "pad.impexp.importing": "ייבוא...", - "pad.impexp.confirmimport": "ייבוא של קובץ יבטל את הטקסט הנוכחי בפנקס. האם ברצונך להמשיך?", - "pad.impexp.convertFailed": "לא הצלחנו לייבא את הקובץ הזה. נא להשתמש בתסדיר מסמך שונה או להעתיק ולהדביק ידנית", - "pad.impexp.padHasData": "לא הצלחנו לייבא את הקובץ הזה, כי בפנקס הזה כבר יש שינויים. נא לייבא לפנקס חדש.", - "pad.impexp.uploadFailed": "ההעלאה נכשלה, נא לנסות שוב", - "pad.impexp.importfailed": "הייבוא נכשל", - "pad.impexp.copypaste": "נא להעתיק ולהדביק", - "pad.impexp.exportdisabled": "ייצוא בתסדיר {{type}} אינו פעיל. מנהל המערכת שלך יוכל לספר לך על זה עוד פרטים." -} diff --git a/sources/src/locales/hi.json b/sources/src/locales/hi.json deleted file mode 100644 index c78d74d..0000000 --- a/sources/src/locales/hi.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Sfic" - ] - }, - "pad.toolbar.bold.title": "गहरा (Ctrl+B)", - "pad.toolbar.italic.title": "तिरछा (Ctrl+I)", - "pad.toolbar.strikethrough.title": "काटें (Ctrl+5)", - "pad.colorpicker.save": "सहेजें", - "pad.colorpicker.cancel": "रद्द करें", - "pad.loading": "लोड हो रहा है...", - "pad.settings.language": "भाषा:", - "pad.importExport.import_export": "आयात/निर्यात", - "pad.importExport.exportpdf": "पीडीएफ़", - "pad.modals.cancel": "रद्द करें", - "timeslider.toolbar.authors": "लेखक:", - "timeslider.toolbar.exportlink.title": "निर्यात", - "timeslider.version": "संस्करण {{version}}", - "timeslider.saved": "{{day}} {{month}} {{year}} सहेजा गया", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "जनवरी", - "timeslider.month.february": "फ़रवरी", - "timeslider.month.march": "मार्च", - "timeslider.month.april": "अप्रैल", - "timeslider.month.may": "मई", - "timeslider.month.june": "जून", - "timeslider.month.july": "जुलाई", - "timeslider.month.august": "अगस्त", - "timeslider.month.september": "सितम्बर", - "timeslider.month.october": "अक्टूबर", - "timeslider.month.november": "नवम्बर", - "timeslider.month.december": "दिसम्बर", - "pad.userlist.guest": "अतिथि", - "pad.impexp.importbutton": "अभी आयात करें", - "pad.impexp.importing": "आयात कर रहा...", - "pad.impexp.importfailed": "आयात विफल हुआ", - "pad.impexp.copypaste": "कृपया कॉपी पेस्ट करें" -} diff --git a/sources/src/locales/hr.json b/sources/src/locales/hr.json deleted file mode 100644 index 2c7190f..0000000 --- a/sources/src/locales/hr.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Bugoslav" - ] - }, - "index.newPad": "Novi blokić", - "index.createOpenPad": "ili stvori/otvori blokić s imenom:", - "pad.toolbar.bold.title": "Masno (Ctrl+B)", - "pad.toolbar.italic.title": "Ukošeno (Ctrl+I)", - "pad.toolbar.underline.title": "Podcrtano (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Prekriženo (Ctrl+5)", - "pad.toolbar.ol.title": "Uređeni popis (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Neuređeni popis (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Uvlaka (TAB)", - "pad.toolbar.unindent.title": "Izvlaka (Shift+TAB)", - "pad.toolbar.undo.title": "Poništi (Ctrl+Z)", - "pad.toolbar.redo.title": "Ponovi (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Ukloni boje autorstva (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Uvezi/izvezi iz/na različite datotečne formate", - "pad.toolbar.timeslider.title": "Pokazivač vremenske lente", - "pad.toolbar.savedRevision.title": "Spremi inačicu", - "pad.toolbar.settings.title": "Postavke", - "pad.toolbar.embed.title": "Dijeli i umetni ovaj blokić", - "pad.toolbar.showusers.title": "Pokaži suradnike ovoga blokića", - "pad.colorpicker.save": "Spremi", - "pad.colorpicker.cancel": "Otkaži", - "pad.loading": "Učitavanje...", - "pad.noCookie": "Kolačić nije pronađen. Molimo Vas da uključite kolačiće u Vašem pregledniku!", - "pad.passwordRequired": "Potrebna Vam je zaporka za pristup ovomu blokiću", - "pad.permissionDenied": "Nemate dopuštenje za pristup ovome blokiću", - "pad.wrongPassword": "Vaša zaporka nije valjana", - "pad.settings.padSettings": "Postavke blokića", - "pad.settings.myView": "Vaš prikaz", - "pad.settings.stickychat": "Stavi čavrljanje uvijek na ekranu", - "pad.settings.chatandusers": "Prikaži čavrljanje i suradnike", - "pad.settings.colorcheck": "Boje autorstva", - "pad.settings.linenocheck": "Brojevi redaka", - "pad.settings.rtlcheck": "Želite li prikaz sadržaja s desna na lijevo?", - "pad.settings.fontType": "Vrsta fonta:", - "pad.settings.globalView": "Globalni prikaz", - "pad.settings.language": "Jezik:", - "pad.importExport.import_export": "Uvoz/Izvoz", - "pad.importExport.import": "Postavite bilo koju tekstualnu datoteku ili dokument", - "pad.importExport.importSuccessful": "Uspješno!", - "pad.importExport.export": "Izvezi trenutačni blokić kao:", - "pad.importExport.exportetherpad": "Etherpad (virtualni blokići)", - "pad.importExport.exporthtml": "HTML (oblikovanje sadržaja)", - "pad.importExport.exportplain": "Obični tekst (bez oblikovanja)", - "pad.importExport.exportword": "Datoteku programa Microsoft Word", - "pad.importExport.exportpdf": "Datoteku Acrobatova PDF formata", - "pad.importExport.exportopen": "Datoteku formata Open Document (ODF)", - "pad.importExport.abiword.innerHTML": "Možete uvoziti datoteke formata za obični tekst (bez oblikovanja) te datoteke u HTML-u. Za naprednije mogućnosti uvoza molimo Vas, instalirajte program AbiWord.", - "pad.modals.connected": "Povezano.", - "pad.modals.reconnecting": "Ponovo Vas povezujemo s Vašim blokićem...", - "pad.modals.forcereconnect": "Prisilno se ponovo poveži", - "pad.modals.reconnecttimer": "Sustav Vas pokušava ponovo povezati", - "pad.modals.cancel": "Odustani", - "pad.modals.userdup": "Otvoreno u drugom prozoru", - "pad.modals.userdup.explanation": "Čini se da je ovaj blokić otvoren u više od jednoga prozora Vašega preglednika na ovom računalu.", - "pad.modals.userdup.advice": "Ponovo se povežite da biste rabili ovaj prozor.", - "pad.modals.unauth": "Niste ovlašteni", - "pad.modals.unauth.explanation": "Vaše su ovlasti promijenjene za vrijeme dok ste pregledavali stranicu.\nPokušajte se ponovo spojiti.", - "pad.modals.looping.explanation": "Postoje komunikacijski problemi sa sinkronizacijskim poslužiteljem.", - "pad.modals.looping.cause": "Možda ste se spojili preko nekompatibilne sigurnosne stijene ili proxyja.", - "pad.modals.initsocketfail": "Poslužitelj nije dostupan.", - "pad.modals.initsocketfail.explanation": "Ne mogu se povezati sa sinkronizacijskim poslužiteljem.", - "pad.modals.initsocketfail.cause": "Najvjerojatnije je došlo do problema s Vašim preglednikom ili s Vašom internetskom vezom.", - "pad.modals.slowcommit.explanation": "Poslužitelj ne šalje odziv.", - "pad.modals.slowcommit.cause": "Najvjerojatnije je došlo do problema s dostupnošću mreže.", - "pad.modals.badChangeset.explanation": "Sinkronizacijski poslužitelj označio je Vaše uređivanje kao nedopušteno.", - "pad.modals.badChangeset.cause": "Moguće je da je došlo do pogrješke konfiguracije poslužitelja ili nekog drugog neočekivanog događaja odnosno postupka. Molimo Vas da kontaktirate s Vašim administratorom usluge, ukoliko držite da je ovo pogrješka. Molimo Vas, pokušajte se ponovo spojiti kako biste nastavili s uređivanjem.", - "pad.modals.corruptPad.explanation": "Blokić kom pokušavate pristupiti je oštećen.", - "pad.modals.corruptPad.cause": "Moguće je došlo do pogrješne konfiguracije poslužitelja ili nekog drugog neočekivanog događaja ili postupka. Molimo Vas, kontaktirajte administratora usluge.", - "pad.modals.deleted": "Pobrisano.", - "pad.modals.deleted.explanation": "Blokić je bio uklonjen.", - "pad.modals.disconnected": "Vaša je veza prekinuta.", - "pad.modals.disconnected.explanation": "Veza s poslužiteljem je izgubljena.", - "pad.modals.disconnected.cause": "Moguće je da poslužitelj nije dostupan. Molimo Vas, obavijestite administratora usluge ukoliko se to nastavi događati.", - "pad.share": "Dijeljenje ovoga blokića.", - "pad.share.readonly": "Samo za čitanje", - "pad.share.link": "Poveznica", - "pad.share.emebdcode": "Umetni poveznicu (URL)", - "pad.chat": "Čavrljanje", - "pad.chat.title": "Otvori čavrljanje uz ovaj blokić.", - "pad.chat.loadmessages": "Učitaj više poruka", - "timeslider.pageTitle": "{{appTitle}} Vremenska lenta", - "timeslider.toolbar.returnbutton": "Vrati se natrag na blokić", - "timeslider.toolbar.authors": "Autori:", - "timeslider.toolbar.authorsList": "Nema autora", - "timeslider.toolbar.exportlink.title": "Izvoz", - "timeslider.exportCurrent": "Izvezi trenutačnu inačicu kao:", - "timeslider.version": "Inačica {{version}}", - "timeslider.saved": "Spremljeno dana {{day}}. {{month}} {{year}}.", - "timeslider.playPause": "Izvrti/pauziraj sadržaj blokića", - "timeslider.backRevision": "Idi jednu inačicu ovog blokića natrag", - "timeslider.forwardRevision": "Idi jednu inačicu ovog blokića naprijed", - "timeslider.dateformat": "{{day}}. {{month}}. {{year}}. {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "siječnja", - "timeslider.month.february": "veljače", - "timeslider.month.march": "ožujka", - "timeslider.month.april": "travnja", - "timeslider.month.may": "svibnja", - "timeslider.month.june": "lipnja", - "timeslider.month.july": "srpnja", - "timeslider.month.august": "kolovoza", - "timeslider.month.september": "rujna", - "timeslider.month.october": "listopada", - "timeslider.month.november": "studenoga", - "timeslider.month.december": "prosinca", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovani autor, plural(num) two: neimenovana autora, plural(num) other: neimenovanih autora ]}", - "pad.savedrevs.marked": "Ova inačica označena je sada kao spremljena inačica", - "pad.savedrevs.timeslider": "Možete vidjeti spremljene inačice rabeći vremensku lentu (timeslider)", - "pad.userlist.entername": "Unesite Vaše suradničko ime", - "pad.userlist.unnamed": "bez imena", - "pad.userlist.guest": "Gost", - "pad.userlist.deny": "Odbij", - "pad.userlist.approve": "Odobri", - "pad.editbar.clearcolors": "Ukloniti boje autorstva u cijelom blokiću?", - "pad.impexp.importbutton": "Uvezi odmah", - "pad.impexp.importing": "Uvoženje...", - "pad.impexp.confirmimport": "Uvoženje datoteke presnimit će trenutačni sadržaj blokića.\nJeste li sigurni da želite nastaviti?", - "pad.impexp.convertFailed": "Nismo bili u mogućnosti uvesti tu datoteku. Molimo Vas, rabite neki drugi format dokumenta ili ručno preslikajte/zalijepite sadržaj", - "pad.impexp.padHasData": "Nismo bili u mogućnosti uvesti navedenu datoteku, jer je blokić već bio mijenjan, molimo Vas uvezite u novi blokić", - "pad.impexp.uploadFailed": "Postavljanje nije uspjelo. molimo Vas, pokušajte ponovo", - "pad.impexp.importfailed": "Uvoz nije uspio", - "pad.impexp.copypaste": "Molimo preslikajte/zalijepite", - "pad.impexp.exportdisabled": "Izvoz u formatu {{type}} nije omogućen. Molimo Vas, kontaktirajte Vašega administratora sustava za više pojedinosti." -} diff --git a/sources/src/locales/hrx.json b/sources/src/locales/hrx.json deleted file mode 100644 index 74630ef..0000000 --- a/sources/src/locales/hrx.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Paul Beppler" - ] - }, - "index.newPad": "Neies Pad", - "index.createOpenPad": "Pad mit follichendem Noome uffmache:", - "pad.toolbar.bold.title": "Fett (Strg-B)", - "pad.toolbar.italic.title": "Kursiv (Strg-I)", - "pad.toolbar.underline.title": "Unnerstrich (Strg-U)", - "pad.toolbar.strikethrough.title": "Dorrichgestrich", - "pad.toolbar.ol.title": "Nummerierte List", - "pad.toolbar.ul.title": "Ungeordnete List", - "pad.toolbar.indent.title": "Einrück (TAB)", - "pad.toolbar.unindent.title": "Ausrück (Shift+TAB)", - "pad.toolbar.undo.title": "Rückgängich (Strg-Z)", - "pad.toolbar.redo.title": "Wiederhole (Strg-Y)", - "pad.toolbar.clearAuthorship.title": "Autorefarbe zurücksetze", - "pad.toolbar.import_export.title": "Import/Export von/zu verschiedne Dateiformate", - "pad.toolbar.timeslider.title": "Pad-Versionsgeschicht oonzeiche", - "pad.toolbar.savedRevision.title": "Version markiere", - "pad.toolbar.settings.title": "Einstellunge", - "pad.toolbar.embed.title": "Pad teile orrer inbette", - "pad.toolbar.showusers.title": "Aktuell verbundne Benutzer oonzeiche", - "pad.colorpicker.save": "Speichre", - "pad.colorpicker.cancel": "Abbreche", - "pad.loading": "Loode …", - "pad.passwordRequired": "Sie benötiche en Passwort, um uff das Pad zuzugreife", - "pad.permissionDenied": "Du host ken Berechtichung, um uff das Pad zuzugreif", - "pad.wrongPassword": "Dein Passwort woor falsch", - "pad.settings.padSettings": "Pad Einstellunge", - "pad.settings.myView": "Eichne Oonsicht", - "pad.settings.stickychat": "Chat immer oonzeiche", - "pad.settings.colorcheck": "Autorenfarbe oonzeiche", - "pad.settings.linenocheck": "Zeilenummer", - "pad.settings.rtlcheck": "Inhalt von rechts bis links lese?", - "pad.settings.fontType": "Schriftoort:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Gemeinsame Oonsicht", - "pad.settings.language": "Sproch:", - "pad.importExport.import_export": "Import/Export", - "pad.importExport.import": "Text-Datei orrer Dokument hochloode", - "pad.importExport.importSuccessful": "Erfollichreich!", - "pad.importExport.export": "Aktuelles Pad exportiere wie:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Textdatei", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Sie können nur aus Klartext oder HTML-Formaten importieren. Für mehr erweiterte Importfunktionen installieren Sie bitte abiword.", - "pad.modals.connected": "Verbünd (konnektiert).", - "pad.modals.reconnecting": "Wiederherstelle von der Verbinnung …", - "pad.modals.forcereconnect": "Erneit Verbinne", - "pad.modals.userdup": "In enem andren Fenster schon uff (geöffnet)", - "pad.modals.userdup.explanation": "Das Pad scheint in meahr wie enem Browser-Fenster uff dem Komputadoar uff sin (geöffnet zu sein).", - "pad.modals.userdup.advice": "Um das Fenster se benutze, verbinn bittschön wieder erneit.", - "pad.modals.unauth": "Net authorisiert.", - "pad.modals.unauth.explanation": "Dein Zugriffsberechtichung für das Pad hot sich zwischichzeitlich geännert. Du kannst versuche das Pad wieder erneit uffserufe.", - "pad.modals.looping.explanation": "Es gebt Probleme bei der Kommunikation mit dem Pad-Server.", - "pad.modals.looping.cause": "Möchlicherweis bist dorrich en inkompatible Firewall orrer üwer en inkompatible Proxy mit dem Pad-Server verbünd (konnektiert).", - "pad.modals.initsocketfail": "Pad-Server net erreichbar.", - "pad.modals.initsocketfail.explanation": "Do konnt ken Verbinnung zum Pad-Server heargestellt sin.", - "pad.modals.initsocketfail.cause": "Dies könnt an deinem Browser orrer dein Internet-Verbinnung leihe.", - "pad.modals.slowcommit.explanation": "Der Pad-Server reagiert net.", - "pad.modals.slowcommit.cause": "Das könnt en Netzwerkverbinnungsproblem sin orrer en momentane Üwerlaschtung von der Pad-Server.", - "pad.modals.badChangeset.explanation": "En von dein gemachte Ännrung woard vom Pad-Server wie ungültich ingeschtuft (klassifiziert).", - "pad.modals.badChangeset.cause": "Das könnt uffgrund von en falsche Serverkonfiguration orrer en annre unerwoortete Verhalt passiert sin. Bittschön kontaktier den Diensteadministratoar, falls du gloobst, dass das sich um en Fehler handelt. Versuch dich wieder erneit se verbinne, um mit dem Beoorbeite fortzufoohre.", - "pad.modals.corruptPad.explanation": "Das Pad, uff das du zugreife willst, ist beschädicht.", - "pad.modals.corruptPad.cause": "Das könnt an en falsche Serverkonfiguration orrer en annre unerwoortete Verhalten liehn. Bittschön kontaktier den Diensteadministratoar.", - "pad.modals.deleted": "Abgewischt.", - "pad.modals.deleted.explanation": "Das Pad woard entfernt.", - "pad.modals.disconnected": "Verbinnung unnerbroch (du bist jetzt deskonnektiert).", - "pad.modals.disconnected.explanation": "Die Verbinnung (konnektion) zu dem Pad-Server woard unnerbroch.", - "pad.modals.disconnected.cause": "Möchlicherweis ist der Pad-Server net erreichbar. Bittschön benachrichtig den Dienstadministratoar, falls das weiterhin passiere tut.", - "pad.share": "Das Pad teile", - "pad.share.readonly": "Ingeschränkter Nur-Lese-Zugriff", - "pad.share.link": "Link", - "pad.share.emebdcode": "In Webseite einbette", - "pad.chat": "Chat", - "pad.chat.title": "Den Chat von dem Pad uffmache", - "pad.chat.loadmessages": "Weitre Nachrichte loode", - "timeslider.pageTitle": "{{appTitle}} Pad-Versionsgeschicht", - "timeslider.toolbar.returnbutton": "Zurück zum Pad", - "timeslider.toolbar.authors": "Autore:", - "timeslider.toolbar.authorsList": "ken Autore", - "timeslider.toolbar.exportlink.title": "Die Version exportiere", - "timeslider.exportCurrent": "Exportier die Version wie:", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Gespeichert am {{day}}.{{month}}.{{year}}", - "timeslider.dateformat": "{{day}}.{{month}}.{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januar", - "timeslider.month.february": "Februar", - "timeslider.month.march": "März", - "timeslider.month.april": "April", - "timeslider.month.may": "Mai", - "timeslider.month.june": "Juni", - "timeslider.month.july": "Juli", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "Oktober", - "timeslider.month.november": "November", - "timeslider.month.december": "Dezember", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: unbenannter Autoar, other: unbenannte Autore ]}", - "pad.savedrevs.marked": "Die Version woard jetzt wie gespeicherte Version gekennzeichnet", - "pad.userlist.entername": "Tue en Noome ren gebe", - "pad.userlist.unnamed": "unbenannt", - "pad.userlist.guest": "Gast", - "pad.userlist.deny": "Verweihe (negiere)", - "pad.userlist.approve": "Genehmiche (approviere)", - "pad.editbar.clearcolors": "Autorefarbe im gesamte Dokument zurücksetze?", - "pad.impexp.importbutton": "Jetzt importiere", - "pad.impexp.importing": "Importiere …", - "pad.impexp.confirmimport": "Das Importiere von en Datei üwerschreibt den aktuelle Text von dem Pad. Willst du weerklich fortfoohre?", - "pad.impexp.convertFailed": "Mir könne die Datei net importiere. Bittschön verwenn en anner Dokumentformat orrer üwertrooh den Text manuell.", - "pad.impexp.uploadFailed": "Der Upload ist fehlgeschloohn (das hot net funktioniert). Bittschön versuch das wieder erneit.", - "pad.impexp.importfailed": "Import fehlgeschloohn (das hot net funktioniert)", - "pad.impexp.copypaste": "Bittschön tue kopiere und einfüche (oonklebe)", - "pad.impexp.exportdisabled": "Der Export im {{type}}-Format ist deaktiviert. Für Einzelheite (Detalhes) tue bittschön dein Systemadministratoar kontaktiere." -} diff --git a/sources/src/locales/hsb.json b/sources/src/locales/hsb.json deleted file mode 100644 index 798c596..0000000 --- a/sources/src/locales/hsb.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Michawiki" - ] - }, - "index.newPad": "Nowy zapisnik", - "index.createOpenPad": "abo wutwor/wočiń zapisnik z mjenom:", - "pad.toolbar.bold.title": "Tučny (Strg-B)", - "pad.toolbar.italic.title": "Kursiwny (Strg-I)", - "pad.toolbar.underline.title": "Podšmórnyć (Strg-U)", - "pad.toolbar.strikethrough.title": "Přešmórnyć (Strg+5)", - "pad.toolbar.ol.title": "Čisłowana lisćina (Strg+Umsch+N)", - "pad.toolbar.ul.title": "Naličenje (Strg+Umsch+L)", - "pad.toolbar.indent.title": "Zasunyć (TAB)", - "pad.toolbar.unindent.title": "Wusunyć (Umsch+TAB)", - "pad.toolbar.undo.title": "Cofnyć (Strg-Z)", - "pad.toolbar.redo.title": "Wospjetować (Strg-Y)", - "pad.toolbar.clearAuthorship.title": "Awtorowe barby wotstronić (Strg+Umsch+C)", - "pad.toolbar.import_export.title": "Import/Eksport z/do druhich datajowych formatow", - "pad.toolbar.timeslider.title": "Historijowa strona", - "pad.toolbar.savedRevision.title": "Wersiju składować", - "pad.toolbar.settings.title": "Nastajenja", - "pad.toolbar.embed.title": "Tutón zapisnik dźělić a zasadźić", - "pad.toolbar.showusers.title": "Wužiwarjow na tutym zapisniku pokazać", - "pad.colorpicker.save": "Składować", - "pad.colorpicker.cancel": "Přetorhnyć", - "pad.loading": "Začituje so...", - "pad.noCookie": "Plack njeje so namakał. Prošu dopušćće placki w swojim wobhladowaku!", - "pad.passwordRequired": "Trjebaš hesło, zo by na tutón zapisnik přistup měł", - "pad.permissionDenied": "Nimaće prawo za přistup na tutón zapisnik.", - "pad.wrongPassword": "Twoje hesło bě wopak", - "pad.settings.padSettings": "Nastajenja zapisnika", - "pad.settings.myView": "Mój napohlad", - "pad.settings.stickychat": "Chat přeco na wobrazowce pokazać", - "pad.settings.chatandusers": "Chat a wužiwarjow pokazać", - "pad.settings.colorcheck": "Awtorowe barby", - "pad.settings.linenocheck": "Linkowe čisła", - "pad.settings.rtlcheck": "Wobsah wotprawa nalěwo čitać?", - "pad.settings.fontType": "Pismowa družina:", - "pad.settings.fontType.normal": "Normalny", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Globalny napohlad", - "pad.settings.language": "Rěč:", - "pad.importExport.import_export": "Import/Eksport", - "pad.importExport.import": "Tekstowu dataju abo dokument nahrać", - "pad.importExport.importSuccessful": "Wuspěšny!", - "pad.importExport.export": "Aktualny zapisnik eksportować jako:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Luty tekst", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Móžeš jenož z formatow luteho teksta abo z HTML-formata importować. Za bóle rozšěrjene importowanske funkcije instaluj prošu Abiword.", - "pad.modals.connected": "Zwjazany.", - "pad.modals.reconnecting": "Zwjazuje so znowa z twojim zapisnikom...", - "pad.modals.forcereconnect": "Znowa zwjazać", - "pad.modals.userdup": "W druhim woknje wočinjeny", - "pad.modals.userdup.explanation": "Zda so, zo tutón zapisnik je so we wjace hač jednym woknje wobhladowaka na tutym ličaku wočinił.", - "pad.modals.userdup.advice": "Zwjazaj znowa, zo by tute wokno město toho wužiwał.", - "pad.modals.unauth": "Njeawtorizowany", - "pad.modals.unauth.explanation": "Při wobhladowanju tuteje strony su so twoje prawa změnili. Spytaj so znowa zwjazać.", - "pad.modals.looping.explanation": "Su komunikaciske problemy ze synchronizowanskim serwerom.", - "pad.modals.looping.cause": "Snano sy přez njekompatibelnu wohnjowu murju abo proksy zwjazany.", - "pad.modals.initsocketfail": "Serwer je njedocpějomny.", - "pad.modals.initsocketfail.explanation": "Zwisk ze synchronizowanskim serwerom móžno njeje.", - "pad.modals.initsocketfail.cause": "To je najskerje problem z twojim wobhladowakom abo twojim internetnym zwiskom.", - "pad.modals.slowcommit.explanation": "Serwer njewotmołwja.", - "pad.modals.slowcommit.cause": "To móhło problem syćoweho zwiska być.", - "pad.modals.badChangeset.explanation": "Změna, kotruž sy přewjedł, je so přez synchronizowanski serwer jako njedowolenu woznamjeniła.", - "pad.modals.badChangeset.cause": "To je so snano wopačneje serweroweje konfiguracije dla abo druheho njewočakowaneho zadźerženja dla stało. Prošu staj so ze słužbowym administratorom do zwiska, jeli sej mysliš, zo to je zmylk. Spytaj hišće raz zwjazać, zo by z wobdźěłowanjom pokročował.", - "pad.modals.corruptPad.explanation": "Zapisnik, na kotryž chceš přistup měć, je wobškodźeny.", - "pad.modals.corruptPad.cause": "To je so snano wopačneje serweroweje konfiguracije dla abo druheho njewočakowaneho zadźerženja dla stało. Prošu staj so ze słužbowym administratorom do zwiska.", - "pad.modals.deleted": "Zhašany.", - "pad.modals.deleted.explanation": "Tutón zapisnik je so wotstronił.", - "pad.modals.disconnected": "Zwisk je přetorhnjeny.", - "pad.modals.disconnected.explanation": "Zwisk ze serwerom je so zhubił", - "pad.modals.disconnected.cause": "Serwer k dispoziciji njesteji. Prošu informuj słužboweho administratora, jeli to so dale stawa.", - "pad.share": "Tutón zapisnik dźělić", - "pad.share.readonly": "Jenož čitajomny", - "pad.share.link": "Wotkaz", - "pad.share.emebdcode": "URL zasadźić", - "pad.chat": "Chat", - "pad.chat.title": "Chat za tutón zapisnik wočinić", - "pad.chat.loadmessages": "Dalše powěsće začitać", - "timeslider.pageTitle": "{{appTitle}} - wersijowa historija", - "timeslider.toolbar.returnbutton": "Wróćo k zapisnikej", - "timeslider.toolbar.authors": "Awtorojo:", - "timeslider.toolbar.authorsList": "Žane awtorojo", - "timeslider.toolbar.exportlink.title": "Eksportować", - "timeslider.exportCurrent": "Aktualnu wersiju eksportować jako:", - "timeslider.version": "Wersija {{version}}", - "timeslider.saved": "Składowany {{day}}. {{month}} {{year}}", - "timeslider.playPause": "Wobdźěłanje wothrać/pawzować", - "timeslider.backRevision": "Wo jednu wersiju w tutym dokumenće wróćo hić", - "timeslider.forwardRevision": "Wo jednu wersiju w tutym dokumenće doprědka hić", - "timeslider.dateformat": "{{day}}. {{month}} {{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "januara", - "timeslider.month.february": "februara", - "timeslider.month.march": "měrca", - "timeslider.month.april": "apryla", - "timeslider.month.may": "meje", - "timeslider.month.june": "junija", - "timeslider.month.july": "julija", - "timeslider.month.august": "awgusta", - "timeslider.month.september": "septembra", - "timeslider.month.october": "oktobra", - "timeslider.month.november": "nowembra", - "timeslider.month.december": "decembra", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: awtor, two: awtoraj, few: awtorojo, other: awtorow ]} bjez mjena", - "pad.savedrevs.marked": "Tuta wersija je so nětko jako składowana wersija woznamjeniła", - "pad.savedrevs.timeslider": "Móžeš sej składowane wersije wobhladować, wopytujo historiju dokumenta.", - "pad.userlist.entername": "Zapodaj swoje mjeno", - "pad.userlist.unnamed": "bjez mjena", - "pad.userlist.guest": "Hósć", - "pad.userlist.deny": "Wotpokazać", - "pad.userlist.approve": "Schwalić", - "pad.editbar.clearcolors": "Awtorowe barby w cyłym dokumenće zhašeć?", - "pad.impexp.importbutton": "Nětko importować", - "pad.impexp.importing": "Importuje so...", - "pad.impexp.confirmimport": "Importowanje dataje přepisa aktualny tekst zapisnika. Chceš woprawdźe pokročować?", - "pad.impexp.convertFailed": "Njemóžachmy tutu dataju importować. Prošu wužij druhi dokumentowy format abo kopěruj manuelnje", - "pad.impexp.padHasData": "Njemóžachmy tutu dataju importować, dokelž tutón dokument hižo změny wobsahuje, prošu importuj nowy dokument.", - "pad.impexp.uploadFailed": "Nahraće njeje so poradźiło, prošu spytaj hišće raz", - "pad.impexp.importfailed": "Import njeje so poradźiło", - "pad.impexp.copypaste": "Prošu kopěrować a zasadźić", - "pad.impexp.exportdisabled": "Eksport jako format {{type}} je znjemóžnjeny. Prošu staj so ze swojim systemowym administratorom za podrobnosće do zwiska." -} diff --git a/sources/src/locales/hu.json b/sources/src/locales/hu.json deleted file mode 100644 index e8045a7..0000000 --- a/sources/src/locales/hu.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Dj", - "Misibacsi", - "R-Joe", - "Tgr", - "Csega", - "BanKris", - "Notramo" - ] - }, - "index.newPad": "Új notesz", - "index.createOpenPad": "vagy notesz létrehozása/megnyitása ezzel a névvel:", - "pad.toolbar.bold.title": "Félkövér (Ctrl+B)", - "pad.toolbar.italic.title": "Dőlt (Ctrl+I)", - "pad.toolbar.underline.title": "Aláhúzás (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Áthúzás (Ctrl+5)", - "pad.toolbar.ol.title": "Számozott lista (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Számozatlan lista (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Behúzás növelése (TAB)", - "pad.toolbar.unindent.title": "Behúzás csökkentése (Shift+TAB)", - "pad.toolbar.undo.title": "Visszavonás (Ctrl-Z)", - "pad.toolbar.redo.title": "Újra (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Szerzők színezésének kikapcsolása (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importálás/exportálás különböző fájlformátumokból/ba", - "pad.toolbar.timeslider.title": "Időcsúszka", - "pad.toolbar.savedRevision.title": "Revízió mentése", - "pad.toolbar.settings.title": "Beállítások", - "pad.toolbar.embed.title": "Notesz beágyazása és megosztása", - "pad.toolbar.showusers.title": "Notesz felhasználóinak megmutatása", - "pad.colorpicker.save": "Mentés", - "pad.colorpicker.cancel": "Mégsem", - "pad.loading": "Betöltés…", - "pad.noCookie": "Nem található a süti. Engedélyezd a böngésződben a sütik használatát!", - "pad.passwordRequired": "Jelszóra van szükséged ezen notesz eléréséhez", - "pad.permissionDenied": "Nincs engedélyed ezen notesz eléréséhez", - "pad.wrongPassword": "A jelszó rossz volt", - "pad.settings.padSettings": "Notesz beállításai", - "pad.settings.myView": "Az én nézetem", - "pad.settings.stickychat": "Mindig mutasd a csevegés-dobozt", - "pad.settings.chatandusers": "Csevegés és felhasználók mutatása", - "pad.settings.colorcheck": "Szerzők színei", - "pad.settings.linenocheck": "Sorok számozása", - "pad.settings.rtlcheck": "Tartalom olvasása balról jobbra?", - "pad.settings.fontType": "Betűtípus:", - "pad.settings.fontType.normal": "Szokásos", - "pad.settings.fontType.monospaced": "Írógépes", - "pad.settings.globalView": "Globális nézet", - "pad.settings.language": "Nyelv:", - "pad.importExport.import_export": "Import/export", - "pad.importExport.import": "Tetszőleges szövegfájl vagy dokumentum feltöltése", - "pad.importExport.importSuccessful": "Siker!", - "pad.importExport.export": "Jelenlegi notesz exportálása így:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Sima szöveg", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document formátum)", - "pad.importExport.abiword.innerHTML": "Csak szöveges, vagy HTML formátumokból importálhatsz. A speciális importálási funkciókért kérjük telepítsd az abiword-öt.", - "pad.modals.connected": "Kapcsolódva.", - "pad.modals.reconnecting": "Újrakapcsolódás a noteszhez...", - "pad.modals.forcereconnect": "Újrakapcsolódás kényszerítése", - "pad.modals.reconnecttimer": "Megpróbálok újracsatlakozni ennyi múlva:", - "pad.modals.cancel": "Mégse", - "pad.modals.userdup": "Új ablakban megnyitva", - "pad.modals.userdup.explanation": "Úgy tűnik, ez a notesz több különböző böngészőablakban is meg van nyitva a számítógépeden.", - "pad.modals.userdup.advice": "Kapcsolódj újra, ha ezt az ablakot akarod használni.", - "pad.modals.unauth": "Nincs rá jogosultságod", - "pad.modals.unauth.explanation": "A jogosultságaid megváltoztak, miközben ezt az oldalt nézted. Próbálj meg újrakapcsolódni!", - "pad.modals.looping.explanation": "Nem sikerült a kommunikáció a szinkronizációs szerverrel.", - "pad.modals.looping.cause": "Talán egy túl szigorú tűzfalon vagy proxyn keresztül kapcsolódtál az internetre.", - "pad.modals.initsocketfail": "A szerver nem érhető el.", - "pad.modals.initsocketfail.explanation": "Nem sikerült kapcsolódni a szinkronizációs szerverhez.", - "pad.modals.initsocketfail.cause": "Valószínűleg a böngésződdel vagy az internetkapcsolatoddal van probléma.", - "pad.modals.slowcommit.explanation": "A szerver nem válaszol.", - "pad.modals.slowcommit.cause": "Valószínűleg az internetkapcsolattal van probléma.", - "pad.modals.badChangeset.explanation": "Szerkesztéseded a szinkronizációs szerver illegálisnak sorolta be.", - "pad.modals.badChangeset.cause": "Ennek oka lehet egy rossz szerver konfiguráció, vagy más váratlan viselkedés. Ha úgy érzi, ez hiba eredménye, lépjen kapcsolatba a szolgáltatás adminisztrátorával. Próbáljon meg újrakapcsolódni a szerkesztés folytatásához.", - "pad.modals.corruptPad.explanation": "A notesz, amit megpróbálsz elérni, sérült.", - "pad.modals.corruptPad.cause": "Ennek oka lehet egy rossz szerver konfiguráció, vagy más váratlan viselkedés. Kérjük, lépj kapcsolatba a szolgáltatás adminisztrátorával.", - "pad.modals.deleted": "Törölve.", - "pad.modals.deleted.explanation": "Ez a notesz el lett távolítva.", - "pad.modals.disconnected": "Kapcsolat bontva.", - "pad.modals.disconnected.explanation": "A szerverrel való kapcsolat megszűnt", - "pad.modals.disconnected.cause": "Lehet, hogy a szerver nem elérhető. Kérlek, értesítsd a szolgáltatás adminisztrátorát, ha a probléma tartósan fennáll.", - "pad.share": "Notesz megosztása", - "pad.share.readonly": "Csak olvasható", - "pad.share.link": "Hivatkozás", - "pad.share.emebdcode": "URL beágyazása", - "pad.chat": "Csevegés", - "pad.chat.title": "A noteszhez tartozó csevegés megnyitása.", - "pad.chat.loadmessages": "További üzenetek betöltése", - "timeslider.pageTitle": "{{appTitle}} időcsúszka", - "timeslider.toolbar.returnbutton": "Vissza a noteszhez", - "timeslider.toolbar.authors": "Szerzők:", - "timeslider.toolbar.authorsList": "Nincsenek szerzők", - "timeslider.toolbar.exportlink.title": "Exportálás", - "timeslider.exportCurrent": "Jelenlegi változat exportálása így:", - "timeslider.version": "{{version}} verzió", - "timeslider.saved": "{{year}}. {{month}} {{day}}-n elmentve", - "timeslider.playPause": "Notesz tartalom visszajátszása / leállítása", - "timeslider.backRevision": "Egy revízióval vissza a noteszben", - "timeslider.forwardRevision": "Egy revízióval előre a noteszben", - "timeslider.dateformat": "{{year}}/{{month}}/{{day}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "január", - "timeslider.month.february": "február", - "timeslider.month.march": "március", - "timeslider.month.april": "április", - "timeslider.month.may": "május", - "timeslider.month.june": "június", - "timeslider.month.july": "július", - "timeslider.month.august": "augusztus", - "timeslider.month.september": "szeptember", - "timeslider.month.october": "október", - "timeslider.month.november": "november", - "timeslider.month.december": "december", - "timeslider.unnamedauthors": "{{num}} névtelen {[plural(num), one: szerző, other: szerző]}", - "pad.savedrevs.marked": "Ez a revízió mostantól mentettként jelölve", - "pad.savedrevs.timeslider": "A mentett revíziókat az időcsúszkán tudod megnézni", - "pad.userlist.entername": "Add meg a nevedet", - "pad.userlist.unnamed": "névtelen", - "pad.userlist.guest": "Vendég", - "pad.userlist.deny": "Megtagad", - "pad.userlist.approve": "Jóváhagy", - "pad.editbar.clearcolors": "A szerzőséget jelző színeket törlöd a teljes dokumentumból?", - "pad.impexp.importbutton": "Importálás most", - "pad.impexp.importing": "Importálás…", - "pad.impexp.confirmimport": "Egy fájl importálása felülírja a jelenlegi szöveget a noteszben. Biztos hogy folytatod?", - "pad.impexp.convertFailed": "Nem tudtuk importálni ezt a fájlt. Kérjük, használj másik dokumentum formátumot, vagy kézzel másold és illeszd be a tartalmat", - "pad.impexp.padHasData": "Nem tudjuk importálni ezt a fájlt, mert ez a notesz már megváltozott, kérjük, importálj egy új noteszba.", - "pad.impexp.uploadFailed": "A feltöltés sikertelen, próbáld meg újra", - "pad.impexp.importfailed": "Az importálás nem sikerült", - "pad.impexp.copypaste": "Kérjük másold be", - "pad.impexp.exportdisabled": "{{type}} formátumba az exportálás nem engedélyezett. Kérjük, a részletekért fordulj a rendszeradminisztrátorhoz." -} diff --git a/sources/src/locales/hy.json b/sources/src/locales/hy.json deleted file mode 100644 index 20e0026..0000000 --- a/sources/src/locales/hy.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Kareyac" - ] - }, - "pad.toolbar.underline.title": "ընդգծելով (Ctrl-U)", - "pad.toolbar.undo.title": "Չեղարկել (Ctrl-Z)", - "pad.toolbar.redo.title": "Վերադարձնել (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Մաքրել փաստաթղթի գույներ (Ctrl+Shift+C)", - "pad.toolbar.savedRevision.title": "Պահպանել տարբերակը", - "pad.toolbar.settings.title": "Կարգավորումներ", - "pad.toolbar.embed.title": "Կիսվել և ներդնել այդ փաստաթուղթը", - "pad.toolbar.showusers.title": "Ցույց տալ մասնակիցներին այս փաստաթղթում", - "pad.colorpicker.save": "Պահպանել", - "pad.colorpicker.cancel": "Չեղարկել", - "pad.loading": "Բեռնվում է…", - "pad.wrongPassword": "Սխալ գաղտնաբառ", - "pad.settings.myView": "Իմ տեսարան", - "pad.settings.rtlcheck": "Կարդալ բովանդակությունը աջից ձախ", - "pad.settings.fontType": "Տառատեսակի տեսակը", - "pad.settings.globalView": "Ընդհանուր տեսքը", - "pad.settings.language": "Լեզու", - "pad.importExport.import_export": "Ներմուծում/արտահանում", - "pad.importExport.import": "Բեռնել ցանկացած տեքստային ֆայլը կամ փաստաթուղթ", - "pad.importExport.importSuccessful": "Հաջողություն", - "pad.importExport.export": "Արտահանել ընթացիկ փաստաթուղթ է որպես", - "pad.importExport.exportplain": "Պարզ տեքստ", - "pad.importExport.exportpdf": "PDF", - "pad.modals.connected": "Կապված է", - "pad.modals.forcereconnect": "Հարկադիր վերամիավորել", - "pad.modals.cancel": "Չեղարկել", - "pad.modals.userdup": "Բաց է մյուս պատուհանում", - "pad.modals.initsocketfail": "Սերվերը անհասանելի է ։", - "pad.modals.slowcommit.explanation": "Սերվերը չի պատասխանում։", - "pad.modals.deleted": "Ջնջված է", - "pad.share.readonly": "Միայն կարդալու", - "pad.share.link": "Հղում", - "timeslider.toolbar.authors": "Հեղինակներ", - "timeslider.month.january": "Հունվար", - "timeslider.month.february": "Փետրվար", - "timeslider.month.march": "Մարտ", - "timeslider.month.april": "Ապրիլ", - "timeslider.month.may": "Մայիս", - "timeslider.month.june": "Հունիս", - "timeslider.month.july": "Հուլիս", - "timeslider.month.august": "Օգոստոս", - "timeslider.month.september": "Սեպտեմբեր", - "timeslider.month.october": "Հոկտեմբեր", - "timeslider.month.november": "Նոյեմբեր", - "timeslider.month.december": "Դեկտեմբեր", - "pad.userlist.entername": "Մուտքագրեք ձեր անունը", - "pad.userlist.unnamed": "անանուն", - "pad.userlist.guest": "Հյուր", - "pad.userlist.deny": "Մերժել", - "pad.userlist.approve": "Հաստատել", - "pad.impexp.importbutton": "Ներմուծել հիմա", - "pad.impexp.copypaste": "Խնդրում ենք պատճենել" -} diff --git a/sources/src/locales/ia.json b/sources/src/locales/ia.json deleted file mode 100644 index 9a3fd31..0000000 --- a/sources/src/locales/ia.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "@metadata": { - "authors": [ - "McDutchie" - ] - }, - "index.newPad": "Nove pad", - "index.createOpenPad": "o crear/aperir un pad con le nomine:", - "pad.toolbar.bold.title": "Grasse (Ctrl-B)", - "pad.toolbar.italic.title": "Italic (Ctrl-I)", - "pad.toolbar.underline.title": "Sublinear (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Cancellar (Ctrl+5)", - "pad.toolbar.ol.title": "Lista ordinate (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Lista non ordinate (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Indentar (TAB)", - "pad.toolbar.unindent.title": "Disindentar (Shift+TAB)", - "pad.toolbar.undo.title": "Disfacer (Ctrl-Z)", - "pad.toolbar.redo.title": "Refacer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Rader colores de autor (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importar/exportar in differente formatos de file", - "pad.toolbar.timeslider.title": "Glissa-tempore", - "pad.toolbar.savedRevision.title": "Version salveguardate", - "pad.toolbar.settings.title": "Configuration", - "pad.toolbar.embed.title": "Divider e incorporar iste pad", - "pad.toolbar.showusers.title": "Monstrar le usatores de iste pad", - "pad.colorpicker.save": "Salveguardar", - "pad.colorpicker.cancel": "Cancellar", - "pad.loading": "Cargamento…", - "pad.noCookie": "Le cookie non pote esser trovate. Per favor permitte le cookies in tu navigator!", - "pad.passwordRequired": "Un contrasigno es necessari pro acceder a iste pad", - "pad.permissionDenied": "Tu non ha le permission de acceder a iste pad", - "pad.wrongPassword": "Le contrasigno es incorrecte", - "pad.settings.padSettings": "Configuration del pad", - "pad.settings.myView": "Mi vista", - "pad.settings.stickychat": "Chat sempre visibile", - "pad.settings.chatandusers": "Monstrar chat e usatores", - "pad.settings.colorcheck": "Colores de autor", - "pad.settings.linenocheck": "Numeros de linea", - "pad.settings.rtlcheck": "Leger le contento de dextra a sinistra?", - "pad.settings.fontType": "Typo de litteras:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospatial", - "pad.settings.globalView": "Vista global", - "pad.settings.language": "Lingua:", - "pad.importExport.import_export": "Importar/Exportar", - "pad.importExport.import": "Incargar qualcunque file de texto o documento", - "pad.importExport.importSuccessful": "Succedite!", - "pad.importExport.export": "Exportar le pad actual como:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Texto simple", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Tu pote solmente importar files in formato de texto simple o HTML. Pro functionalitate de importation plus extense, installa AbiWord.", - "pad.modals.connected": "Connectite.", - "pad.modals.reconnecting": "Reconnecte a tu pad…", - "pad.modals.forcereconnect": "Fortiar reconnexion", - "pad.modals.reconnecttimer": "Tentativa de reconnexion in", - "pad.modals.cancel": "Cancellar", - "pad.modals.userdup": "Aperte in un altere fenestra", - "pad.modals.userdup.explanation": "Iste pad pare esser aperte in plus de un fenestra de navigator in iste computator.", - "pad.modals.userdup.advice": "Reconnecte pro usar iste fenestra.", - "pad.modals.unauth": "Non autorisate", - "pad.modals.unauth.explanation": "Tu permissiones ha cambiate durante que tu legeva iste pagina. Tenta reconnecter.", - "pad.modals.looping.explanation": "Il ha problemas de communication con le servitor de synchronisation.", - "pad.modals.looping.cause": "Il es possibile que tu connexion passa per un firewall o proxy incompatibile.", - "pad.modals.initsocketfail": "Le servitor es inattingibile.", - "pad.modals.initsocketfail.explanation": "Impossibile connecter al servitor de synchronisation.", - "pad.modals.initsocketfail.cause": "Isto es probabilemente causate per un problema con tu navigator o connexion a internet.", - "pad.modals.slowcommit.explanation": "Le servitor non responde.", - "pad.modals.slowcommit.cause": "Isto pote esser causate per problemas con le connexion al rete.", - "pad.modals.badChangeset.explanation": "Un modification que tu ha facite ha essite classificate como incorrecte per le servitor de synchronisation.", - "pad.modals.badChangeset.cause": "Isto pote esser causate per un configuration incorrecte del servitor o per alcun altere comportamento impreviste. Per favor contacta le administrator del servicio si tu pensa que se tracta de un error. Tenta reconnecter te pro continuar a modificar.", - "pad.modals.corruptPad.explanation": "Le pad al qual tu tenta acceder es corrumpite.", - "pad.modals.corruptPad.cause": "Isto pote esser debite a un configuration incorrecte del servitor o a alcun altere comportamento impreviste. Per favor contacta le administrator del servicio.", - "pad.modals.deleted": "Delite.", - "pad.modals.deleted.explanation": "Iste pad ha essite removite.", - "pad.modals.disconnected": "Tu ha essite disconnectite.", - "pad.modals.disconnected.explanation": "Le connexion al servitor ha essite perdite.", - "pad.modals.disconnected.cause": "Le servitor pote esser indisponibile. Per favor notifica le administrator del servicio si isto continua a producer se.", - "pad.share": "Diffunder iste pad", - "pad.share.readonly": "Lectura solmente", - "pad.share.link": "Ligamine", - "pad.share.emebdcode": "Codice de incorporation", - "pad.chat": "Chat", - "pad.chat.title": "Aperir le chat pro iste pad.", - "pad.chat.loadmessages": "Cargar plus messages", - "timeslider.pageTitle": "Glissa-tempore pro {{appTitle}}", - "timeslider.toolbar.returnbutton": "Retornar al pad", - "timeslider.toolbar.authors": "Autores:", - "timeslider.toolbar.authorsList": "Nulle autor", - "timeslider.toolbar.exportlink.title": "Exportar", - "timeslider.exportCurrent": "Exportar le version actual como:", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Salveguardate le {{day}} de {{month}} {{year}}", - "timeslider.playPause": "Reproducer/pausar le contento del pad", - "timeslider.backRevision": "Recular un version in iste pad", - "timeslider.forwardRevision": "Avantiar un version in iste pad", - "timeslider.dateformat": "{{year}}-{{month}}-{{day}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "januario", - "timeslider.month.february": "februario", - "timeslider.month.march": "martio", - "timeslider.month.april": "april", - "timeslider.month.may": "maio", - "timeslider.month.june": "junio", - "timeslider.month.july": "julio", - "timeslider.month.august": "augusto", - "timeslider.month.september": "septembre", - "timeslider.month.october": "octobre", - "timeslider.month.november": "novembre", - "timeslider.month.december": "decembre", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor, other: autores ]} sin nomine", - "pad.savedrevs.marked": "Iste version es ora marcate como version salveguardate", - "pad.savedrevs.timeslider": "Tu pote vider versiones salveguardate con le chronologia glissante.", - "pad.userlist.entername": "Entra tu nomine", - "pad.userlist.unnamed": "sin nomine", - "pad.userlist.guest": "Invitato", - "pad.userlist.deny": "Refusar", - "pad.userlist.approve": "Approbar", - "pad.editbar.clearcolors": "Rader le colores de autor in tote le documento?", - "pad.impexp.importbutton": "Importar ora", - "pad.impexp.importing": "Importation in curso…", - "pad.impexp.confirmimport": "Le importation de un file superscribera le texto actual del pad. Es tu secur de voler continuar?", - "pad.impexp.convertFailed": "Nos non ha potite importar iste file. Per favor usa un altere formato de documento o copia e colla le texto manualmente.", - "pad.impexp.padHasData": "Nos non ha potite importar iste file perque iste Pad ha jam habite cambiamentos. Per favor importa lo a un nove pad.", - "pad.impexp.uploadFailed": "Le incargamento ha fallite. Per favor reproba.", - "pad.impexp.importfailed": "Importation fallite", - "pad.impexp.copypaste": "Per favor copia e colla", - "pad.impexp.exportdisabled": "Le exportation in formato {{type}} es disactivate. Per favor contacta le administrator del systema pro detalios." -} diff --git a/sources/src/locales/is.json b/sources/src/locales/is.json deleted file mode 100644 index 3d51bd7..0000000 --- a/sources/src/locales/is.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Sveinn í Felli", - "Sveinki" - ] - }, - "index.newPad": "Ný skrifblokk", - "index.createOpenPad": "eða búa til/opna skrifblokk með heitinu:", - "pad.toolbar.bold.title": "Feitletrað (Ctrl+B)", - "pad.toolbar.italic.title": "Skáletrað (Ctrl+I)", - "pad.toolbar.underline.title": "Undirstrikað (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Yfirstrikun (Ctrl+5)", - "pad.toolbar.ol.title": "Raðaður listi (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Óraðaður listi (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Inndráttur (TAB)", - "pad.toolbar.unindent.title": "Draga til baka (Shift+TAB)", - "pad.toolbar.undo.title": "Afturkalla (Ctrl+Z)", - "pad.toolbar.redo.title": "Endurtaka (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Hreinsa liti höfunda (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Flytja inn/út frá/í önnur skráasnið", - "pad.toolbar.timeslider.title": "Tímalína", - "pad.toolbar.savedRevision.title": "Vista endurskoðaða útgáfu", - "pad.toolbar.settings.title": "Stillingar", - "pad.toolbar.embed.title": "Deila og ívefja þessari skrifblokk", - "pad.toolbar.showusers.title": "Sýna notendur þessarar skrifblokkar", - "pad.colorpicker.save": "Vista", - "pad.colorpicker.cancel": "Hætta við", - "pad.loading": "Hleð inn...", - "pad.noCookie": "Smákaka fannst ekki. Þú verður að leyfa smákökur í vafranum þínum!", - "pad.passwordRequired": "Þú þarft að gefa upp lykilorð til að komast á þessa skrifblokk", - "pad.permissionDenied": "Þú hefur ekki réttindi til að nota þessa skrifblokk", - "pad.wrongPassword": "Lykilorðinu þínu var hafnað", - "pad.settings.padSettings": "Stillingar skrifblokkar", - "pad.settings.myView": "Mitt yfirlit", - "pad.settings.stickychat": "Spjall alltaf á skjánum", - "pad.settings.chatandusers": "Sýna spjall og notendur", - "pad.settings.colorcheck": "Litir höfunda", - "pad.settings.linenocheck": "Línunúmer", - "pad.settings.rtlcheck": "Lesa innihaldið frá hægri til vinstri?", - "pad.settings.fontType": "Leturgerð:", - "pad.settings.fontType.normal": "Venjulegt", - "pad.settings.fontType.monospaced": "Jafnbreitt", - "pad.settings.globalView": "Yfirlitssýn", - "pad.settings.language": "Tungumál:", - "pad.importExport.import_export": "Flytja inn/út", - "pad.importExport.import": "Settu inn hverskyns texta eða skjal", - "pad.importExport.importSuccessful": "Heppnaðist!", - "pad.importExport.export": "Flytja út núverandi skrifblokk sem:", - "pad.importExport.exportetherpad": "Etherpad netskrifblokk", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Hreinn texti", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Þú getur aðeins flutt inn úr hreinum texta eða HTML sniðum. Til að geta nýtt \nfleiri þróaðri innflutningssnið settu þá upp abiword forritið.", - "pad.modals.connected": "Tengt.", - "pad.modals.reconnecting": "Endurtengist skrifblokkinni þinni...", - "pad.modals.forcereconnect": "Þvinga endurtengingu", - "pad.modals.reconnecttimer": "Reyni aftur að tengjast eftir", - "pad.modals.cancel": "Hætta við", - "pad.modals.userdup": "Opnað í öðrum glugga", - "pad.modals.userdup.explanation": "Þessi skrifblokk virðist vera opin í fleiri en einum vafraglugga á þessari tölvu.", - "pad.modals.userdup.advice": "Endurtengdu til að nota þennan glugga í staðinn.", - "pad.modals.unauth": "Ekki leyfilegt", - "pad.modals.unauth.explanation": "Heimildir þínar hafa breyst á meðan þú skoðaðir þessa síðu. Reyndu að endurtengjast.", - "pad.modals.looping.explanation": "Það eru samskiptavandamál við samstillingarmiðlarann.", - "pad.modals.looping.cause": "Hugsanlega ertu tengdur í gegnum ósamhæfðan eldvegg eða milliþjón.", - "pad.modals.initsocketfail": "Næ ekki sambandi við netþjón.", - "pad.modals.initsocketfail.explanation": "Gat ekki tengst samstillingarmiðlaranum.", - "pad.modals.initsocketfail.cause": "Þetta er líklega vegna vandamáls varðandi vafrann þinn eða internettenginguna þína.", - "pad.modals.slowcommit.explanation": "Þjónninn svarar ekki.", - "pad.modals.slowcommit.cause": "Þetta gæti verið vegna vandamála varðandi nettengingar.", - "pad.modals.badChangeset.explanation": "Breyting sem þú gerðir var flokkuð sem óleyfileg af samstillingarmiðlaranum.", - "pad.modals.badChangeset.cause": "Þetta gæti verið vegna rangrar uppsetningar á þjóninum eða annarar óvæntrar hegðunar. Hafðu samband við stjórnanda þjónustunnar ef þér sýnist þetta vera villa. Reyndu að endurtengjast til að halda áfram með breytingar.", - "pad.modals.corruptPad.explanation": "Skrifblokkin sem þú ert að reyna að tengjast er skemmd.", - "pad.modals.corruptPad.cause": "Þetta gæti verið vegna rangrar uppsetningar á þjóninum eða annarar óvæntrar hegðunar. Hafðu samband við stjórnanda þjónustunnar.", - "pad.modals.deleted": "Eytt.", - "pad.modals.deleted.explanation": "Þessi skrifblokk hefur verið fjarlægð.", - "pad.modals.disconnected": "Þú hefur verið aftengd(ur).", - "pad.modals.disconnected.explanation": "Missti tengingu við miðlara", - "pad.modals.disconnected.cause": "Miðlarinn gæti verið ekki tiltækur. Láttu kerfisstjóra vita ef þetta heldur áfram að gerast.", - "pad.share": "Deila þessari skrifblokk", - "pad.share.readonly": "Skrifvarið", - "pad.share.link": "Tengill", - "pad.share.emebdcode": "Ívefja slóð", - "pad.chat": "Spjall", - "pad.chat.title": "Opna spjallið fyrir þessa skrifblokk.", - "pad.chat.loadmessages": "Hlaða inn fleiri skeytum", - "timeslider.pageTitle": "Tímalína {{appTitle}}", - "timeslider.toolbar.returnbutton": "Fara til baka í skrifblokk", - "timeslider.toolbar.authors": "Höfundar:", - "timeslider.toolbar.authorsList": "Engir höfundar", - "timeslider.toolbar.exportlink.title": "Flytja út", - "timeslider.exportCurrent": "Flytja út núverandi útgáfu sem:", - "timeslider.version": "Útgáfa {{version}}", - "timeslider.saved": "Vistað {{day}}. {{month}}, {{year}}", - "timeslider.playPause": "Afspilun / Hlé á efni skrifblokkar", - "timeslider.backRevision": "Fara til baka um eina útgáfu í þessari skrifblokk", - "timeslider.forwardRevision": "Fara áfram um eina útgáfu í þessari skrifblokk", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Janúar", - "timeslider.month.february": "febrúar", - "timeslider.month.march": "mars", - "timeslider.month.april": "apríl", - "timeslider.month.may": "maí", - "timeslider.month.june": "júní", - "timeslider.month.july": "Júlí", - "timeslider.month.august": "ágúst", - "timeslider.month.september": "september", - "timeslider.month.october": "október", - "timeslider.month.november": "nóvember", - "timeslider.month.december": "desember", - "timeslider.unnamedauthors": "{{num}} ónefnt {[plural(num) one: höfundur, other: höfundar ]}", - "pad.savedrevs.marked": "Þessi útgáfa er núna merkt sem vistuð útgáfa", - "pad.savedrevs.timeslider": "Þú getur skoðað vistaðar útgáfur með því að fara á tímalínuna", - "pad.userlist.entername": "Settu inn nafnið þitt", - "pad.userlist.unnamed": "ónefnt", - "pad.userlist.guest": "Gestur", - "pad.userlist.deny": "Hafna", - "pad.userlist.approve": "Samþykkja", - "pad.editbar.clearcolors": "Hreinsa liti höfunda á öllu skjalinu?", - "pad.impexp.importbutton": "Flytja inn núna", - "pad.impexp.importing": "Flyt inn...", - "pad.impexp.confirmimport": "Innflutningur á skrá mun skrifa yfir þann texta sem er á skrifblokkinni núna. \nErtu viss um að þú viljir halda áfram?", - "pad.impexp.convertFailed": "Við getum ekki flutt inn þessa skrá. Notaðu annað skráasnið eða afritaðu og \nlímdu handvirkt", - "pad.impexp.padHasData": "Við getum ekki flutt inn þessa skrá því þegar er búið að breyta þessari skrifblokk, flyttu inn í nýja skrifblokk", - "pad.impexp.uploadFailed": "Sending mistókst, endilega reyndu aftur", - "pad.impexp.importfailed": "Innflutningur mistókst", - "pad.impexp.copypaste": "Afritaðu og límdu", - "pad.impexp.exportdisabled": "Útflutningur á {{type}} sniði er óvirkur. Hafðu samband við kerfisstjóra til að fá frekari aðstoð." -} diff --git a/sources/src/locales/it.json b/sources/src/locales/it.json deleted file mode 100644 index d7d7c09..0000000 --- a/sources/src/locales/it.json +++ /dev/null @@ -1,136 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Beta16", - "Gianfranco", - "Muxator", - "Vituzzu", - "Macofe", - "Nivit" - ] - }, - "index.newPad": "Nuovo Pad", - "index.createOpenPad": "o creare o aprire un Pad con il nome:", - "pad.toolbar.bold.title": "Grassetto (Ctrl-B)", - "pad.toolbar.italic.title": "Corsivo (Ctrl-I)", - "pad.toolbar.underline.title": "Sottolineato (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Barrato (Ctrl+5)", - "pad.toolbar.ol.title": "Elenco numerato (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Elenco puntato (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Rientro (TAB)", - "pad.toolbar.unindent.title": "Riduci rientro (Shift+TAB)", - "pad.toolbar.undo.title": "Annulla (Ctrl-Z)", - "pad.toolbar.redo.title": "Ripeti (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Elimina i colori che indicano gli autori (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importa/esporta da/a diversi formati di file", - "pad.toolbar.timeslider.title": "Presentazione cronologia", - "pad.toolbar.savedRevision.title": "Versione salvata", - "pad.toolbar.settings.title": "Impostazioni", - "pad.toolbar.embed.title": "Condividi ed incorpora questo Pad", - "pad.toolbar.showusers.title": "Visualizza gli utenti su questo Pad", - "pad.colorpicker.save": "Salva", - "pad.colorpicker.cancel": "Annulla", - "pad.loading": "Caricamento in corso…", - "pad.noCookie": "Il cookie non è stato trovato. Consenti i cookie nel tuo browser!", - "pad.passwordRequired": "Per accedere a questo Pad è necessaria una password", - "pad.permissionDenied": "Non si dispone dei permessi necessari per accedere a questo Pad", - "pad.wrongPassword": "La password è sbagliata", - "pad.settings.padSettings": "Impostazioni del Pad", - "pad.settings.myView": "Mia visualizzazione", - "pad.settings.stickychat": "Chat sempre sullo schermo", - "pad.settings.chatandusers": "Mostra chat e utenti", - "pad.settings.colorcheck": "Colori che indicano gli autori", - "pad.settings.linenocheck": "Numeri di riga", - "pad.settings.rtlcheck": "Leggere il contenuto da destra a sinistra?", - "pad.settings.fontType": "Tipo di carattere:", - "pad.settings.fontType.normal": "Normale", - "pad.settings.fontType.monospaced": "A larghezza fissa", - "pad.settings.globalView": "Visualizzazione globale", - "pad.settings.language": "Lingua:", - "pad.importExport.import_export": "Importazione/esportazione", - "pad.importExport.import": "Carica un file di testo o un documento", - "pad.importExport.importSuccessful": "Riuscito!", - "pad.importExport.export": "Esportare il Pad corrente come:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Testo normale", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "È possibile importare solo i formati di testo semplice o HTML. Per metodi più avanzati di importazione installare AbiWord.", - "pad.modals.connected": "Connesso.", - "pad.modals.reconnecting": "Riconnessione al pad in corso...", - "pad.modals.forcereconnect": "Forza la riconnessione", - "pad.modals.reconnecttimer": "Tentativo di riconnessione", - "pad.modals.cancel": "Annulla", - "pad.modals.userdup": "Aperto in un'altra finestra", - "pad.modals.userdup.explanation": "Questo Pad sembra essere aperto in più di una finestra del browser su questo computer.", - "pad.modals.userdup.advice": "Riconnettiti per utilizzare invece questa finestra.", - "pad.modals.unauth": "Non autorizzato", - "pad.modals.unauth.explanation": "Le tue autorizzazioni sono state modificate durante la visualizzazione di questa pagina. Prova a riconnetterti.", - "pad.modals.looping.explanation": "Ci sono problemi di comunicazione con il server di sincronizzazione.", - "pad.modals.looping.cause": "Forse sei connesso attraverso un firewall o un server proxy non compatibili.", - "pad.modals.initsocketfail": "Il server non è raggiungibile.", - "pad.modals.initsocketfail.explanation": "Impossibile connettersi al server di sincronizzazione.", - "pad.modals.initsocketfail.cause": "Questo probabilmente è dovuto a un problema con il tuo browser o con la tua connessione a internet.", - "pad.modals.slowcommit.explanation": "Il server non risponde.", - "pad.modals.slowcommit.cause": "Questo potrebbe essere dovuto a problemi con la connettività di rete.", - "pad.modals.badChangeset.explanation": "Una modifica che hai fatto è stata considerata illegale dal server di sincronizzazione.", - "pad.modals.badChangeset.cause": "Ciò potrebbe essere causato da una errata configurazione del server o qualche altro comportamento imprevisto. Si prega di contattare l'amministratore del servizio, se si ritiene che questo sia un errore. Prova a riconnetterti per tentare di continuare a modificare.", - "pad.modals.corruptPad.explanation": "Il pad a cui stai tentando di accedere è danneggiato.", - "pad.modals.corruptPad.cause": "Ciò potrebbe essere causato da una errata configurazione del server o qualche altro comportamento imprevisto. Si prega di contattare l'amministratore del servizio.", - "pad.modals.deleted": "Cancellato.", - "pad.modals.deleted.explanation": "Questo Pad è stato rimosso.", - "pad.modals.disconnected": "Sei stato disconnesso.", - "pad.modals.disconnected.explanation": "La connessione al server è stata persa", - "pad.modals.disconnected.cause": "Il server potrebbe essere non disponibile. Informa l'amministrazione del servizio se il problema persiste.", - "pad.share": "Condividi questo Pad", - "pad.share.readonly": "Sola lettura", - "pad.share.link": "Link", - "pad.share.emebdcode": "Incorpora URL", - "pad.chat": "Chat", - "pad.chat.title": "Apri la chat per questo Pad.", - "pad.chat.loadmessages": "Carica altri messaggi", - "timeslider.pageTitle": "Cronologia {{appTitle}}", - "timeslider.toolbar.returnbutton": "Ritorna al Pad", - "timeslider.toolbar.authors": "Autori:", - "timeslider.toolbar.authorsList": "Nessun autore", - "timeslider.toolbar.exportlink.title": "Esporta", - "timeslider.exportCurrent": "Esporta la versione corrente come:", - "timeslider.version": "Versione {{version}}", - "timeslider.saved": "Salvato {{day}} {{month}} {{year}}", - "timeslider.playPause": "Riproduzione / Pausa contenuti Pad", - "timeslider.backRevision": "Vai indietro di una versione in questo Pad", - "timeslider.forwardRevision": "Vai avanti di una versione in questo Pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "gennaio", - "timeslider.month.february": "febbraio", - "timeslider.month.march": "marzo", - "timeslider.month.april": "aprile", - "timeslider.month.may": "maggio", - "timeslider.month.june": "giugno", - "timeslider.month.july": "luglio", - "timeslider.month.august": "agosto", - "timeslider.month.september": "settembre", - "timeslider.month.october": "ottobre", - "timeslider.month.november": "novembre", - "timeslider.month.december": "dicembre", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autore, other: autori ]} senza nome", - "pad.savedrevs.marked": "Questa revisione è ora contrassegnata come una versione salvata", - "pad.savedrevs.timeslider": "Puoi vedere le versioni salvate visitando la cronologia", - "pad.userlist.entername": "Inserisci il tuo nome", - "pad.userlist.unnamed": "senza nome", - "pad.userlist.guest": "Ospite", - "pad.userlist.deny": "Nega", - "pad.userlist.approve": "Approva", - "pad.editbar.clearcolors": "Eliminare i colori degli autori sull'intero documento?", - "pad.impexp.importbutton": "Importa ora", - "pad.impexp.importing": "Importazione in corso...", - "pad.impexp.confirmimport": "L'importazione del file sovrascriverà il testo attuale del Pad. Sei sicuro di voler procedere?", - "pad.impexp.convertFailed": "Non è stato possibile importare questo file. Utilizzare un formato differente o copiare ed incollare a mano", - "pad.impexp.padHasData": "Non è possibile importare questo file poiché questo Pad ha già avuto modifiche; importalo in un nuovo Pad", - "pad.impexp.uploadFailed": "Caricamento non riuscito, riprovare", - "pad.impexp.importfailed": "Importazione fallita", - "pad.impexp.copypaste": "Si prega di copiare e incollare", - "pad.impexp.exportdisabled": "L'esportazione come {{type}} è disabilitata. Contattare l'amministratore per i dettagli." -} diff --git a/sources/src/locales/ja.json b/sources/src/locales/ja.json deleted file mode 100644 index fe200fc..0000000 --- a/sources/src/locales/ja.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Shirayuki", - "Torinky", - "Omotecho", - "Aefgh39622" - ] - }, - "index.newPad": "新規作成", - "index.createOpenPad": "または作成/編集するパッド名を入力:", - "pad.toolbar.bold.title": "太字 (Ctrl+B)", - "pad.toolbar.italic.title": "斜体 (Ctrl+I)", - "pad.toolbar.underline.title": "下線 (Ctrl+U)", - "pad.toolbar.strikethrough.title": "取り消し線 (Ctrl+5)", - "pad.toolbar.ol.title": "番号付きリスト (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "番号なしリスト (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "インデント (Tab)", - "pad.toolbar.unindent.title": "インデント解除 (Shift+Tab)", - "pad.toolbar.undo.title": "元に戻す (Ctrl+Z)", - "pad.toolbar.redo.title": "やり直し (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "作者の色分けを消去(Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "他の形式のファイルのインポート/エクスポート", - "pad.toolbar.timeslider.title": "タイムスライダー", - "pad.toolbar.savedRevision.title": "版を保存", - "pad.toolbar.settings.title": "設定", - "pad.toolbar.embed.title": "このパッドを共有する/埋め込む", - "pad.toolbar.showusers.title": "このパッドのユーザーを表示", - "pad.colorpicker.save": "保存", - "pad.colorpicker.cancel": "キャンセル", - "pad.loading": "読み込み中...", - "pad.noCookie": "クッキーが見つかりません。ブラウザの設定でクッキーの使用を許可してください。", - "pad.passwordRequired": "このパッドにアクセスするにはパスワードが必要です", - "pad.permissionDenied": "あなたにはこのパッドへのアクセス許可がありません", - "pad.wrongPassword": "パスワードが間違っています", - "pad.settings.padSettings": "パッドの設定", - "pad.settings.myView": "個人設定", - "pad.settings.stickychat": "画面にチャットを常に表示", - "pad.settings.chatandusers": "チャットとユーザーを表示", - "pad.settings.colorcheck": "作者の色分け", - "pad.settings.linenocheck": "行番号", - "pad.settings.rtlcheck": "右横書きにする", - "pad.settings.fontType": "フォントの種類:", - "pad.settings.fontType.normal": "通常", - "pad.settings.fontType.monospaced": "固定幅", - "pad.settings.globalView": "グローバル設定", - "pad.settings.language": "言語:", - "pad.importExport.import_export": "インポート/エクスポート", - "pad.importExport.import": "あらゆるテキストファイルや文書をアップロードできます", - "pad.importExport.importSuccessful": "完了しました。", - "pad.importExport.export": "現在のパッドをエクスポートする形式:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "プレーンテキスト", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "プレーンテキストまたは HTML ファイルからのみインポートできます。より高度なインポート機能を使用するには、AbiWord をインストールしてください。", - "pad.modals.connected": "接続されました。", - "pad.modals.reconnecting": "パッドに再接続中...", - "pad.modals.forcereconnect": "強制的に再接続", - "pad.modals.reconnecttimer": "再接続を試行中", - "pad.modals.cancel": "中止", - "pad.modals.userdup": "別のウィンドウで開かれています", - "pad.modals.userdup.explanation": "このコンピューターの複数のブラウザーウィンドウで、このパッドを開いているようです。", - "pad.modals.userdup.advice": "代わりにこのウィンドウを再接続します。", - "pad.modals.unauth": "権限がありません", - "pad.modals.unauth.explanation": "このページの閲覧中にあなたの権限が変更されました。再接続をお試しください。", - "pad.modals.looping.explanation": "同期サーバーとの通信に問題点があります。", - "pad.modals.looping.cause": "ご使用中のファイアウォールまたはプロキシとは互換性がない可能性があります。", - "pad.modals.initsocketfail": "サーバーに到達できません。", - "pad.modals.initsocketfail.explanation": "同期サーバーに接続できませんでした。", - "pad.modals.initsocketfail.cause": "これはご使用中のブラウザーやインターネット接続の問題が原因である可能性があります。", - "pad.modals.slowcommit.explanation": "サーバーが応答しません。", - "pad.modals.slowcommit.cause": "これはネットワーク接続の問題が原因である可能性があります。", - "pad.modals.badChangeset.explanation": "投稿した編集は同期サーバーによって違法性のあるものとして秘匿されました。", - "pad.modals.badChangeset.cause": "これはサーバーの構成不良か、予期せぬ挙動を見せたために発生した事象である可能性があります。これがエラーである疑いがあれば、当サービス管理者に問い合わせてください。編集を続行するには再接続してみてください。", - "pad.modals.corruptPad.explanation": "アクセスしようとしているパッドは破損しています。", - "pad.modals.corruptPad.cause": "これはサーバーの構成不良か、予期せぬ挙動を見せたために発生した事象である可能性があります。当サービス管理者にお問い合わせください。", - "pad.modals.deleted": "削除されました。", - "pad.modals.deleted.explanation": "このパッドは削除されました。", - "pad.modals.disconnected": "切断されました。", - "pad.modals.disconnected.explanation": "サーバーとの接続が失われました", - "pad.modals.disconnected.cause": "サーバーを利用できない可能性があります。この問題が解決しない場合はサービスの管理者にお知らせください。", - "pad.share": "このパッドを共有", - "pad.share.readonly": "読み取り専用", - "pad.share.link": "リンク", - "pad.share.emebdcode": "埋め込み用 URL", - "pad.chat": "チャット", - "pad.chat.title": "このパッドのチャットを開きます。", - "pad.chat.loadmessages": "その他のメッセージを読み込む", - "timeslider.pageTitle": "{{appTitle}} タイムスライダー", - "timeslider.toolbar.returnbutton": "パッドに戻る", - "timeslider.toolbar.authors": "作者:", - "timeslider.toolbar.authorsList": "作者なし", - "timeslider.toolbar.exportlink.title": "エクスポート", - "timeslider.exportCurrent": "現在の版をエクスポートする形式:", - "timeslider.version": "バージョン {{version}}", - "timeslider.saved": "| {{year}}年{{month}}{{day}}日に保存", - "timeslider.playPause": "パッドの過去の内容を再生/一時停止", - "timeslider.backRevision": "前の版に戻る", - "timeslider.forwardRevision": "次の版に進む", - "timeslider.dateformat": "{{year}}年{{month}}月{{day}}日 {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "1月", - "timeslider.month.february": "2月", - "timeslider.month.march": "3月", - "timeslider.month.april": "4月", - "timeslider.month.may": "5月", - "timeslider.month.june": "6月", - "timeslider.month.july": "7月", - "timeslider.month.august": "8月", - "timeslider.month.september": "9月", - "timeslider.month.october": "10月", - "timeslider.month.november": "11月", - "timeslider.month.december": "12月", - "timeslider.unnamedauthors": "{{num}} 人の匿名の{[plural(num) other: 作者 ]}", - "pad.savedrevs.marked": "この版を、保存済みの版としてマークしました。", - "pad.savedrevs.timeslider": "タイムスライダーで保存された版を確認できます", - "pad.userlist.entername": "名前を入力", - "pad.userlist.unnamed": "名前なし", - "pad.userlist.guest": "ゲスト", - "pad.userlist.deny": "拒否", - "pad.userlist.approve": "承認", - "pad.editbar.clearcolors": "文書全体の作者の色分けを消去しますか?", - "pad.impexp.importbutton": "インポートする", - "pad.impexp.importing": "インポート中...", - "pad.impexp.confirmimport": "ファイルをインポートすると、パッドの現在のテキストが上書きされます。本当に続行しますか?", - "pad.impexp.convertFailed": "このファイルをインポートできませんでした。他の文書形式を使用するか、手作業でコピー & ペーストしてください", - "pad.impexp.padHasData": "このパッドは変更されたため、ファイルからインポートできませんでした。新しいパッドにインポートしてください。", - "pad.impexp.uploadFailed": "アップロードに失敗しました。もう一度お試しください", - "pad.impexp.importfailed": "インポートに失敗しました", - "pad.impexp.copypaste": "コピー & ペーストしてください", - "pad.impexp.exportdisabled": "{{type}}形式でのエクスポートは無効になっています。詳細はシステム管理者にお問い合わせください。" -} diff --git a/sources/src/locales/kab.json b/sources/src/locales/kab.json deleted file mode 100644 index 905c385..0000000 --- a/sources/src/locales/kab.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Belkacem77" - ] - }, - "index.newPad": "Apad amaynut", - "index.createOpenPad": "neɣ rnu/ldi apad s yisem:", - "pad.toolbar.bold.title": "Zur (Ctrl+B)", - "pad.toolbar.italic.title": "Uknan (Ctrl+I)", - "pad.toolbar.underline.title": "Ituderrer (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Ittujerreḍ (Ctrl+5)", - "pad.toolbar.ol.title": "Tabdart n usmizzwer (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Tabdart s war asmizzwer (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Rigel (TAB)", - "pad.toolbar.unindent.title": "Kkes ariger (Shift+TAB)", - "pad.toolbar.undo.title": "Sefsex (Ctrl+Z)", - "pad.toolbar.redo.title": "Err-d (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Sfeḍ initen yemmalen imeskaren (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Kter/Sifeḍ seg/ɣer umasal n ufaylu-nnḍen", - "pad.toolbar.timeslider.title": "Amazray asmussan", - "pad.toolbar.savedRevision.title": "Sekles aceggir", - "pad.toolbar.settings.title": "Iɣewwaṛen", - "pad.toolbar.embed.title": "Bḍu sakin seddu apad-agi", - "pad.toolbar.showusers.title": "Sken iseqdacen ɣef upad-agi", - "pad.colorpicker.save": "Sekles", - "pad.colorpicker.cancel": "Sefsex", - "pad.loading": "Asali...", - "pad.noCookie": "Anagi n tuqqna ulac-it. Sireg inagan n tuqqna deg iminig-ik!", - "pad.passwordRequired": "Tesriḍ awal uffir akken ad tkecmeḍ ar upad-agi", - "pad.permissionDenied": "Ur ɣur-k ara tasiregt akken ad tkecmeḍ ar upad-agi", - "pad.wrongPassword": "Awal-uhhir mačči d ameɣtu", - "pad.settings.padSettings": "Iɣewwaṛen n upad", - "pad.settings.myView": "Timeẓri-iw", - "pad.settings.stickychat": "Asqerdec yezga deg ugdil", - "pad.settings.chatandusers": "Sken asqerdec akken iseqdacen", - "pad.settings.colorcheck": "Initen n usulu", - "pad.settings.linenocheck": "Uṭṭunen n izirigen", - "pad.settings.rtlcheck": "Ɣeṛ agbur seg uyeffus s azelmaḍ?", - "pad.settings.fontType": "Anaw n tsefsit:", - "pad.settings.globalView": "Timeẓri tamatut:", - "pad.settings.language": "Tutlayt:", - "pad.importExport.import_export": "Kter/Sifeḍ", - "pad.importExport.import": "Sali aḍris neɣ isemli", - "pad.importExport.importSuccessful": "Yedda!", - "pad.importExport.export": "Sifeḍ apad amiran am:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Adris aččuran", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Tzemreḍ kan ad ketreḍ aḍris aččuran neɣ imasalen HTML. Ugar n tmahilin n ukter leqqayen, rzu ar Sebded AbiWord.", - "pad.modals.connected": "Iqqen.", - "pad.modals.reconnecting": "Tulsa n tuqqna ar upad-ik.", - "pad.modals.forcereconnect": "Ḥettem tulsa n tuqqna", - "pad.modals.reconnecttimer": "Ɛreḍ tikelt-nniḍen tuqqna", - "pad.modals.cancel": "Sefsex", - "pad.modals.userdup": "Yeldi deg usfaylu-nniḍen", - "pad.modals.userdup.explanation": "Apad-agi yettban yeldi deg isfuyla-nniḍen deg uselkim-agi.", - "pad.modals.userdup.advice": "Ales tuqqna akken ad tesqedceḍ asfaylu-agi.", - "pad.modals.unauth": "Ur uettwasireg ara", - "pad.modals.unauth.explanation": "Tisirag-ik beddlent makken ad d-yettwaskan usebter. Ɛreḍ ad teqqneḍ.", - "pad.modals.looping.explanation": "Nufa-d uguren n teywalt akked uqeddac n umtawi.", - "pad.modals.looping.cause": "Ahat teqqneḍ s uɣrab n tmes neɣ apṛuksi ur yemṣadan ara", - "pad.modals.initsocketfail": "Ulac aqeddac.", - "pad.modals.initsocketfail.explanation": "Ur izmir ara ad yeqqen ar uqeddac n umtawi.", - "pad.modals.initsocketfail.cause": "Ahat d ugur i d-yekkan seg iminig-ik neɣ tuqqna ar Internet.", - "pad.modals.slowcommit.explanation": "Aqeddac ur d-yettara ara awal.", - "pad.modals.slowcommit.cause": "Ahat d ugur i d-yekkan seg tuqqna ar uẓeṭṭa.", - "pad.modals.badChangeset.explanation": "Abeddel i tgiḍ yettwammel d ayen ur ilaqen ara deg uqeddac n umtawi.", - "pad.modals.badChangeset.cause": "Ahat ayagi yekka-d si yir tawila n uqeddac neɣ kra n wayen ur nerǧi ara. Nermes anebdal n umeẓlu, ma yella tḥulfaḍ d tuccḍa. Ɛreḍ tuqqna akken ad tkemmleḍ taẓrigt.", - "pad.modals.corruptPad.explanation": "Apad i tettaɣraḍeḍ ad tkecmeḍ yexseṛ.", - "pad.modals.corruptPad.cause": "Ayagi ahat yekka-d seg yir tawila n uqeddac neɣ ayen ur yettwaṛǧan ara. Nermes anebdal n umeẓlu.", - "pad.modals.deleted": "Yettwakkes.", - "pad.modals.deleted.explanation": "Apad-agi yettwakkes.", - "pad.modals.disconnected": "Suffren-k.", - "pad.modals.disconnected.explanation": "Tuqqna ar uqeddac truḥ", - "pad.modals.disconnected.cause": "Ahat aqeddac ulac-it. Nermes anebdal n umeẓlu ma yella yezga iḍeṛṛu", - "pad.share": "Bḍu apad-agi", - "pad.share.readonly": "Taɣuri kan", - "pad.share.link": "Aseɣwen", - "pad.share.emebdcode": "Seddu URL", - "pad.chat": "Asqerdec", - "pad.chat.title": "Ldi asqerdec deg upad-agi.", - "pad.chat.loadmessages": "Sali-d ugar n yiznan", - "timeslider.pageTitle": "Amazray asmussan n {{appTitle}}", - "timeslider.toolbar.returnbutton": "Uqal ar upad", - "timeslider.toolbar.authors": "Imeskaren:", - "timeslider.toolbar.authorsList": "Ulac imeskaren", - "timeslider.toolbar.exportlink.title": "Sifeḍ", - "timeslider.exportCurrent": "Sifeḍ lqem-agi amiran am:", - "timeslider.version": "Lqem {{version}}", - "timeslider.saved": "Yettwasekles deg {{day}}-{{month}}-{{year}}", - "timeslider.playPause": "Taɣuri/Aserǧu n igburen n upad", - "timeslider.backRevision": "Uɣal s yiwen n uceggir ar deffir deg upad-agi", - "timeslider.forwardRevision": "Ddu ar zdat s yiwen n uceggir deg upad-agi", - "timeslider.dateformat": "{{day}}-{{month}}-{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Yennayer", - "timeslider.month.february": "Fuṛaṛ", - "timeslider.month.march": "Meɣres", - "timeslider.month.april": "Yebrir", - "timeslider.month.may": "Mayyu", - "timeslider.month.june": "Yunyu", - "timeslider.month.july": "Yulyu", - "timeslider.month.august": "Ɣuct", - "timeslider.month.september": "Ctamber", - "timeslider.month.october": "Tuber", - "timeslider.month.november": "Wamber", - "timeslider.month.december": "Dujamber", - "timeslider.unnamedauthors": "{{num}}{[plural(num) one: ameskar udrig, other: imeskaren udrigen]}", - "pad.savedrevs.marked": "Aceggir-agi yettwacreḍ tura d aceggir yettwaskelsen", - "pad.savedrevs.timeslider": "Tzemreḍ ad waliḍ iceggiren yettwaskelsen ticki teldiḍ amazray", - "pad.userlist.entername": "Sekcem isem-ik", - "pad.userlist.unnamed": "udrig", - "pad.userlist.guest": "Inebgi", - "pad.userlist.deny": "Agwi", - "pad.userlist.approve": "Qbel", - "pad.editbar.clearcolors": "Sfeḍ akk initen icudden ar imeskaren deg isemliyen meṛṛa?", - "pad.impexp.importbutton": "Kter tura", - "pad.impexp.importing": "Aktar iteddu...", - "pad.impexp.confirmimport": "Akter n ufaylu ad yesfeɛj aḍris amiran deg upad. Tebɣiḍ ad tkemleḍ?", - "pad.impexp.convertFailed": "Ur nezmir ara ad d-nekter afaylu-agi. Ma ulac aɣilif seqdec amasal n isemli-nniḍen neɣ nɣel/senteḍ s ufus.", - "pad.impexp.padHasData": "Ur nezmir ara ad d-nekter afaylu-agi acku apad-agi ibeddel yakan, ma ulac aɣilif, kter ar upad amaynut", - "pad.impexp.uploadFailed": "Asali yecceḍ, ma ulac aɣilif ɛreḍ tikelt-nniḍen", - "pad.impexp.importfailed": "Akter ur yeddi ara", - "pad.impexp.copypaste": "Ma ulac aɣilif nɣel/senteḍ", - "pad.impexp.exportdisabled": "Aɣewwaṛ n usifeḍ s umasal{{type}} yensa. Nermes anebdal-ik n unagraw i ugar n telqayt." -} diff --git a/sources/src/locales/km.json b/sources/src/locales/km.json deleted file mode 100644 index 4dea037..0000000 --- a/sources/src/locales/km.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "@metadata": { - "authors": [ - "វ័ណថារិទ្ធ", - "Sovichet" - ] - }, - "index.newPad": "ផេតថ្មី", - "index.createOpenPad": "ឬបង្កើត/បើកផេតដែលមានឈ្មោះ៖", - "pad.toolbar.bold.title": "ដិត (Ctrl-B)", - "pad.toolbar.italic.title": "ទ្រេត (Ctrl-I)", - "pad.toolbar.underline.title": "គូសបន្ទាត់ (Ctrl-U)", - "pad.toolbar.strikethrough.title": "ឆូតចោល", - "pad.toolbar.ol.title": "បញ្ជីតាមតម្រៀប", - "pad.toolbar.ul.title": "បញ្ជីមិនតាមតម្រៀប", - "pad.toolbar.indent.title": "ខិតចូលក្នុង (TAB)", - "pad.toolbar.unindent.title": "ខិតចេញក្រៅ (Shift+TAB)", - "pad.toolbar.undo.title": "អាន់ឌូ (Ctrl-Z)", - "pad.toolbar.redo.title": "រីឌូ (Ctrl-Y)", - "pad.toolbar.import_export.title": "នាំចូល/នាំចេញ ពី/ទៅប្រភេទឯកសារផ្សេងទៀត", - "pad.toolbar.savedRevision.title": "រក្សាទុកកំណែ", - "pad.toolbar.settings.title": "ការកំណត់​", - "pad.toolbar.embed.title": "ចែក​រំលែក​និង​បង្កប់​ផេត​នេះ", - "pad.toolbar.showusers.title": "បង្ហាញ​អ្នក​ប្រើ​លើ​ផេត​នេះ", - "pad.colorpicker.save": "រក្សាទុក", - "pad.colorpicker.cancel": "បោះបង់", - "pad.loading": "កំពុងផ្ទុក…", - "pad.passwordRequired": "អ្នក​ត្រូវ​មាន​ពាក្យ​សម្ងាត់ ដើម្បី​ចូល​ផេត​នេះ", - "pad.permissionDenied": "អ្នក​មិន​មាន​សិទ្ធិ​ចូល​ផេត​នេះ​ទេ", - "pad.wrongPassword": "ពាក្យ​សម្ងាត់​របស់​អ្នក ខុស​ហើយ", - "pad.settings.padSettings": "ការ​កំណត់​ផេត", - "pad.settings.myView": "គំហើញរបស់ខ្ញុំ", - "pad.settings.stickychat": "តែង​បង្ហាញ​ការ​ជជែក​លើ​អេក្រង់", - "pad.settings.linenocheck": "លេខ​បន្ទាត់", - "pad.settings.rtlcheck": "អាន​ពី​ស្ដាំ​ទៅ​ឆ្វេង?", - "pad.settings.fontType": "ប្រភេទពុម្ពអក្សរ៖", - "pad.settings.fontType.normal": "ធម្មតា", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "គំហើញសកល", - "pad.settings.language": "ភាសា៖", - "pad.importExport.import_export": "នាំចូល/នាំចេញ", - "pad.importExport.import": "ផ្ទុក​ឡើង​ឯកសារ​អត្ថបទ​ណាមួយ", - "pad.importExport.importSuccessful": "ដោយជោគជ័យ!", - "pad.importExport.export": "នាំ​ចេញ​ផេត​បច្ចុប្បន្ន​ជា៖", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Plain text", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.modals.connected": "បាន​តភ្ជាប់​។", - "pad.modals.reconnecting": "កំពុង​ភ្ជាប់​ទៅ​ផេត​របស់​អ្នក​ម្ដង​ទៀត..", - "pad.modals.forcereconnect": "បង្ខំ​ឲ្យ​ភ្ជាប់​ឡើង​វិញ", - "pad.modals.userdup": "បាន​បើក​ក្នុង​វីនដូ​មួយ​ទៀត", - "pad.modals.unauth.explanation": "សិទ្ធិ​របស់​អ្នក​ត្រូវ​បាន​ប្ដូរ ខណៈ​ពេល​កំពុង​មើល​ទំព័រ​នេះ។ សូម​ព្យាយាម​ភ្ជាប់​ឡើង​វិញ។", - "pad.modals.looping.cause": "ប្រហែល​ជា​អ្នក​បាន​ភ្ជាប់​តាម firewall ឬ ប្រុកស៊ី ដែល​មិន​ត្រូវ​គ្នា។", - "pad.modals.initsocketfail": "មិន​អាច​ទៅ​ដល់​ម៉ាស៊ីន​បម្រើ។", - "pad.modals.initsocketfail.cause": "នេះ​អាច​ជា​បញ្ហា​ជាមួយ​កម្មវិធី​អ៊ីនធឺណិត ឬ​ការ​តភ្ជាប់​អ៊ីនធឺណិត​របស់​អ្នក។", - "pad.modals.slowcommit.explanation": "មិន​មាន​ចម្លើយ​តប​ពី​ម៉ាស៊ីន​បម្រើ​ទេ។", - "pad.modals.deleted": "បាន​លុប។", - "pad.modals.deleted.explanation": "បាន​លុប​ផេត​នេះ​ចេញ។", - "pad.modals.disconnected.explanation": "បាន​បាត់​ការ​តភ្ជាប់​ទៅ​ម៉ាស៊ីន​បម្រើ", - "pad.share": "ចែក​រំលែក​ផេត​នេះ", - "pad.share.readonly": "អាន​តែ​ប៉ុណ្ណោះ", - "pad.share.link": "តំណ​ភ្ជាប់", - "pad.share.emebdcode": "URL បង្កប់", - "pad.chat": "ជជែក", - "pad.chat.title": "បើក​ការ​ជជែក​សម្រាប់​ផេត​នេះ។", - "pad.chat.loadmessages": "ផ្ទុក​សារ​ថែម​ទៀត", - "timeslider.toolbar.returnbutton": "ត្រឡប់​ទៅ​ផេត", - "timeslider.toolbar.authors": "អ្នក​បង្កើត៖", - "timeslider.toolbar.authorsList": "គ្មាន​អ្នក​បង្កើត", - "timeslider.toolbar.exportlink.title": "នាំចេញ", - "timeslider.exportCurrent": "នាំ​ចេញ​កំណែ​បច្ចុប្បន្ន​ជា៖", - "timeslider.version": "កំណែ {{version}}", - "timeslider.saved": "បាន​រក្សា​ទុក {{month}} {{day}}, {{year}}", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "មករា", - "timeslider.month.february": "កុម្ភៈ", - "timeslider.month.march": "មិនា", - "timeslider.month.april": "មេសា", - "timeslider.month.may": "ឧសភា", - "timeslider.month.june": "មិថុនា​", - "timeslider.month.july": "កក្ដដា​", - "timeslider.month.august": "សីហា", - "timeslider.month.september": "កញ្ញា", - "timeslider.month.october": "តុលា", - "timeslider.month.november": "វិច្ឆិកា", - "timeslider.month.december": "ធ្នូ", - "pad.userlist.entername": "បញ្ចូល​ឈ្មោះ​របស់​អ្នក", - "pad.userlist.unnamed": "គ្មាន​ឈ្មោះ", - "pad.userlist.guest": "ភ្ញៀវ", - "pad.userlist.deny": "បដិសេធ", - "pad.userlist.approve": "យល់​ព្រម", - "pad.impexp.importbutton": "នាំចូលឥឡូវនេះ", - "pad.impexp.importing": "កំពុងនាំចូល​...", - "pad.impexp.importfailed": "នាំចូល​មិន​បាន​សម្រេច", - "pad.impexp.copypaste": "សូម​ចម្លង​ហើយ​បិទ​ភ្ជាប់", - "pad.impexp.exportdisabled": "ការ​នាំចេញ​ជា {{type}} ត្រូវ​បាន​បិទ។ សូម​ទាក់ទង​អ្នក​គ្រប់​គ្រង​ប្រព័ន្ធ សម្រាប់​ព័ត៌មាន​បន្ថែម។" -} diff --git a/sources/src/locales/ko.json b/sources/src/locales/ko.json deleted file mode 100644 index 19625ea..0000000 --- a/sources/src/locales/ko.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Hym411", - "아라", - "Revi", - "Kurousagi", - "SeoJeongHo", - "Ykhwong", - "CYAN" - ] - }, - "index.newPad": "새 패드", - "index.createOpenPad": "또는 다음 이름으로 패드 만들기/열기:", - "pad.toolbar.bold.title": "굵게 (Ctrl+B)", - "pad.toolbar.italic.title": "기울임꼴 (Ctrl+I)", - "pad.toolbar.underline.title": "밑줄 (Ctrl+U)", - "pad.toolbar.strikethrough.title": "취소선 (Ctrl+5)", - "pad.toolbar.ol.title": "순서 있는 목록 (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "순서 없는 목록 (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "들여쓰기 (TAB)", - "pad.toolbar.unindent.title": "내어쓰기 (Shift+TAB)", - "pad.toolbar.undo.title": "실행 취소 (Ctrl+Z)", - "pad.toolbar.redo.title": "다시 실행 (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "저자의 색 지우기 (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "다른 파일 형식으로 가져오기/내보내기", - "pad.toolbar.timeslider.title": "시간슬라이더", - "pad.toolbar.savedRevision.title": "판 저장", - "pad.toolbar.settings.title": "설정", - "pad.toolbar.embed.title": "이 패드를 공유하고 포함하기", - "pad.toolbar.showusers.title": "이 패드의 사용자 보기", - "pad.colorpicker.save": "저장", - "pad.colorpicker.cancel": "취소", - "pad.loading": "불러오는 중...", - "pad.noCookie": "쿠키를 찾을 수 없습니다. 브라우저에서 쿠키를 허용해주세요!", - "pad.passwordRequired": "이 패드에 접근하려면 비밀번호가 필요합니다", - "pad.permissionDenied": "이 패드에 접근할 권한이 없습니다", - "pad.wrongPassword": "비밀번호가 잘못되었습니다", - "pad.settings.padSettings": "패드 설정", - "pad.settings.myView": "내 보기", - "pad.settings.stickychat": "화면에 항상 대화 보기", - "pad.settings.chatandusers": "대화와 사용자 보기", - "pad.settings.colorcheck": "저자 색", - "pad.settings.linenocheck": "줄 번호", - "pad.settings.rtlcheck": "우횡서(오른쪽에서 왼쪽으로)입니까?", - "pad.settings.fontType": "글꼴 종류:", - "pad.settings.fontType.normal": "보통", - "pad.settings.fontType.monospaced": "고정 폭", - "pad.settings.globalView": "전역 보기", - "pad.settings.language": "언어:", - "pad.importExport.import_export": "가져오기/내보내기", - "pad.importExport.import": "텍스트 파일이나 문서 올리기", - "pad.importExport.importSuccessful": "성공!", - "pad.importExport.export": "다음으로 현재 패드 내보내기:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "일반 텍스트", - "pad.importExport.exportword": "마이크로소프트 워드", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format, 개방형 문서 형식)", - "pad.importExport.abiword.innerHTML": "일반 텍스트나 HTML 형식으로만 가져올 수 있습니다. 고급 가져오기 기능에 대해서는 AbiWord를 설치하세요.", - "pad.modals.connected": "연결했습니다.", - "pad.modals.reconnecting": "패드에 다시 연결 중..", - "pad.modals.forcereconnect": "강제로 다시 연결", - "pad.modals.reconnecttimer": "다시 접속 시도 중", - "pad.modals.cancel": "취소", - "pad.modals.userdup": "다른 창에서 열렸습니다", - "pad.modals.userdup.explanation": "이 패드는 이 컴퓨터에 하나 이상의 브라우저 창에서 열린 것 같습니다.", - "pad.modals.userdup.advice": "대신 이 창을 사용해 다시 연결합니다.", - "pad.modals.unauth": "권한이 없음", - "pad.modals.unauth.explanation": "이 페이지를 보는 동안 권한이 바뀌었습니다. 연결을 다시 시도하세요.", - "pad.modals.looping.explanation": "동기화 서버와 통신 문제가 있습니다.", - "pad.modals.looping.cause": "아마 호환되지 않는 방화벽이나 프록시를 통해 연결되어 있습니다.", - "pad.modals.initsocketfail": "서버에 연결할 수 없습니다.", - "pad.modals.initsocketfail.explanation": "동기 서버에 연결할 수 없습니다.", - "pad.modals.initsocketfail.cause": "아마도 브라우저나 인터넷 연결에 문제가 있기 때문일 수 있습니다.", - "pad.modals.slowcommit.explanation": "서버가 응답하지 않습니다.", - "pad.modals.slowcommit.cause": "네트워크 연결에 문제가 있기 때문일 수 있습니다.", - "pad.modals.badChangeset.explanation": "당신의 편집은 동기화 서버에 의해 불법적인 것으로 분류되었습니다.", - "pad.modals.badChangeset.cause": "잘못된 서버 구성이나 예기치 못한 행동 때문에 발생했을 수 있습니다. 서버 관리자와 연락하시기 바랍니다. 만약 이 메시지가 오류라고 생각된다면, 편집을 다시 시도해 보세요.", - "pad.modals.corruptPad.explanation": "당신이 시도하려는 패드는 손상되었습니다.", - "pad.modals.corruptPad.cause": "잘못된 서버 구성 또는 다른 예기치 않은 오류 때문에 발생했을 수 있습니다. 서버 관리자와 연락하세요.", - "pad.modals.deleted": "삭제되었습니다.", - "pad.modals.deleted.explanation": "이 패드를 제거했습니다.", - "pad.modals.disconnected": "연결이 끊어졌습니다.", - "pad.modals.disconnected.explanation": "서버에서 연결을 잃었습니다", - "pad.modals.disconnected.cause": "서버를 사용할 수 없습니다. 이 문제가 계속 발생하면 서비스 관리자에게 알려주시기 바랍니다.", - "pad.share": "이 패드 공유하기", - "pad.share.readonly": "읽기 전용", - "pad.share.link": "링크", - "pad.share.emebdcode": "URL 포함", - "pad.chat": "대화", - "pad.chat.title": "이 패드에 대화를 엽니다.", - "pad.chat.loadmessages": "더 많은 메시지 불러오기", - "timeslider.pageTitle": "{{appTitle}} 시간슬라이더", - "timeslider.toolbar.returnbutton": "패드로 돌아가기", - "timeslider.toolbar.authors": "저자:", - "timeslider.toolbar.authorsList": "저자 없음", - "timeslider.toolbar.exportlink.title": "내보내기", - "timeslider.exportCurrent": "현재 버전으로 내보내기:", - "timeslider.version": "버전 {{version}}", - "timeslider.saved": "{{year}}년 {{month}} {{day}}일에 저장함", - "timeslider.playPause": "시작 / 패드 내용을 일시 중지", - "timeslider.backRevision": "패드의 수정판으로 다시 가기", - "timeslider.forwardRevision": "패드의 수정판을 앞으로 이동 시키기", - "timeslider.dateformat": "{{year}}년/{{month}}/{{day}}일 {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "1월", - "timeslider.month.february": "2월", - "timeslider.month.march": "3월", - "timeslider.month.april": "4월", - "timeslider.month.may": "5월", - "timeslider.month.june": "6월", - "timeslider.month.july": "7월", - "timeslider.month.august": "8월", - "timeslider.month.september": "9월", - "timeslider.month.october": "10월", - "timeslider.month.november": "11월", - "timeslider.month.december": "12월", - "timeslider.unnamedauthors": "이름 없는 {[plural(num) one: 저자, other: 저자 ]} {{num}}명", - "pad.savedrevs.marked": "이 판은 이제 저장한 판으로 표시합니다.", - "pad.savedrevs.timeslider": "당신은 타임슬라이더를 통해 저장된 버전을 볼 수 있습니다", - "pad.userlist.entername": "이름을 입력하세요", - "pad.userlist.unnamed": "이름없음", - "pad.userlist.guest": "손님", - "pad.userlist.deny": "거부", - "pad.userlist.approve": "승인", - "pad.editbar.clearcolors": "전체 문서의 저자 색을 지우시겠습니까?", - "pad.impexp.importbutton": "지금 가져오기", - "pad.impexp.importing": "가져오는 중...", - "pad.impexp.confirmimport": "파일을 가져오면 패드의 현재 텍스트를 덮어쓰게 됩니다. 진행하시겠습니까?", - "pad.impexp.convertFailed": "이 파일을 가져올 수 없습니다. 다른 문서 형식을 사용하거나 수동으로 복사하여 붙여넣으세요", - "pad.impexp.padHasData": "우리는 이 파일을 가져올 수 없었습니다. 이 패드는 이미 수정되었으니, 새 패드를 가져와 주십시오", - "pad.impexp.uploadFailed": "올리기를 실패했습니다. 다시 시도하세요", - "pad.impexp.importfailed": "가져오기를 실패했습니다", - "pad.impexp.copypaste": "복사하여 붙여넣으세요", - "pad.impexp.exportdisabled": "{{type}} 형식으로 내보내기가 비활성화되어 있습니다. 자세한 내용은 시스템 관리자에게 문의하시기 바랍니다." -} diff --git a/sources/src/locales/krc.json b/sources/src/locales/krc.json deleted file mode 100644 index df04e94..0000000 --- a/sources/src/locales/krc.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Ernác" - ] - }, - "pad.toolbar.settings.title": "Джарашдырыула", - "pad.colorpicker.save": "Сакъла", - "pad.loading": "Джюклениу...", - "pad.settings.fontType.normal": "Нормал", - "pad.settings.fontType.monospaced": "Монокенгликли", - "pad.settings.globalView": "Глобал кёрюнюу", - "pad.settings.language": "Тил:", - "pad.importExport.import_export": "Импорт/экспорт", - "pad.importExport.importSuccessful": "Тыйыншлы!", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Тюз текст", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (OpenOffice'ни документи)", - "pad.chat": "Чат", - "timeslider.toolbar.returnbutton": "Документге", - "timeslider.toolbar.authors": "Авторла:", - "timeslider.toolbar.exportlink.title": "Эспорт эт", - "timeslider.version": "{{version}} версия", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}.{{minutes}}.{{seconds}}", - "timeslider.month.january": "январь", - "timeslider.month.february": "февраль", - "timeslider.month.march": "март", - "timeslider.month.april": "апрель", - "timeslider.month.may": "май", - "timeslider.month.june": "июнь", - "timeslider.month.july": "июль", - "timeslider.month.august": "август", - "timeslider.month.september": "сентябрь", - "timeslider.month.october": "октябрь", - "timeslider.month.november": "ноябрь", - "timeslider.month.december": "декабрь", - "pad.userlist.guest": "Къонакъ", - "pad.impexp.importing": "Импорт этиу…" -} diff --git a/sources/src/locales/ksh.json b/sources/src/locales/ksh.json deleted file mode 100644 index f6d0c3b..0000000 --- a/sources/src/locales/ksh.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Purodha" - ] - }, - "index.newPad": "Neu Pädd", - "index.createOpenPad": "udder maach e Pädd op med däm Nahme:", - "pad.toolbar.bold.title": "Fättschreff (Strg-B)", - "pad.toolbar.italic.title": "Scheive Schreff (Strg-I)", - "pad.toolbar.underline.title": "Ongerstresche (Strg-U)", - "pad.toolbar.strikethrough.title": "Dorschjeschtresche (Strg+5)", - "pad.toolbar.ol.title": "Leß met Nommere (Strg+Jruhß+N)", - "pad.toolbar.ul.title": "Leß met Pongkte (Strg+Jruhß+L)", - "pad.toolbar.indent.title": "Enjerök (TAB)", - "pad.toolbar.unindent.title": "Ußjerök (Jruhßschreff+TAB)", - "pad.toolbar.undo.title": "Retuhr nämme (Strg+Z)", - "pad.toolbar.redo.title": "Norrens (Strg-Y)", - "pad.toolbar.clearAuthorship.title": "Donn dä Schriiver ier Färve fottnämme (Strg+Jruhß+C)", - "pad.toolbar.import_export.title": "Ongerscheidlijje Dattei_Fommaate empotteere udder äxpotteere", - "pad.toolbar.timeslider.title": "Verjangeheid afschpelle", - "pad.toolbar.savedRevision.title": "Di Väsjohn faßhallde", - "pad.toolbar.settings.title": "Enschtällonge", - "pad.toolbar.embed.title": "Donn dat Pädd öffentlesch maache un enbenge", - "pad.toolbar.showusers.title": "Verbonge Metschriiver aanzeije", - "pad.colorpicker.save": "Faßhallde", - "pad.colorpicker.cancel": "Ophüre", - "pad.loading": "Ben aam Lahde …", - "pad.noCookie": "Dat Pläzje wood nit jevonge. Don dat en Dingem Brauser zohlohße!", - "pad.passwordRequired": "Do bruchs e Paßwoot för heh dat Pädd.", - "pad.permissionDenied": "Do häs nit dat Rääsch, op heh dat Pädd zohzejriife.", - "pad.wrongPassword": "Ding Paßwoot wohr verkeht.", - "pad.settings.padSettings": "Däm Pädd sing Enschtällonge", - "pad.settings.myView": "Aanseesch", - "pad.settings.stickychat": "Donn der Klaaf emmer aanzeije", - "pad.settings.chatandusers": "Dunn de Metmaacher un der Klaaf aanzeije", - "pad.settings.colorcheck": "Färve för de Schrihver", - "pad.settings.linenocheck": "Nommere för de Reije", - "pad.settings.rtlcheck": "Schreff vun Rääschß noh Lenks?", - "pad.settings.fontType": "Zoot Schreff", - "pad.settings.fontType.normal": "Nommahl", - "pad.settings.fontType.monospaced": "einheidlesch brejde Zeische", - "pad.settings.globalView": "Et Ußsin för Alle", - "pad.settings.language": "Schprohch:", - "pad.importExport.import_export": "Empoot/Äxpoot", - "pad.importExport.import": "Donn jeede Täx udder jeede Zoot Dokemänt huhlaade", - "pad.importExport.importSuccessful": "Jeschaff!", - "pad.importExport.export": "Don dat Pädd äxpoteere alß:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Eijfach Täx", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF (Poteerbaa Dokemänte Fommaat)", - "pad.importExport.exportopen": "ODF (Offe Dokemänte-Fommaat)", - "pad.importExport.abiword.innerHTML": "Mer künne bloß eijfaache Täxte udder HTML_Fommaate empoteere. Opwändejere Müjjeleschkeite fö der Empoot jon och, doför bruch mer en Enschtallazjuhn met Abiword.", - "pad.modals.connected": "Verbonge.", - "pad.modals.reconnecting": "Ben wider aam Verbenge …", - "pad.modals.forcereconnect": "Wider verbenge", - "pad.modals.userdup": "En enem andere Finster en Ärbeid", - "pad.modals.userdup.explanation": "Heh dat Padd schingk en mieh wi einem Finster vun enem Brauser op heh däm Rääschner op ze sin.", - "pad.modals.userdup.advice": "En heh däm Finster wider verbenge.", - "pad.modals.unauth": "Nit berääschtesch", - "pad.modals.unauth.explanation": "Ding Berääschtejong hät sesch jeändert, derwiehl De di Sigg aam beloore wohrß. Versöhk en neu Verbendong ze maache.", - "pad.modals.looping.explanation": "Et jitt Probleeme met dä Verbendong mem ẞööver för de Schriiver ier Aandeile zesamme_ze_bränge.", - "pad.modals.looping.cause": "Künnt sin, Ding Verbendong jeiht dorj_ene onzopaß proxy-ẞööver udder firewall.", - "pad.modals.initsocketfail": "Dä ẞööver es nit ze äreische.", - "pad.modals.initsocketfail.explanation": "Kein Verbendong met däm ẞööver ze krijje.", - "pad.modals.initsocketfail.cause": "Dat künnt aam Brauser udder aan däm singer Verbendong övver et Internet lijje.", - "pad.modals.slowcommit.explanation": "Dä ẞööver antwoot nit.", - "pad.modals.slowcommit.cause": "Dat künnt aan Probleeme met Verbendonge em Näzwärrek lijje.", - "pad.modals.badChangeset.explanation": "En Änderong, di De jemaat häs, wood vum ẞööver nit aanjenumme.", - "pad.modals.badChangeset.cause": "Dat künnt sin wääje ener verkehte Enschtällong vum ẞööver udder ohnjät, wat mer nit äwaadt hät. Donn Desch aan däm ßööver singe Bedriever wände, wann De meins, dat dat ene Fähler wör. Donn desch neu verbende, öm mem Schriive wigger ze maache.", - "pad.modals.corruptPad.explanation": "Dat Pädd, wo De desch met verbenge wells, es kappott.", - "pad.modals.corruptPad.cause": "Dat künnt sin wääje ener verkehte Enschtällong vum ẞööver udder öhnßjät, wat mer nit äwaadt hät. Donn Desch aan däm ßööver singe Bedriever wände.", - "pad.modals.deleted": "Fottjeschmeße.", - "pad.modals.deleted.explanation": "Dat Pädd es fottjeschmeße woode.", - "pad.modals.disconnected": "Do bes nit mih verbonge.", - "pad.modals.disconnected.explanation": "De Verbendong mem ẞööver es fott.", - "pad.modals.disconnected.cause": "Dä ẞööver künnt nit mih loufe.\nSidd_esu jood und saad ons Bescheid, wann dadd esu bliiv.", - "pad.share": "Maach heh dat Pädd öffentlesch", - "pad.share.readonly": "Nor för ze Lässe", - "pad.share.link": "Lengk", - "pad.share.emebdcode": "Donn en URL enboue", - "pad.chat": "Klaaf", - "pad.chat.title": "Maach dä Klaaf för heh dat Pädd op", - "pad.chat.loadmessages": "Mih Nohreeschte lahde …", - "timeslider.pageTitle": "{{appTitle}} - Verjangeheid affschpelle", - "timeslider.toolbar.returnbutton": "Jangk retuhr nohm Pädd", - "timeslider.toolbar.authors": "De Schrihver:", - "timeslider.toolbar.authorsList": "Kein Schriivere", - "timeslider.toolbar.exportlink.title": "Äxpotteere", - "timeslider.exportCurrent": "Donn de neußte Väsjohn äxpotteere alß:", - "timeslider.version": "Väsjohn {{version}}", - "timeslider.saved": "Faßjehallde aam {{day}}. {{month}} {{year}}", - "timeslider.playPause": "Donn der Enhalld vum Päd afschpelle udder aanhallde", - "timeslider.backRevision": "Jangk ein Väsjohn retuhr en dämm Pahdt", - "timeslider.forwardRevision": "Jangg en Väsjohn vörwääz en heh däm Pahdt.", - "timeslider.dateformat": "aam {{day}}. {{month}} {{year}} öm {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Jannewaa", - "timeslider.month.february": "Fääbrowaa", - "timeslider.month.march": "Määz", - "timeslider.month.april": "Apprell", - "timeslider.month.may": "Mai", - "timeslider.month.june": "Juuni", - "timeslider.month.july": "Juuli", - "timeslider.month.august": "Oujoß", - "timeslider.month.september": "Säptämber", - "timeslider.month.october": "Oktoober", - "timeslider.month.november": "Novämber", - "timeslider.month.december": "Dezämber", - "timeslider.unnamedauthors": "{[plural(num) zero: keine, one: eine, other: {{num}} ]} nahmeloose Schriiver", - "pad.savedrevs.marked": "Heh di Väsjohn es jäz faßjehallde.", - "pad.savedrevs.timeslider": "Mer kann de faßjehallde Väsjohne belohre beim Verjangeheid afschpelle", - "pad.userlist.entername": "Jif Dinge Nahme en", - "pad.userlist.unnamed": "nahmeloßß", - "pad.userlist.guest": "Jaßß", - "pad.userlist.deny": "Aflehne", - "pad.userlist.approve": "Johdheiße", - "pad.editbar.clearcolors": "Sulle mer de Färve för de Schriiver uss_em janze Täx fott maache?", - "pad.impexp.importbutton": "Jäz empoteere", - "pad.impexp.importing": "Ben aam Empottehre …", - "pad.impexp.confirmimport": "En Dattei ze empotteere määt der janze Täx em Pädd fott. Wells De dat verfaftesch hann?", - "pad.impexp.convertFailed": "Mer kunnte di Dattei nit empoteere. Nemm en ander Dattei-Fommaat udder donn dä Täx vun Hand kopeere un ennföhje.", - "pad.impexp.padHasData": "Mer kunnte di Dattei nit empottehre weil et Pädd alt Veränderonge metjemaht hät. Donn se en e neu Pädd empottehre.", - "pad.impexp.uploadFailed": "Dat Huhlaade es donävve jejange. Bes esu johd un probeer et norr_ens.", - "pad.impexp.importfailed": "Et Empoteere es donävve jejange.", - "pad.impexp.copypaste": "Bes esu johd un donn et koppeere un enfööje", - "pad.impexp.exportdisabled": "Et Äxpotteere em {{type}}-Formmaat es affjeschalldt. De Verwallder vun heh dä Sigge künne doh velleisch wiggerhällefe." -} diff --git a/sources/src/locales/ku-latn.json b/sources/src/locales/ku-latn.json deleted file mode 100644 index b5edc68..0000000 --- a/sources/src/locales/ku-latn.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Bikarhêner", - "Dilyaramude", - "George Animal", - "Gomada", - "Mehk63", - "Ghybu" - ] - }, - "index.newPad": "Bloknota nû", - "index.createOpenPad": "Yan Padekê li gel navê biafirîne/veke:", - "pad.toolbar.bold.title": "Stûr (Ctrl-B)", - "pad.toolbar.italic.title": "Xwar (Ctrl-I)", - "pad.toolbar.underline.title": "Binxet (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Serxêzkirî (Ctrl+5)", - "pad.toolbar.ol.title": "Lîsteya rêzkirî (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Lîsteya tevlîhev (Ctrl+Shift+L)", - "pad.toolbar.undo.title": "Vegerîne (Ctrl-Z)", - "pad.toolbar.redo.title": "Dîsa bike (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Rengên nivîskariyê jê bibe (Ctrl+Shift+C)", - "pad.toolbar.savedRevision.title": "Sererastkirinê tomar bike", - "pad.toolbar.settings.title": "Eyar", - "pad.colorpicker.save": "Tomar bike", - "pad.colorpicker.cancel": "Betal bike", - "pad.loading": "Tê barkirin...", - "pad.settings.padSettings": "Eyarên bloknotê", - "pad.settings.myView": "Dîmena min", - "pad.settings.stickychat": "Di ekranê de hertim çet bike", - "pad.settings.chatandusers": "Çeta û Bikarhênera Nîşan bide", - "pad.settings.colorcheck": "Rengên nivîskarîye", - "pad.settings.linenocheck": "Hejmarên rêze", - "pad.settings.rtlcheck": "Bila naverok ji raste ber bi çepe be xwendin?", - "pad.settings.fontType": "Tîpa nivîsê:", - "pad.settings.language": "Ziman:", - "pad.importExport.importSuccessful": "Biserketî!", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.modals.connected": "Hate girêdan.", - "pad.modals.reconnecting": "Ji bloknota te re dîsa tê girêdan...", - "pad.modals.cancel": "Betal bike", - "pad.modals.userdup": "Di pencereyek din de vebû", - "pad.modals.userdup.advice": "Ji bo di vê pencereye de bikarbînîy dîsa giredanek çeke.", - "pad.modals.unauth": "Desthilatdar nîne", - "pad.modals.deleted": "Hate jêbirin.", - "pad.modals.deleted.explanation": "Ev bloknot hatiye rakirin.", - "pad.modals.disconnected": "Pêwendîya te qut bû.", - "pad.modals.disconnected.explanation": "Pêwendîya rajeker qut bû", - "pad.share": "Vê bloknotê parve bike", - "pad.share.link": "Girêdan", - "pad.chat": "Çet", - "pad.chat.title": "Ji bo vê bloknotê çet veke.", - "pad.chat.loadmessages": "Peyamên bêhtir barbike", - "timeslider.toolbar.returnbutton": "Vegere bloknotê", - "timeslider.toolbar.authors": "Nivîser:", - "timeslider.toolbar.authorsList": "Nivîser Tine", - "timeslider.version": "Guhertoya {{version}}", - "timeslider.saved": "Di dîroka {{day}} {{month}} {{year}} de hate tomarkirin", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}.{{minutes}}.{{seconds}}", - "timeslider.month.january": "rêbendan", - "timeslider.month.february": "reşemî", - "timeslider.month.march": "adar", - "timeslider.month.april": "avrêl", - "timeslider.month.may": "gulan", - "timeslider.month.june": "pûşper", - "timeslider.month.july": "tîrmeh", - "timeslider.month.august": "gelawêj", - "timeslider.month.september": "rezber", - "timeslider.month.october": "kewçêr", - "timeslider.month.november": "Mijdar", - "timeslider.month.december": "berfanbar", - "pad.userlist.entername": "Navê xwe têkeve", - "pad.userlist.unnamed": "nenavkirî", - "pad.userlist.guest": "Mêvan", - "pad.userlist.deny": "Red bike", - "pad.userlist.approve": "Bipejirîne", - "pad.impexp.copypaste": "Ji kerema xwe re jê bigre û pê ve deyne (Ctrl+c, Ctrl+v)" -} diff --git a/sources/src/locales/lb.json b/sources/src/locales/lb.json deleted file mode 100644 index 2f1432a..0000000 --- a/sources/src/locales/lb.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Robby", - "Soued031", - "Gromper" - ] - }, - "index.newPad": "Neie Pad", - "index.createOpenPad": "oder maacht ee Pad mat dësem Numm op:", - "pad.toolbar.bold.title": "Fett (Strg-B)", - "pad.toolbar.italic.title": "Schréi (Ctrl+I)", - "pad.toolbar.underline.title": "Ënnerstrach (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Duerchgestrach (Ctrl+5)", - "pad.toolbar.ol.title": "Numeréiert Lëscht (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Net-numeréiert Lëscht (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Aréckelen (TAB)", - "pad.toolbar.unindent.title": "Erausréckelen (Shift+TAB)", - "pad.toolbar.undo.title": "Réckgängeg (Ctrl-Z)", - "pad.toolbar.redo.title": "Widderhuelen (Ctrl-Y)", - "pad.toolbar.savedRevision.title": "Versioun späicheren", - "pad.toolbar.settings.title": "Astellungen", - "pad.toolbar.showusers.title": "Aktuell Benotzer vun dësem Pad uweisen", - "pad.colorpicker.save": "Späicheren", - "pad.colorpicker.cancel": "Ofbriechen", - "pad.loading": "Lueden...", - "pad.noCookie": "Cookie gouf net fonnt. Erlaabt w.e.g. Cookien an Ärem Browser!", - "pad.passwordRequired": "Dir braucht ee Passwuert fir dëse Pad opzemaachen", - "pad.permissionDenied": "Dir hutt net déi néideg Rechter fir dëse Pad opzemaachen", - "pad.wrongPassword": "Äert Passwuert ass falsch", - "pad.settings.myView": "Méng Usiicht", - "pad.settings.linenocheck": "Zeilennummeren", - "pad.settings.rtlcheck": "Inhalt vu riets no lénks liesen?", - "pad.settings.fontType": "Schrëftart:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.globalView": "Global Vue", - "pad.settings.language": "Sprooch:", - "pad.importExport.import_export": "Import/Export", - "pad.importExport.import": "Text-Fichier oder Dokument eroplueden", - "pad.importExport.importSuccessful": "Erfollegräich", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Kloertext", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.modals.connected": "Verbonnen.", - "pad.modals.cancel": "Ofbriechen", - "pad.modals.userdup": "An enger anerer Fënster opgemaach", - "pad.modals.unauth": "Net autoriséiert", - "pad.modals.unauth.explanation": "Är Rechter hu geännert während deem Dir dës säit gekuckt hutt. Probéiert fir Iech nei ze connectéieren.", - "pad.modals.looping.explanation": "Et gëtt Kommunikatiounsproblemer mam Synchronisatiouns-Server.", - "pad.modals.initsocketfail": "De Server kann net erreecht ginn.", - "pad.modals.slowcommit.explanation": "De Server äntwert net.", - "pad.modals.deleted": "Geläscht.", - "pad.modals.disconnected": "Äre Verbindung ass ofgebrach.", - "pad.modals.disconnected.explanation": "D'Verbindung mam Server ass verluergaang.", - "pad.share.readonly": "Nëmme liesen", - "pad.share.link": "Link", - "pad.chat": "Chat", - "pad.chat.loadmessages": "Méi Message lueden", - "timeslider.toolbar.authors": "Auteuren:", - "timeslider.toolbar.authorsList": "Keng Auteuren", - "timeslider.toolbar.exportlink.title": "Exportéieren", - "timeslider.exportCurrent": "Exportéiert déi aktuell Versioun als:", - "timeslider.version": "Versioun {{version}}", - "timeslider.saved": "Gespäichert de(n) {{day}} {{month}} {{year}}", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januar", - "timeslider.month.february": "Februar", - "timeslider.month.march": "Mäerz", - "timeslider.month.april": "Abrëll", - "timeslider.month.may": "Mee", - "timeslider.month.june": "Juni", - "timeslider.month.july": "Juli", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "Oktober", - "timeslider.month.november": "November", - "timeslider.month.december": "Dezember", - "pad.savedrevs.marked": "Dës Versioun ass elo als gespäichert Versioun markéiert", - "pad.userlist.entername": "Gitt Ären Numm an", - "pad.userlist.unnamed": "anonym", - "pad.userlist.guest": "Gaascht", - "pad.userlist.deny": "Refuséieren", - "pad.userlist.approve": "Zoustëmmen", - "pad.impexp.importbutton": "Elo importéieren", - "pad.impexp.importing": "Importéieren...", - "pad.impexp.uploadFailed": "D'Eroplueden huet net funktionéiert, probéiert w.e.g. nach eng Kéier", - "pad.impexp.importfailed": "Den Import huet net funktionéiert" -} diff --git a/sources/src/locales/lki.json b/sources/src/locales/lki.json deleted file mode 100644 index c8b8ecc..0000000 --- a/sources/src/locales/lki.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Hosseinblue", - "Arash71", - "Lakzon" - ] - }, - "index.newPad": "تازۀpad", - "index.createOpenPad": ":وە نۆم Pad یا سازین/واز کردن یإگلە", - "pad.toolbar.bold.title": "پررنگ-تئژ(Ctrl-B)", - "pad.toolbar.italic.title": "ایتالیک (Ctrl-I)", - "pad.toolbar.underline.title": "ژئر خطی(Ctrl-U)", - "pad.toolbar.strikethrough.title": "(Ctrl+5)خط هوواردێ", - "pad.toolbar.ol.title": " (Ctrl+5)لیست مرتب بی", - "pad.toolbar.ul.title": "(Ctrl+5)لیست شؤیا/نامرتب", - "pad.toolbar.indent.title": "تورفتگی(إنۆم چێن)(TAB)", - "pad.toolbar.unindent.title": "(Shift+TAB)بیرون آمدگی-درچئن", - "pad.toolbar.undo.title": "گِلّا دائن-ئآهۀتن(Ctrl-Z)", - "pad.toolbar.redo.title": "وە نووآ هەتن (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "(Ctrl+Shift+C)پاک‌کردن رنگةل نویسندگی", - "pad.toolbar.import_export.title": "دەربردن/إنۆم آووِردن إژ/وە قاڵبەل گوناگون", - "pad.toolbar.timeslider.title": "اسلایدر وختی-زمانی", - "pad.toolbar.savedRevision.title": "نسخە بِیل(ذخیره کە)", - "pad.toolbar.settings.title": "تنظیمۀل", - "pad.toolbar.embed.title": "بەشآکردن ؤ نیائن(اشتراک ونشاندن)وە نۆم سایت", - "pad.toolbar.showusers.title": "نیشان دائن کاربەر أنۆم اێ\nیادداشتە", - "pad.colorpicker.save": "هیشتن(ذخیره)", - "pad.colorpicker.cancel": "ئآهووسانن/لغو", - "pad.loading": "...(loading)بارنیائن", - "pad.noCookie": "کوکی یافت نشد. لطفاً اجازهٔ اجرای کوکی در مروگرتان را بدهید!", - "pad.passwordRequired": "هؤمۀ رمزتؤنه گرۀکۀ-لازمۀ ئۀرا اتصال ئئ \npad", - "pad.permissionDenied": "شما اجازه‌ی دسترسی به این دفترچه یادداشت را ندارید", - "pad.wrongPassword": "رمزۀ تؤن دؤرس نیۀ", - "pad.settings.padSettings": "pad تنظیمۀل", - "pad.settings.myView": "نمایش-سئرکردن مه", - "pad.settings.stickychat": "گەپ(قسە)هەمۆیشە وە وەڵگە نمایش بوو", - "pad.settings.chatandusers": "نمایش چت و کاربران", - "pad.settings.colorcheck": "رنگۀل تالیفی", - "pad.settings.linenocheck": "شؤمارۀل خطی", - "pad.settings.rtlcheck": "خواندن نۆم جِک(محتوا)أژ لآ ڕاس بە چەپ؟", - "pad.settings.fontType": ":شئؤۀ فؤنت", - "pad.settings.fontType.normal": "عادی", - "pad.settings.fontType.monospaced": "پئنی-پهنا", - "pad.settings.globalView": "نمایش جەهانی", - "pad.settings.language": ":زوون", - "pad.importExport.import_export": "دەر بردن/إنۆم آووِردن", - "pad.importExport.import": "بارنیائن هر جور نوشته یا سندئ", - "pad.importExport.importSuccessful": "! موفق بی-پیرووز بی", - "pad.importExport.export": ":برون‌ریزی این دفترچه یادداشت با قالب", - "pad.importExport.exportetherpad": "اترپد", - "pad.importExport.exporthtml": "html", - "pad.importExport.exportplain": "متن پئن-درئژ", - "pad.importExport.exportword": "مایکروسافت وورد", - "pad.importExport.exportpdf": "پی دی اف", - "pad.importExport.exportopen": " (قالب سند باز)ODF", - "pad.importExport.abiword.innerHTML": "شما تنها می‌توانید از قالب متن ساده یا اچ‌تی‌ام‌ال درون‌ریزی کنید. برای بیشتر شدن ویژگی‌های درون‌ریزی پیشرفته AbiWord را نصب کنید.", - "pad.modals.connected": "وصل بیۀ", - "pad.modals.reconnecting": "..در حال اتصال دوباره به دفترچه یادداشت شما", - "pad.modals.forcereconnect": "واداشتن به اتصال دوباره", - "pad.modals.userdup": "ئة پنجرإ تر واز بو", - "pad.modals.userdup.explanation": "گمان می‌رود این دفترچه یادداشت در بیش از یک پنجره‌ی مرورگر باز شده‌است.", - "pad.modals.userdup.advice": "برای استفاده از این پنجره دوباره وصل شوید.", - "pad.modals.unauth": "مجاز نیة", - "pad.modals.unauth.explanation": "دسترسی شما در حین مشاهده‌ی این برگه تغییر یافته‌است. دوباره متصل شوید.", - "pad.modals.looping.explanation": "مشکلاتی ارتباطی با سرور همگام‌سازی وجود دارد.", - "pad.modals.looping.cause": "شاید شما از طریق یک فایروال یا پروکسی ناسازگار متصل شده‌اید.", - "pad.modals.initsocketfail": "سرور در دسترس نیست.", - "pad.modals.initsocketfail.explanation": ".نمی‌توان به سرور همگام سازی وصل شد", - "pad.modals.initsocketfail.cause": ".شاید این به خاطر مشکلی در مرورگر یا اتصال اینترنتی شما باشد", - "pad.modals.slowcommit.explanation": ".سرور پاسخ نمی‌دهد", - "pad.modals.slowcommit.cause": ".این می‌تواند به خاطر مشکلاتی در اتصال به شبکه باشد", - "pad.modals.badChangeset.explanation": "ویرایشی که شما انجام داده‌اید توسط سرور همگام‌سازی نادرست طیقه‌بندی شده است.", - "pad.modals.badChangeset.cause": "این می‌تواند به دلیل پیکربندی اشتباه یا سایر رفتارهای غیرمنتظره باشد. اگر فکر می‌کنید این یک خطا است لطفاً با مدیر خدمت تماس بگیرید. برای ادامهٔ ویرایش سعی کنید که دوباره متصل شوید.", - "pad.modals.corruptPad.explanation": ".پدی که شما سعی دارید دسترسی پیدا کنید خراب است", - "pad.modals.corruptPad.cause": "این احتمالاً به دلیل تنظیمات اشتباه کارساز یا سایر رفتارهای غیرمنتظره است. لطفاً با مدیر خدمت تماس حاصل کنید.", - "pad.modals.deleted": "پاک بیا-حذف بی", - "pad.modals.deleted.explanation": "این دفترچه یادداشت پاک شده‌است.", - "pad.modals.disconnected": "اتصال شما قطع شده‌است.", - "pad.modals.disconnected.explanation": ".اتصال وة سرور قطع بیة", - "pad.modals.disconnected.cause": "ممکن است سرور در دسترس نباشد. اگر این مشکل باز هم رخ داد مدیر حدمت را .آگاه کنید", - "pad.share": "به اشتراک‌گذاری این دفترچه یادداشت", - "pad.share.readonly": "تەنیا(فقط)خووەنن", - "pad.share.link": "لینک", - "pad.share.emebdcode": "جاسازی نشانی", - "pad.chat": "گپ", - "pad.chat.title": "بازکردن گفتگو برای این دفترچه یادداشت", - "pad.chat.loadmessages": "پئامۀلئ تر باره سۀر", - "timeslider.pageTitle": "لغزندهٔ زمان {{appTitle}}", - "timeslider.toolbar.returnbutton": "بازگشت به دفترچه یادداشت", - "timeslider.toolbar.authors": "نویسندگان:", - "timeslider.toolbar.authorsList": "بدون نویسنده", - "timeslider.toolbar.exportlink.title": "در بِردن", - "timeslider.exportCurrent": "برون‌ریزی نگارش کنونی به عنوان:", - "timeslider.version": "نگارش {{version}}", - "timeslider.saved": "{{month}} {{day}}، {{year}} ذخیره شد", - "timeslider.playPause": "اجرای مجدد/متوقف کردن پخش", - "timeslider.backRevision": "رفتن به نسخهٔ پیشین در این دفترچه", - "timeslider.forwardRevision": "رفتن به نسخهٔ بعدی در این دفترچه", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "دی)نورووژ)", - "timeslider.month.february": "(خاکه لێه(بهمن", - "timeslider.month.march": "(مانگ ئێد(اسفندگان", - "timeslider.month.april": "(په نجه(فروردین", - "timeslider.month.may": "(مێرێان(اردیبهشت", - "timeslider.month.june": "(گاکوور(خرداد", - "timeslider.month.july": "تیر)ئاگرانی)", - "timeslider.month.august": "مرداد)مردار)", - "timeslider.month.september": "(ماڵه ژێر(شهریور", - "timeslider.month.october": "(ماڵه ژێر دوماێنه(مهر", - "timeslider.month.november": "آبان)تویل ته کن)", - "timeslider.month.december": "(مانگه سێه(آذر", - "timeslider.unnamedauthors": " نویسندة بی‌ نام{{num}}", - "pad.savedrevs.marked": "این بازنویسی هم اکنون به عنوان ذخیره شده علامت‌گذاری شد", - "pad.savedrevs.timeslider": "شما می‌توانید نسخه‌های ذخیره شده را با دیدن نوار زمان ببنید", - "pad.userlist.entername": "نۆم ووژت وارد کە", - "pad.userlist.unnamed": "بێ نۆم", - "pad.userlist.guest": "مئمان", - "pad.userlist.deny": "رد کردن", - "pad.userlist.approve": "راووا داشتن-تصویب کردن", - "pad.editbar.clearcolors": "رنگ نویسندگی از همه‌ی سند پاک شود؟", - "pad.impexp.importbutton": "ایسگە وارد کە", - "pad.impexp.importing": "...وارد مۀهه", - "pad.impexp.confirmimport": "با درون‌ریزی یک پرونده نوشتهٔ کنونی دفترچه پاک می‌شود. آیا می‌خواهید ادامه دهید؟", - "pad.impexp.convertFailed": "ما نمی‌توانیم این پرونده را درون‌ریزی کنیم. خواهشمندیم قالب دیگری برای سندتان انتخاب کرده یا بصورت دستی آنرا کپی کنید", - "pad.impexp.padHasData": "امکان درون‌ریز این پرونده نیست زیرا این پد تغییر کرده‌است. لطفاً در پد جدید درون‌ریزی کنید.", - "pad.impexp.uploadFailed": "آپلود انجام نشد، دوباره تلاش کنید", - "pad.impexp.importfailed": "وارد نؤنئ-خطای واردکردن", - "pad.impexp.copypaste": "کپی پیست کنید", - "pad.impexp.exportdisabled": "برون‌ریزی با قالب {{type}} از کار افتاده است. برای جزئیات بیشتر با مدیر سیستمتان تماس بگیرید." -} diff --git a/sources/src/locales/lrc.json b/sources/src/locales/lrc.json deleted file mode 100644 index 910f8f1..0000000 --- a/sources/src/locales/lrc.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Mogoeilor" - ] - }, - "index.newPad": "دشته تازه", - "pad.toolbar.bold.title": "توپر", - "pad.toolbar.italic.title": "کج کوله(ctrl-l)", - "pad.toolbar.underline.title": "زیر خط دار بین (Ctrl-U)", - "pad.toolbar.ol.title": "نوم گه منظم", - "pad.toolbar.ul.title": "نوم گه بی نظم", - "pad.toolbar.indent.title": "مئن رئته(TAB)", - "pad.toolbar.unindent.title": "وه در رئته (Shift+TAB)", - "pad.toolbar.undo.title": "رد انجوم دئین (Ctrl-Z)", - "pad.toolbar.redo.title": "د نو انجوم دئین(Ctrl-Y)", - "pad.toolbar.settings.title": "میزوکاری", - "pad.colorpicker.save": "ذخيره كردن", - "pad.colorpicker.cancel": "انجوم شیو كردن", - "pad.loading": "د حالت سوار كرد", - "pad.wrongPassword": "پاسوردتو اشتوائه", - "pad.settings.padSettings": "میزوکاری دشته", - "pad.settings.myView": "نظرگه مه", - "pad.settings.stickychat": "همیشه د بلگه چک چنه بکید", - "pad.settings.linenocheck": "شماره خطیا", - "pad.settings.fontType": "نوع فونت:", - "pad.settings.fontType.normal": "عادی", - "pad.settings.fontType.monospaced": "تک جاگه", - "pad.settings.globalView": "دیئن جهونی", - "pad.settings.language": "زون:", - "pad.importExport.import_export": "وامین آوردن/د در دئن", - "pad.importExport.importSuccessful": "موفق بی!", - "pad.importExport.export": "دشته تازه چی وه در بیه:", - "pad.importExport.exporthtml": "اچ تی ام ال", - "pad.importExport.exportplain": "نیسسه ساده", - "pad.importExport.exportword": "واجه پالایشتگر مایکروسافت", - "pad.importExport.exportpdf": "پی دی اف", - "pad.importExport.exportopen": "او دی اف(قالو سند وا بیه)", - "pad.modals.connected": "وصل بیه", - "pad.modals.forcereconnect": "سی وصل بین مژبور کو", - "pad.modals.userdup": "د نیمدری هنی واز بیه", - "pad.modals.initsocketfail": "سرور د دسرسی نئ.", - "pad.modals.deleted": "پاک بیه", - "pad.modals.deleted.explanation": "ای دشته جا وه جا بیه", - "pad.modals.disconnected": "ارتواطتو قطع بیه", - "pad.share": "ای دشته نه بهر کو", - "pad.share.readonly": "فقط بحون", - "pad.share.link": "هوم پیوند", - "pad.chat": "گپ زئن", - "pad.chat.title": "گپ چنه نه سی دشته وا کو.", - "pad.chat.loadmessages": "پیغومیا بیشتر نه سوار کو", - "timeslider.toolbar.returnbutton": "ورگرد د دشته", - "timeslider.toolbar.authors": "نیسنه یا:", - "timeslider.toolbar.authorsList": "بی نیسنه", - "timeslider.toolbar.exportlink.title": "وه در ديئن", - "timeslider.version": "نسقه{{نسقه}}", - "timeslider.month.january": "جانويه", - "timeslider.month.february": "فوريه", - "timeslider.month.march": "مارس", - "timeslider.month.april": "آوريل", - "timeslider.month.may": "ما", - "timeslider.month.june": "جوئن", - "timeslider.month.july": "جولای", - "timeslider.month.august": "اگوست", - "timeslider.month.september": "سپتامر", - "timeslider.month.october": "اكتور", - "timeslider.month.november": "نوامر", - "timeslider.month.december": "دسامر", - "pad.userlist.entername": "نوم تونه وارد بکید", - "pad.userlist.unnamed": "نوم نهشته", - "pad.userlist.guest": "میزوان", - "pad.userlist.deny": "پرو کردن", - "pad.userlist.approve": "اصلا کردن", - "pad.impexp.importbutton": "ایسه وارد کو", - "pad.impexp.importing": "د حالت وارد کردن", - "pad.impexp.importfailed": "وامین آوردن شکست حرد", - "pad.impexp.copypaste": "خواهشن وردار بدیسن" -} diff --git a/sources/src/locales/lt.json b/sources/src/locales/lt.json deleted file mode 100644 index f0f02d1..0000000 --- a/sources/src/locales/lt.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Eitvys200", - "Mantak111", - "I-svetaines", - "Zygimantus" - ] - }, - "index.newPad": "Naujas bloknotas", - "index.createOpenPad": "arba sukurkite/atidarykite Bloknotą su pavadinimu:", - "pad.toolbar.bold.title": "Paryškintasis (Ctrl-B)", - "pad.toolbar.italic.title": "Pasvirasis (Ctrl-I)", - "pad.toolbar.underline.title": "Pabraukimas (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Perbrauktasis (Ctrl+5)", - "pad.toolbar.ol.title": "Numeruotas sąrašas (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Nenumeruotas Sąrašas (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Įtrauka", - "pad.toolbar.unindent.title": "Atvirkštinė įtrauka (Shift+TAB)", - "pad.toolbar.undo.title": "Anuliuoti (Ctrl-Z)", - "pad.toolbar.redo.title": "Perdaryti (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Valyti Autorystės Spalvas (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importuoti/Eksportuoti iš/į įvairius failų formatus", - "pad.toolbar.timeslider.title": "Laiko slankiklis", - "pad.toolbar.savedRevision.title": "Išsaugoti peržiūrą", - "pad.toolbar.settings.title": "Nustatymai", - "pad.toolbar.embed.title": "Dalintis ir įterpti šį bloknotą", - "pad.toolbar.showusers.title": "Rodyti naudotojus šiame bloknote", - "pad.colorpicker.save": "Išsaugoti", - "pad.colorpicker.cancel": "Atšaukti", - "pad.loading": "Įkraunama...", - "pad.noCookie": "Slapuko nepavyko rasti. Prašome leisti slapukus interneto naršyklėje!", - "pad.passwordRequired": "Jums reikia slaptažodžio kad galėtumėte matyti šį bloknotą", - "pad.permissionDenied": "Jūs neturite leidimo patekti į šį bloknotą", - "pad.wrongPassword": "Jūsų slaptažodis neteisingas", - "pad.settings.padSettings": "Bloknoto nustatymai", - "pad.settings.myView": "Mano Vaizdas", - "pad.settings.stickychat": "Pokalbiai visada viršuje", - "pad.settings.chatandusers": "Rodyti Pokalbius ir Vartotojus", - "pad.settings.colorcheck": "Autorystės spalvos", - "pad.settings.linenocheck": "Eilučių numeriai", - "pad.settings.rtlcheck": "Skaityti turinį iš dešinės į kairę?", - "pad.settings.fontType": "Šrifto tipas:", - "pad.settings.fontType.normal": "Normalus", - "pad.settings.globalView": "Bendras Vaizdas", - "pad.settings.language": "Kalba:", - "pad.importExport.import_export": "Importuoti/Eksportuoti", - "pad.importExport.import": "Įkelkite bet kokį tekstinį failą arba dokumentą", - "pad.importExport.importSuccessful": "Pavyko!", - "pad.importExport.export": "Eksportuoti dabartinį bloknotą kaip:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Paprastasis tekstas", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Atvirasis dokumento formatas)", - "pad.importExport.abiword.innerHTML": "Galite importuoti tik iš paprasto teksto ar HTML formato. Dėl išplėstinių importavimo funkcijų prašome įdiegti abiword.", - "pad.modals.connected": "Prisijungta.", - "pad.modals.reconnecting": "Iš naujo prisijungiama prie Jūsų bloknoto", - "pad.modals.forcereconnect": "Priversti prisijungti iš naujo", - "pad.modals.userdup": "Atidaryta kitame lange", - "pad.modals.userdup.explanation": "Šis bloknotas, atrodo yra atidarytas daugiau nei viename šio kompiuterio naršyklės lange.", - "pad.modals.userdup.advice": "Prisijunkite iš naujo, kad vietoj to naudotumėte šį langą.", - "pad.modals.unauth": "Neleidžiama", - "pad.modals.unauth.explanation": "Jūsų teiisės pasikeitė kol žiūrėjote šį puslapį. Bandykite prisijungti iš naujo.", - "pad.modals.looping.explanation": "Yra komunikacijos problemų su sinchronizacijos serveriu.", - "pad.modals.looping.cause": "Galbūt prisijungėte per nesuderinamą ugniasienę ar proxy.", - "pad.modals.initsocketfail": "Serveris yra nepasiekiamas.", - "pad.modals.initsocketfail.explanation": "Nepavyko prisijungti prie sinchronizacijos serverio.", - "pad.modals.initsocketfail.cause": "Tai tikriausiai nutiko dėl problemų su jūsų naršykle ar jūsų interneto ryšiu.", - "pad.modals.slowcommit.explanation": "Serveris neatsako.", - "pad.modals.slowcommit.cause": "Tai gali būti dėl problemų su tinklo ryšiu.", - "pad.modals.badChangeset.explanation": "Pakeitimas, kurį atlikote buvo klasifikuotas sinchorizacijos serverio kaip neteisėtas.", - "pad.modals.badChangeset.cause": "Tai galėjo nutikti dėl neteisingos serverio konfigūracijos ar kitos netikėtos elgsenos. Prašome susisiekti su paslaugos administratoriumi jei manote, kad tai klaida. Pabandykite prisijungti iš naujo, kad tęstumėte redagavimą.", - "pad.modals.corruptPad.explanation": "Bloknotas, kurį bandote pasiekti yra sugadintas.", - "pad.modals.corruptPad.cause": "Tai gali nutikti dėl neteisingos serverio konfigūracijos ar kitos netikėtos elgsenos. Prašome susisiekti su paslaugos administratoriumi.", - "pad.modals.deleted": "Ištrintas.", - "pad.modals.deleted.explanation": "Bloknotas buvo pašalintas.", - "pad.modals.disconnected": "Jūs atsijungėte.", - "pad.modals.disconnected.explanation": "Ryšys su serveriu nutrūko", - "pad.modals.disconnected.cause": "Gali būti, kad serveris yra nepasiekiamas. Prašome informuoti paslaugos administratorių jei tai tęsiasi.", - "pad.share": "Dalintis šiuo bloknotu", - "pad.share.readonly": "Tik skaityti", - "pad.share.link": "Nuoroda", - "pad.share.emebdcode": "Įterptasis URL", - "pad.chat": "Pokalbiai", - "pad.chat.title": "Atverti šio bloknoto pokalbį.", - "pad.chat.loadmessages": "Įkrauti daugiau pranešimų", - "timeslider.pageTitle": "{{appTitle}} Laiko slinkiklis", - "timeslider.toolbar.returnbutton": "Grįžti į bloknotą", - "timeslider.toolbar.authors": "Autoriai:", - "timeslider.toolbar.authorsList": "Nėra autorių", - "timeslider.toolbar.exportlink.title": "Eksportuoti", - "timeslider.exportCurrent": "Eksportuoti dabartinę versiją kaip:", - "timeslider.version": "Versija {{version}}", - "timeslider.saved": "Išsaugota {{year}},{{month}} {{day}}", - "timeslider.playPause": "Atkurti / Pristabdyti Bloknoto Turinį", - "timeslider.backRevision": "Grįžti viena Bloknoto peržiūra atgal", - "timeslider.forwardRevision": "Eiti viena Bloknoto peržiūra į priekį", - "timeslider.dateformat": "{{year}}-{{month}}-{{day}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Sausis", - "timeslider.month.february": "Vasaris", - "timeslider.month.march": "Kovas", - "timeslider.month.april": "Balandis", - "timeslider.month.may": "Gegužė", - "timeslider.month.june": "Birželis", - "timeslider.month.july": "Liepa", - "timeslider.month.august": "Rugpjūtis", - "timeslider.month.september": "Rugsėjis", - "timeslider.month.october": "Spalis", - "timeslider.month.november": "Lapkritis", - "timeslider.month.december": "Gruodis", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: bevardis autorius, other: bevardžiai autoriai ]}", - "pad.savedrevs.marked": "Peržiūrą dabar pažymėta kaip išsaugota peržiūra", - "pad.savedrevs.timeslider": "Galite peržiūrėti išsaugotas peržiūras apsilankydami laiko slinkiklyje", - "pad.userlist.entername": "Įveskite savo vardą", - "pad.userlist.unnamed": "bevardis", - "pad.userlist.guest": "Svečias", - "pad.userlist.deny": "Neigti", - "pad.userlist.approve": "Patvirtinti", - "pad.editbar.clearcolors": "Išvalyti autorystės spalvas visame dokumente?", - "pad.impexp.importbutton": "Importuoti dabar", - "pad.impexp.importing": "Importuojama...", - "pad.impexp.confirmimport": "Failo importavimas pakeis dabartinį bloknoto tekstą. Ar tikrai norite tęsti?", - "pad.impexp.convertFailed": "Mums nepavyko importuoti šio failo. Prašome naudoti kitokį dokumento formatą arba nukopijuoti ir įklijuoti rankiniu būdu", - "pad.impexp.padHasData": "Mums nepavyko importuoti šio failo, nes šis Bloknotas jau turėjo pakeitimų, prašome importuoti į naują bloknotą", - "pad.impexp.uploadFailed": "Įkėlimas nepavyko, bandykite dar kartą", - "pad.impexp.importfailed": "Importuoti nepavyko", - "pad.impexp.copypaste": "Prašome nukopijuoti ir įklijuoti", - "pad.impexp.exportdisabled": "Eksportavimas {{type}} formatu yra išjungtas. Prašome susisiekti su savo sistemos administratoriumi dėl informacijos." -} diff --git a/sources/src/locales/lv.json b/sources/src/locales/lv.json deleted file mode 100644 index 7c0bc96..0000000 --- a/sources/src/locales/lv.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Admresdeserv.", - "Jmg.cmdi", - "Papuass", - "Silraks" - ] - }, - "pad.toolbar.bold.title": "Treknrakstā (CTRL + B)", - "pad.toolbar.italic.title": "Slīpraksta (Ctrl-es)", - "pad.toolbar.underline.title": "Pasvītrojuma (CTRL + U)", - "pad.toolbar.strikethrough.title": "Pārsvītrojums (Ctrl+5)", - "pad.toolbar.ol.title": "Sakārtots saraksts (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Nesakārtots saraksts (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Atkāpe (TAB)", - "pad.toolbar.unindent.title": "Izkāpe (Shift+TAB)", - "pad.toolbar.undo.title": "Atsaukt (CTRL + Z)", - "pad.toolbar.redo.title": "Atcelt atsaukšanu (CTRL + Y)", - "pad.toolbar.clearAuthorship.title": "Notīrit autoru krāsas (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importēšanas/eksportēšanas no un uz citu failu formātiem", - "pad.toolbar.savedRevision.title": "Saglabāt pārskatīšanu", - "pad.toolbar.settings.title": "Iestatījumi", - "pad.toolbar.embed.title": "Koplietot un iegut šo pad", - "pad.toolbar.showusers.title": "Parādīt šo padu lietotājus", - "pad.colorpicker.save": "Saglabāt", - "pad.colorpicker.cancel": "Atcelt", - "pad.loading": "Ielādē…", - "pad.passwordRequired": "Ir nepieciešama parole, lai piekļūtu šim pad", - "pad.permissionDenied": "Atvaino, bet tev nav pieejas šim pad.", - "pad.wrongPassword": "Jūsu parole bija nepareiza", - "pad.settings.padSettings": "Pad Iestatijumi", - "pad.settings.myView": "Mans viedoklis", - "pad.settings.stickychat": "Čats vienmēr ekrānā", - "pad.settings.colorcheck": "Autorības krāsas", - "pad.settings.linenocheck": "Rindiņu numurus", - "pad.settings.rtlcheck": "Lasīt saturu no labās puses uz kreiso?", - "pad.settings.fontType": "Fonta tips:", - "pad.settings.fontType.normal": "Normāls", - "pad.settings.globalView": "Globālu skatījumu", - "pad.settings.language": "Valoda:", - "pad.importExport.import_export": "Importet/Eksportet", - "pad.importExport.import": "Augšupielādēt jebkuru teksta failu vai dokumentu", - "pad.importExport.importSuccessful": "Veiksmīgi!", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Vienkārša teksta", - "pad.importExport.exportword": "Programma Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open dokumenta formāts)", - "pad.modals.connected": "Pievienojies.", - "pad.modals.cancel": "Atcelt", - "pad.modals.userdup": "Atvērts citā logā", - "pad.modals.unauth": "Nav atļauts", - "pad.modals.looping.explanation": "Pastāv sakaru problēmas ar sinhronizācijas servera.", - "pad.modals.initsocketfail": "Serveris nav sasniedzams.", - "pad.modals.initsocketfail.explanation": "Nevarēja izveidot savienojumu ar sinhronizācijas serveri.", - "pad.modals.slowcommit.explanation": "Serveris nereaģē.", - "pad.modals.deleted": "Dzēsts", - "pad.modals.disconnected": "Jūs esat atvienots.", - "pad.modals.disconnected.explanation": "Tika zaudēts savienojums ar serveri", - "pad.modals.disconnected.cause": "Iespējams, ka serveris nav pieejams. Lūgums paziņot pakalpojuma administratoram, ja tas turpina notikt.", - "pad.share": "Koplietot šo pad", - "pad.share.readonly": "Tikai lasāms", - "pad.share.link": "Saite", - "pad.chat": "Čats", - "timeslider.toolbar.authors": "Autori:", - "timeslider.toolbar.authorsList": "Nav autoru", - "timeslider.toolbar.exportlink.title": "Eksportēt", - "timeslider.month.january": "Janvāris", - "timeslider.month.february": "Februāris", - "timeslider.month.march": "Marts", - "timeslider.month.april": "Aprīlis", - "timeslider.month.may": "Maijs", - "timeslider.month.june": "Jūnijs", - "timeslider.month.july": "Jūlijs", - "timeslider.month.august": "Augusts", - "timeslider.month.september": "Septembris", - "timeslider.month.october": "Oktobris", - "timeslider.month.november": "Novembris", - "timeslider.month.december": "Decembris", - "pad.userlist.entername": "Ievadiet savu vārdu", - "pad.userlist.unnamed": "nenosaukts", - "pad.userlist.guest": "Viesis", - "pad.impexp.importbutton": "Importēt tūlīt", - "pad.impexp.importing": "Importē...", - "pad.impexp.uploadFailed": "Augšupielāde neizdevās, lūdzu, mēģiniet vēlreiz", - "pad.impexp.importfailed": "Imports neizdevās" -} diff --git a/sources/src/locales/map-bms.json b/sources/src/locales/map-bms.json deleted file mode 100644 index 8ebf70c..0000000 --- a/sources/src/locales/map-bms.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "@metadata": { - "authors": [ - "StefanusRA", - "Empu" - ] - }, - "index.newPad": "Pad Anyar", - "index.createOpenPad": "utawa gawe/bukak Pad nganggo jeneng:", - "pad.toolbar.bold.title": "Kandhel (Ctrl-B)", - "pad.toolbar.italic.title": "Miring (Ctrl-I)", - "pad.toolbar.underline.title": "Garisngisor (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Corettengaeh", - "pad.toolbar.ol.title": "Daftar nganggo nomer", - "pad.toolbar.ul.title": "Daftar ora nganggo nomer", - "pad.toolbar.indent.title": "Nggantung", - "pad.toolbar.unindent.title": "nggantung njaba", - "pad.toolbar.undo.title": "Batalna (Ctrl-Z)", - "pad.toolbar.redo.title": "Baleni (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Busek ''Authorship Colors''", - "pad.toolbar.import_export.title": "Impor/Ekspor sekang/maring format berkas sejen", - "pad.toolbar.timeslider.title": "Timeslider", - "pad.toolbar.savedRevision.title": "Simpen revisi", - "pad.toolbar.settings.title": "Pangaturan", - "pad.toolbar.embed.title": "Sebarna lan ''embed'' pad kiye", - "pad.toolbar.showusers.title": "Tidokna panganggo-panganggo nang pad kiye", - "pad.colorpicker.save": "Simpen", - "pad.colorpicker.cancel": "Batalna", - "pad.loading": "Muatna...", - "pad.passwordRequired": "Rika perlu tembung sandhi kanggo ngakses pad kiye", - "pad.permissionDenied": "Rika ora duwe idin kanggo ngakses pad kiye", - "pad.wrongPassword": "Tembung sandhine Rika salah", - "pad.settings.padSettings": "Pangaturan Pad", - "pad.settings.myView": "Delengané Inyong", - "pad.settings.stickychat": "Dopokan mesti nang layar", - "pad.settings.colorcheck": "Authorship colors", - "pad.settings.linenocheck": "Nomer baris", - "pad.settings.rtlcheck": "Waca isi sekang tengen maring kiwe?", - "pad.settings.fontType": "Tipe Font:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Global View", - "pad.settings.language": "Basa:", - "pad.importExport.import_export": "Impor/Ekspor", - "pad.importExport.import": "Unggahna berkas teks utawa dokumen", - "pad.importExport.importSuccessful": "Sukses!", - "pad.importExport.export": "Ekspor pad kiye dadi:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "t", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Rika mung teyeng impor sekang format plain text utawa HTML. Kanggo fitur impor sing lewih maju monggo masang abiword.", - "pad.modals.connected": "Nyambung.", - "pad.modals.reconnecting": "Mbaleli nyambung ming pad Rika...", - "pad.modals.forcereconnect": "Maksa nyambung maning", - "pad.modals.userdup": "Bukak nang jendela sejen", - "pad.modals.userdup.explanation": "Pad kiye kayane dibukak nang lewih sekang siji browser nang komputer kiye.", - "pad.modals.userdup.advice": "Nyambung maning nganggo jendela kiye baen.", - "pad.modals.unauth": "Not authorized", - "pad.modals.unauth.explanation": "Idin-e Rika wis diowahi dong lagi ndeleng kaca kiye. Jajal nyambung maning.", - "pad.modals.looping.explanation": "Pra ana masalah komunikasi karo server sinkronisasi.", - "pad.modals.looping.cause": "Ndeyan Rika gole nyambung nganggo firewall utawa proksi sing ora pas.", - "pad.modals.initsocketfail": "Server ora teyeng dihubungi.", - "pad.modals.initsocketfail.explanation": "Ora teyeng nyambung maring sinkronisasi server.", - "pad.modals.initsocketfail.cause": "Kiye ndeyan ana masalah karo perambanne Rika utawa sambungan internete Rika.", - "pad.modals.slowcommit.explanation": "Server ora respon.", - "pad.modals.slowcommit.cause": "Kiye ndeyan ana masalah karo sambungan jaringan.", - "pad.modals.deleted": "Dibusek.", - "pad.modals.deleted.explanation": "Pad kiye wis dibusek.", - "pad.modals.disconnected": "Rika wis dipedot sambungane.", - "pad.modals.disconnected.explanation": "Sambungan maring server wis ilang", - "pad.modals.disconnected.cause": "Servere ndeyan ora ana. Monggo tidokna inyong angger kahanan kiye terus kedaden maning.", - "pad.share": "Sebarna pad kiye", - "pad.share.readonly": "Waca thok", - "pad.share.link": "Pranala", - "pad.share.emebdcode": "Embed URL", - "pad.chat": "Dopokan", - "pad.chat.title": "Buka dopokan kanggo pad kiye.", - "pad.chat.loadmessages": "Muatna pesen lewih akeh", - "timeslider.pageTitle": "{{appTitle}} Timeslider", - "timeslider.toolbar.returnbutton": "Mbalik ming pad", - "timeslider.toolbar.authors": "Penulise:", - "timeslider.toolbar.authorsList": "Ora ana penulise", - "timeslider.toolbar.exportlink.title": "Ekspor", - "timeslider.exportCurrent": "Ekspor versi sekiye dadi:", - "timeslider.version": "Versi {{version}}", - "timeslider.saved": "Simpen {{day}} {{month}} {{year}}", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januari", - "timeslider.month.february": "Februari", - "timeslider.month.march": "Maret", - "timeslider.month.april": "April", - "timeslider.month.may": "Mei", - "timeslider.month.june": "Juni", - "timeslider.month.july": "Juli", - "timeslider.month.august": "Agustus", - "timeslider.month.september": "September", - "timeslider.month.october": "Oktober", - "timeslider.month.november": "November", - "timeslider.month.december": "Desember", - "timeslider.unnamedauthors": "{{num}} durung dijenengi {[plural(num) one: author, other: authors ]}", - "pad.savedrevs.marked": "Revisi kiye sekiye ditandani dadi revisi sing wis disimpen", - "pad.userlist.entername": "Lebokna jenenge Rika", - "pad.userlist.unnamed": "durungdijenengi", - "pad.userlist.guest": "Dayoh", - "pad.userlist.deny": "Ora olih", - "pad.userlist.approve": "Sarujuk", - "pad.editbar.clearcolors": "Busek ''authorship colors'' nang kabeh dokumen?", - "pad.impexp.importbutton": "Impor Sekiye", - "pad.impexp.importing": "Lagi ngimpor...", - "pad.impexp.confirmimport": "Ngimpor berkas bakal dadi nindih teks sekiye nang pad. Apa Rika wis mantep arep mroses kiye?", - "pad.impexp.convertFailed": "Inyong ora teyeng ngimpor berkas kiye. Jajal nganggo format dokumen sejen utawa salin-tempel manual.", - "pad.impexp.uploadFailed": "Gole ngunggah gagal, monggo dijajal maning", - "pad.impexp.importfailed": "Gole ngimpor gagal", - "pad.impexp.copypaste": "Monggo salin-tempel", - "pad.impexp.exportdisabled": "Ngekspor maring format {{type}} ora olih. Monggo takon maring administrator sisteme Rika kanggo detile." -} diff --git a/sources/src/locales/mg.json b/sources/src/locales/mg.json deleted file mode 100644 index 5279bdf..0000000 --- a/sources/src/locales/mg.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Jagwar" - ] - }, - "index.newPad": "Pad vaovao", - "index.createOpenPad": "na hamorona/hanokatra Pad manana anarana:", - "pad.toolbar.bold.title": "Matevina (Ctrl-B)", - "pad.toolbar.italic.title": "Mandry (Ctrl-L)", - "pad.toolbar.underline.title": "Tsipihana (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Voatsipika", - "pad.toolbar.ol.title": "Lisitra nalamina", - "pad.toolbar.ul.title": "Lisitra tsy voalamina", - "pad.toolbar.undo.title": "Averina (Ctrl-Z)", - "pad.toolbar.redo.title": "Averina (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Hanala ny loko famantarana mpanorona", - "pad.toolbar.import_export.title": "Hampiditra/Hamoaka amin'ny karazan-drakitra hafa", - "pad.toolbar.settings.title": "Fanafahana", - "pad.colorpicker.save": "Tehirizina", - "pad.colorpicker.cancel": "Aoka ihany", - "pad.loading": "Am-pakàna…", - "pad.permissionDenied": "Tsy manana lalalana mijery ity pad ity ianao", - "pad.wrongPassword": "Diso ny tenimiafinao", - "pad.settings.padSettings": "Safidin'ny ped", - "pad.settings.myView": "Ny jeriko", - "pad.settings.linenocheck": "Laharan'ny andalana", - "pad.settings.rtlcheck": "Hamaky ny votoatiny miankavia?", - "pad.settings.fontType": "Karazan-tarehintsoratra:", - "pad.settings.globalView": "Jery ankapobe", - "pad.settings.language": "Fiteny:", - "pad.importExport.import_export": "Hampiditra/Hamoaka", - "pad.importExport.import": "Hampiditra raki-tsoratra na rakitra", - "pad.importExport.importSuccessful": "Vita soa aman-tsara!", - "pad.importExport.export": "Hamoaka ny pad ankehitriny ho:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Soratra tsotra", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.modals.connected": "Tafaray.", - "pad.modals.forcereconnect": "Hanery ny famerenam-pifandraisana", - "pad.modals.reconnecttimer": "Manandrana mamerim-pifandraisana", - "pad.modals.cancel": "Aoka ihany", - "pad.modals.userdup": "Nosokafana tanaty varavarankely hafa", - "pad.modals.unauth": "Tsy nahazo alalana", - "pad.modals.initsocketfail": "Tsy hita ny lohamilina.", - "pad.modals.slowcommit.explanation": "Tsy mamaly ny lohamilina", - "pad.modals.slowcommit.cause": "Izany zavatra izany dia mety nohon'ny fifandraisana ratsy amin'ny lohamilina.", - "pad.modals.badChangeset.explanation": "Voasokajin'ny lohamilim-pirindrana ho tsy azo atao ny fiovana nataonao.", - "pad.modals.badChangeset.cause": "Izany zavatra izany dia mety nohon'ny configuration lohamilina diso na hetsika tsy nampoizina hafa. Mifandraisa amin'ny mpandrindran'ny serivisy, raha heverinao fa hadisoana io. Mifandraisa indray ahafahanao manohy ny fanovana.", - "pad.modals.deleted": "Voafafa.", - "pad.modals.deleted.explanation": "Nesorina ity pad ity.", - "pad.modals.disconnected": "Tapaka ny fifandraisanao.", - "pad.modals.disconnected.explanation": "Very ny fifandraisana tamin'ny lohamilina", - "pad.share": "Hizara ity pad ity", - "pad.share.readonly": "Vakiana ihany", - "pad.share.link": "Rohy", - "pad.share.emebdcode": "Hampiditra URL", - "pad.chat": "Resaka mivantana", - "pad.chat.title": "Hampiditra ny karajia ho an'ity pad ity.", - "pad.chat.loadmessages": "Haka hafatra be kokoa", - "timeslider.pageTitle": "Tantara dinamikan'i {{appTitle}}", - "timeslider.toolbar.returnbutton": "Hiverina amin'ny pad", - "timeslider.toolbar.authors": "Mpamorona:", - "timeslider.toolbar.authorsList": "Tsy misy mpamorona", - "timeslider.toolbar.exportlink.title": "Avoaka", - "timeslider.exportCurrent": "Hamoaka ny versiona ankehitriny ho:", - "timeslider.version": "Versiona {{version}}", - "timeslider.saved": "Notahirizina ny {{day}} {{month}} {{year}}", - "timeslider.month.january": "Janoary", - "timeslider.month.february": "Febroary", - "timeslider.month.march": "Martsa", - "timeslider.month.april": "Aprily", - "timeslider.month.may": "Mey", - "timeslider.month.june": "Jiona", - "timeslider.month.july": "Jolay", - "timeslider.month.august": "Aogositra", - "timeslider.month.september": "Septambra", - "timeslider.month.october": "Oktobra", - "timeslider.month.november": "Novambra", - "timeslider.month.december": "Desambra", - "pad.userlist.unnamed": "tsy manana naarana", - "pad.userlist.guest": "Nasaina", - "pad.userlist.deny": "Lavina", - "pad.userlist.approve": "Ekena", - "pad.impexp.importbutton": "Ampidirina izao", - "pad.impexp.importing": "Mampiditra..." -} diff --git a/sources/src/locales/mk.json b/sources/src/locales/mk.json deleted file mode 100644 index 2ca0417..0000000 --- a/sources/src/locales/mk.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Bjankuloski06", - "Brest" - ] - }, - "index.newPad": "Нова тетратка", - "index.createOpenPad": "или направете/отворете тетратка со името:", - "pad.toolbar.bold.title": "Задебелено (Ctrl-B)", - "pad.toolbar.italic.title": "Косо (Ctrl-I)", - "pad.toolbar.underline.title": "Подвлечено (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Прецртано (Ctrl+5)", - "pad.toolbar.ol.title": "Подреден список (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Неподреден список (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Отстап (TAB)", - "pad.toolbar.unindent.title": "Истап (Shift+TAB)", - "pad.toolbar.undo.title": "Врати (Ctrl-Z)", - "pad.toolbar.redo.title": "Повтори (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Тргни ги авторските бои (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Увоз/Извоз од/во разни податотечни формати", - "pad.toolbar.timeslider.title": "Историски преглед", - "pad.toolbar.savedRevision.title": "Зачувај преработка", - "pad.toolbar.settings.title": "Поставки", - "pad.toolbar.embed.title": "Споделете и вметнете ја тетраткава", - "pad.toolbar.showusers.title": "Прикаж. корисниците на тетраткава", - "pad.colorpicker.save": "Зачувај", - "pad.colorpicker.cancel": "Откажи", - "pad.loading": "Вчитувам...", - "pad.noCookie": "Не можев да го најдам колачето. Овозможете колачиња во вашиот прелистувач!", - "pad.passwordRequired": "Потребна е лозинка за пристап", - "pad.permissionDenied": "За овде не е потребна дозвола за пристап", - "pad.wrongPassword": "Погрешна лозинка", - "pad.settings.padSettings": "Поставки на тетратката", - "pad.settings.myView": "Мој поглед", - "pad.settings.stickychat": "Разговорите секогаш на екранот", - "pad.settings.chatandusers": "Прикажи разговор и корисници", - "pad.settings.colorcheck": "Авторски бои", - "pad.settings.linenocheck": "Броеви на редовите", - "pad.settings.rtlcheck": "Содржините да се читаат од десно на лево?", - "pad.settings.fontType": "Тип на фонт:", - "pad.settings.fontType.normal": "Нормален", - "pad.settings.fontType.monospaced": "Непропорционален", - "pad.settings.globalView": "Општ поглед", - "pad.settings.language": "Јазик:", - "pad.importExport.import_export": "Увоз/Извоз", - "pad.importExport.import": "Подигање на било каква текстуална податотека или документ", - "pad.importExport.importSuccessful": "Успешно!", - "pad.importExport.export": "Извези ја тековната тетратка како", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Прост текст", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Можете да увезувате само од прост текст и HTML-формат. Понапредни можности за увоз ќе добиете ако воспоставите AbiWord.", - "pad.modals.connected": "Поврзано.", - "pad.modals.reconnecting": "Ве преповрзувам со тетратката...", - "pad.modals.forcereconnect": "Наметни преповрзување", - "pad.modals.reconnecttimer": "Се преповрзувам за", - "pad.modals.cancel": "Откажи", - "pad.modals.userdup": "Отворено во друг прозорец", - "pad.modals.userdup.explanation": "Оваа тетратка е отворена на повеќе од еден прозорец (во прелистувач) на сметачот.", - "pad.modals.userdup.advice": "Преповрзете се за да го користите овој прозорец.", - "pad.modals.unauth": "Неовластено", - "pad.modals.unauth.explanation": "Вашите дозволи се имаат изменето додека ја гледавте страницава. Обидете се да се преповрзете.", - "pad.modals.looping.explanation": "Се јавија проблеми со врската со усогласителниот опслужувач.", - "pad.modals.looping.cause": "Можеби сте поврзани преку нескладен огнен ѕид или застапник.", - "pad.modals.initsocketfail": "Опслужувачот е недостапен.", - "pad.modals.initsocketfail.explanation": "Не можев да се поврзам со усогласителниот опслужувач.", - "pad.modals.initsocketfail.cause": "Ова веројатно се должи на проблем со вашиот прелистувач или семрежната врска.", - "pad.modals.slowcommit.explanation": "Опслужувачот не се одѕива.", - "pad.modals.slowcommit.cause": "Ова може да се должи на проблеми со мрежното поврзување.", - "pad.modals.badChangeset.explanation": "Опслужувачот за усогласување го смета уредувањето што го направивте за недопуштено.", - "pad.modals.badChangeset.cause": "Ова може да се должи на погрешна поставеност на опслужувачот или некое друго неочекувано поведение. Обратете се кај администраторот доколку сметате дека ова е грешка. Обидете се да се превклучите за да продолжите со уредување.", - "pad.modals.corruptPad.explanation": "Тетратката што сакате да ја отворите е расипана.", - "pad.modals.corruptPad.cause": "Ова може да се должи на погрешна поставеност на опслужувачот или некое друго неочекувано поведение. Обратете се кај администраторот.", - "pad.modals.deleted": "Избришано.", - "pad.modals.deleted.explanation": "Оваа тетратка е отстранета.", - "pad.modals.disconnected": "Врската е прекината.", - "pad.modals.disconnected.explanation": "Врската со опслужувачот е прекината", - "pad.modals.disconnected.cause": "Опслужувачот може да е недостапен. Известете го администраторот ако ова продолжи да ви се случува.", - "pad.share": "Сподели ја тетраткава", - "pad.share.readonly": "Само читање", - "pad.share.link": "Врска", - "pad.share.emebdcode": "Вметни URL", - "pad.chat": "Разговор", - "pad.chat.title": "Отвори го разговорот за оваа тетратка.", - "pad.chat.loadmessages": "Вчитај уште пораки", - "timeslider.pageTitle": "{{appTitle}} Историски преглед", - "timeslider.toolbar.returnbutton": "Назад на тетратката", - "timeslider.toolbar.authors": "Автори:", - "timeslider.toolbar.authorsList": "Нема автори", - "timeslider.toolbar.exportlink.title": "Извоз", - "timeslider.exportCurrent": "Извези ја тековната верзија како:", - "timeslider.version": "Верзија {{version}}", - "timeslider.saved": "Зачувано на {{day}} {{month}} {{year}} г.", - "timeslider.playPause": "Пушти/запри содржина на тетратката", - "timeslider.backRevision": "Назад за една преработка на тетратката", - "timeslider.forwardRevision": "Напред за една преработка на тетратката", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "јануари", - "timeslider.month.february": "февруари", - "timeslider.month.march": "март", - "timeslider.month.april": "април", - "timeslider.month.may": "мај", - "timeslider.month.june": "јуни", - "timeslider.month.july": "јули", - "timeslider.month.august": "август", - "timeslider.month.september": "септември", - "timeslider.month.october": "октомври", - "timeslider.month.november": "ноември", - "timeslider.month.december": "декември", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: неименуван автор, other: неименувани автори ]}", - "pad.savedrevs.marked": "Оваа преработка сега е означена како зачувана", - "pad.savedrevs.timeslider": "Можете да ги погледате зачуваните преработки посетувајќи го времеследниот лизгач", - "pad.userlist.entername": "Внесете го вашето име", - "pad.userlist.unnamed": "без име", - "pad.userlist.guest": "Гостин", - "pad.userlist.deny": "Одбиј", - "pad.userlist.approve": "Одобри", - "pad.editbar.clearcolors": "Да ги отстранам авторските бои од целиот документ?", - "pad.impexp.importbutton": "Увези сега", - "pad.impexp.importing": "Увезувам...", - "pad.impexp.confirmimport": "Увезувајќи ја податотеката ќе го замените целиот досегашен текст во тетратката. Дали сте сигурни дека сакате да продолжите?", - "pad.impexp.convertFailed": "Не можев да ја увезам податотеката. Послужете се со поинаков формат или прекопирајте го текстот рачно.", - "pad.impexp.padHasData": "Не можевме да ја увеземе оваа податотека бидејќи оваа тетратка веќе има промени. Увезете ја во нова тетратка.", - "pad.impexp.uploadFailed": "Подигањето не успеа. Обидете се повторно.", - "pad.impexp.importfailed": "Увозот не успеа", - "pad.impexp.copypaste": "Прекопирајте", - "pad.impexp.exportdisabled": "Извозот во форматот {{type}} е оневозможен. Ако сакате да дознаете повеќе за ова, обратете се кај системскиот администратор." -} diff --git a/sources/src/locales/ml.json b/sources/src/locales/ml.json deleted file mode 100644 index 371e1ce..0000000 --- a/sources/src/locales/ml.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Akhilan", - "Clockery", - "Hrishikesh.kb", - "Praveenp", - "Santhosh.thottingal", - "Nesi" - ] - }, - "index.newPad": "പുതിയ പാഡ്", - "index.createOpenPad": "അല്ലെങ്കിൽ പേരുപയോഗിച്ച് പാഡ് സൃഷ്ടിക്കുക/തുറക്കുക:", - "pad.toolbar.bold.title": "കടുപ്പത്തിലെഴുതുക (Ctrl-B)", - "pad.toolbar.italic.title": "ചെരിച്ചെഴുതുക (Ctrl-I)", - "pad.toolbar.underline.title": "അടിവരയിടുക (Ctrl-U)", - "pad.toolbar.strikethrough.title": "വെട്ടുക (Ctrl+5)", - "pad.toolbar.ol.title": "ക്രമത്തിലുള്ള പട്ടിക (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "ക്രമരഹിത പട്ടിക (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "വലത്തേക്ക് തള്ളുക (ടാബ്)", - "pad.toolbar.unindent.title": "ഇടത്തേക്ക് തള്ളുക (ഷിഫ്റ്റ്+ടാബ്)", - "pad.toolbar.undo.title": "തിരസ്കരിക്കുക (Ctrl-Z)", - "pad.toolbar.redo.title": "വീണ്ടും ചെയ്യുക (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "രചയിതാക്കൾക്കുള്ള നിറം കളയുക (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "വ്യത്യസ്ത ഫയൽ തരങ്ങളിലേക്ക്/തരങ്ങളിൽ നിന്ന് ഇറക്കുമതി/കയറ്റുമതി ചെയ്യുക", - "pad.toolbar.timeslider.title": "സമയരേഖ", - "pad.toolbar.savedRevision.title": "നാൾപ്പതിപ്പ് സേവ് ചെയ്യുക", - "pad.toolbar.settings.title": "സജ്ജീകരണങ്ങൾ", - "pad.toolbar.embed.title": "ഈ പാഡ് പങ്ക് വെയ്ക്കുക, എംബെഡ് ചെയ്യുക", - "pad.toolbar.showusers.title": "ഈ പാഡിലുള്ള ഉപയോക്താക്കളെ പ്രദർശിപ്പിക്കുക", - "pad.colorpicker.save": "സേവ് ചെയ്യുക", - "pad.colorpicker.cancel": "റദ്ദാക്കുക", - "pad.loading": "ശേഖരിക്കുന്നു...", - "pad.noCookie": "കുക്കി കണ്ടെത്താനായില്ല. ദയവായി താങ്കളുടെ ബ്രൗസറിൽ കുക്കികൾ അനുവദിക്കുക!", - "pad.passwordRequired": "ഈ പാഡ് ഉപയോഗിക്കുന്നതിനായി ഒരു രഹസ്യവാക്ക് നൽകേണ്ടതാണ്", - "pad.permissionDenied": "ഈ പാഡ് കാണുവാൻ താങ്കൾക്ക് അനുമതിയില്ല", - "pad.wrongPassword": "താങ്കൾ നല്കിയ രഹസ്യവാക്ക് തെറ്റായിരുന്നു", - "pad.settings.padSettings": "പാഡ് സജ്ജീകരണങ്ങൾ", - "pad.settings.myView": "എന്റെ കാഴ്ച", - "pad.settings.stickychat": "തത്സമയസംവാദം എപ്പോഴും സ്ക്രീനിൽ കാണിക്കുക", - "pad.settings.chatandusers": "ഉപയോക്താക്കളേയും ചാറ്റും കാണിക്കുക", - "pad.settings.colorcheck": "എഴുത്തുകാർക്കുള്ള നിറങ്ങൾ", - "pad.settings.linenocheck": "വരികളുടെ ക്രമസംഖ്യ", - "pad.settings.rtlcheck": "ഉള്ളടക്കം വലത്തുനിന്ന് ഇടത്തോട്ടാണോ വായിക്കേണ്ടത്?", - "pad.settings.fontType": "ഫോണ്ട് തരം:", - "pad.settings.fontType.normal": "സാധാരണം", - "pad.settings.fontType.monospaced": "മോണോസ്പേസ്", - "pad.settings.globalView": "മൊത്തക്കാഴ്ച", - "pad.settings.language": "ഭാഷ:", - "pad.importExport.import_export": "ഇറക്കുമതി/കയറ്റുമതി ചെയ്യുക", - "pad.importExport.import": "എന്തെങ്കിലും എഴുത്തു പ്രമാണമോ രേഖയോ അപ്‌ലോഡ് ചെയ്യുക", - "pad.importExport.importSuccessful": "വിജയകരം!", - "pad.importExport.export": "ഇപ്പോഴത്തെ പാഡ് ഇങ്ങനെ കയറ്റുമതി ചെയ്യുക:", - "pad.importExport.exportetherpad": "ഈതർപാഡ്", - "pad.importExport.exporthtml": "എച്ച്.റ്റി.എം.എൽ.", - "pad.importExport.exportplain": "വെറും എഴുത്ത്", - "pad.importExport.exportword": "മൈക്രോസോഫ്റ്റ് വേഡ്", - "pad.importExport.exportpdf": "പി.ഡി.എഫ്.", - "pad.importExport.exportopen": "ഒ.ഡി.എഫ്. (ഓപ്പൺ ഡോക്യുമെന്റ് ഫോർമാറ്റ്)", - "pad.importExport.abiword.innerHTML": "പ്ലെയിൻ ടെക്സ്റ്റോ എച്ച്.റ്റി.എം.എൽ. തരമോ മാത്രമേ താങ്കൾക്ക് ഇറക്കുമതി ചെയ്യാനാവൂ. കൂടുതൽ വിപുലീകൃത ഇറക്കുമതി സൗകര്യങ്ങൾക്കായി ദയവായി അബിവേഡ് ഇൻസ്റ്റോൾ ചെയ്യുക.", - "pad.modals.connected": "ബന്ധിപ്പിച്ചിരിക്കുന്നു.", - "pad.modals.reconnecting": "താങ്കളുടെ പാഡിലേയ്ക്ക് വീണ്ടും ബന്ധിപ്പിക്കുന്നു...", - "pad.modals.forcereconnect": "എന്തായാലും ബന്ധിപ്പിക്കുക", - "pad.modals.userdup": "മറ്റൊരു ജാലകത്തിൽ തുറന്നിരിക്കുന്നു", - "pad.modals.userdup.explanation": "ഈ കമ്പ്യൂട്ടറിൽ ഈ പാഡ് ഒന്നിലധികം ബ്രൗസർ ജാലകങ്ങളിൽ തുറന്നതായി കാണുന്നു.", - "pad.modals.userdup.advice": "ഈ ജാലകം തന്നെ ഉപയോഗിക്കാനായി ബന്ധിപ്പിക്കുക", - "pad.modals.unauth": "അനുവാദമില്ല", - "pad.modals.unauth.explanation": "ഈ താൾ കണ്ടുകൊണ്ടിരിക്കെ താങ്കൾക്കുള്ള അനുമതികളിൽ മാറ്റമുണ്ടായി. വീണ്ടും ബന്ധപ്പെടാൻ ശ്രമിക്കുക.", - "pad.modals.looping.explanation": "സിംക്രണൈസേഷൻ സെർവറുമായുള്ള ആശയവിനിമയത്തിൽ പ്രശ്നങ്ങളുണ്ട്.", - "pad.modals.looping.cause": "ഒരുപക്ഷേ പൊരുത്തപ്പെടാത്ത ഫയർവാളിലൂടെയോ പ്രോക്സിയിലൂടെയോ ആകാം താങ്കൾ ബന്ധിച്ചിരുന്നത്.", - "pad.modals.initsocketfail": "സെർവറിലെത്താൻ പറ്റുന്നില്ല.", - "pad.modals.initsocketfail.explanation": "സിംക്രണൈസേഷൻ സെർവറുമായി ബന്ധപ്പെടാൻ കഴിഞ്ഞില്ല.", - "pad.modals.initsocketfail.cause": "താങ്കളുടെ ഇന്റർനെറ്റ് കണക്ഷന്റെയോ ബ്രൗസറിന്റെയോ പ്രശ്നമാകാം", - "pad.modals.slowcommit.explanation": "സെർവർ പ്രതികരിക്കുന്നില്ല.", - "pad.modals.slowcommit.cause": "നെറ്റ്‌വർക്ക് പ്രശ്നം കാരണമാകാം.", - "pad.modals.badChangeset.explanation": "താങ്കൾ ചെയ്ത ഒരു തിരുത്ത് സമീകരണ സെർവർ നയവിരുദ്ധമെന്ന് പെടുത്തിയിരിക്കുന്നു.", - "pad.modals.badChangeset.cause": "ഇത്, തെറ്റായ സെർവർ ക്രമീകരണം മൂലമോ മറ്റെന്തെങ്കിലും അപ്രതീക്ഷിത കാരണം കൊണ്ടോ ഉണ്ടായതായേക്കാം. ഇത് തെറ്റാണെന്ന് താങ്കൾക്ക് തോന്നുന്നുണ്ടെങ്കിൽ സേവന കാര്യനിർവാഹകയെ(നെ) താങ്കൾക്ക് സമീപിക്കാവുന്നതാണ്. തിരുത്തൽ തുടരാൻ വീണ്ടും ബദ്ധപ്പെടുക.", - "pad.modals.corruptPad.explanation": "താങ്കൾ എടുക്കാൻ ശ്രമിക്കുന്ന പാഡ് കേടാണ്.", - "pad.modals.corruptPad.cause": "ഇത്, തെറ്റായ സെർവർ ക്രമീകരണം മൂലമോ മറ്റെന്തെങ്കിലും അപ്രതീക്ഷിത കാരണം കൊണ്ടോ ഉണ്ടായതായേക്കാം. ദയവായി സേവന കാര്യനിർവാഹകയെ(നെ) സമീപിക്കുക.", - "pad.modals.deleted": "മായ്ച്ചു", - "pad.modals.deleted.explanation": "ഈ പാഡ് നീക്കം ചെയ്തു.", - "pad.modals.disconnected": "താങ്കൾ വേർപെട്ടിരിക്കുന്നു.", - "pad.modals.disconnected.explanation": "സെർവറുമായുള്ള ബന്ധം നഷ്ടപ്പെട്ടു", - "pad.modals.disconnected.cause": "സെർവർ ലഭ്യമല്ലായിരിക്കാം. ഇത് തുടർച്ചയായി സംഭവിക്കുന്നുണ്ടെങ്കിൽ ദയവായി സേവന കാര്യനിർവാഹകയെ(നെ) അറിയിക്കുക.", - "pad.share": "ഈ പാഡ് പങ്കിടുക", - "pad.share.readonly": "വായിക്കൽ മാത്രം", - "pad.share.link": "കണ്ണി", - "pad.share.emebdcode": "എംബെഡ് യു.ആർ.എൽ.", - "pad.chat": "തത്സമയസംവാദം", - "pad.chat.title": "ഈ പാഡിന്റെ തത്സമയസംവാദം തുറക്കുക.", - "pad.chat.loadmessages": "കൂടുതൽ സന്ദേശങ്ങൾ എടുക്കുക", - "timeslider.pageTitle": "{{appTitle}} സമയരേഖ", - "timeslider.toolbar.returnbutton": "പാഡിലേക്ക് മടങ്ങുക", - "timeslider.toolbar.authors": "രചയിതാക്കൾ:", - "timeslider.toolbar.authorsList": "ആരും എഴുതിയിട്ടില്ല", - "timeslider.toolbar.exportlink.title": "കയറ്റുമതി", - "timeslider.exportCurrent": "ഈ പതിപ്പ് ഇങ്ങനെ എടുക്കുക:", - "timeslider.version": "പതിപ്പ് {{version}}", - "timeslider.saved": "സേവ് ചെയ്തത് {{month}} {{day}}, {{year}}", - "timeslider.backRevision": "ഈ പാഡിലെ ഒരു നാൾപ്പതിപ്പിലേക്ക് മടങ്ങുക", - "timeslider.forwardRevision": "ഈ പാഡിലെ അടുത്ത മാറ്റത്തിലേക്ക് പോവുക", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "ജനുവരി", - "timeslider.month.february": "ഫെബ്രുവരി", - "timeslider.month.march": "മാർച്ച്", - "timeslider.month.april": "ഏപ്രിൽ", - "timeslider.month.may": "മേയ്", - "timeslider.month.june": "ജൂൺ", - "timeslider.month.july": "ജൂലൈ", - "timeslider.month.august": "ഓഗസ്റ്റ്", - "timeslider.month.september": "സെപ്റ്റംബർ", - "timeslider.month.october": "ഒക്ടോബർ", - "timeslider.month.november": "നവംബർ", - "timeslider.month.december": "ഡിസംബർ", - "timeslider.unnamedauthors": "{{num}} പേരില്ലാത്ത {[plural(num) one: രചയിതാവ്, other: രചയിതാക്കൾ }}", - "pad.savedrevs.marked": "ഈ നാൾപ്പതിപ്പ് സേവ് ചെയ്തിട്ടുള്ള നാൾപ്പതിപ്പായി അടയാളപ്പെടുത്തിയിരിക്കുന്നു", - "pad.savedrevs.timeslider": "സേവ് ചെയ്ത മറ്റു നാൾപ്പതിപ്പുകൾ സമയസൂചികയിൽ കാണാവുന്നതാണ്", - "pad.userlist.entername": "താങ്കളുടെ പേര് നൽകുക", - "pad.userlist.unnamed": "പേരില്ലാത്തവ", - "pad.userlist.guest": "അതിഥി", - "pad.userlist.deny": "നിരസിക്കുക", - "pad.userlist.approve": "അംഗീകരിക്കുക", - "pad.editbar.clearcolors": "ഡോക്യുമെന്റിൽ രചയിതാക്കളെ സൂചിപ്പിക്കാനായി നൽകിയിട്ടുള്ള നിറങ്ങൾ ഒഴിവാക്കട്ടെ?", - "pad.impexp.importbutton": "ഇറക്കുമതി ചെയ്യുക", - "pad.impexp.importing": "ഇറക്കുമതി ചെയ്യുന്നു...", - "pad.impexp.confirmimport": "ഒരു പ്രമാണം ഇറക്കുമതി ചെയ്യുന്നത് നിലവിലുള്ള എഴുത്തുകൾ നഷ്ടപ്പെടാനിടയാക്കും, തുടരണമെന്ന് ഉറപ്പാണോ?", - "pad.impexp.convertFailed": "ഈ പ്രമാണം ഇറക്കുമതി ചെയ്യാൻ സാധിച്ചില്ല. ദയവായി മറ്റൊരു ഡോക്യുമെന്റ് ഫോർമാറ്റ് ഉപയോഗിക്കുകയോ, സ്വന്തമായി പകർത്തി ചേർക്കുകയോ ചെയ്യുക", - "pad.impexp.padHasData": "ഈ പാഡിൽ ഇതിനകം തന്നെ മാറ്റങ്ങൾ നടന്നിട്ടുള്ളതിനാൽ, നൽകിയ പ്രമാണം ഇതിലേക്ക് ചേർക്കാൻ സാധിച്ചില്ല. ദയവായി പുതിയ ഒരു പാഡിലേക്ക് ചേർക്കുക", - "pad.impexp.uploadFailed": "അപ്‌‌ലോഡ് പരാജയപ്പെട്ടു. ദയവായി വീണ്ടും ശ്രമിക്കുക", - "pad.impexp.importfailed": "ഇറക്കുമതി പരാജയപ്പെട്ടു", - "pad.impexp.copypaste": "ദയവായി പകർത്തി ചേർക്കുക", - "pad.impexp.exportdisabled": "{{type}} ഫോർമാറ്റിൽ കയറ്റുമതി ചെയ്യുന്നത് തടഞ്ഞിരിക്കുന്നു. കൂടുതൽ വിവരങ്ങൾക്ക് താങ്കളുടെ സിസ്റ്റം അഡ്മിനിസ്ട്രേറ്ററുമായി ബന്ധപ്പെടുക." -} diff --git a/sources/src/locales/mn.json b/sources/src/locales/mn.json deleted file mode 100644 index 6242d59..0000000 --- a/sources/src/locales/mn.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "@metadata": { - "authors": [ - "MongolWiki", - "Wisdom", - "Munkhzaya.E" - ] - }, - "pad.toolbar.bold.title": "Болд тескт (Ctrl-B)", - "pad.toolbar.italic.title": "Налуу тескт (Ctrl-I)", - "pad.toolbar.underline.title": "Доогуур зураас (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Дундуураа зураастай", - "pad.toolbar.ol.title": "Эрэмбэлэгдсэн жагсаалт", - "pad.toolbar.ul.title": "Эрэмбэлээгүй жагсаалт", - "pad.toolbar.indent.title": "Догол мөр (TAB)", - "pad.toolbar.unindent.title": "Догол мөрийг буцаах (Shift+TAB)", - "pad.toolbar.undo.title": "Буцаах (Ctrl-Z)", - "pad.toolbar.redo.title": "Давтах (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Зохиогчийн өнгийг буцаах (Ctrl+Shift+C)", - "pad.toolbar.timeslider.title": "Засварласан түүх", - "pad.toolbar.savedRevision.title": "Хувилбарыг хадгалах", - "pad.toolbar.settings.title": "Тохиргоо", - "pad.colorpicker.save": "Хадгалах", - "pad.colorpicker.cancel": "Цуцлах", - "pad.loading": "Уншиж байна...", - "pad.wrongPassword": "Таны оруулсан нууц үг буруу байна", - "pad.settings.padSettings": "Падын тохиргоо", - "pad.settings.myView": "Өөрийн харагдац", - "pad.settings.linenocheck": "Мөрийн дугаар", - "pad.settings.fontType": "Фонтын төрөл:", - "pad.settings.fontType.normal": "Ердийн", - "pad.settings.fontType.monospaced": "Зай ихтэй фонт", - "pad.settings.language": "Хэл:", - "pad.importExport.import_export": "Импорт/Экспорт", - "pad.importExport.import": "Бичвэр, текст файл оруулах", - "pad.importExport.importSuccessful": "Амжилттай!", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Цулгаа бичвэр", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF файл", - "pad.importExport.exportopen": "ODF файл", - "pad.modals.connected": "Холбогдсон.", - "pad.modals.unauth": "Үл зөвшөөрөгдсөн", - "pad.modals.initsocketfail": "Сервер холбогдох боломжгүй.", - "pad.modals.slowcommit.explanation": "Сервер хариу өгөхгүй байна.", - "pad.modals.deleted": "Устгагдсан", - "pad.modals.deleted.explanation": "Энэ паб устсан байна.", - "pad.modals.disconnected": "Таны холболт салсан байна.", - "pad.modals.disconnected.explanation": "Серверын холболт салсан байна", - "pad.share": "Энэ падыг тараах", - "pad.share.readonly": "Зөвхөн унших", - "pad.share.link": "Холбоос", - "pad.share.emebdcode": "URL хавсаргах", - "pad.chat": "Чат", - "pad.chat.loadmessages": "Нэмэж мессеж оруулах", - "timeslider.toolbar.returnbutton": "Падруу буцах", - "timeslider.toolbar.authors": "Зохиогч:", - "timeslider.toolbar.authorsList": "Зохиогчгүй", - "timeslider.toolbar.exportlink.title": "Экспорт", - "timeslider.exportCurrent": "Энэ хувилбарыг экспортлохдоо:", - "timeslider.version": "Хувилбар {{version}}", - "timeslider.saved": "{{year}}-ы {{month}}-н {{day}}-нд да;галсан.", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Нэгдүгээр сар", - "timeslider.month.february": "Хоёрдугаар сар", - "timeslider.month.march": "Гуравдугаар сар", - "timeslider.month.april": "Дөрөвдүгээр сар", - "timeslider.month.may": "Тавдугаар сар", - "timeslider.month.june": "Зургаадугаар сар", - "timeslider.month.july": "Долоодугаар сар", - "timeslider.month.august": "Наймдугаар сар", - "timeslider.month.september": "Есдүгээр сар", - "timeslider.month.october": "Аравдугаар сар", - "timeslider.month.november": "Арваннэгдүгээр сар", - "timeslider.month.december": "Арванхоёрдугаар сар", - "pad.savedrevs.marked": "Энэ хувилбар хадгалагдаагүй байна", - "pad.userlist.entername": "Нэрээ бичнэ үү", - "pad.userlist.unnamed": "нэргүй", - "pad.userlist.guest": "Зочин", - "pad.userlist.deny": "Үл зөвшөөр", - "pad.userlist.approve": "Зөвшөөр", - "pad.impexp.importbutton": "Одоо импорт хий", - "pad.impexp.importing": "Импортлож байна...", - "pad.impexp.importfailed": "Импортлоход алдаа", - "pad.impexp.copypaste": "Хуулаад тавина уу" -} diff --git a/sources/src/locales/mr.json b/sources/src/locales/mr.json deleted file mode 100644 index 536b578..0000000 --- a/sources/src/locales/mr.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Ganeshgiram", - "V.narsikar", - "Ydyashad" - ] - }, - "index.newPad": "नव पान", - "pad.toolbar.bold.title": "ठळक (Ctrl-B)", - "pad.toolbar.italic.title": "तिरपी मुद्राक्षरे (Ctrl-I)", - "pad.toolbar.underline.title": "अधोरेखन (Ctrl-U)", - "pad.toolbar.strikethrough.title": "अक्षरांवर काट", - "pad.toolbar.savedRevision.title": "आवृत्ती जतन करा", - "pad.toolbar.settings.title": "संरचना", - "pad.colorpicker.save": "जतन करा", - "pad.colorpicker.cancel": "रद्द करा", - "pad.loading": "प्रभारण करीत आहे", - "pad.wrongPassword": "आपला परवलीचा शब्द चूक होता", - "pad.settings.myView": "माझे दृश्य", - "pad.settings.linenocheck": "रेषांचे क्रमांक", - "pad.settings.language": "भाषा", - "pad.importExport.import_export": "आयात/निर्यात", - "pad.importExport.importSuccessful": "यशस्वी!", - "pad.importExport.exportplain": "साधा मजकूर", - "pad.importExport.exportword": "मायक्रोसॉफ्ट वर्ड", - "pad.importExport.exportpdf": "पीडीएफ", - "pad.importExport.exportopen": "ओडीएफ(ओपन डॉक्यूमेंट फॉरमॅट)", - "pad.modals.connected": "अनुबंधित", - "pad.modals.initsocketfail": "विदागारास पोच नाही.", - "pad.modals.deleted": "वगळले.", - "pad.modals.disconnected.cause": "बहुतेक सरवर उपलब्ध होणार नाही। अस वारंवार झाल्यास कृपया आम्हाला कळवा।", - "pad.share.link": "दुवा", - "pad.chat": "गप्पा", - "timeslider.toolbar.authorsList": "लेखक नाही", - "timeslider.month.january": "जानेवारी", - "timeslider.month.february": "फेब्रुवारी", - "timeslider.month.march": "मार्च", - "timeslider.month.april": "एप्रिल", - "timeslider.month.may": "मे", - "timeslider.month.june": "जून", - "timeslider.month.july": "जुलै", - "timeslider.month.august": "ऑगस्ट", - "timeslider.month.september": "सप्टेंबर", - "timeslider.month.october": "ऑक्टोबर", - "timeslider.month.november": "नोव्हेंबर", - "timeslider.month.december": "डिसेंबर", - "pad.userlist.entername": "आपले नाव टाका", - "pad.userlist.unnamed": "निनावी", - "pad.userlist.guest": "पाहूणा", - "pad.userlist.approve": "मंजूर करा", - "pad.impexp.importbutton": "आता आयात करा", - "pad.impexp.importing": "आयात करीत आहे...", - "pad.impexp.importfailed": "आयात अयशस्वी", - "pad.impexp.copypaste": "कृपया नकल-डकवा" -} diff --git a/sources/src/locales/ms.json b/sources/src/locales/ms.json deleted file mode 100644 index e23fa30..0000000 --- a/sources/src/locales/ms.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Anakmalaysia", - "Jeluang Terluang" - ] - }, - "index.newPad": "Pad baru", - "index.createOpenPad": "atau cipta/buka Pad yang bernama:", - "pad.toolbar.bold.title": "Tebal (Ctrl-B)", - "pad.toolbar.italic.title": "Miring (Ctrl-I)", - "pad.toolbar.underline.title": "Garis bawah (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Garis lorek (Ctrl+5)", - "pad.toolbar.ol.title": "Senarai tertib (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Senarai tak tertib (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Engsot ke dalam (TAB)", - "pad.toolbar.unindent.title": "Engsot ke luar (Shift + TAB)", - "pad.toolbar.undo.title": "Buat asal (Ctrl-Z)", - "pad.toolbar.redo.title": "Buat semula (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Padamkan Warna Pengarang (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Import/Eksport dari/ke format-format fail berbeza", - "pad.toolbar.timeslider.title": "Gelangsar masa", - "pad.toolbar.savedRevision.title": "Simpan Semakan", - "pad.toolbar.settings.title": "Tetapan", - "pad.toolbar.embed.title": "Kongsikan dan Terapkan pad ini", - "pad.toolbar.showusers.title": "Tunjukkan pengguna pada pad ini", - "pad.colorpicker.save": "Simpan", - "pad.colorpicker.cancel": "Batalkan", - "pad.loading": "Sedang dimuatkan...", - "pad.noCookie": "Cookie tidak dapat dijumpai. Tolong benarkan cookie dalam pelayar anda!", - "pad.passwordRequired": "Anda memerlukan kata laluan untuk mengakses pad ini", - "pad.permissionDenied": "Anda tiada kebenaran untuk mengakses pad ini", - "pad.wrongPassword": "Kata laluan anda salah", - "pad.settings.padSettings": "Tetapan Pad", - "pad.settings.myView": "Paparan Saya", - "pad.settings.stickychat": "Sentiasa bersembang pada skrin", - "pad.settings.chatandusers": "Paparkan Ruang Sembang dan Pengguna-Pengguna", - "pad.settings.colorcheck": "Warna pengarang", - "pad.settings.linenocheck": "Nombor baris", - "pad.settings.rtlcheck": "Membaca dari kanan ke kiri?", - "pad.settings.fontType": "Jenis fon:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Paparan Sejagat", - "pad.settings.language": "Bahasa:", - "pad.importExport.import_export": "Import/Eksport", - "pad.importExport.import": "Muat naik sebarang fail teks atau dokumen", - "pad.importExport.importSuccessful": "Berjaya!", - "pad.importExport.export": "Eksport pad semasa sebagai:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Teks biasa", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Anda hanya boleh mengimport dari format teks biasa atau html. Untuk ciri-ciri import yang lebih maju, sila memasang abiword.", - "pad.modals.connected": "Bersambung.", - "pad.modals.reconnecting": "Bersambung semula dengan pad anda...", - "pad.modals.forcereconnect": "Sambung semula secara paksa", - "pad.modals.userdup": "Dibuka di tetingkap lain", - "pad.modals.userdup.explanation": "Pad ini nampaknya telah dibuka di lebih daripada satu tetingkap pelayar pada komputer ini.", - "pad.modals.userdup.advice": "Sambung semula untuk menggunakan tetingkap ini pula.", - "pad.modals.unauth": "Tidak dibenarkan", - "pad.modals.unauth.explanation": "Kebenaran anda telah berubah sewaktu memaparkan halaman ini. Cuba bersambung semula.", - "pad.modals.looping.explanation": "Terdapat masalah komunikasi dengan pelayan penyegerakan.", - "pad.modals.looping.cause": "Mungkin anda telah bersambung melalui tembok api atau proksi yang tidak serasi.", - "pad.modals.initsocketfail": "Pelayan tidak boleh dicapai.", - "pad.modals.initsocketfail.explanation": "Tidak dapat bersambung dengan pelayar penyegerakan.", - "pad.modals.initsocketfail.cause": "Ini mungkin disebabkan oleh masalah dengan pelayar atau sambungan internet anda.", - "pad.modals.slowcommit.explanation": "Pelayan tidak membalas.", - "pad.modals.slowcommit.cause": "Ini mungkin disebabkan oleh masalah dengan kesambungan rangkaian anda.", - "pad.modals.badChangeset.explanation": "Suntingan yang telah anda lakukan telah dikira sebagai terlarang oleh pelayan penyegerakan.", - "pad.modals.badChangeset.cause": "Hal ini mungkin disebabkan oleh konfigurasi pelayan salah atau sesuatu kelakuan yang tidak dijangka. Sila hubungi penyelia servis anda jika anda merasakan ini ialah satu kesilapan. Cuba sambungkan semula talian untuk terus menyunting.", - "pad.modals.corruptPad.explanation": "Pad yang anda cuba akses itu telah tercemar.", - "pad.modals.corruptPad.cause": "Ini mungkin disebabkan oleh konfigurasi pelayan salah atau sesuatu kelakuan yang tidak dijangka. Sila hubungi penyelia servis anda.", - "pad.modals.deleted": "Dihapuskan.", - "pad.modals.deleted.explanation": "Pad ini telah dibuang.", - "pad.modals.disconnected": "Sambungan anda telah diputuskan.", - "pad.modals.disconnected.explanation": "Sambungan ke pelayan terputus", - "pad.modals.disconnected.cause": "Pelayan mungkin tidak dapat dicapai. Sila beritahu penyelia servis jika masalah ini berterusan.", - "pad.share": "Kongsikan pad ini", - "pad.share.readonly": "Baca sahaja", - "pad.share.link": "Pautan", - "pad.share.emebdcode": "Benamkan URL", - "pad.chat": "Sembang", - "pad.chat.title": "Buka ruang sembang untuk pad ini.", - "pad.chat.loadmessages": "Muatkan banyak lagi pesanan", - "timeslider.pageTitle": "Gelangsar Masa {{appTitle}}", - "timeslider.toolbar.returnbutton": "Kembali ke pad", - "timeslider.toolbar.authors": "Pengarang:", - "timeslider.toolbar.authorsList": "Tiada Pengarang", - "timeslider.toolbar.exportlink.title": "Eksport", - "timeslider.exportCurrent": "Eksport versi semasa sebagai:", - "timeslider.version": "Versi {{version}}", - "timeslider.saved": "Disimpan pada {{day}} {{month}} {{year}}", - "timeslider.playPause": "Mainkan / Pausekan Kandungan Pad", - "timeslider.backRevision": "Undur satu semakan di Pad ini", - "timeslider.forwardRevision": "Maju satu semakan dalam Pad ini", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januari", - "timeslider.month.february": "Februari", - "timeslider.month.march": "Mac", - "timeslider.month.april": "April", - "timeslider.month.may": "Mei", - "timeslider.month.june": "Jun", - "timeslider.month.july": "Julai", - "timeslider.month.august": "Ogos", - "timeslider.month.september": "September", - "timeslider.month.october": "Oktober", - "timeslider.month.november": "November", - "timeslider.month.december": "Disember", - "timeslider.unnamedauthors": "{{num}} orang {[plural(num) other: pengarang]} awanama", - "pad.savedrevs.marked": "Semakan ini telah ditandai sebagai semakan tersimpan", - "pad.savedrevs.timeslider": "Anda boleh melihat semakan yang tersimpan dengan melawat gelangsar masa", - "pad.userlist.entername": "Taipkan nama anda", - "pad.userlist.unnamed": "tanpa nama", - "pad.userlist.guest": "Tetamu", - "pad.userlist.deny": "Tolak", - "pad.userlist.approve": "Terima", - "pad.editbar.clearcolors": "Padamkan warna pengarang pada seluruh dokumen?", - "pad.impexp.importbutton": "Import Sekarang", - "pad.impexp.importing": "Sedang mengimport...", - "pad.impexp.confirmimport": "Mengimport fail akan menulis ganti teks semasa pada pad ini. Adakah anda benar-benar ingin teruskan?", - "pad.impexp.convertFailed": "Fail tidak dapat diimport. Sila gunakan format dokumen yang lain atau salin tampal secara manual", - "pad.impexp.padHasData": "Kami tidak dapat mengimport fail ini kerana Pad ini sudah mengalami perubahan. Sila import ke pad yang baru", - "pad.impexp.uploadFailed": "Muat naik gagal, sila cuba lagi", - "pad.impexp.importfailed": "Import gagal", - "pad.impexp.copypaste": "Sila salin tampal", - "pad.impexp.exportdisabled": "Mengeksport dalam format {{type}} dilarang. Sila hubungi pentadbir sistem anda untuk keterangan lanjut." -} diff --git a/sources/src/locales/nah.json b/sources/src/locales/nah.json deleted file mode 100644 index 262766b..0000000 --- a/sources/src/locales/nah.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Akapochtli", - "Taresi" - ] - }, - "index.newPad": "Yancuic Pad", - "index.createOpenPad": "auh xicchīhua/xictlapo cē Pad in ītōcā:", - "pad.toolbar.bold.title": "Tilāhuac (Ctrl+B)", - "pad.toolbar.italic.title": "Coltic (Ctrl+I)", - "pad.toolbar.underline.title": "Tlahuahuantli (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Tlīlhuahuantli (Ctrl+5)", - "pad.toolbar.undo.title": "Xicmācuepa (Ctrl+Z)", - "pad.toolbar.redo.title": "Occeppa (Ctrl+Y)", - "pad.toolbar.settings.title": "Tlatlālīliztli", - "pad.colorpicker.save": "Xicpiya", - "pad.colorpicker.cancel": "Xiccāhua", - "pad.settings.padSettings": "Pad Ītlatlālīliz", - "pad.settings.myView": "Notlachiyaliz", - "pad.settings.language": "Tlahtōlli:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.modals.deleted": "Omopohpoloh.", - "pad.modals.deleted.explanation": "Ōmopoloh inīn Pad.", - "timeslider.version": "Inīc {{version}} Cuepaliztli", - "timeslider.month.january": "Īccēmētztli", - "timeslider.month.february": "Īcōmemētztli", - "timeslider.month.march": "Īcyēyimētztli", - "timeslider.month.april": "Īcnāhuimētztli", - "timeslider.month.may": "Īcmācuīllimētztli", - "timeslider.month.june": "Īcchicuacemmētztli", - "timeslider.month.july": "Īcchicōmemētztli", - "timeslider.month.august": "Īcchicuēyimētztli", - "timeslider.month.september": "Īcchiucnāhuimētztli", - "timeslider.month.october": "Īcmahtlactlimētztli", - "timeslider.month.november": "Īcmahtlactlioncēmētztli", - "timeslider.month.december": "Īcmahtlactliomōmemētztli" -} diff --git a/sources/src/locales/nap.json b/sources/src/locales/nap.json deleted file mode 100644 index c31d525..0000000 --- a/sources/src/locales/nap.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Chelin", - "C.R." - ] - }, - "index.newPad": "Nuovo Pad", - "index.createOpenPad": "o crià o arape nu Pad cu 'o nomme:", - "pad.toolbar.bold.title": "Grassetto (Ctrl-B)", - "pad.toolbar.italic.title": "Cursivo (Ctrl-I)", - "pad.toolbar.underline.title": "Sottolineato (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Barrato (Ctrl+5)", - "pad.toolbar.ol.title": "Ennece nummerato (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Ennece puntato (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Rientro (TAB)", - "pad.toolbar.unindent.title": "Riduce rientro (Shift+TAB)", - "pad.toolbar.undo.title": "Annulla (Ctrl-Z)", - "pad.toolbar.redo.title": "Ripete (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Elimina 'e culure ca 'ndicanno 'e auture (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "'Mporta/esporta 'e/a diverse furmate 'e file", - "pad.toolbar.timeslider.title": "Presentazzione cronologgia", - "pad.toolbar.savedRevision.title": "Sarva revisione", - "pad.toolbar.settings.title": "Mpustaziune", - "pad.toolbar.embed.title": "Sparte e nzerta stu Pad", - "pad.toolbar.showusers.title": "Mmusta ll'utente ncopp'a stu Pad", - "pad.colorpicker.save": "Sarva", - "pad.colorpicker.cancel": "Canciella", - "pad.loading": "Carecamiento 'n curso…", - "pad.noCookie": "Cookie nun truvata. Pe' piacere premmettete 'e cookies dint' 'o navigatóre vuosto!", - "pad.passwordRequired": "Pe' accede a chisto Pad è necessaria 'na password", - "pad.permissionDenied": "Nun se dispunne d\"e permisse necessare pe' accede a chisto Pad", - "pad.wrongPassword": "'A password è sbagliata", - "pad.settings.padSettings": "Mpostazzione d\"o pad", - "pad.settings.myView": "Mia Veruta", - "pad.settings.stickychat": "Chat sempe ncopp' 'o schermo", - "pad.settings.colorcheck": "Auturevolezza pe' culure", - "pad.settings.linenocheck": "Nummere 'e riga", - "pad.settings.rtlcheck": "Lieggere 'e cuntenute 'a destra a smerza?", - "pad.settings.fontType": "Tipo 'e funte:", - "pad.settings.fontType.normal": "Nurmale", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Visualizzazione globbale", - "pad.settings.language": "Llengua:", - "pad.importExport.import_export": "Mpurtaziune/sportaziune", - "pad.importExport.import": "Carreca coccherunto testo o documento", - "pad.importExport.importSuccessful": "Ngarrata!", - "pad.importExport.export": "Sportà stu Pad comme:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Testo nurmale", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Putite surtanto mpurtà testo chiano o furmatte HTML. Pe n'avé sisteme cchiù annanze 'e mpurtazione pe' piacere installate Abiword.", - "pad.modals.connected": "Cunnesso.", - "pad.modals.reconnecting": "Ricunnessione ô pad 'n curso...", - "pad.modals.forcereconnect": "Forza 'a ricunnessione", - "pad.modals.userdup": "Aprito 'n n'ata fenesta", - "pad.modals.userdup.explanation": "Stu Pad pare fosse araputo dint'a cchiù 'e na fenesta 'e navigatore dint'a stu computer.", - "pad.modals.userdup.advice": "Riconnettateve pe' putè ausà mmece sta fenesta.", - "pad.modals.unauth": "Nun autorizzato", - "pad.modals.unauth.explanation": "'E premmesse vuoste so' cagnate pe' tramente ca se vereva sta paggena. Tentate 'e ve riconnettà.", - "pad.modals.looping.explanation": "Ce stanno probbleme 'e comunicazione c' 'o server 'e sincronizzaziona.", - "pad.modals.looping.cause": "Può darse ca ve site cullegato pe' mmiez' 'e nu firewall incompatibbele o proxy.", - "pad.modals.initsocketfail": "Nun se può arrevà 'o server.", - "pad.modals.initsocketfail.explanation": "Nun se può cunnettà 'o server e sincronizzaziona.", - "pad.modals.initsocketfail.cause": "Stu fatto è succiesso, probabbilmente pe' bbìa 'e nu probblema c' 'o navigatóre 'o ll'internet.", - "pad.modals.slowcommit.explanation": "'O server nun risponne.", - "pad.modals.slowcommit.cause": "Stu fatto può darse ca è causato pe' bbìa 'e prubbleme 'e connettività 'e rezza.", - "pad.modals.badChangeset.explanation": "Nu cagnamento ca stavate facenno è stato classeficato comme illegale p' 'o server 'e sincronizzaziona.", - "pad.modals.badChangeset.cause": "Chistu fatto può darse ca è causato pe' bbìa 'e na mpustazione errata d' 'o server o cocch'atu comportamento nun preveduto. Pe' piacere cuntattate l'ammenistratore d' 'o servizio, si se pienza ca chist'è n'errore. Tentate a ve riconnettà pe' cuntinuà 'a edità.", - "pad.modals.corruptPad.explanation": "'O pad addò vulevate trasì è scassato.", - "pad.modals.deleted": "Canciellato.", - "pad.share.link": "Jonta", - "pad.chat": "Chiàcchiera", - "timeslider.pageTitle": "Cronologgia {{appTitle}}", - "timeslider.toolbar.returnbutton": "Ritorna ô Pad", - "timeslider.toolbar.authors": "Auture:", - "timeslider.toolbar.authorsList": "Nisciun autore", - "timeslider.toolbar.exportlink.title": "Espurta", - "timeslider.exportCurrent": "Espurta 'a verzione corrente comme:", - "timeslider.version": "Verzione {{version}}", - "timeslider.saved": "Sarvato {{day}} {{month}} {{year}}", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Jennaro", - "timeslider.month.february": "Frevaro", - "timeslider.month.march": "Màrzo", - "timeslider.month.april": "Abbrile", - "timeslider.month.may": "Màjo", - "timeslider.month.june": "Giùgno", - "timeslider.month.july": "Luglio", - "timeslider.month.august": "Aùsto", - "timeslider.month.september": "Settembre", - "timeslider.month.october": "Ottovre", - "timeslider.month.november": "Nuvembre", - "timeslider.month.december": "Dicembre", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autore, other: auture ]} senza nomme", - "pad.userlist.entername": "'Nserisce 'o tujo nomme", - "pad.userlist.unnamed": "senza nomme", - "pad.userlist.guest": "Ospite", - "pad.userlist.deny": "Nega", - "pad.userlist.approve": "Appruva", - "pad.impexp.importbutton": "'Mpurta mmo", - "pad.impexp.importing": "'Mpurtazzione 'n curso..." -} diff --git a/sources/src/locales/nb.json b/sources/src/locales/nb.json deleted file mode 100644 index bd39b18..0000000 --- a/sources/src/locales/nb.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Laaknor", - "Cocu", - "Chameleon222", - "SuperPotato", - "Jon Harald Søby" - ] - }, - "index.newPad": "Ny Pad", - "index.createOpenPad": "eller opprette/åpne en ny Pad med dette navnet:", - "pad.toolbar.bold.title": "Fet (Ctrl+B)", - "pad.toolbar.italic.title": "Kursiv (Ctrl+I)", - "pad.toolbar.underline.title": "Understreking (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Gjennomstreking (Ctrl+5)", - "pad.toolbar.ol.title": "Nummerert liste (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Punktliste (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Innrykk (TAB)", - "pad.toolbar.unindent.title": "Rykk ut (Shift+TAB)", - "pad.toolbar.undo.title": "Angre (Ctrl+Z)", - "pad.toolbar.redo.title": "Gjør omigjen (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Fjern forfatterfarger (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importer/eksporter fra/til forskjellige filformater", - "pad.toolbar.timeslider.title": "Tidslinje", - "pad.toolbar.savedRevision.title": "Lagre revisjoner", - "pad.toolbar.settings.title": "Innstillinger", - "pad.toolbar.embed.title": "Del og sett inn denne Paden", - "pad.toolbar.showusers.title": "Vis brukerne av denne Paden", - "pad.colorpicker.save": "Lagre", - "pad.colorpicker.cancel": "Avbryt", - "pad.loading": "Laster...", - "pad.noCookie": "Kunne ikke finne informasjonskapselen. Vennligst tillat informasjonskapsler (cookies) i din webleser!", - "pad.passwordRequired": "Du trenger et passord for å få tilgang til denne Paden", - "pad.permissionDenied": "Du har ikke tilgang til denne Paden", - "pad.wrongPassword": "Feil passord", - "pad.settings.padSettings": "Padinnstillinger", - "pad.settings.myView": "Min Visning", - "pad.settings.stickychat": "Chat alltid synlig", - "pad.settings.chatandusers": "Vis chat og brukere", - "pad.settings.colorcheck": "Forfatterfarger", - "pad.settings.linenocheck": "Linjenummer", - "pad.settings.rtlcheck": "Les innhold fra høyre til venstre?", - "pad.settings.fontType": "Skrifttype:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Fast bredde", - "pad.settings.globalView": "Global visning", - "pad.settings.language": "Språk:", - "pad.importExport.import_export": "Importer/eksporter", - "pad.importExport.import": "Last opp tekstfil eller dokument", - "pad.importExport.importSuccessful": "Vellykket!", - "pad.importExport.export": "Eksporter blokken som:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Ren tekst", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Du kan bare importere fra ren tekst eller HTML-formater. For mer avanserte importfunksjoner, installer AbiWord.", - "pad.modals.connected": "Tilkoblet.", - "pad.modals.reconnecting": "Kobler til din blokk på nytt...", - "pad.modals.forcereconnect": "Tving gjenoppkobling", - "pad.modals.reconnecttimer": "Prøver å koble til igjen", - "pad.modals.cancel": "Avbryt", - "pad.modals.userdup": "Åpnet i nytt vindu", - "pad.modals.userdup.explanation": "Denne blokken ser ut til å være åpnet i mer enn et nettleservindu på denne maskinen.", - "pad.modals.userdup.advice": "Koble til igjen for å bruke dette vinduet i stedenfor.", - "pad.modals.unauth": "Ikke tillatt", - "pad.modals.unauth.explanation": "Dine rettigheter har blitt endret mens du så på denne siden. Prøv å koble til på nytt", - "pad.modals.looping.explanation": "Det er kommunikasjonsproblemer med synkroniseringsserveren.", - "pad.modals.looping.cause": "Kanskje du koblet til en inkompatibel brannmur eller mellomtjener", - "pad.modals.initsocketfail": "Serveren er utilgjengelig", - "pad.modals.initsocketfail.explanation": "Kunne ikke koble til synkroniseringsserveren.", - "pad.modals.initsocketfail.cause": "Dette er sannsynligvis på grunn av et problem med nettleseren eller din internettoppkobling", - "pad.modals.slowcommit.explanation": "Serveren svarer ikke.", - "pad.modals.slowcommit.cause": "Dette kan være et problem med nettverkstilkoblingen", - "pad.modals.badChangeset.explanation": "En redigering som du gjorde ble klassifisert som ulovlig av synkroniseringsserveren.", - "pad.modals.badChangeset.cause": "Dette kan komme av feil serverkonfigurasjon eller en annen uventet adferd. Vennligst kontakt serviceadministratoren hvis du anser dette å være feil. Prøv å gjenopprette forbindelsen for å fortsette med redigeringen.", - "pad.modals.corruptPad.explanation": "Blokken du forsøker å få tilgang til er skadet.", - "pad.modals.corruptPad.cause": "Dette kan komme av feil serverkonfigurasjon eller en annen uventet adferd. Vennligst kontakt serviceadministratoren hvis du anser dette å være feil.", - "pad.modals.deleted": "Slettet.", - "pad.modals.deleted.explanation": "Denne blokken har blitt fjernet", - "pad.modals.disconnected": "Du har blitt frakoblet.", - "pad.modals.disconnected.explanation": "Mistet tilkobling til serveren.", - "pad.modals.disconnected.cause": "Serveren kan være utilgjengelig. Vennligst si i fra til oss hvis dette fortsetter å skje.", - "pad.share": "Del denne blokken", - "pad.share.readonly": "Skrivebeskyttet", - "pad.share.link": "Lenke", - "pad.share.emebdcode": "URL for innbygging", - "pad.chat": "Chat", - "pad.chat.title": "Åpne chatten for denne blokken.", - "pad.chat.loadmessages": "Last flere beskjeder", - "timeslider.pageTitle": "{{appTitle}} Tidslinje", - "timeslider.toolbar.returnbutton": "Gå tilbake til blokk", - "timeslider.toolbar.authors": "Forfattere:", - "timeslider.toolbar.authorsList": "Ingen forfattere", - "timeslider.toolbar.exportlink.title": "Eksporter", - "timeslider.exportCurrent": "Eksporter nåværende versjon som:", - "timeslider.version": "Versjon {{version}}", - "timeslider.saved": "Lagret {{day}}. {{month}} {{year}}", - "timeslider.playPause": "Spill av/Pause blokkinnholdet", - "timeslider.backRevision": "Gå tilbake en revisjon i denne blokken", - "timeslider.forwardRevision": "Gå fremover en revisjon i denne blokken", - "timeslider.dateformat": "{{day}}. {{month}} {{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "januar", - "timeslider.month.february": "februar", - "timeslider.month.march": "mars", - "timeslider.month.april": "april", - "timeslider.month.may": "mai", - "timeslider.month.june": "juni", - "timeslider.month.july": "juli", - "timeslider.month.august": "august", - "timeslider.month.september": "september", - "timeslider.month.october": "oktober", - "timeslider.month.november": "november", - "timeslider.month.december": "desember", - "timeslider.unnamedauthors": "{{num}} navnløse {[plural(num) one: forfatter, other: forfattere ]}", - "pad.savedrevs.marked": "Denne revisjonen er nå markert som en lagret revisjon", - "pad.savedrevs.timeslider": "Du kan se lagrede revisjoner med tidslinjen", - "pad.userlist.entername": "Skriv inn ditt navn", - "pad.userlist.unnamed": "navnløs", - "pad.userlist.guest": "Gjest", - "pad.userlist.deny": "Nekt", - "pad.userlist.approve": "Godkjenn", - "pad.editbar.clearcolors": "Fjern forfatterfarger på hele dokumentet?", - "pad.impexp.importbutton": "Importer nå", - "pad.impexp.importing": "Importerer...", - "pad.impexp.confirmimport": "Importering av en fil vil overskrive den nåværende teksten på blokken. Er du sikker på at du vil fortsette?", - "pad.impexp.convertFailed": "Vi greide ikke å importere denne filen. Bruk et annet dokumentformat eller kopier og lim inn teksten manuelt", - "pad.impexp.padHasData": "Vi kunne ikke importere denne filen fordi blokken allerede hadde endringer. Importer til en ny blokk.", - "pad.impexp.uploadFailed": "Opplastning feilet. Prøv igjen", - "pad.impexp.importfailed": "Import feilet", - "pad.impexp.copypaste": "Vennligst kopier og lim inn", - "pad.impexp.exportdisabled": "Eksporterer som {{type}} er deaktivert. Vennligst kontakt din systemadministrator for detaljer." -} diff --git a/sources/src/locales/nds.json b/sources/src/locales/nds.json deleted file mode 100644 index dfb9227..0000000 --- a/sources/src/locales/nds.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Gthoele", - "Joachim Mos" - ] - }, - "index.newPad": "Nee'et Pad", - "index.createOpenPad": "oder Pad mit düssen Naam apen maken:", - "pad.toolbar.bold.title": "Fett (Strg-B)", - "pad.toolbar.italic.title": "Kursiv (Strg-I)", - "pad.toolbar.underline.title": "Mit Streek dor ünner (Strg-U)", - "pad.toolbar.strikethrough.title": "Mit Streek dor dör", - "pad.toolbar.ol.title": "List na Nummern", - "pad.toolbar.ul.title": "List ahn Nummern", - "pad.toolbar.indent.title": "Text na rechts", - "pad.toolbar.unindent.title": "Text na links", - "pad.toolbar.undo.title": "Een Stapp retuur (Strg-Z)", - "pad.toolbar.redo.title": "Noch mal (Strg-Y)", - "pad.toolbar.clearAuthorship.title": "Klöör vun den Schriever wegnehmen", - "pad.toolbar.import_export.title": "Rinhalen/Rutgeven in verscheden Dateiformate", - "pad.toolbar.timeslider.title": "Geschicht vun de Pad-Faten wiesen", - "pad.toolbar.savedRevision.title": "Faten sekern", - "pad.toolbar.settings.title": "Instellungen", - "pad.toolbar.embed.title": "Düt Pad verdelen oder annerswo ringeven", - "pad.toolbar.showusers.title": "Wokeen is online?", - "pad.colorpicker.save": "Spiekern", - "pad.colorpicker.cancel": "Afbreken", - "pad.loading": "Läädt…", - "pad.passwordRequired": "Du bruukst en Passwoort, wenn du in düt Pad rinwullt", - "pad.permissionDenied": "In düt Pad dröffst du nich rin", - "pad.wrongPassword": "Dien Passwoort weer nich richtig", - "pad.settings.padSettings": "So is dat Pad instellt", - "pad.settings.myView": "So heff ik dat instellt", - "pad.settings.stickychat": "Chat jümmers wiesen", - "pad.settings.colorcheck": "Klören vun de Schrievers wiesen", - "pad.settings.linenocheck": "Nummer vun de Reeg", - "pad.settings.rtlcheck": "Lees Pad vun rechts nach links", - "pad.settings.fontType": "Schriftoort:", - "pad.settings.fontType.normal": "Normaal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Ansicht för all", - "pad.settings.language": "Spraak:", - "pad.importExport.import_export": "Rinhalen/Rutgeven", - "pad.importExport.import": "Datei oder Dokument hoochladen", - "pad.importExport.importSuccessful": "Hett slumpt!", - "pad.importExport.export": "Düt Pad rutgeven as:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Textdatei", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Se köönt blots wat vun Kloortext oder HTML-Stücken röverhalen. Mit köönt Se ok anner Saken röverhalen. Dorför mööt Se bidde abiword inrichten.", - "pad.modals.connected": "Verbindung steiht.", - "pad.modals.reconnecting": "En Verbindung wedder opboen ...", - "pad.modals.forcereconnect": "Noch mal verbinnen", - "pad.modals.userdup": "In en anner Fenster op", - "pad.modals.userdup.explanation": "Dat lett, düt Pat is op düssen Reekner in mehr as een Browser-Fenster op.", - "pad.modals.userdup.advice": "Wullt du düt Fenster bruken, bidde noch mal de Verbindung opboen.", - "pad.modals.unauth": "Nich freegeven.", - "pad.modals.unauth.explanation": "Du hest nu anner Rechten för düt Pad. Maak dat bidde noch mal wedder nee op.", - "pad.modals.looping.explanation": "Dat gifft Kummer bi de Verbindung mit den Pad-Server.", - "pad.modals.looping.cause": "Mag ween un du hest Verbindung mit den Padserver över en Firewall, de nich passt, oder en Proxy, de nich passt.", - "pad.modals.initsocketfail": "Wi köönt den Pad-Server nich faat kriegen.", - "pad.modals.initsocketfail.explanation": "De Verbindung mit den Pad-Server hett nich klappt.", - "pad.modals.initsocketfail.cause": "Mag ween un dat liggt an dien Browser oder an dien Internet-Verbindung.", - "pad.modals.slowcommit.explanation": "De Pad-Server gifft keen Antwoort.", - "pad.modals.slowcommit.cause": "Kunn wenn un dat liggt an dat Nettwark, oder dor arbeidt jüst to veel Lüüd op den Pad-Server.", - "pad.modals.deleted": "Weg is dat!", - "pad.modals.deleted.explanation": "Düt Pad is nu weg.", - "pad.modals.disconnected": "De Kuntakt is afreten.", - "pad.modals.disconnected.explanation": "De Kuntakt mit den Pad-Server is afreten.", - "pad.modals.disconnected.cause": "Mag ween un wi köönt den Pad-Server jüst nich faat kriegen. Schull dat so wiedergahn, segg man Bescheed.", - "pad.share": "Düt Pad ok anner Lüüd wiesen", - "pad.share.readonly": "Se köönt hier jüst blots lesen", - "pad.share.link": "Link", - "pad.share.emebdcode": "In Websiet ringeven", - "pad.chat": "Chat", - "pad.chat.title": "Den Chat vun düt Pad apen maken", - "pad.chat.loadmessages": "Mehr Narichten laden", - "timeslider.pageTitle": "{{appTitle}} Öllere Faten vun dat Pad", - "timeslider.toolbar.returnbutton": "Retuur na dat Pad", - "timeslider.toolbar.authors": "Schrievers:", - "timeslider.toolbar.authorsList": "keen Schrievers", - "timeslider.toolbar.exportlink.title": "Rutschicken", - "timeslider.exportCurrent": "Schick düsse Faten rut as:", - "timeslider.version": "Faten {{version}}", - "timeslider.saved": "Sekert an den {{day}}.{{month}}.{{year}}", - "timeslider.dateformat": "{{day}}.{{month}}.{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januar", - "timeslider.month.february": "Februar", - "timeslider.month.march": "März", - "timeslider.month.april": "April", - "timeslider.month.may": "Mai", - "timeslider.month.june": "Juni", - "timeslider.month.july": "Juli", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "Oktober", - "timeslider.month.november": "November", - "timeslider.month.december": "Dezember", - "timeslider.unnamedauthors": "{{num}} Schriever ohn Naam {[plural(num) one: Schriever, other: Schrievers ]}", - "pad.savedrevs.marked": "Düsse Faten hett nu dat Teken: sekerte Faten", - "pad.userlist.entername": "Schriev dien Naam", - "pad.userlist.unnamed": "hett keen Naam", - "pad.userlist.guest": "Besöker", - "pad.userlist.deny": "Deit uns Leed, wieder geiht dat nich", - "pad.userlist.approve": "Man to!", - "pad.editbar.clearcolors": "Klören vun de Schrievers in dat ganze Dokument torüchsetten?", - "pad.impexp.importbutton": "Nu rinhalen", - "pad.impexp.importing": "Haal dat rin …", - "pad.impexp.confirmimport": "Wenn du nu en Datei rinhaalst, warrt de Text in dat Pad överschreven. Wullt du würklich wieder maken?", - "pad.impexp.convertFailed": "Wi köönt düsse Datei nich rinhalen. Ännert Se bidde dat Format vun dat Dokument oder haalt Se den Text mit de Hand rin.", - "pad.impexp.uploadFailed": "Dat Hoochladen hett nich slumpt. Versöök dat man noch mal.", - "pad.impexp.importfailed": "Dat Rinhalen hett nich slumpt", - "pad.impexp.copypaste": "Bidde koperen un rinsetten", - "pad.impexp.exportdisabled": "Du kannst dat nich in dat {{type}}-Format rutschicken. Wenn du mehr weten wullt, fraag man den Systemadministrator." -} diff --git a/sources/src/locales/ne.json b/sources/src/locales/ne.json deleted file mode 100644 index 3e23659..0000000 --- a/sources/src/locales/ne.json +++ /dev/null @@ -1,109 +0,0 @@ -{ - "@metadata": { - "authors": [ - "सरोज कुमार ढकाल", - "Nirjal stha", - "राम प्रसाद जोशी" - ] - }, - "index.newPad": "नयाँ प्याड", - "index.createOpenPad": "नाम सहितको नयाँ प्याड सिर्जना गर्ने / खोल्ने :", - "pad.toolbar.bold.title": "मोटो (Ctrl-B)", - "pad.toolbar.italic.title": "ढल्के (Ctrl-I)", - "pad.toolbar.underline.title": "निम्न रेखाङ्कन (Ctrl-U)", - "pad.toolbar.strikethrough.title": "बीचको धर्को (Ctrl+5)", - "pad.toolbar.ol.title": "क्रमवद्ध सूची (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "अक्रमाङ्कित सूची (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "इन्डेन्ट (TAB)", - "pad.toolbar.unindent.title": "आउटडेन्ट (Shift+TAB)", - "pad.toolbar.undo.title": "रद्द (Ctrl-Z)", - "pad.toolbar.redo.title": "पुन:लागु (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "लेखकीय रङ्ग हटाउने (Ctrl+Shift+C)", - "pad.toolbar.timeslider.title": "टाइमस्लाइडर", - "pad.toolbar.savedRevision.title": "पुनरावलोकन संग्रहगर्ने", - "pad.toolbar.settings.title": "सेटिङ्गहरू", - "pad.toolbar.embed.title": "यस प्याडलाई बाड्ने या इम्बेड गर्ने", - "pad.toolbar.showusers.title": "यस प्याडमा रहेका प्रयोगकर्ता देखाउने", - "pad.colorpicker.save": "सङ्ग्रह गर्ने", - "pad.colorpicker.cancel": "रद्द", - "pad.loading": "लोड हुदैछ...", - "pad.passwordRequired": "यो प्यड खोल्न पासवर्ड चाहिन्छ", - "pad.permissionDenied": "तपाईंलाई यो प्याड खोल्न अनुमति छैन", - "pad.wrongPassword": "तपाईंको पासवर्ड गलत थियो", - "pad.settings.padSettings": "प्याड सेटिङ्गहरू", - "pad.settings.myView": "मेरो दृष्य", - "pad.settings.stickychat": "पर्दामा सधै च्याट गर्ने", - "pad.settings.chatandusers": "वार्ता तथा प्रयोगकर्ताहरू देखाउने", - "pad.settings.colorcheck": "लेखकीय रङ्ग", - "pad.settings.linenocheck": "हरफ संख्या", - "pad.settings.rtlcheck": "के सामग्री दाहिने देखि देब्रे पढ्ने हो ?", - "pad.settings.fontType": "फन्ट प्रकार:", - "pad.settings.fontType.normal": "सामान्य", - "pad.settings.fontType.monospaced": "मोनोस्पेस", - "pad.settings.globalView": "विश्वव्यापी दृष्य", - "pad.settings.language": "भाषा:", - "pad.importExport.import_export": "आयात/निर्यात", - "pad.importExport.import": "कुनै पनि पाठ रहेको फाइल या कागजात अपलोड गर्नुहोस्", - "pad.importExport.importSuccessful": "सफल भयो!", - "pad.importExport.export": "निम्न रुपमा प्याड निर्यात गर्ने :", - "pad.importExport.exportetherpad": "इथरप्याड", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "साधारण पाठ", - "pad.importExport.exportword": "माइक्रोसफ्ट वर्ड", - "pad.importExport.exportpdf": "पिडिएफ", - "pad.importExport.exportopen": "ओडिएफ(खुल्ला कागजात ढाँचा)", - "pad.modals.connected": "जोडीएको।", - "pad.modals.reconnecting": "तपाईंको प्याडमा पुन: जडान गर्दै", - "pad.modals.forcereconnect": "जडानको लागि जोडगर्ने", - "pad.modals.userdup": "अर्को सन्झ्यालमा खोल्ने", - "pad.modals.unauth": "अनुमती नदिइएको", - "pad.modals.initsocketfail": "सर्भरमा पहुँच पुर्‍याउन सकिएन ।", - "pad.modals.slowcommit.explanation": "सर्भरसँग सम्पर्क हुने सकेन ।", - "pad.modals.deleted": "मेटिएको ।", - "pad.modals.deleted.explanation": "यो प्याड हटाइसकेको छ ।", - "pad.modals.disconnected": "तपाईंको जडान अवरुद्ध भयो ।", - "pad.modals.disconnected.explanation": "तपाईंको सर्भरसँगको जडान अवरुद्ध भयो", - "pad.share": "यस प्यडलाई बाड्ने", - "pad.share.readonly": "पढ्ने मात्र", - "pad.share.link": "लिङ्क", - "pad.share.emebdcode": "URL थप्ने", - "pad.chat": "कुराकानी", - "pad.chat.title": "यस प्याडको लागि कुराकानी खोल्ने", - "pad.chat.loadmessages": "थप सन्देशहरू खोल्ने", - "timeslider.pageTitle": "{{appTitle}} समय रेखा", - "timeslider.toolbar.returnbutton": "प्याडमा फर्कनुहोस्", - "timeslider.toolbar.authors": "लेखकहरु:", - "timeslider.toolbar.authorsList": "कुनै पनि लेखकहरू छैनन्", - "timeslider.toolbar.exportlink.title": "निर्यात", - "timeslider.exportCurrent": "हालको संस्करण निम्म रुपमा निर्यात गर्ने :", - "timeslider.version": "संस्करण {{version}}", - "timeslider.saved": "सङ्ग्रह गरिएको {{month}} {{day}}, {{year}}", - "timeslider.playPause": "प्याडको सामग्रीहरूलाई चालु/बन्द गर्नुहोस", - "timeslider.backRevision": "यो प्याडको एक संस्करण पहिले जानुहोस्", - "timeslider.forwardRevision": "यो प्याडको एक संस्करण पछि जानुहोस्", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "जनवरी", - "timeslider.month.february": "फेब्रुअरी", - "timeslider.month.march": "मार्च", - "timeslider.month.april": "एप्रील", - "timeslider.month.may": "मे", - "timeslider.month.june": "जुन", - "timeslider.month.july": "जुलाई", - "timeslider.month.august": "अगस्ट", - "timeslider.month.september": "सेप्टेम्बर", - "timeslider.month.october": "अक्टोबर", - "timeslider.month.november": "नोभेम्बर", - "timeslider.month.december": "डिसेम्बर", - "timeslider.unnamedauthors": "{{num}} unnamed {[plural(num) one: author, other: authors ]}", - "pad.savedrevs.marked": "यस संस्करणलाई संग्रहितको रुपमा चिनो लगाइएको छैन", - "pad.userlist.entername": "तपाईंको नाम लेख्नुहोस्", - "pad.userlist.unnamed": "नाम नखुलाइएको", - "pad.userlist.guest": "पाहुना", - "pad.userlist.deny": "अस्वीकार गर्ने", - "pad.userlist.approve": "स्वीकृत गर्ने", - "pad.impexp.importbutton": "अहिले आयात गर्ने", - "pad.impexp.importing": "आयात गर्ने...", - "pad.impexp.uploadFailed": "अपलोड असफल भयो , कृपया पुन: प्रयास गर्नुहोस् ।", - "pad.impexp.importfailed": "आयात असफल भयो", - "pad.impexp.copypaste": "कृपया कपी पेस्ट गर्नुहोस" -} diff --git a/sources/src/locales/nl.json b/sources/src/locales/nl.json deleted file mode 100644 index 727e8ab..0000000 --- a/sources/src/locales/nl.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Siebrand", - "Macofe", - "Robin0van0der0vliet", - "Robin van der Vliet" - ] - }, - "index.newPad": "Nieuw pad", - "index.createOpenPad": "Pad maken op openen met de naam:", - "pad.toolbar.bold.title": "Vet (Ctrl-B)", - "pad.toolbar.italic.title": "Cursief (Ctrl-I)", - "pad.toolbar.underline.title": "Onderstrepen (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Doorhalen (Ctrl+5)", - "pad.toolbar.ol.title": "Geordende lijst (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Ongeordende lijst (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Inspringen (Tab)", - "pad.toolbar.unindent.title": "Inspringing verkleinen (Shift+Tab)", - "pad.toolbar.undo.title": "Ongedaan maken (Ctrl-Z)", - "pad.toolbar.redo.title": "Opnieuw uitvoeren (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Kleuren auteurs wissen (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Naar/van andere opmaak exporteren/importeren", - "pad.toolbar.timeslider.title": "Tijdlijn", - "pad.toolbar.savedRevision.title": "Versie opslaan", - "pad.toolbar.settings.title": "Instellingen", - "pad.toolbar.embed.title": "Pad delen en insluiten", - "pad.toolbar.showusers.title": "Gebruikers van dit pad weergeven", - "pad.colorpicker.save": "Opslaan", - "pad.colorpicker.cancel": "Annuleren", - "pad.loading": "Bezig met laden…", - "pad.noCookie": "Er kon geen cookie gevonden worden. Zorg ervoor dat uw browser cookies accepteert.", - "pad.passwordRequired": "U hebt een wachtwoord nodig om toegang te krijgen tot deze pad", - "pad.permissionDenied": "U hebt geen rechten om deze pad te bekijken", - "pad.wrongPassword": "U hebt een onjuist wachtwoord ingevoerd", - "pad.settings.padSettings": "Padinstellingen", - "pad.settings.myView": "Mijn overzicht", - "pad.settings.stickychat": "Chat altijd zichtbaar", - "pad.settings.chatandusers": "Chat en gebruikers weergeven", - "pad.settings.colorcheck": "Kleuren auteurs", - "pad.settings.linenocheck": "Regelnummers", - "pad.settings.rtlcheck": "Inhoud van rechts naar links lezen?", - "pad.settings.fontType": "Lettertype:", - "pad.settings.fontType.normal": "Normaal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Globaal overzicht", - "pad.settings.language": "Taal:", - "pad.importExport.import_export": "Importeren/exporteren", - "pad.importExport.import": "Tekstbestand of document uploaden", - "pad.importExport.importSuccessful": "Afgerond", - "pad.importExport.export": "Huidige pad exporteren als", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Tekst zonder opmaak", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "Pdf", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "U kunt alleen importeren vanuit Tekst zonder opmaak of een HTML-opmaak. Installeer abiword om meer geavanceerde importmogelijkheden te krijgen.", - "pad.modals.connected": "Verbonden.", - "pad.modals.reconnecting": "Opnieuw verbinding maken met uw pad...", - "pad.modals.forcereconnect": "Opnieuw verbinden", - "pad.modals.reconnecttimer": "Proberen te verbinden over", - "pad.modals.cancel": "Annuleren", - "pad.modals.userdup": "In een ander venster geopend", - "pad.modals.userdup.explanation": "Dit pad is meer dan één keer geopend in een browservenster op deze computer.", - "pad.modals.userdup.advice": "Maak opnieuw verbinding als u dit venster wilt gebruiken.", - "pad.modals.unauth": "Niet toegestaan", - "pad.modals.unauth.explanation": "Uw rechten zijn gewijzigd terwijl u de pagina aan het bekijken was. Probeer opnieuw te verbinden.", - "pad.modals.looping.explanation": "Er is een probleem opgetreden tijdens de communicatie met de synchronisatieserver.", - "pad.modals.looping.cause": "Mogelijk gebruikt de server een niet compatibele firewall of proxy server.", - "pad.modals.initsocketfail": "De server is niet bereikbaar.", - "pad.modals.initsocketfail.explanation": "Het was niet mogelijk te verbinden met de synchronisatieserver.", - "pad.modals.initsocketfail.cause": "Mogelijk komt dit door uw browser of internetverbinding.", - "pad.modals.slowcommit.explanation": "De server reageert niet.", - "pad.modals.slowcommit.cause": "Dit komt mogelijk door netwerkproblemen.", - "pad.modals.badChangeset.explanation": "Een door u gemaakte bewerking is door de synchronisatieserver als incorrect aangemerkt.", - "pad.modals.badChangeset.cause": "Dit kan komen door een onjuiste serverinstelling of door ander onverwacht gedrag. Neem contact op met de servicebeheerder als u denkt dat er een onverwachte uitkomst is. Probeer opnieuw te verbinden om door te gaan met bewerken.", - "pad.modals.corruptPad.explanation": "Het pad dat u wilt openen is beschadigd.", - "pad.modals.corruptPad.cause": "Dit kan komen door een onjuiste serverinstelling of door ander onverwacht gedrag. Neem contact op met de servicebeheerder.", - "pad.modals.deleted": "Verwijderd.", - "pad.modals.deleted.explanation": "Dit pad is verwijderd.", - "pad.modals.disconnected": "Uw verbinding is verbroken.", - "pad.modals.disconnected.explanation": "De verbinding met de server is verbroken", - "pad.modals.disconnected.cause": "De server is mogelijk niet beschikbaar. Stel de servicebeheerder op de hoogte.", - "pad.share": "Pad delen", - "pad.share.readonly": "Alleen-lezen", - "pad.share.link": "Koppeling", - "pad.share.emebdcode": "URL insluiten", - "pad.chat": "Chatten", - "pad.chat.title": "Chat voor dit pad opnenen", - "pad.chat.loadmessages": "Meer berichten laden", - "timeslider.pageTitle": "Tijdlijn voor {{appTitle}}", - "timeslider.toolbar.returnbutton": "Terug naar pad", - "timeslider.toolbar.authors": "Auteurs:", - "timeslider.toolbar.authorsList": "Geen auteurs", - "timeslider.toolbar.exportlink.title": "Exporteren", - "timeslider.exportCurrent": "Huidige versie exporteren als:", - "timeslider.version": "Versie {{version}}", - "timeslider.saved": "Opgeslagen op {{day}} {{month}} {{year}}", - "timeslider.playPause": "Padinhoud afspelen of pauzeren", - "timeslider.backRevision": "Een versie teruggaan voor deze pad", - "timeslider.forwardRevision": "Een versie vooruit gaan voor deze pad", - "timeslider.dateformat": "{{year}}-{{month}}-{{day}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "januari", - "timeslider.month.february": "februari", - "timeslider.month.march": "maart", - "timeslider.month.april": "april", - "timeslider.month.may": "mei", - "timeslider.month.june": "juni", - "timeslider.month.july": "juli", - "timeslider.month.august": "augustus", - "timeslider.month.september": "september", - "timeslider.month.october": "oktober", - "timeslider.month.november": "november", - "timeslider.month.december": "december", - "timeslider.unnamedauthors": "{{num}} onbekende {[plural(num) one: auteur, other: auteurs ]}", - "pad.savedrevs.marked": "Deze versie is nu gemarkeerd als opgeslagen versie", - "pad.savedrevs.timeslider": "U kunt opgeslagen versies bekijken via de tijdschuiver.", - "pad.userlist.entername": "Geef uw naam op", - "pad.userlist.unnamed": "zonder naam", - "pad.userlist.guest": "Gast", - "pad.userlist.deny": "Weigeren", - "pad.userlist.approve": "Goedkeuren", - "pad.editbar.clearcolors": "Auteurskleuren voor het hele document wissen?", - "pad.impexp.importbutton": "Nu importeren", - "pad.impexp.importing": "Bezig met importeren…", - "pad.impexp.confirmimport": "Door een bestand te importeren overschrijft u de huidige tekst van de pad. Wilt u echt doorgaan?", - "pad.impexp.convertFailed": "Het was niet mogelijk dit bestand te importeren. Gebruik een andere documentopmaak of kopieer en plak de inhoud handmatig", - "pad.impexp.padHasData": "Het was niet mogelijk dit bestand te importeren omdat er al wijzigingen aan de etherpad zijn gemaakt. Importeer naar een nieuwe etherpad.", - "pad.impexp.uploadFailed": "Het uploaden is mislukt. Probeer het opnieuw", - "pad.impexp.importfailed": "Importeren is mislukt", - "pad.impexp.copypaste": "Gebruik kopiëren en plakken", - "pad.impexp.exportdisabled": "Exporteren als {{type}} is uitgeschakeld. Neem contact op met de systeembeheerder voor details." -} diff --git a/sources/src/locales/nn.json b/sources/src/locales/nn.json deleted file mode 100644 index dc6368e..0000000 --- a/sources/src/locales/nn.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Unhammer" - ] - }, - "index.newPad": "Ny blokk", - "index.createOpenPad": "eller opprett/opna ei blokk med namnet:", - "pad.toolbar.bold.title": "Feit (Ctrl-B)", - "pad.toolbar.italic.title": "Kursiv (Ctrl-I)", - "pad.toolbar.underline.title": "Understreking (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Gjennomstreking", - "pad.toolbar.ol.title": "Nummerert liste", - "pad.toolbar.ul.title": "Punktliste", - "pad.toolbar.indent.title": "Innrykk", - "pad.toolbar.unindent.title": "Rykk ut", - "pad.toolbar.undo.title": "Angra (Ctrl-Z)", - "pad.toolbar.redo.title": "Gjer om (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Fjern forfattarfargar", - "pad.toolbar.import_export.title": "Importer/eksporter til/frå ulike filformat", - "pad.toolbar.timeslider.title": "Tidslinje", - "pad.toolbar.savedRevision.title": "Lagra utgåver", - "pad.toolbar.settings.title": "Innstillingar", - "pad.toolbar.embed.title": "Bygg inn blokka i ei nettside", - "pad.toolbar.showusers.title": "Syn brukarane på blokka", - "pad.colorpicker.save": "Lagra", - "pad.colorpicker.cancel": "Avbryt", - "pad.loading": "Lastar …", - "pad.passwordRequired": "Du treng eit passord for å opna denne blokka", - "pad.permissionDenied": "Du har ikkje tilgang til denne blokka", - "pad.wrongPassword": "Feil passord", - "pad.settings.padSettings": "Blokkinnstillingar", - "pad.settings.myView": "Mi visning", - "pad.settings.stickychat": "Prat alltid synleg", - "pad.settings.colorcheck": "Forfattarfargar", - "pad.settings.linenocheck": "Linjenummer", - "pad.settings.fontType": "Skrifttype:", - "pad.settings.fontType.normal": "Vanleg", - "pad.settings.fontType.monospaced": "Fast breidd", - "pad.settings.globalView": "Global visning", - "pad.settings.language": "Språk:", - "pad.importExport.import_export": "Importer/eksporter", - "pad.importExport.import": "Last opp tekstfiler eller dokument", - "pad.importExport.importSuccessful": "Vellukka!", - "pad.importExport.export": "Eksporter blokka som:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Rein tekst", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Du kan berre importera frå rein tekst- eller HTML-format. Ver venleg og installer Abiword om du treng meir avanserte importfunksjonar.", - "pad.modals.connected": "Tilkopla.", - "pad.modals.reconnecting": "Gjenopprettar tilkoplinga til blokka di …", - "pad.modals.forcereconnect": "Tving gjentilkopling", - "pad.modals.userdup": "Opna i eit anna vindauge", - "pad.modals.userdup.explanation": "Det ser ut som om denne blokka er open i meir enn eitt nettlesarvindauge på denne maskinen.", - "pad.modals.userdup.advice": "Kopla til om att for å bruka dette vinduage i staden.", - "pad.modals.unauth": "Ikkje tillate", - "pad.modals.unauth.explanation": "Rettane dine blei endra under visning av denne sida. Prøv å kopla til på nytt.", - "pad.modals.looping.explanation": "Det oppstod kommunikasjonsproblem med synkroniseringstenaren.", - "pad.modals.looping.cause": "Kanskje du kopla til gjennom ein inkompatibel brannmur eller mellomtenar.", - "pad.modals.initsocketfail": "Klarte ikkje å nå tenaren.", - "pad.modals.initsocketfail.explanation": "Klarte ikkje å kopla til synkroniseringstenaren.", - "pad.modals.initsocketfail.cause": "Dette er sannsynlegvis på grunn av eit problem med nettlesaren eller internettilkoplinga di.", - "pad.modals.slowcommit.explanation": "Tenaren svarer ikkje.", - "pad.modals.slowcommit.cause": "Dette kan vera på grunn av problem med nettilkoplinga.", - "pad.modals.deleted": "Sletta.", - "pad.modals.deleted.explanation": "Denne blokka er fjerna.", - "pad.modals.disconnected": "Du blei fråkopla.", - "pad.modals.disconnected.explanation": "Mista tilkoplinga til tenaren", - "pad.modals.disconnected.cause": "Tenaren er ikkje tilgjengeleg. Ver venleg og gi oss ei melding om dette skjer fleire gonger.", - "pad.share": "Del denne blokka", - "pad.share.readonly": "Skriveverna", - "pad.share.link": "Lenkje", - "pad.share.emebdcode": "URL for innebygging", - "pad.chat": "Prat", - "pad.chat.title": "Opna pratepanelet for denne blokka.", - "timeslider.pageTitle": "Tidslinje for {{appTitle}}", - "timeslider.toolbar.returnbutton": "Attende til blokka", - "timeslider.toolbar.authors": "Forfattarar:", - "timeslider.toolbar.authorsList": "Ingen forfattarar", - "timeslider.toolbar.exportlink.title": "Eksporter", - "timeslider.exportCurrent": "Eksporter denne utgåva som:", - "timeslider.version": "Utgåve {{version}}", - "timeslider.saved": "Lagra {{day}}. {{month}}, {{year}}", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}.{{minutes}}.{{seconds}}", - "timeslider.month.january": "januar", - "timeslider.month.february": "februar", - "timeslider.month.march": "mars", - "timeslider.month.april": "april", - "timeslider.month.may": "mai", - "timeslider.month.june": "juni", - "timeslider.month.july": "juli", - "timeslider.month.august": "august", - "timeslider.month.september": "september", - "timeslider.month.october": "oktober", - "timeslider.month.november": "november", - "timeslider.month.december": "desember", - "pad.savedrevs.marked": "Denne utgåva er no merkt som ei lagra utgåve", - "pad.userlist.entername": "Skriv namnet ditt", - "pad.userlist.unnamed": "utan namn", - "pad.userlist.guest": "Gjest", - "pad.userlist.deny": "Nekt", - "pad.userlist.approve": "Godkjenn", - "pad.editbar.clearcolors": "Fjern forfattarfargar i heile dokumentet?", - "pad.impexp.importbutton": "Importer no", - "pad.impexp.importing": "Importerer …", - "pad.impexp.confirmimport": "Viss du importerer ei fil, vil denne blokka bli overskriven. Er du sikker på at du vil fortsetja?", - "pad.impexp.convertFailed": "Me klarte ikkje å importera denne fila. Ver venleg og bruk eit anna dokumentformat, eller kopier og lim inn for hand.", - "pad.impexp.uploadFailed": "Feil ved opplasting, ver venleg og prøv om att", - "pad.impexp.importfailed": "Feil ved importering", - "pad.impexp.copypaste": "Ver venleg og kopier og lim inn", - "pad.impexp.exportdisabled": "Eksport av {{type}} er skrudd av. Ver venleg og ta kontakt med systemadministrator for meir informasjon." -} diff --git a/sources/src/locales/oc.json b/sources/src/locales/oc.json deleted file mode 100644 index 5ec8090..0000000 --- a/sources/src/locales/oc.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Cedric31" - ] - }, - "index.newPad": "Pad novèl", - "index.createOpenPad": "o crear/dobrir un Pad intitulat :", - "pad.toolbar.bold.title": "Gras (Ctrl-B)", - "pad.toolbar.italic.title": "Italica (Ctrl-I)", - "pad.toolbar.underline.title": "Soslinhat (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Raiat (Ctrl+5)", - "pad.toolbar.ol.title": "Lista ordenada (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Lista pas ordenada (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Indentar (TAB)", - "pad.toolbar.unindent.title": "Desindentar (Maj+TAB)", - "pad.toolbar.undo.title": "Anullar (Ctrl-Z)", - "pad.toolbar.redo.title": "Restablir (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Escafar las colors qu'identifican los autors (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importar/Exportar de/cap a un format de fichièr diferent", - "pad.toolbar.timeslider.title": "Istoric dinamic", - "pad.toolbar.savedRevision.title": "Enregistrar la revision", - "pad.toolbar.settings.title": "Paramètres", - "pad.toolbar.embed.title": "Partejar e integrar aqueste Pad", - "pad.toolbar.showusers.title": "Afichar los utilizaires del Pad", - "pad.colorpicker.save": "Enregistrar", - "pad.colorpicker.cancel": "Anullar", - "pad.loading": "Cargament...", - "pad.noCookie": "Lo cookie a pas pogut èsser trobat. Autorizatz los cookies dins vòstre navigador !", - "pad.passwordRequired": "Avètz besonh d'un senhal per accedir a aqueste Pad", - "pad.permissionDenied": "Vos es pas permés d’accedir a aqueste Pad.", - "pad.wrongPassword": "Senhal incorrècte", - "pad.settings.padSettings": "Paramètres del Pad", - "pad.settings.myView": "Ma vista", - "pad.settings.stickychat": "Afichar totjorn lo chat", - "pad.settings.chatandusers": "Afichar la discussion e los utilizaires", - "pad.settings.colorcheck": "Colors d’identificacion", - "pad.settings.linenocheck": "Numèros de linhas", - "pad.settings.rtlcheck": "Lectura de dreita a esquèrra", - "pad.settings.fontType": "Tipe de poliça :", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Vista d’ensemble", - "pad.settings.language": "Lenga :", - "pad.importExport.import_export": "Importar/Exportar", - "pad.importExport.import": "Cargar un tèxte o un document", - "pad.importExport.importSuccessful": "Capitat !", - "pad.importExport.export": "Exportar lo Pad actual coma :", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Tèxte brut", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Podètz pas importar que de formats tèxte brut o html. Per de foncionalitats d'importacion mai evoluadas, installatz abiword.", - "pad.modals.connected": "Connectat.", - "pad.modals.reconnecting": "Reconnexion cap a vòstre Pad...", - "pad.modals.forcereconnect": "Forçar la reconnexion.", - "pad.modals.reconnecttimer": "Ensag de reconnexion", - "pad.modals.cancel": "Anullar", - "pad.modals.userdup": "Dobèrt dins una autra fenèstra", - "pad.modals.userdup.explanation": "Sembla qu'aqueste Pad es dobèrt dins mai d'una fenèstra de vòstre navigador sus aqueste ordinator.", - "pad.modals.userdup.advice": "Se reconnectar en utilizant aquesta fenèstra.", - "pad.modals.unauth": "Pas autorizat", - "pad.modals.unauth.explanation": "Vòstras permissions son estadas cambiadas al moment de l'afichatge d'aquesta pagina. Ensajatz de vos reconnectar.", - "pad.modals.looping.explanation": "Avèm un problèma de comunicacion amb lo servidor de sincronizacion.", - "pad.modals.looping.cause": "Es possible que vòstra connexion siá protegida per un parafuòc incompatible o un servidor proxy incompatible.", - "pad.modals.initsocketfail": "Lo servidor es introbable.", - "pad.modals.initsocketfail.explanation": "Impossible de se connectar al servidor de sincronizacion.", - "pad.modals.initsocketfail.cause": "Lo problèma pòt venir de vòstre navigador web o de vòstra connexion Internet.", - "pad.modals.slowcommit.explanation": "Lo servidor respond pas.", - "pad.modals.slowcommit.cause": "Aqueste problèma pòt venir d'una marrida connectivitat a la ret.", - "pad.modals.badChangeset.explanation": "Una modificacion qu'avètz efectuada es estada classada coma illegala pel servidor de sincronizacion.", - "pad.modals.badChangeset.cause": "Aquò pòt èsser degut a una marrida configuracion del servidor o a un autre comportament inesperat. Contactatz l’administrator del servici, si pensatz qu’es una error. Ensajatz de vos reconnectar per contunhar de modificar.", - "pad.modals.corruptPad.explanation": "Lo blòt al qual ensajatz d’accedir es corromput.", - "pad.modals.corruptPad.cause": "Aquò pòt èsser degut a una marrida configuracion del servidor o a un autre comportament inesperat. Contactatz l’administrator del servici.", - "pad.modals.deleted": "Suprimit.", - "pad.modals.deleted.explanation": "Aqueste Pad es estat suprimit.", - "pad.modals.disconnected": "Sètz estat desconnectat.", - "pad.modals.disconnected.explanation": "La connexion al servidor a fracassat.", - "pad.modals.disconnected.cause": "Es possible que lo servidor siá indisponible. Se lo problèma contunha, informatz-ne l'administrator del servici.", - "pad.share": "Partejar aqueste Pad", - "pad.share.readonly": "Lectura sola", - "pad.share.link": "Ligam", - "pad.share.emebdcode": "Ligam d'integrar", - "pad.chat": "Chat", - "pad.chat.title": "Dobrir lo chat associat a aqueste pad.", - "pad.chat.loadmessages": "Cargar mai de messatges.", - "timeslider.pageTitle": "Istoric dinamic de {{appTitle}}", - "timeslider.toolbar.returnbutton": "Retorn a aqueste Pad.", - "timeslider.toolbar.authors": "Autors :", - "timeslider.toolbar.authorsList": "Pas cap d'autor", - "timeslider.toolbar.exportlink.title": "Exportar", - "timeslider.exportCurrent": "Exportar la version actuala en :", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Enregistrat lo {{day}} de {{month}} de {{year}}", - "timeslider.playPause": "Lectura / Pausa dels contenguts del pad", - "timeslider.backRevision": "Recular d’una revision dins aqueste pad", - "timeslider.forwardRevision": "Avançar d’una revision dins aqueste pad", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Genièr", - "timeslider.month.february": "Febrièr", - "timeslider.month.march": "Març", - "timeslider.month.april": "Abril", - "timeslider.month.may": "Mai", - "timeslider.month.june": "Junh", - "timeslider.month.july": "Julhet", - "timeslider.month.august": "Agost", - "timeslider.month.september": "Setembre", - "timeslider.month.october": "Octobre", - "timeslider.month.november": "Novembre", - "timeslider.month.december": "Decembre", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor anonim, other: autors anonims ]}", - "pad.savedrevs.marked": "Aquesta revision es ara marcada coma revision enregistrada", - "pad.savedrevs.timeslider": "Podètz veire las revisions enregistradas en visitant l’ascensor temporal", - "pad.userlist.entername": "Entratz vòstre nom", - "pad.userlist.unnamed": "sens nom", - "pad.userlist.guest": "Convidat", - "pad.userlist.deny": "Refusar", - "pad.userlist.approve": "Aprovar", - "pad.editbar.clearcolors": "Escafar las colors de paternitat dins tot lo document ?", - "pad.impexp.importbutton": "Importar ara", - "pad.impexp.importing": "Impòrt en cors...", - "pad.impexp.confirmimport": "Importar un fichièr espotirà lo tèxte actual del blòt. Sètz segur que lo volètz far ?", - "pad.impexp.convertFailed": "Podèm pas importar aqueste fichièr. Utilizatz un autre format de document o fasètz un copiar/pegar manual", - "pad.impexp.padHasData": "Avèm pas pogut importar aqueste fichièr perque aqueste blòt a ja agut de modificacions ; importatz cap a un blòt novèl", - "pad.impexp.uploadFailed": "Lo telecargament a fracassat, reensajatz", - "pad.impexp.importfailed": "Fracàs de l'importacion", - "pad.impexp.copypaste": "Copiatz/pegatz", - "pad.impexp.exportdisabled": "Exportar al format {{type}} es desactivat. Contactatz vòstre administrator del sistèma per mai de detalhs." -} diff --git a/sources/src/locales/olo.json b/sources/src/locales/olo.json deleted file mode 100644 index e8db16f..0000000 --- a/sources/src/locales/olo.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Denö", - "Mashoi7", - "Ilja.mos" - ] - }, - "pad.toolbar.underline.title": "Alleviivua (Ctrl+U)", - "pad.toolbar.settings.title": "Azetukset", - "pad.colorpicker.save": "Tallenda", - "pad.colorpicker.cancel": "Hylgiä", - "pad.wrongPassword": "Peittosana oli viärin", - "pad.settings.linenocheck": "Riädynoumerot", - "pad.settings.rtlcheck": "Luve syväindö oigielpäi huruale?", - "pad.settings.language": "Kieli:", - "pad.importExport.import_export": "Tuo/Vie", - "pad.importExport.importSuccessful": "Ozavui!", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.modals.userdup": "Avattu toizes ikkunas", - "pad.modals.unauth": "Ei lubua", - "pad.modals.initsocketfail": "Palvelin ei ole tavattavis.", - "pad.modals.initsocketfail.explanation": "Ei suadu yhtevytty sinhronisaciipalvelimeh.", - "pad.modals.slowcommit.explanation": "Palvelin ei vastua.", - "pad.modals.disconnected.explanation": "Yhtevys palvelimeh kavotettu", - "timeslider.toolbar.authors": "Luadijat:", - "timeslider.toolbar.authorsList": "Ei luadijoi", - "timeslider.toolbar.exportlink.title": "Vie", - "timeslider.exportCurrent": "Vie nygöine versii nimel:", - "timeslider.version": "Versii {{version}}", - "timeslider.saved": "Tallendettu {{month}} {{day}}, {{year}}", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "pakkaskuudu", - "timeslider.month.february": "tuhukuudu", - "timeslider.month.march": "kevätkuudu", - "timeslider.month.april": "sulakuudu", - "timeslider.month.may": "oraskuudu", - "timeslider.month.june": "kezäkuudu", - "timeslider.month.july": "heinykuudu", - "timeslider.month.august": "elokuudu", - "timeslider.month.september": "syvyskuudu", - "timeslider.month.october": "ligakuudu", - "timeslider.month.november": "kylmykuudu", - "timeslider.month.december": "talvikuudu", - "pad.userlist.entername": "Kirjuta sinun nimi", - "pad.userlist.unnamed": "nimetöi", - "pad.userlist.guest": "Gost'u", - "pad.impexp.importbutton": "Tuo nygöi", - "pad.impexp.importing": "Tuou..." -} diff --git a/sources/src/locales/os.json b/sources/src/locales/os.json deleted file mode 100644 index 941fe2b..0000000 --- a/sources/src/locales/os.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Bouron" - ] - }, - "index.newPad": "Ног", - "index.createOpenPad": "кӕнӕ сараз/бакӕн ног документ ахӕм номимӕ:", - "pad.toolbar.bold.title": "Бӕзджын (Ctrl-B)", - "pad.toolbar.italic.title": "Къӕдз (Ctrl-I)", - "pad.toolbar.underline.title": "Бынылхахх (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Хахх", - "pad.toolbar.ol.title": "Нымад номхыгъд", - "pad.toolbar.ul.title": "Ӕнӕнымад номхыгъд", - "pad.toolbar.indent.title": "Хаст", - "pad.toolbar.unindent.title": "Ӕттӕмӕхаст", - "pad.toolbar.undo.title": "Раздӕхын (Ctrl-Z)", - "pad.toolbar.redo.title": "Рацаразын (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Фыссӕджы нысӕнттӕ айсынӕн", - "pad.toolbar.import_export.title": "Импорт/экспорт ӕндӕр файлы форматтӕй/форматтӕм", - "pad.toolbar.timeslider.title": "Рӕстӕджы хахх", - "pad.toolbar.savedRevision.title": "Фӕлтӕр бавӕрынӕн", - "pad.toolbar.settings.title": "Уагӕвӕрдтӕ", - "pad.toolbar.embed.title": "Ацы документ бафтау æмæ йæ тыххæй ахъæр кæн", - "pad.toolbar.showusers.title": "Ацы документы архайджыты равдисын", - "pad.colorpicker.save": "Нывæрын", - "pad.colorpicker.cancel": "Ныууадзын", - "pad.loading": "Æвгæд цæуы...", - "pad.passwordRequired": "Ацы документмӕ рывналынӕн дӕ хъӕуы пароль", - "pad.permissionDenied": "Дӕуӕн нӕй бар ацы документмӕ рывналын", - "pad.wrongPassword": "Дӕ пароль раст нӕу", - "pad.settings.padSettings": "Документы уагӕвӕрдтытӕ", - "pad.settings.myView": "Мӕ уынд", - "pad.settings.stickychat": "Ныхас алкуыдӕр ӕвдисын", - "pad.settings.colorcheck": "Фыссӕджы хуызтӕ", - "pad.settings.linenocheck": "Рӕнхъыты номыртӕ", - "pad.settings.rtlcheck": "Мидис рахизӕй галиумӕ хъӕуы фӕрсын?", - "pad.settings.fontType": "Шрифты хуыз:", - "pad.settings.fontType.normal": "Хуымӕтӕг", - "pad.settings.fontType.monospaced": "Ӕмуӕрӕх", - "pad.settings.globalView": "Иууылы уынд", - "pad.settings.language": "Æвзаг:", - "pad.importExport.import_export": "Импорт/экспорт", - "pad.importExport.import": "Исты текст файл кӕнӕ документ бавгӕнын", - "pad.importExport.importSuccessful": "Ӕнтыст!", - "pad.importExport.export": "Ныры документ сэкпорт кӕнын куыд:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Хуымæтæг текст", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Дӕ бон у импорт кӕнын ӕрмӕст хуымӕтӕг текст кӕнӕ html форматӕй. Лӕмбынӕг импорты миниуджытӕн, дӕ хорзӕхӕй, сӕвӕр abiword.", - "pad.modals.connected": "Иугонд.", - "pad.modals.reconnecting": "Дӕ документмӕ ногӕй иугонд цӕуы..", - "pad.modals.forcereconnect": "Тыххӕй баиу кӕнын", - "pad.modals.userdup": "Ног рудзынджы бакӕнын", - "pad.modals.userdup.explanation": "Ацы документ ӕвӕццӕгӕн ацы компьютеры иуӕй фылдӕр рудзынджы у гом.", - "pad.modals.userdup.advice": "Ногӕй баиу уын, ацы рудзынгӕй архайыны бӕсты.", - "pad.modals.unauth": "Нӕ авторизацигонд", - "pad.modals.unauth.explanation": "Дӕ бартӕ фӕивтой, цалынмӕ ды ацы фарс кастӕ. Бафӕлвар ногӕй баиу уын.", - "pad.modals.looping.explanation": "Синхронизацийы серверимӕ баиу кӕныны проблемӕ.", - "pad.modals.looping.cause": "Уӕццӕгӕн ды баиу дӕ ӕнӕмбӕлгӕ файрвол кӕнӕ проксийы уылты.", - "pad.modals.initsocketfail": "Сервермӕ баиугӕнӕн нӕй.", - "pad.modals.initsocketfail.explanation": "Нӕ рауадис синхронизацийы сервермӕ баиу уын.", - "pad.modals.initsocketfail.cause": "Ай уӕццӕгӕн дӕ сгарӕн кӕнӕ дӕ интернеты тыххӕй у.", - "pad.modals.slowcommit.explanation": "Сервер нӕ дзуапп кӕны.", - "pad.modals.slowcommit.cause": "Ай гӕнӕн ис у хызы проблемӕйы тыххӕй.", - "pad.modals.deleted": "Хафт.", - "pad.modals.deleted.explanation": "Документ хафт ӕрцыд.", - "pad.modals.disconnected": "Ды хицӕнгонд ӕрцыдтӕ.", - "pad.modals.disconnected.explanation": "Серверимӕ иугонд фесӕфтис", - "pad.modals.disconnected.cause": "Сервермӕ гӕнӕн ис баиугӕнӕн нӕй. Дӕ хорзӕхӕй, фехъусын нын ӕй кӕн, кӕд афтӕ дарддӕр кӕна.", - "pad.share": "Ацы документ райуарын", - "pad.share.readonly": "Ӕрмӕст фӕрсынӕн", - "pad.share.link": "Ӕрвитӕн", - "pad.share.emebdcode": "URL бавӕрын", - "pad.chat": "Ныхас", - "pad.chat.title": "Оцы документӕн чат бакӕн.", - "pad.chat.loadmessages": "Фылдӕр фыстӕг равгӕнын", - "timeslider.pageTitle": "{{appTitle}}-ы рӕтӕджы хахх", - "timeslider.toolbar.returnbutton": "Фӕстӕмӕ, документмӕ", - "timeslider.toolbar.authors": "Фыссӕджытӕ:", - "timeslider.toolbar.authorsList": "Фыссӕджытӕ нӕй", - "timeslider.toolbar.exportlink.title": "Экспорт", - "timeslider.exportCurrent": "Сэкспорт кӕнын ныры фӕлтӕр куыд:", - "timeslider.version": "Верси {{version}}", - "timeslider.saved": "Ӕвӕрд ӕрцыд {{year}}-ӕм азы, {{day}}-ӕм {{month}}-ы", - "timeslider.dateformat": "{{day}}.{{month}}.{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "январь", - "timeslider.month.february": "февраль", - "timeslider.month.march": "мартъи", - "timeslider.month.april": "апрель", - "timeslider.month.may": "май", - "timeslider.month.june": "июнь", - "timeslider.month.july": "июль", - "timeslider.month.august": "август", - "timeslider.month.september": "сентябрь", - "timeslider.month.october": "октябрь", - "timeslider.month.november": "ноябрь", - "timeslider.month.december": "декабрь", - "timeslider.unnamedauthors": "{{num}} ӕнӕном фыссӕджы", - "pad.savedrevs.marked": "Ацы фӕлтӕр ныр куыд ӕвӕрд фӕлтӕр нысангонд ӕрцыд", - "pad.userlist.entername": "Дӕ ном бафысс", - "pad.userlist.unnamed": "ӕнӕном", - "pad.userlist.guest": "Уазӕг", - "pad.userlist.deny": "Ныууадзын", - "pad.userlist.approve": "Сбӕлвырд кӕнын", - "pad.editbar.clearcolors": "Ӕнӕхъӕн документӕй хъӕуы айсын фыссӕджыты нысӕнттӕ?", - "pad.impexp.importbutton": "Еныр симпорт кӕнын", - "pad.impexp.importing": "Импорт цӕуы...", - "pad.impexp.confirmimport": "Файлы импорт документы ныры текст бынтон фӕивдзӕнис. Ӕцӕг дӕ фӕнды уый саразын?", - "pad.impexp.convertFailed": "Махӕн нӕ бон не ссис ацы файл симпорт кӕнын. Дӕ хорзӕхӕй, спайда кӕн ӕндӕр файлы форматӕй, кӕнӕ скъопи кӕн ӕмӕ батысс текст дӕхӕдӕг.", - "pad.impexp.uploadFailed": "Бавгӕнын нӕ рауад, дӕ хорзӕхӕй, фӕстӕдӕр бафӕлвар", - "pad.impexp.importfailed": "Импорт нӕ рауад", - "pad.impexp.copypaste": "Дӕ хорзӕхӕй, къопи кӕн ӕмӕ ӕвӕр", - "pad.impexp.exportdisabled": "{{type}} форматы экспорт хицӕн у. Дӕ хорзӕхӕй, бадзур дӕ системон администратортӕм фылдӕр базонынӕн." -} diff --git a/sources/src/locales/pa.json b/sources/src/locales/pa.json deleted file mode 100644 index f1e8ffc..0000000 --- a/sources/src/locales/pa.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Aalam", - "Babanwalia", - "ਪ੍ਰਚਾਰਕ", - "Tow" - ] - }, - "index.newPad": "ਨਵਾਂ ਪੈਡ", - "index.createOpenPad": "ਜਾਂ ਨਾਂ ਨਾਲ ਨਵਾਂ ਪੈਡ ਬਣਾਓ/ਖੋਲ੍ਹੋ:", - "pad.toolbar.bold.title": "ਗੂੜ੍ਹਾ (Ctrl-B)", - "pad.toolbar.italic.title": "ਤਿਰਛਾ (Ctrl-I)", - "pad.toolbar.underline.title": "ਹੇਠਾਂ-ਰੇਖਾ (Ctrl-U)", - "pad.toolbar.strikethrough.title": "ਵਿੰਨ੍ਹੋ (Ctrl+5)", - "pad.toolbar.ol.title": "ਲੜੀਵਾਰ ਸੂਚੀ", - "pad.toolbar.ul.title": "ਬਿਨ-ਲੜੀਬੱਧ ਸੂਚੀ", - "pad.toolbar.indent.title": "ਹਾਸ਼ੀਏ ਤੋਂ ਪਰ੍ਹੇ (ਟੈਬ)", - "pad.toolbar.unindent.title": "ਹਾਸ਼ੀਏ ਵੱਲ (ਸ਼ਿਫ਼ਟ+ਟੈਬ)", - "pad.toolbar.undo.title": "ਵਾਪਸ (Ctrl-Z)", - "pad.toolbar.redo.title": "ਪਰਤਾਓ (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "ਪਰਮਾਣਕਿਤਾ ਰੰਗ ਸਾਫ਼ ਕਰੋ (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "ਵੱਖ-ਵੱਖ ਫਾਇਲ ਫਾਰਮੈਟ ਤੋਂ/ਵਿੱਚ ਇੰਪੋਰਟ/ਐਕਸਪੋਰਟ ਕਰੋ", - "pad.toolbar.timeslider.title": "ਸਮਾਂ-ਲਕੀਰ", - "pad.toolbar.savedRevision.title": "ਰੀਵਿਜ਼ਨ ਸੰਭਾਲੋ", - "pad.toolbar.settings.title": "ਸੈਟਿੰਗ", - "pad.toolbar.embed.title": "ਇਹ ਪੈਡ ਸਾਂਝਾ ਤੇ ਇੰਬੈੱਡ ਕਰੋ", - "pad.toolbar.showusers.title": "ਇਹ ਪੈਡ ਉੱਤੇ ਯੂਜ਼ਰ ਵੇਖਾਓ", - "pad.colorpicker.save": "ਸੰਭਾਲੋ", - "pad.colorpicker.cancel": "ਰੱਦ ਕਰੋ", - "pad.loading": "…ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ", - "pad.noCookie": "ਕੂਕੀਜ਼ ਨਹੀਂ ਲੱਭੀਅਾਂ। ਕਿਰਪਾ ਕਰਕੇ ਬ੍ਰਾੳੂਜ਼ਰ ਵਿੱਚ ਕੂਕੀਜ਼ ਲਾਗੂ ਕਰੋ।", - "pad.passwordRequired": "ਇਹ ਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਤੁਹਾਨੂੰ ਪਾਸਵਰਡ ਚਾਹੀਦਾ ਹੈ", - "pad.permissionDenied": "ਇਹ ਪੈਡ ਵਰਤਨ ਲਈ ਤੁਹਾਨੂੰ ਅਧਿਕਾਰ ਨਹੀਂ ਹਨ", - "pad.wrongPassword": "ਤੁਹਾਡਾ ਪਾਸਵਰਡ ਗਲਤੀ ਸੀ", - "pad.settings.padSettings": "ਪੈਡ ਸੈਟਿੰਗ", - "pad.settings.myView": "ਮੇਰੀ ਝਲਕ", - "pad.settings.stickychat": "ਹਮੇਸ਼ਾ ਸਕਰੀਨ ਉੱਤੇ ਗੱਲ ਕਰੋ", - "pad.settings.chatandusers": "ਗੱਲ-ਬਾਤ ਅਤੇ ਵਰਤੋਂਕਾਰ ਦਿਖਾਵੋ", - "pad.settings.colorcheck": "ਲੇਖਕੀ ਰੰਗ", - "pad.settings.linenocheck": "ਲਾਈਨ ਨੰਬਰ", - "pad.settings.rtlcheck": "ਸਮੱਗਰੀ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਪੜ੍ਹਨੀ ਹੈ?", - "pad.settings.fontType": "ਫੋਂਟ ਕਿਸਮ:", - "pad.settings.fontType.normal": "ਸਧਾਰਨ", - "pad.settings.fontType.monospaced": "ਮੋਨੋਸਪੇਸ", - "pad.settings.globalView": "ਗਲੋਬਲ ਝਲਕ", - "pad.settings.language": "ਭਾਸ਼ਾ:", - "pad.importExport.import_export": "ਇੰਪੋਰਟ/ਐਕਸਪੋਰਟ", - "pad.importExport.import": "ਕੋਈ ਵੀ ਟੈਕਸਟ ਫਾਇਲ ਜਾਂ ਦਸਤਾਵੇਜ਼ ਅੱਪਲੋਡ ਕਰੋ", - "pad.importExport.importSuccessful": "ਸਫ਼ਲ!", - "pad.importExport.export": "ਮੌਜੂਦਾ ਪੈਡ ਨੂੰ ਐਕਸਪੋਰਟ ਕਰੋ:", - "pad.importExport.exportetherpad": "ੲੈਥਰਪੈਡ", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "ਸਧਾਰਨ ਟੈਕਸਟ", - "pad.importExport.exportword": "ਮਾਈਕਰੋਸਾਫਟ ਵਰਡ", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (ਓਪਨ ਡੌਕੂਮੈਂਟ ਫਾਰਮੈਟ)", - "pad.importExport.abiword.innerHTML": "ਤੁਸੀਂ ਸਿਰਫ਼ ਸਾਦੀਆਂ ਲਿਖਤੀ ਜਾਂ ਐੱਚ.ਟੀ.ਐੱਮ.ਐੱਲ. ਰੂਪ-ਰੇਖਾਵਾਂ ਤੋਂ ਦਰਾਮਦ ਕਰ ਸਕਦੇ ਹੋ। ਹੋਰ ਉੱਨਤ ਦਰਾਮਦੀ ਗੁਣਾਂ ਵਾਸਤੇ ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਐਬੀਵਰਡ ਥਾਪੋ।", - "pad.modals.connected": "ਕੁਨੈਕਟ ਹੈ।", - "pad.modals.reconnecting": "..ਤੁਹਾਡੇ ਪੈਡ ਨਾਲ ਮੁੜ-ਕੁਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ", - "pad.modals.forcereconnect": "ਧੱਕੇ ਨਾਲ ਮੁੜ-ਕੁਨੈਕਟ ਕਰੋ", - "pad.modals.userdup": "ਹੋਰ ਵਿੰਡੋ ਵਿੱਚ ਖੁੱਲ੍ਹਿਆ ਹੈ", - "pad.modals.userdup.explanation": "ਇਹ ਪੈਡ ਇਸ ਕੰਪਿਊਟਰ 'ਤੇ ਇੱਕ ਤੋਂ ਵੱਧ ਫਰੋਲੂ ਬਾਰੀ ਵਿੱਚ ਖੁੱਲ੍ਹਿਆ ਜਾਪਦਾ ਹੈ।", - "pad.modals.userdup.advice": "ਸਗੋਂ ਇਹ ਬਾਰੀ ਵਰਤਣ ਵਾਸਤੇ ਮੁੜ ਜੁੜੋ।", - "pad.modals.unauth": "ਪਰਮਾਣਿਤ ਨਹੀਂ ਹੈ", - "pad.modals.unauth.explanation": "ਇਹ ਸਫ਼ਾ ਵੇਖਦੇ-ਵੇਖਦੇ ਤੁਹਾਨੂੰ ਮਿਲ਼ੀਆਂ ਇਜਾਜ਼ਤਾਂ ਬਦਲ ਗਈਆਂ ਹਨ। ਮੁੜ ਜੁੜਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।", - "pad.modals.looping.explanation": "ਇੱਕਰੂਪੀ ਸਰਵਰ ਨਾਲ਼ ਸੰਚਾਰੀ ਔਕੜਾਂ ਆ ਰਹੀਆਂ ਹਨ।", - "pad.modals.looping.cause": "ਸ਼ਾਇਦ ਤੁਸੀਂ ਕਿਸੇ ਅਢੁਕਵੀਂ ਸੁਰੱਖਿਆ ਪ੍ਰਨਾਲ਼ੀ ਜਾਂ ਪ੍ਰਾਕਸੀ ਰਾਹੀਂ ਜੁੜੇ ਹੋ।", - "pad.modals.initsocketfail": "ਸਰਵਰ ਪਹੁੰਚ ਵਿੱਚ ਨਹੀਂ ਹੈ।", - "pad.modals.initsocketfail.explanation": "ਇੱਕਰੂਪੀ ਸਰਵਰ ਨਾਲ਼ ਰਾਬਤਾ ਨਹੀਂ ਬਣ ਸਕਿਆ।", - "pad.modals.initsocketfail.cause": "ਇਹ ਸ਼ਾਇਦ ਤੁਹਾਡੇ ਫਰੋਲੂ ਜਾਂ ਇੰਟਰਨੈੱਟ ਜੋੜ ਦੀਆਂ ਗੁੰਝਲਾਂ ਕਰਕੇ ਹੋ ਰਿਹਾ ਹੈ।", - "pad.modals.slowcommit.explanation": "ਸਰਵਰ ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਿਹਾ ਹੈ।", - "pad.modals.slowcommit.cause": "ਇਹ ਨੈੱਟਵਰਕ ਕੁਨੈਕਸ਼ਨ ਨਾਲ ਸਮੱਸਿਆ ਕਰਕੇ ਹੋ ਸਕਦਾ ਹੈ।", - "pad.modals.badChangeset.explanation": "ਤੁਹਾਡੇ ਵੱਲੋਂ ਕੀਤੀ ਇੱਕ ਸੋਧ ਨੂੰ ਇੱਕਰੂਪੀ ਸਰਵਰ ਨੇ ਗ਼ੈਰ-ਕਨੂੰਨੀ ਕਰਾਰ ਦਿੱਤਾ ਹੈ।", - "pad.modals.badChangeset.cause": "ਇਹ ਸਿਸਟਮ ਦੀ ਕਿਸੇ ਗ਼ਲਤ ਨੁਹਾਰ ਜਾਂ ਕੋਈ ਹੋਰ ਅਣਸੋਚੇ ਵਤੀਰਾ ਕਰਕੇ ਵਾਪਰ ਸਕਦਾ ਹੈ। ਜੇਕਰ ਤੁਹਾਨੂੰ ਇਹ ਇੱਕ ਦੋਸ਼ ਲੱਗਦਾ ਹੈ ਤਾਂ ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪ੍ਰਬੰਧਕ ਨਾਲ਼ ਰਾਬਤਾ ਬਣਾਉ। ਸੋਧ ਜਾਰੀ ਰੱਖਣ ਵਾਸਤੇ ਮੁੜ ਜੁੜੋ।", - "pad.modals.corruptPad.explanation": "ਜਿਸ ਪੈਡ ਤੱਕ ਤੁਸੀਂ ਪਹੁੰਚਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਉਹ ਖੋਟਾ ਹੈ।", - "pad.modals.corruptPad.cause": "ਇਹ ਸਿਸਟਮ ਦੀ ਕਿਸੇ ਗ਼ਲਤ ਨੁਹਾਰ ਜਾਂ ਕੋਈ ਹੋਰ ਅਣਸੋਚੇ ਵਤੀਰਾ ਕਰਕੇ ਵਾਪਰ ਸਕਦਾ ਹੈ। ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪ੍ਰਬੰਧਕ ਨਾਲ਼ ਰਾਬਤਾ ਬਣਾਉ।", - "pad.modals.deleted": "ਹਟਾਇਆ।", - "pad.modals.deleted.explanation": "ਇਹ ਪੈਡ ਹਟਾਇਆ ਜਾ ਚੁੱਕਾ ਹੈ।", - "pad.modals.disconnected": "ਤੁਸੀਂ ਡਿਸ-ਕੁਨੈਕਟ ਹੋ ਚੁੱਕੇ ਹੋ।", - "pad.modals.disconnected.explanation": "ਸਰਵਰ ਨਾਲ ਕੁਨੈਕਸ਼ਨ ਖਤਮ ਹੋਇਆ ਹੈ", - "pad.modals.disconnected.cause": "ਸਰਵਰ ਨਾਮੌਜੂਦ ਹੋ ਸਕਦਾ ਹੈ। ਜੇਕਰ ਇਹ ਹੁੰਦਾ ਰਹੇ ਤਾਂ ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਸੇਵਾ ਪ੍ਰਬੰਧਕ ਨੂੰ ਖ਼ਬਰ ਕਰੋ।", - "pad.share": "ਇਹ ਪੈਡ ਸਾਂਝਾ ਕਰੋ", - "pad.share.readonly": "ਕੇਵਲ ਪੜ੍ਹਨ ਲਈ", - "pad.share.link": "ਲਿੰਕ", - "pad.share.emebdcode": "ਇੰਬੈੱਡ URL", - "pad.chat": "ਗੱਲਬਾਤ", - "pad.chat.title": "ਇਹ ਪੈਡ ਲਈ ਗੱਲਬਾਤ ਖੋਲ੍ਹੋ।", - "pad.chat.loadmessages": "ਹੋਰ ਸੁਨੇਹੇ ਲੋਡ ਕਰੋ", - "timeslider.pageTitle": "{{appTitle}} ਸਮਾਂ-ਲਕੀਰ", - "timeslider.toolbar.returnbutton": "ਪੈਡ ਉੱਤੇ ਵਾਪਸ", - "timeslider.toolbar.authors": "ਲੇਖਕ:", - "timeslider.toolbar.authorsList": "ਕੋਈ ਲੇਖਕ ਨਹੀਂ", - "timeslider.toolbar.exportlink.title": "ਐਕਸਪੋਰਟ", - "timeslider.exportCurrent": "ਮੌਜੂਦਾ ਵਰਜਨ ਇੰਝ ਐਕਸਪੋਰਟ ਕਰੋ:", - "timeslider.version": "ਵਰਜ਼ਨ {{version}}", - "timeslider.saved": "{{day}} {{month}} {{year}} ਨੂੰ ਸੰਭਾਲਿਆ", - "timeslider.playPause": "ਪੈਡ ਸਮੱਗਰੀ ਚਲਾਓ / ਵਿਰਾਮ ਕਰੋ", - "timeslider.backRevision": "ਇਸ ਪੈਡ ਵਿੱਚ ਪਿਛਲੇ ਰੀਵਿਜ਼ਨ ਤੇ ਜਾਓ", - "timeslider.forwardRevision": "ਇਸ ਪੈਡ ਵਿੱਚ ਅਗਲੇ ਰੀਵਿਜ਼ਨ ਤੇ ਜਾਓ", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "ਜਨਵਰੀ", - "timeslider.month.february": "ਫ਼ਰਵਰੀ", - "timeslider.month.march": "ਮਾਰਚ", - "timeslider.month.april": "ਅਪਰੈਲ", - "timeslider.month.may": "ਮਈ", - "timeslider.month.june": "ਜੂਨ", - "timeslider.month.july": "ਜੁਲਾਈ", - "timeslider.month.august": "ਅਗਸਤ", - "timeslider.month.september": "ਸਤੰਬਰ", - "timeslider.month.october": "ਅਕਤੂਬਰ", - "timeslider.month.november": "ਨਵੰਬਰ", - "timeslider.month.december": "ਦਸੰਬਰ", - "timeslider.unnamedauthors": "{{num}} ਬੇਨਾਮ {[plural(num) one: ਲੇਖਕ, other: ਲੇਖਕ ]}", - "pad.savedrevs.marked": "ਇਹ ਰੀਵਿਜ਼ਨ ਨੂੰ ਹੁਣ ਸੰਭਾਲੇ ਹੋਏ ਰੀਵਿਜ਼ਨ ਵਜੋਂ ਮੰਨਿਆ ਗਿਆ ਹੈ", - "pad.savedrevs.timeslider": "ਤੁਸੀੰ ਸਾੰਭੀਆੰ ਹੋਈਆੰ ਵਰਜਨਾੰ ਸਮਾੰਸਲਾਈਡਰ ਤੇ ਜਾ ਕੇ ਵੇਖ ਸਕਦੇ ਹੋ", - "pad.userlist.entername": "ਆਪਣਾ ਨਾਂ ਦਿਉ", - "pad.userlist.unnamed": "ਬੇਨਾਮ", - "pad.userlist.guest": "ਮਹਿਮਾਨ", - "pad.userlist.deny": "ਪਾਬੰਦੀ", - "pad.userlist.approve": "ਮਨਜ਼ੂਰ", - "pad.editbar.clearcolors": "ਪੂਰੇ ਦਸਾਤਵੇਜ਼ ਉੱਤੇ ਪਰਮਾਣਕਿਤਾ ਰੰਗ ਸਾਫ਼ ਕਰਨੇ ਹਨ?", - "pad.impexp.importbutton": "ਹੁਣੇ ਇੰਪੋਰਟ ਕਰੋ", - "pad.impexp.importing": "...ਇੰਪੋਰਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ", - "pad.impexp.confirmimport": "ਕੋਈ ਫ਼ਾਈਲ ਦਰਾਮਦ ਕਾਰਨ ਨਾਲ਼ ਪੈਡ ਦੀ ਮੌਜੂਦਾ ਲਿਖਤ ਉੱਤੇ ਲਿਖਿਆ ਜਾਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਸੱਚੀਂ ਇਹ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?", - "pad.impexp.convertFailed": "ਅਸੀਂ ਇਸ ਫ਼ਾਈਲ ਦੀ ਦਰਾਮਦ ਨਹੀਂ ਕਰ ਸਕੇ। ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਕੋਈ ਵੱਖਰੀ ਦਸਤਾਵੇਜ਼ੀ ਰੂਪ-ਰੇਖਾ ਵਰਤੋ ਜਾਂ ਹੱਥੀਂ ਨਕਲ-ਚੇਪੀ ਕਰੋ।", - "pad.impexp.padHasData": "ਅਸੀ ਇਸ ਫਾਈਲ ਨੂੰ ਆਯਾਤ ਨਹੀੰ ਕਰ ਸਕੇ ਕਿਉੰਕਿ ਇਸ ਪੈਡ ਉੱਤੇ ਪਹਿਲਾੰ ਹੀ ਤਬਦੀਲੀਆੰ ਕੀਤੀਆੰ ਜਾ ਚੁਕੀਆੰ ਹਨ, ਕਿਰਪਾ ਕਰਕੇ ਨਵੇੰ ਪੈਡ ਵਿਚ ਆਯਾਤ ਕਰੋ", - "pad.impexp.uploadFailed": "ਅੱਪਲੋਡ ਲਈ ਫੇਲ੍ਹ ਹੈ, ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਜੀ।", - "pad.impexp.importfailed": "ਇੰਪੋਰਟ ਫੇਲ੍ਹ ਹੈ", - "pad.impexp.copypaste": "ਕਾਪੀ ਕਰੋ ਚੇਪੋ ਜੀ", - "pad.impexp.exportdisabled": "{{type}} ਫਾਰਮੈਟ ਵਜੋਂ ਬਰਾਮਦ ਕਰਨਾ ਬੰਦ ਹੈ। ਵੇਰਵੇ ਵਾਸਤੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪਰਬੰਧਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।" -} diff --git a/sources/src/locales/pl.json b/sources/src/locales/pl.json deleted file mode 100644 index c263287..0000000 --- a/sources/src/locales/pl.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Rezonansowy", - "Ty221", - "WTM", - "Woytecr", - "Macofe", - "Pan Cube", - "Mateon1", - "Teeed" - ] - }, - "index.newPad": "Nowy dokument", - "index.createOpenPad": "lub stwórz/otwórz dokument o nazwie:", - "pad.toolbar.bold.title": "Pogrubienie (Ctrl-B)", - "pad.toolbar.italic.title": "Kursywa (Ctrl-I)", - "pad.toolbar.underline.title": "Podkreślenie (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Przekreślenie (Ctrl+5)", - "pad.toolbar.ol.title": "Lista uporządkowana (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Lista nieuporządkowana (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Wcięcie (TAB)", - "pad.toolbar.unindent.title": "Usunięcie wcięcia (Shift + TAB)", - "pad.toolbar.undo.title": "Cofnij (Ctrl-Z)", - "pad.toolbar.redo.title": "Ponów (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Usuń kolory autorów (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Import/eksport z/do różnych formatów plików", - "pad.toolbar.timeslider.title": "Oś czasu", - "pad.toolbar.savedRevision.title": "Zapisz wersję", - "pad.toolbar.settings.title": "Ustawienia", - "pad.toolbar.embed.title": "Podziel się i osadź ten dokument", - "pad.toolbar.showusers.title": "Pokaż użytkowników", - "pad.colorpicker.save": "Zapisz", - "pad.colorpicker.cancel": "Anuluj", - "pad.loading": "Ładowanie...", - "pad.noCookie": "Nie znaleziono pliku cookie. Proszę zezwolić na pliki cookie w przeglądarce!", - "pad.passwordRequired": "Musisz podać hasło aby uzyskać dostęp do tego dokumentu", - "pad.permissionDenied": "Nie masz uprawnień dostępu do tego dokumentu", - "pad.wrongPassword": "Nieprawidłowe hasło", - "pad.settings.padSettings": "Ustawienia dokumentu", - "pad.settings.myView": "Mój widok", - "pad.settings.stickychat": "Czat zawsze na ekranie", - "pad.settings.chatandusers": "Pokaż czat i użytkowników", - "pad.settings.colorcheck": "Kolory autorstwa", - "pad.settings.linenocheck": "Numery linii", - "pad.settings.rtlcheck": "Czytasz treść od prawej do lewej?", - "pad.settings.fontType": "Rodzaj czcionki:", - "pad.settings.fontType.normal": "Normalna", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Widok ogólny", - "pad.settings.language": "Język:", - "pad.importExport.import_export": "Import/eksport", - "pad.importExport.import": "Prześlij dowolny plik tekstowy lub dokument", - "pad.importExport.importSuccessful": "Sukces!", - "pad.importExport.export": "Eksportuj bieżący dokument jako:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Zwykły tekst", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Możesz importować pliki tylko w formacie zwykłego tekstu lub html. Aby umożliwić bardziej zaawansowane funkcje importu, zainstaluj abiword.", - "pad.modals.connected": "Połączony.", - "pad.modals.reconnecting": "Ponowne łączenie z dokumentem...", - "pad.modals.forcereconnect": "Wymuś ponowne połączenie", - "pad.modals.reconnecttimer": "Trwa próba ponownego połączenia", - "pad.modals.cancel": "Anuluj", - "pad.modals.userdup": "Otwarty w innym oknie", - "pad.modals.userdup.explanation": "Ten dokument prawdopodobnie został otwarty w więcej niż jednym oknie przeglądarki.", - "pad.modals.userdup.advice": "Połącz ponownie przy użyciu tego okna.", - "pad.modals.unauth": "Brak autoryzacji", - "pad.modals.unauth.explanation": "Twoje uprawnienia uległy zmianie podczas przeglądania tej strony. Spróbuj ponownie się połączyć.", - "pad.modals.looping.explanation": "Wystąpiły problemy z komunikacją z serwerem synchronizacji.", - "pad.modals.looping.cause": "Być może jesteś połączony przez niezgodną zaporę lub serwer proxy.", - "pad.modals.initsocketfail": "Serwer jest nieosiągalny.", - "pad.modals.initsocketfail.explanation": "Nie udało się połączyć z serwerem synchronizacji.", - "pad.modals.initsocketfail.cause": "Prawdopodobnie jest to spowodowane problemami z przeglądarką lub połączeniem internetowym.", - "pad.modals.slowcommit.explanation": "Serwer nie odpowiada.", - "pad.modals.slowcommit.cause": "Może być to spowodowane problemami z Twoim połączeniem sieciowym.", - "pad.modals.badChangeset.explanation": "Edycja, którą wykonałeś, została uznana przez serwer synchronizacji jako niepoprawna.", - "pad.modals.badChangeset.cause": "Może być to spowodowane złą konfiguracją serwera lub innym nieoczekiwanym zachowaniem. Skontaktuj się z administratorem serwisu, jeżeli wydaje Ci się, że to jest błąd. Spróbuj połączyć się ponownie aby kontynuować edycję.", - "pad.modals.corruptPad.explanation": "Dokument, do którego próbujesz uzyskać dostęp, jest uszkodzony.", - "pad.modals.corruptPad.cause": "Może być to spowodowane złą konfiguracją serwera lub innym nieoczekiwanym zachowaniem. Skontaktuj się z administratorem serwisu.", - "pad.modals.deleted": "Usunięto.", - "pad.modals.deleted.explanation": "Ten dokument został usunięty.", - "pad.modals.disconnected": "Zostałeś rozłączony.", - "pad.modals.disconnected.explanation": "Utracono połączenie z serwerem", - "pad.modals.disconnected.cause": "Serwer może być niedostępny. Poinformuj administratora serwisu jeżeli problem będzie się powtarzał.", - "pad.share": "Udostępnij ten dokument", - "pad.share.readonly": "Tylko do odczytu", - "pad.share.link": "Link", - "pad.share.emebdcode": "URL do umieszczenia", - "pad.chat": "Czat", - "pad.chat.title": "Otwórz czat dla tego dokumentu.", - "pad.chat.loadmessages": "Załaduj więcej wiadomości", - "timeslider.pageTitle": "Oś czasu {{appTitle}}", - "timeslider.toolbar.returnbutton": "Powróć do dokumentu", - "timeslider.toolbar.authors": "Autorzy:", - "timeslider.toolbar.authorsList": "Brak autorów", - "timeslider.toolbar.exportlink.title": "Eksportuj", - "timeslider.exportCurrent": "Eksportuj bieżącą wersję jako:", - "timeslider.version": "Wersja {{version}}", - "timeslider.saved": "Zapisano {{day}} {{month}} {{year}}", - "timeslider.playPause": "Odtwarzaj / zatrzymaj przewijanie historii dokumentu", - "timeslider.backRevision": "Przejdź do poprzedniej wersji dokumentu", - "timeslider.forwardRevision": "Przejdź do następnej wersji dokumentu", - "timeslider.dateformat": "{{year}}-{{month}}-{{day}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Styczeń", - "timeslider.month.february": "Luty", - "timeslider.month.march": "Marzec", - "timeslider.month.april": "Kwiecień", - "timeslider.month.may": "Maj", - "timeslider.month.june": "Czerwiec", - "timeslider.month.july": "Lipiec", - "timeslider.month.august": "Sierpień", - "timeslider.month.september": "Wrzesień", - "timeslider.month.october": "Październik", - "timeslider.month.november": "Listopad", - "timeslider.month.december": "Grudzień", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: nienazwany autor, other: nienazwanych autorów ]}", - "pad.savedrevs.marked": "Ta wersja została właśnie oznaczona jako zapisana.", - "pad.savedrevs.timeslider": "Możesz zobaczyć zapisane wersje na osi czasu", - "pad.userlist.entername": "Wprowadź swoją nazwę", - "pad.userlist.unnamed": "bez nazwy", - "pad.userlist.guest": "Gość", - "pad.userlist.deny": "Zabroń", - "pad.userlist.approve": "Zezwól", - "pad.editbar.clearcolors": "Wyczyścić kolory autorstwa w całym dokumencie?", - "pad.impexp.importbutton": "Importuj teraz", - "pad.impexp.importing": "Importowanie...", - "pad.impexp.confirmimport": "Importowanie pliku spowoduje zastąpienie bieżącego tekstu. Czy na pewno chcesz kontynuować?", - "pad.impexp.convertFailed": "Nie byliśmy w stanie zaimportować tego pliku. Proszę użyć innego formatu dokumentu lub skopiować i wkleić ręcznie", - "pad.impexp.padHasData": "Nie udało się zaimportować tego pliku, bo ten dokument ma już zmiany, proszę zaimportować do nowego dokumentu", - "pad.impexp.uploadFailed": "Przesyłanie nie powiodło się, proszę spróbować jeszcze raz", - "pad.impexp.importfailed": "Importowanie nie powiodło się", - "pad.impexp.copypaste": "Proszę skopiować i wkleić", - "pad.impexp.exportdisabled": "Eksport do formatu {{type}} jest wyłączony. Proszę skontaktować się z administratorem aby uzyskać więcej szczegółów." -} diff --git a/sources/src/locales/pms.json b/sources/src/locales/pms.json deleted file mode 100644 index cdc80be..0000000 --- a/sources/src/locales/pms.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Borichèt" - ] - }, - "index.newPad": "Feuj neuv", - "index.createOpenPad": "o creé/duverté un feuj antitolà:", - "pad.toolbar.bold.title": "Grassèt (Ctrl+B)", - "pad.toolbar.italic.title": "Corsiv (Ctrl+I)", - "pad.toolbar.underline.title": "Sotlignà (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Barà (Ctrl+5)", - "pad.toolbar.ol.title": "Lista ordinà (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Lista nen ordinà (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Andenté (TAB)", - "pad.toolbar.unindent.title": "Disandenté (Maj+TAB)", - "pad.toolbar.undo.title": "Anulé (Ctrl+Z)", - "pad.toolbar.redo.title": "Ristabilì (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Dëscancelé ij color ch'a identìfico j'autor (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Amporté/Esporté da/vers dij formà d'archivi diferent", - "pad.toolbar.timeslider.title": "Stòria dinàmica", - "pad.toolbar.savedRevision.title": "Argistré la revision", - "pad.toolbar.settings.title": "Paràmeter", - "pad.toolbar.embed.title": "Partagé e antëgré ës feuj", - "pad.toolbar.showusers.title": "Smon-e j'utent ansima a 's feuj", - "pad.colorpicker.save": "Argistré", - "pad.colorpicker.cancel": "Anulé", - "pad.loading": "Antramentr ch'as caria…", - "pad.noCookie": "Ël bëscotin a l'é nen ëstàit trovà. Për piasì, ch'a autorisa ij bëscotin su sò navigador!", - "pad.passwordRequired": "A l'ha da manca ëd na ciav për acede a cost feuj-sì", - "pad.permissionDenied": "A l'ha nen ël përmess d'acede a 's feuj-sì", - "pad.wrongPassword": "Soa ciav a l'era nen giusta", - "pad.settings.padSettings": "Paràmeter dël feuj", - "pad.settings.myView": "Mia vista", - "pad.settings.stickychat": "Ciaciarade sempe an slë scren", - "pad.settings.chatandusers": "Smon-e le ciaciarade e j'utent", - "pad.settings.colorcheck": "Color d'identificassion", - "pad.settings.linenocheck": "Nùmer ëd linia", - "pad.settings.rtlcheck": "Ël contnù, dev-lo esse lesù da drita a snistra?", - "pad.settings.fontType": "Sòrt ëd caràter:", - "pad.settings.globalView": "Vista d'ansem", - "pad.settings.language": "Lenga:", - "pad.importExport.import_export": "Amporté/Esporté", - "pad.importExport.import": "Carié n'archivi o document ëd test", - "pad.importExport.importSuccessful": "Bele fàit!", - "pad.importExport.export": "Esporté ël feuj atual coma:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Mach test", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "A peul mach amporté dij formà ëd test sempi o HTML. Për dle fonsionalità d'amportassion pi avansà, ch'a anstala AbiWord.", - "pad.modals.connected": "Colegà.", - "pad.modals.reconnecting": "Neuva conession a sò feuj...", - "pad.modals.forcereconnect": "Forsé la neuva conession", - "pad.modals.reconnecttimer": "Tentativ ëd neuva conession", - "pad.modals.cancel": "Anulé", - "pad.modals.userdup": "Duvertà an n'àutra fnestra", - "pad.modals.userdup.explanation": "Ës feuj a smija esse duvert an vàire fnestre ansima a st'ordinator.", - "pad.modals.userdup.advice": "Coleghesse torna për dovré costa fnestra.", - "pad.modals.unauth": "Nen autorisà", - "pad.modals.unauth.explanation": "Ij sò përmess a son cangià antramentre ch'a vëdìa costa pàgina. Ch'a sërca ëd coleghesse torna.", - "pad.modals.looping.explanation": "A-i é dij problema ëd comunicassion con ël servent ëd sincronisassion.", - "pad.modals.looping.cause": "Peul desse che chiel a l'é colegasse con un para-feu o un mandatari incompatìbil.", - "pad.modals.initsocketfail": "Ël servent a l'é introvàbil.", - "pad.modals.initsocketfail.explanation": "Impossìbil coleghesse al servent ëd sincronisassion.", - "pad.modals.initsocketfail.cause": "A l'é probàbil che sòn a sia dovù a sò navigador o a soa conession an sl'aragnà.", - "pad.modals.slowcommit.explanation": "Ël servent a rëspond nen.", - "pad.modals.slowcommit.cause": "Sòn a podrìa esse dovù a dij problema ëd conession a l'aragnà.", - "pad.modals.badChangeset.explanation": "Na modìfica ch'a l'ha fàit a l'é stàita cassificà tanme ilegal dal servent ëd sincronisassion.", - "pad.modals.badChangeset.cause": "Sòn a podrìa esse dovù a na bruta configurassion dël servent o a chèich àutr comportament nen ëspetà. Për piasì, ch'a contata l'aministrator dël servissi, s'a pensa ch'a sia n'eror. Ch'a preuva a rintré torna ant ël sistema për andé anans a modifiché.", - "pad.modals.corruptPad.explanation": "Ël feuj al qual a sërca d'acede a l'é corompù.", - "pad.modals.corruptPad.cause": "Sòn a podrìa esse dovù a na configurassion ësbalià dël servent o a chèich àutr comportament nen ëspetà. Për piasì, ch'a contata l'aministrator dël servissi.", - "pad.modals.deleted": "Dëscancelà.", - "pad.modals.deleted.explanation": "Ës feuj a l'é stàit eliminà.", - "pad.modals.disconnected": "A l'é stàit dëscolegà", - "pad.modals.disconnected.explanation": "La conession al servent a l'é perdusse", - "pad.modals.disconnected.cause": "Ël servent a podrìa esse indisponìbil. Për piasì, ch'a anforma l'aministrator dël servissi si ël problema a persist.", - "pad.share": "Partagé 's feuj", - "pad.share.readonly": "Mach letura", - "pad.share.link": "Liura", - "pad.share.emebdcode": "Ancorporé na liura", - "pad.chat": "Ciaciarada", - "pad.chat.title": "Duverté la ciaciarada për cost feuj.", - "pad.chat.loadmessages": "Carié pi 'd mëssagi", - "timeslider.pageTitle": "Stòria dinàmica ëd {{appTitle}}", - "timeslider.toolbar.returnbutton": "Torné al feuj", - "timeslider.toolbar.authors": "Autor:", - "timeslider.toolbar.authorsList": "Gnun autor", - "timeslider.toolbar.exportlink.title": "Esporté", - "timeslider.exportCurrent": "Esporté la version corenta tanme:", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Argistrà ai {{day}} {{month}} {{year}}", - "timeslider.playPause": "Letura / Pàusa dij contnù dël feuj", - "timeslider.backRevision": "Andé andaré ëd na revision ant ës feuj", - "timeslider.forwardRevision": "Andé anans ëd na revision ant ëd feuj", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Gené", - "timeslider.month.february": "Fërvé", - "timeslider.month.march": "Mars", - "timeslider.month.april": "Avril", - "timeslider.month.may": "Maj", - "timeslider.month.june": "Giugn", - "timeslider.month.july": "Luj", - "timeslider.month.august": "Ost", - "timeslider.month.september": "Stèmber", - "timeslider.month.october": "Otóber", - "timeslider.month.november": "Novèmber", - "timeslider.month.december": "Dzèmber", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor anònim, other: autor anònim ]}", - "pad.savedrevs.marked": "Sa revision a l'é adess marcà tanme revision argistrà", - "pad.savedrevs.timeslider": "A peul vëdde le revision argistrà an visitand la stòria", - "pad.userlist.entername": "Ch'a buta sò nòm", - "pad.userlist.unnamed": "anònim", - "pad.userlist.guest": "Anvità", - "pad.userlist.deny": "Arfudé", - "pad.userlist.approve": "Aprové", - "pad.editbar.clearcolors": "Dëscancelé ij color ëd paternità dj'autor an tut ël document?", - "pad.impexp.importbutton": "Amporté adess", - "pad.impexp.importing": "An camin ch'as ampòrta...", - "pad.impexp.confirmimport": "Amportand n'archivi as dëscancelërà ël test corent dël feuj. É-lo sigur ëd vorèj felo?", - "pad.impexp.convertFailed": "I l'oma nen podù amporté s'archivi. Për piasì, ch'a deuvra n'àutr formà ëd document o ch'a còpia e ancòla a man", - "pad.impexp.padHasData": "I l'oma nen podù amporté s'archivi përché 's feuj a l'ha già avù dle modìfiche; për piasì, ch'a ampòrta un feuj neuv", - "pad.impexp.uploadFailed": "Ël cariament a l'ha falì, për piasì ch'a preuva torna", - "pad.impexp.importfailed": "Amportassion falìa", - "pad.impexp.copypaste": "Për piasì, ch'a còpia e ancòla", - "pad.impexp.exportdisabled": "L'esportassion an formà {{type}} a l'é disativà. Për piasì, ch'a contata sò aministrator ëd sistema për ij detaj." -} diff --git a/sources/src/locales/ps.json b/sources/src/locales/ps.json deleted file mode 100644 index 8db3a89..0000000 --- a/sources/src/locales/ps.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Ahmed-Najib-Biabani-Ibrahimkhel" - ] - }, - "index.newPad": "نوې ليکچه", - "index.createOpenPad": "يا په همدې نوم يوه نوې ليکچه جوړول/پرانيستل:", - "pad.toolbar.bold.title": "زغرد (Ctrl-B)", - "pad.toolbar.italic.title": "رېوند (Ctrl-I)", - "pad.toolbar.underline.title": "لرکرښن (Ctrl+U)", - "pad.toolbar.strikethrough.title": "کرښکاږلی (Ctrl+5)", - "pad.toolbar.ol.title": "ترتيب شوی لړليک (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "ناترتيب شوی لړليک (Ctrl+Shift+L)", - "pad.toolbar.undo.title": "ناکړل (Ctrl-Z)", - "pad.toolbar.redo.title": "بياکړل (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "د ليکوالۍ رنگونه سپينول (Ctrl+Shift+C)", - "pad.toolbar.savedRevision.title": "مخکتنه خوندي کول", - "pad.toolbar.settings.title": "امستنې", - "pad.colorpicker.save": "خوندي کول", - "pad.colorpicker.cancel": "ناگارل", - "pad.loading": "رابرسېرېږي...", - "pad.passwordRequired": "دې ليکچې ته د لاسرسي لپاره تاسې يو پټنوم ته اړتيا لرۍ", - "pad.wrongPassword": "پټنوم مو سم نه و", - "pad.settings.padSettings": "د ليکچې امستنې", - "pad.settings.myView": "زما کتنه", - "pad.settings.stickychat": "تل په پردې بانډار کول", - "pad.settings.chatandusers": "کارنان او بانډار ښکاره کول", - "pad.settings.colorcheck": "د ليکوالۍ رنگونه", - "pad.settings.linenocheck": "د کرښو شمېرې", - "pad.settings.fontType": "ليکبڼې ډول:", - "pad.settings.fontType.normal": "نورمال", - "pad.settings.fontType.monospaced": "مونوسپېس", - "pad.settings.globalView": "نړېواله ښکارېدنه", - "pad.settings.language": "ژبه:", - "pad.importExport.importSuccessful": "بريالی شو!", - "pad.importExport.exportetherpad": "اېترپډ", - "pad.importExport.exporthtml": "اچ ټي ام اېل", - "pad.importExport.exportplain": "ساده متن", - "pad.importExport.exportword": "مايکروسافټ ورډ", - "pad.importExport.exportpdf": "پي ډي اېف", - "pad.importExport.exportopen": "ODF (اوپن ډاکومنټ فارمټ)", - "pad.modals.connected": "اړيکمن شو.", - "pad.modals.slowcommit.explanation": "پالنگر ځواب نه وايي.", - "pad.modals.slowcommit.cause": "دا کېدای شي د جال د اړيکتيايي ستونزو په سبب وي.", - "pad.modals.deleted": "ړنگ شو.", - "pad.share.readonly": "يوازې لوستنه", - "pad.share.link": "تړنه", - "pad.share.emebdcode": "يو آر اېل ټومبل", - "pad.chat": "بانډار", - "pad.chat.loadmessages": "نور پيغامونه برسېرول", - "timeslider.toolbar.authors": "ليکوال:", - "timeslider.toolbar.authorsList": "بې ليکواله", - "timeslider.toolbar.exportlink.title": "صادرول", - "timeslider.version": "بڼه {{version}}", - "timeslider.saved": "خوندي شو {{month}} {{day}}, {{year}}", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "جنوري", - "timeslider.month.february": "فبروري", - "timeslider.month.march": "مارچ", - "timeslider.month.april": "اپرېل", - "timeslider.month.may": "مۍ", - "timeslider.month.june": "جون", - "timeslider.month.july": "جولای", - "timeslider.month.august": "اگسټ", - "timeslider.month.september": "سېپتمبر", - "timeslider.month.october": "اکتوبر", - "timeslider.month.november": "نومبر", - "timeslider.month.december": "ډيسمبر", - "timeslider.unnamedauthors": "{{num}} بې نومه {[ډېرگړي(num) يو: ليکوال، نور: ليکوالان ]}", - "pad.savedrevs.marked": "اوس دا مخکتنه د يوې خوندي شوې مخکتنې په توگه په نښه شوه", - "pad.userlist.entername": "نوم مو ورکړۍ", - "pad.userlist.unnamed": "بې نومه", - "pad.userlist.guest": "مېلمه", - "pad.userlist.deny": "ردول", - "pad.userlist.approve": "منل", - "pad.impexp.importbutton": "اوس واردول", - "pad.impexp.importing": "په واردولو کې دی...", - "pad.impexp.copypaste": "لطفاً لمېسل لېښل ترسره کړئ" -} diff --git a/sources/src/locales/pt-br.json b/sources/src/locales/pt-br.json deleted file mode 100644 index d72a712..0000000 --- a/sources/src/locales/pt-br.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Gusta", - "Luckas", - "Prilopes", - "TheGabrielZaum", - "Titoncio", - "Tuliouel", - "Rafaelff", - "Dianakc", - "Macofe", - "Rodrigo codignoli", - "Webysther", - "Fasouzafreitas", - "Lpagliari", - "Walesson", - "Cainamarques", - "Eduardo Addad de Oliveira" - ] - }, - "index.newPad": "Nova Nota", - "index.createOpenPad": "ou criar-abrir uma Nota com o nome:", - "pad.toolbar.bold.title": "Negrito (Ctrl-B)", - "pad.toolbar.italic.title": "Itálico (Ctrl-I)", - "pad.toolbar.underline.title": "Sublinhado (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Tachado (Ctrl+5)", - "pad.toolbar.ol.title": "Lista ordenada (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Lista não ordenada (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Aumentar Recuo (TAB)", - "pad.toolbar.unindent.title": "Diminuir Recuo (Shift+TAB)", - "pad.toolbar.undo.title": "Desfazer (Ctrl-Z)", - "pad.toolbar.redo.title": "Refazer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Limpar as cores de identificação de autoria (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importar/Exportar de/para diferentes formatos de arquivo", - "pad.toolbar.timeslider.title": "Linha do tempo", - "pad.toolbar.savedRevision.title": "Salvar revisão", - "pad.toolbar.settings.title": "Configurações", - "pad.toolbar.embed.title": "Compartilhar e incorporar esta Nota", - "pad.toolbar.showusers.title": "Mostrar os usuarios nesta Nota", - "pad.colorpicker.save": "Salvar", - "pad.colorpicker.cancel": "Cancelar", - "pad.loading": "Carregando...", - "pad.noCookie": "Cookie não foi encontrado. Por favor, habilite cookies no seu navegador!", - "pad.passwordRequired": "Você precisa de uma senha para acessar esta Nota", - "pad.permissionDenied": "Você não tem permissão para acessar esta Nota", - "pad.wrongPassword": "Senha incorreta", - "pad.settings.padSettings": "Configurações da Nota", - "pad.settings.myView": "Minha Visão", - "pad.settings.stickychat": "Bate-papo sempre visível", - "pad.settings.chatandusers": "Mostrar o bate-papo e os usuários", - "pad.settings.colorcheck": "Cores de autoria", - "pad.settings.linenocheck": "Números de linha", - "pad.settings.rtlcheck": "Ler conteúdo da direita para esquerda?", - "pad.settings.fontType": "Tipo de fonte:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespaçada", - "pad.settings.globalView": "Visão global", - "pad.settings.language": "Idioma:", - "pad.importExport.import_export": "Importar/Exportar", - "pad.importExport.import": "Enviar um arquivo texto ou documento", - "pad.importExport.importSuccessful": "Completo!", - "pad.importExport.export": "Exportar a nota atual como:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Texto puro", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Você só pode importar de formatos de texto puro ou html. Para recursos de importação mais avançados instale o abiword.", - "pad.modals.connected": "Conectado.", - "pad.modals.reconnecting": "Reconectando à sua nota...", - "pad.modals.forcereconnect": "Forçar reconexão", - "pad.modals.reconnecttimer": "Tentando se reconectar", - "pad.modals.cancel": "Cancelar", - "pad.modals.userdup": "Aberto em outra janela", - "pad.modals.userdup.explanation": "Esta nota parece estar aberta em mais de uma janela de navegador deste computador.", - "pad.modals.userdup.advice": "Reconectar para usar esta janela.", - "pad.modals.unauth": "Não autorizado", - "pad.modals.unauth.explanation": "Suas permissões foram mudadas enquanto visualizava esta página. Tente reconectar.", - "pad.modals.looping.explanation": "Há problemas de comunicação com o servidor de sincronização.", - "pad.modals.looping.cause": "Talvez você tenha conectado por um firewall ou proxy incompatível.", - "pad.modals.initsocketfail": "Servidor está indisponível.", - "pad.modals.initsocketfail.explanation": "Não foi possível conectar com o servidor de sincronização.", - "pad.modals.initsocketfail.cause": "Isto provavelmente ocorreu por um problema em seu navegador ou conexão.", - "pad.modals.slowcommit.explanation": "O servidor não responde.", - "pad.modals.slowcommit.cause": "Isto pode ser por problemas com a conexão de rede.", - "pad.modals.badChangeset.explanation": "Uma edição que você fez foi classificada como ilegal pelo servidor de sincronização.", - "pad.modals.badChangeset.cause": "Isto pode ocorrer devido a uma configuração errada do servidor ou algum outro comportamento inesperado. Por favor contate o administrador, se você acredita que é um erro. Tente reconectar para continuar editando.", - "pad.modals.corruptPad.explanation": "A nota que você está tentando acessar está corrompida.", - "pad.modals.corruptPad.cause": "Isto pode ocorrer devido a uma configuração errada do servidor ou algum outro comportamento inesperado. Por favor contate o administrador.", - "pad.modals.deleted": "Excluído.", - "pad.modals.deleted.explanation": "Esta nota foi removida.", - "pad.modals.disconnected": "Você foi desconectado.", - "pad.modals.disconnected.explanation": "A conexão com o servidor foi perdida", - "pad.modals.disconnected.cause": "O servidor pode estar indisponível. Por favor, notifique o administrador caso isso continue.", - "pad.share": "Compartilhar esta nota", - "pad.share.readonly": "Somente leitura", - "pad.share.link": "Link", - "pad.share.emebdcode": "Incorporar o URL", - "pad.chat": "Bate-papo", - "pad.chat.title": "Abrir o bate-papo desta nota.", - "pad.chat.loadmessages": "Carregar mais mensagens", - "timeslider.pageTitle": "Linha do tempo de {{appTitle}}", - "timeslider.toolbar.returnbutton": "Retornar para a nota", - "timeslider.toolbar.authors": "Autores:", - "timeslider.toolbar.authorsList": "Sem autores", - "timeslider.toolbar.exportlink.title": "Exportar", - "timeslider.exportCurrent": "Exportar a versão atual em formato:", - "timeslider.version": "Versão {{version}}", - "timeslider.saved": "Salvo em {{day}} de {{month}} de {{year}}", - "timeslider.playPause": "Reproduzir / Pausar conteúdo no Pad", - "timeslider.backRevision": "Voltar a uma revisão anterior neste Pad", - "timeslider.forwardRevision": "Ir a uma revisão posterior neste Pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Janeiro", - "timeslider.month.february": "Fevereiro", - "timeslider.month.march": "Março", - "timeslider.month.april": "Abril", - "timeslider.month.may": "Maio", - "timeslider.month.june": "Junho", - "timeslider.month.july": "Julho", - "timeslider.month.august": "Agosto", - "timeslider.month.september": "Setembro", - "timeslider.month.october": "Outubro", - "timeslider.month.november": "Novembro", - "timeslider.month.december": "Dezembro", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor anônimo, other: autores anônimos ]}", - "pad.savedrevs.marked": "Esta revisão foi marcada como salva", - "pad.savedrevs.timeslider": "Você pode consultar as revisões salvas visitando a linha do tempo", - "pad.userlist.entername": "Insira o seu nome", - "pad.userlist.unnamed": "Sem título", - "pad.userlist.guest": "Convidado", - "pad.userlist.deny": "Negar", - "pad.userlist.approve": "Aprovar", - "pad.editbar.clearcolors": "Deseja limpar cores de autoria em todo o documento?", - "pad.impexp.importbutton": "Importar agora", - "pad.impexp.importing": "Importando...", - "pad.impexp.confirmimport": "Importar um arquivo sobrescreverá o texto atual da nota. Tem certeza de que deseja prosseguir?", - "pad.impexp.convertFailed": "Não foi possível importar este arquivo. Use outro formato ou copie e cole manualmente", - "pad.impexp.padHasData": "Não foi possível importar este arquivo porque esta nota já tinha alterações, consulte como importar para uma nova nota", - "pad.impexp.uploadFailed": "O envio falhou. Tente outra vez", - "pad.impexp.importfailed": "A importação falhou", - "pad.impexp.copypaste": "Copie e cole", - "pad.impexp.exportdisabled": "A exportação em formato {{type}} está desativada. Comunique-se com o administrador do sistema para detalhes." -} diff --git a/sources/src/locales/pt.json b/sources/src/locales/pt.json deleted file mode 100644 index a65730a..0000000 --- a/sources/src/locales/pt.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Hamilton Abreu", - "Luckas", - "Tuliouel", - "Waldir", - "Imperadeiro98", - "Macofe", - "Ti4goc", - "Cainamarques", - "Athena in Wonderland" - ] - }, - "index.newPad": "Nova Nota", - "index.createOpenPad": "ou crie/abra uma Nota com o nome:", - "pad.toolbar.bold.title": "Negrito (Ctrl-B)", - "pad.toolbar.italic.title": "Itálico (Ctrl-I)", - "pad.toolbar.underline.title": "Sublinhado (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Riscar (Ctrl+5)", - "pad.toolbar.ol.title": "Lista ordenada (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Lista desordenada (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Avançar (TAB)", - "pad.toolbar.unindent.title": "Recuar (Shift+TAB)", - "pad.toolbar.undo.title": "Desfazer (Ctrl-Z)", - "pad.toolbar.redo.title": "Refazer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Limpar cores de autoria (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importar/exportar de/para diferentes formatos de ficheiro", - "pad.toolbar.timeslider.title": "Linha de tempo", - "pad.toolbar.savedRevision.title": "Salvar revisão", - "pad.toolbar.settings.title": "Configurações", - "pad.toolbar.embed.title": "Compartilhar e incorporar este pad", - "pad.toolbar.showusers.title": "Mostrar os utilizadores nesta Nota", - "pad.colorpicker.save": "Gravar", - "pad.colorpicker.cancel": "Cancelar", - "pad.loading": "A carregar…", - "pad.noCookie": "O cookie não foi encontrado. Por favor, ative os cookies no seu navegador!", - "pad.passwordRequired": "Precisa de uma senha para aceder a este pad", - "pad.permissionDenied": "Não tem permissão para aceder a este pad.", - "pad.wrongPassword": "A palavra-chave está errada", - "pad.settings.padSettings": "Configurações da Nota", - "pad.settings.myView": "Minha vista", - "pad.settings.stickychat": "Bate-papo sempre no ecrã", - "pad.settings.chatandusers": "Mostrar a conversação e os utilizadores", - "pad.settings.colorcheck": "Cores de autoria", - "pad.settings.linenocheck": "Números de linha", - "pad.settings.rtlcheck": "Ler o conteúdo da direita para a esquerda?", - "pad.settings.fontType": "Tipo de letra:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespaçada", - "pad.settings.globalView": "Vista global", - "pad.settings.language": "Língua:", - "pad.importExport.import_export": "Importar/Exportar", - "pad.importExport.import": "Carregar qualquer ficheiro de texto ou documento", - "pad.importExport.importSuccessful": "Bem sucedido!", - "pad.importExport.export": "Exportar a Nota atual como:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Texto simples", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Só é possível importar texto sem formatação ou HTML. Para obter funcionalidades de importação mais avançadas, por favor instale o AbiWord.", - "pad.modals.connected": "Ligado.", - "pad.modals.reconnecting": "Reconectando-se ao seu bloco…", - "pad.modals.forcereconnect": "Forçar reconexão", - "pad.modals.reconnecttimer": "A tentar religar", - "pad.modals.cancel": "Cancelar", - "pad.modals.userdup": "Aberto noutra janela", - "pad.modals.userdup.explanation": "Este pad parece estar aberto em mais do que uma janela do navegador neste computador.", - "pad.modals.userdup.advice": "Religar para utilizar esta janela.", - "pad.modals.unauth": "Não autorizado", - "pad.modals.unauth.explanation": "As suas permissões foram alteradas enquanto revia esta página. Tente religar.", - "pad.modals.looping.explanation": "Existem problemas de comunicação com o servidor de sincronização.", - "pad.modals.looping.cause": "Talvez tenha ligado por um firewall ou proxy incompatível.", - "pad.modals.initsocketfail": "O servidor está inacessível.", - "pad.modals.initsocketfail.explanation": "Não foi possível a conexão ao servidor de sincronização.", - "pad.modals.initsocketfail.cause": "Isto provavelmente ocorreu por um problema no seu navegador ou na sua ligação de Internet.", - "pad.modals.slowcommit.explanation": "O servidor não está a responder.", - "pad.modals.slowcommit.cause": "Isto pode ser por problemas com a ligação de rede.", - "pad.modals.badChangeset.explanation": "Uma edição que fez foi classificada como ilegal pelo servidor de sincronização.", - "pad.modals.badChangeset.cause": "Isto pode ocorrer devido a uma configuração errada do servidor ou algum outro comportamento inesperado. Por favor contacte o administrador, se acredita que é um erro. Tente religar para continuar a editar.", - "pad.modals.corruptPad.explanation": "A nota que está a tentar aceder está corrompida.", - "pad.modals.corruptPad.cause": "Isto pode ocorrer devido a uma configuração errada do servidor ou algum outro comportamento inesperado. Por favor contacte o administrador.", - "pad.modals.deleted": "Eliminado.", - "pad.modals.deleted.explanation": "Este pad foi removido.", - "pad.modals.disconnected": "Você foi desconectado.", - "pad.modals.disconnected.explanation": "A conexão com o servidor foi perdida", - "pad.modals.disconnected.cause": "O servidor pode estar indisponível. Por favor, notifique o administrador de serviço se isto continuar a acontecer.", - "pad.share": "Compartilhar este pad", - "pad.share.readonly": "Somente para leitura", - "pad.share.link": "Ligação", - "pad.share.emebdcode": "Incorporar o URL", - "pad.chat": "Bate-papo", - "pad.chat.title": "Abrir o bate-papo para este pad.", - "pad.chat.loadmessages": "Carregar mais mensagens", - "timeslider.pageTitle": "Linha do tempo de {{appTitle}}", - "timeslider.toolbar.returnbutton": "Voltar ao pad", - "timeslider.toolbar.authors": "Autores:", - "timeslider.toolbar.authorsList": "Sem Autores", - "timeslider.toolbar.exportlink.title": "Exportar", - "timeslider.exportCurrent": "Exportar versão atual como:", - "timeslider.version": "Versão {{version}}", - "timeslider.saved": "Gravado a {{day}} de {{month}} de {{ano}}", - "timeslider.playPause": "Reproduzir / Pausar conteúdo do Pad", - "timeslider.backRevision": "Voltar a uma revisão anterior neste Pad", - "timeslider.forwardRevision": "Ir a uma revisão posterior neste Pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Janeiro", - "timeslider.month.february": "Fevereiro", - "timeslider.month.march": "Março", - "timeslider.month.april": "Abril", - "timeslider.month.may": "Maio", - "timeslider.month.june": "Junho", - "timeslider.month.july": "Julho", - "timeslider.month.august": "Agosto", - "timeslider.month.september": "Setembro", - "timeslider.month.october": "Outubro", - "timeslider.month.november": "Novembro", - "timeslider.month.december": "Dezembro", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autor anónimo, other: autores anónimos ]}", - "pad.savedrevs.marked": "Esta revisão está agora marcada como gravada", - "pad.savedrevs.timeslider": "Pode consultar as revisões gravadas visitando a linha do tempo", - "pad.userlist.entername": "Insira o seu nome", - "pad.userlist.unnamed": "sem nome", - "pad.userlist.guest": "Convidado", - "pad.userlist.deny": "Negar", - "pad.userlist.approve": "Aprovar", - "pad.editbar.clearcolors": "Deseja limpar as cores de autoria em todo o documento?", - "pad.impexp.importbutton": "Importar agora", - "pad.impexp.importing": "Importando...", - "pad.impexp.confirmimport": "A importação de um ficheiro irá substituir o texto atual do pad. Tem certeza que deseja continuar?", - "pad.impexp.convertFailed": "Não foi possível importar este ficheiro. Utilize outro formato ou copie e insira manualmente", - "pad.impexp.padHasData": "Não fomos capazes de importar este ficheiro porque este Pad já tinha alterações, por favor importe para um novo pad", - "pad.impexp.uploadFailed": "O upload falhou. Por favor, tente novamente", - "pad.impexp.importfailed": "A importação falhou", - "pad.impexp.copypaste": "Por favor, copie e cole", - "pad.impexp.exportdisabled": "A exportação no formato {{type}} está desativada. Por favor, contacte o administrador do sistema para mais informações." -} diff --git a/sources/src/locales/qqq.json b/sources/src/locales/qqq.json deleted file mode 100644 index 60d62b1..0000000 --- a/sources/src/locales/qqq.json +++ /dev/null @@ -1,123 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Liuxinyu970226", - "Mklehr", - "Nemo bis", - "Shirayuki", - "Siebrand" - ] - }, - "index.newPad": "Used as button text.\nA pad, in the context of Etherpad, is a notepad, something to write on.", - "index.createOpenPad": "label for an input field that allows the user to choose a custom name for his new pad. In case the pad already exists the user will be redirected to its url.", - "pad.toolbar.bold.title": "Used as tooltip of button", - "pad.toolbar.italic.title": "Used as tooltip of button", - "pad.toolbar.underline.title": "Used as tooltip of button", - "pad.toolbar.strikethrough.title": "Used as tooltip of button.\n{{Identical|Strikethrough}}", - "pad.toolbar.ol.title": "Used as tooltip for button", - "pad.toolbar.ul.title": "Used as tooltip for button", - "pad.toolbar.indent.title": "Used as tooltip of button.\n\n\"TAB\" refers to \"Tab key\".\n\nSee also:\n* {{msg-etherpadlite|Pad.toolbar.unindent.title}}\n{{Identical|Indent}}", - "pad.toolbar.unindent.title": "Used as tooltip of button.\n\n\"TAB\" refers to \"Tab key\".\n\nSee also:\n* {{msg-etherpadlite|Pad.toolbar.indent.title}}", - "pad.toolbar.undo.title": "Used as tooltip of button", - "pad.toolbar.redo.title": "Used as tooltip of button\n{{Identical|Redo}}", - "pad.toolbar.clearAuthorship.title": "Used as tooltip of button", - "pad.toolbar.import_export.title": "Used as tooltip of button", - "pad.toolbar.timeslider.title": "The timeslider is a separate \"page\" that allows you to browse through the history of your pad's contents", - "pad.toolbar.savedRevision.title": "Used as tooltip for button.", - "pad.toolbar.settings.title": "settings that determine how the pad content is displayed\n{{Identical|Settings}}", - "pad.toolbar.embed.title": "Used as tooltip for button", - "pad.toolbar.showusers.title": "Used as tooltip for button", - "pad.colorpicker.save": "Used as button text in the \"Color picker\" window.\n\nSee also:\n* {{msg-etherpadlite|Pad.colorpicker.cancel}}\n{{Identical|Save}}", - "pad.colorpicker.cancel": "Used as button text in the \"Color picker\" window.\n\nSee also:\n* {{msg-etherpadlite|Pad.colorpicker.save}}\n{{Identical|Cancel}}", - "pad.loading": "Used to indicate the pad is being loaded.\n{{Identical|Loading}}", - "pad.passwordRequired": "Followed by the \"Password\" input box.", - "pad.permissionDenied": "Used as error message.", - "pad.wrongPassword": "Used as error message if the specified password is wrong.", - "pad.settings.padSettings": "Used as heading of settings window", - "pad.settings.myView": "Section heading for a users personal settings, meaning changes to the settings in this section will only affect the current view (this browser window) of the pad.", - "pad.settings.stickychat": "Used as checkbox label", - "pad.settings.colorcheck": "Used as checkbox label", - "pad.settings.linenocheck": "Used as checkbox label", - "pad.settings.rtlcheck": "Used as label for checkbox for RTL (right-to-left) languages", - "pad.settings.fontType": "Used as label for the \"Font type\" select box which has the following options:\n* {{msg-etherpadlite|Pad.settings.fontType.normal}}\n* {{msg-etherpadlite|Pad.settings.fontType.monospaced}}", - "pad.settings.fontType.normal": "Used as an option in the \"Font type\" select box which is labeled {{msg-etherpadlite|Pad.settings.fontType}}.\n{{Identical|Normal}}", - "pad.settings.fontType.monospaced": "Used as an option in the \"Font type\" select box which is labeled {{msg-etherpadlite|Pad.settings.fontType}}.", - "pad.settings.globalView": "Section heading for global view settings, meaning the settings in this section will affect everyone viewing the pad.", - "pad.settings.language": "This is a label for a select list of languages.\n{{Identical|Language}}", - "pad.importExport.import_export": "Used as HTML

        heading of window.\n\nFollowed by the child heading {{msg-etherpadlite|Pad.importExport.import}}.", - "pad.importExport.import": "Used as HTML

        heading.\n\nPreceded by the parent heading {{msg-etherpadlite|Pad.importExport.import_export}}.", - "pad.importExport.importSuccessful": "Used as success message to indicate that the pad has been imported successfully.\n{{Identical|Successful}}", - "pad.importExport.export": "Used as HTML

        heading.\n\nFollowed by the following link texts:\n* {{msg-etherpadlite|Pad.importExport.exporthtml}}\n* {{msg-etherpadlite|Pad.importExport.exportplain}}\n* {{msg-etherpadlite|Pad.importExport.exportword}}\n* {{msg-etherpadlite|Pad.importExport.exportpdf}}\n* {{msg-etherpadlite|Pad.importExport.exportopen}}\n* {{msg-etherpadlite|Pad.importExport.exportdokuwiki}}", - "pad.importExport.exportetherpad": "{{Identical|Etherpad}}", - "pad.importExport.exporthtml": "Used as link text, preceded by {{msg-etherpadlite|Pad.importExport.export}}.\n{{Related|Pad.importExport.export}}\n{{Identical|HTML}}", - "pad.importExport.exportplain": "Used as link text, preceded by {{msg-etherpadlite|Pad.importExport.export}}.\n{{Related|Pad.importExport.export}}\n{{Identical|Plain text}}", - "pad.importExport.exportword": "Used as link text, preceded by {{msg-etherpadlite|Pad.importExport.export}}.\n{{Related|Pad.importExport.export}}", - "pad.importExport.exportpdf": "Used as link text, preceded by {{msg-etherpadlite|Pad.importExport.export}}.\n{{Related|Pad.importExport.export}}", - "pad.importExport.exportopen": "Used as link text, preceded by {{msg-etherpadlite|Pad.importExport.export}}.\n{{Related|Pad.importExport.export}}", - "pad.importExport.abiword.innerHTML": "Used as intro text for the \"Import file\" form.\n\nPreceded by the heading {{msg-etherpadlite|pad.importExport.import}}.", - "pad.modals.connected": "Used as HTML

        heading to indicate the status.\n\nSee also:\n* {{msg-etherpadlite|Pad.modals.reconnecting}}\n{{Identical|Connected}}", - "pad.modals.reconnecting": "Used as HTML

        heading to indicate the status.\n\nSee also:\n* {{msg-etherpadlite|Pad.modals.connected}}", - "pad.modals.forcereconnect": "Label of a button that will make the browser reconnect to the synchronization server.", - "pad.modals.cancel": "{{Identical|Cancel}}", - "pad.modals.userdup": "Used as HTML

        heading to indicate that the pad is opened in another window on this computer.\n\nFollowed by the following messages:\n* {{msg-etherpadlite|Pad.modals.userdup.explanation}} -

        heading\n* {{msg-etherpadlite|Pad.modals.userdup.advice}}", - "pad.modals.userdup.explanation": "Used as HTML

        heading.\n\nPreceded by the parent heading {{msg-etherpadlite|Pad.modals.userdup}}.\n\nFollowed by the message {{msg-etherpadlite|Pad.modals.userdup.advice}}.", - "pad.modals.userdup.advice": "Preceded by the following headings:\n* {{msg-etherpadlite|Pad.modals.userdup}}\n* {{msg-etherpadlite|Pad.modals.userdup.explanation}}", - "pad.modals.unauth": "Used as HTML

        heading to indicate that the user is not authorized.\n\nFollowed by the explanation {{msg-etherpadlite|Pad.modals.unauth.explanation}}.\n{{Identical|Not authorized}}", - "pad.modals.unauth.explanation": "Used to indicate that the user is not authorized.\n\nPreceded by the heading {{msg-etherpadlite|Pad.modals.unauth}}.", - "pad.modals.looping.explanation": "Used as HTML

        heading.\n\nPreceded by the parent heading {{msg-etherpadlite|Pad.modals.looping}}.\n\nFollowed by the message {{msg-etherpadlite|Pad.modals.looping.cause}}.", - "pad.modals.looping.cause": "Preceded by the following messages:\n* {{msg-etherpadlite|Pad.modals.looping}}\n* {{msg-etherpadlite|Pad.modals.looping.explanation}}", - "pad.modals.initsocketfail": "Used as HTML

        heading.", - "pad.modals.initsocketfail.explanation": "Used as HTML

        heading.", - "pad.modals.initsocketfail.cause": "Preceded by the following headings:\n* {{msg-etherpadlite|Pad.modals.initsocketfail}}\n* {{msg-etherpadlite|Pad.modals.initsocketfail.explanation}}", - "pad.modals.slowcommit.explanation": "Used as HTML

        heading.", - "pad.modals.slowcommit.cause": "Preceded by the following headings:\n* {{msg-etherpadlite|Pad.modals.slowcommit}}\n* {{msg-etherpadlite|Pad.modals.slowcommit.explanation}}\nFollowed by the Submit button which is labeled {{msg-etherpadlite|Pad.modals.forcereconnect}}.", - "pad.modals.deleted": "Used as HTML

        heading.\n{{Identical|Deleted}}", - "pad.modals.deleted.explanation": "Preceded by the heading {{msg-etherpadlite|Pad.modals.deleted}}.", - "pad.modals.disconnected": "Used as HTML

        heading.", - "pad.modals.disconnected.explanation": "Used as HTML

        heading.", - "pad.modals.disconnected.cause": "Preceded by the following headings:\n* {{msg-etherpadlite|Pad.modals.disconnected}}\n* {{msg-etherpadlite|Pad.modals.disconnected.explanation}}\nFollowed by the Submit button which is labeled {{msg-etherpadlite|Pad.modals.forcereconnect}}.", - "pad.share": "Used as heading of window", - "pad.share.readonly": "Used as checkbox label", - "pad.share.link": "Used as label for a field providing URL of the pad.\n{{Identical|Link}}", - "pad.share.emebdcode": "Label for a field providing code that allows you to embed the pad into your website.", - "pad.chat": "Used as button text and as title of Chat window.\n{{Identical|Chat}}", - "pad.chat.title": "Used as tooltip for the Chat button", - "pad.chat.loadmessages": "chat messages", - "timeslider.pageTitle": "{{doc-important|Please leave {{appTitle}} parameter untouched. It will be replaced by app title.}}\nInserted into HTML title tag.", - "timeslider.toolbar.returnbutton": "Used as link title", - "timeslider.toolbar.authors": "A list of Authors follows after the colon.\n{{Identical|Author}}", - "timeslider.toolbar.authorsList": "Displayed when there are no authors of the currently viewed revision.", - "timeslider.toolbar.exportlink.title": "Used in Timeslider view.\n\nUsed as tooltip for the \"Export\" button which enables to export the current pad as HTML, plain text, or DokuWiki.\n\nIf the button is clicked, the following messages appear:\n* {{msg-etherpadlite|Timeslider.exportCurrent}}\n* {{msg-etherpadlite|Pad.importExport.exporthtml}}\n* {{msg-etherpadlite|Pad.importExport.exportplain}}\n* {{msg-etherpadlite|Pad.importExport.exportdokuwiki}}\n{{Identical|Export}}", - "timeslider.exportCurrent": "Used as label in the Timeslider view.\n\nFollowed by the following link texts (which are used to export the current pad):\n* {{msg-etherpadlite|Pad.importExport.exporthtml}}\n* {{msg-etherpadlite|Pad.importExport.exportplain}}\n* {{msg-etherpadlite|Pad.importExport.exportword}}\n* {{msg-etherpadlite|Pad.importExport.exportpdf}}\n* {{msg-etherpadlite|Pad.importExport.exportopen}}\n* {{msg-etherpadlite|Pad.importExport.exportdokuwiki}}", - "timeslider.version": "{{doc-important|Please leave {{version}} parameter untouched. It will be replaced with the version number}}", - "timeslider.saved": "{{doc-important|Do not translate {{month}}, {{day}} and {{year}} parameters. These will be replaced.}}\nParameters:\n* {{month}} - month name such as {{msg-etherpadlite|Timeslider.month.january}}, {{msg-etherpadlite|Timeslider.month.february}} and so on\n* {{day}} - day of the month (01-31)\n* {{year}} - year in 4 digit format", - "timeslider.dateformat": "{{doc-important|Do not translate month, day, year, hours, minutes and seconds parameters. These will be replaced.}}\n* {{month}} - a month number (01-12), NOT {{msg-etherpadlite|Timeslider.month.january}} etc.\n* {{day}} - day of the month (01-31)\n* {{year}} - year in 4 digit format\n* {{hours}} - hours (00-23)\n* {{minutes}} - minutes (00-59)\n* {{seconds}} - seconds (00-59)", - "timeslider.month.january": "Example usage: Saved on August 26, 2014. This message is substituted for:\n* {{msg-etherpadlite|Timeslider.saved|notext=1}}\n* {{msg-etherpadlite|Timeslider.dateformat|notext=1}}\n{{Identical|January}}", - "timeslider.month.february": "Example usage: Saved on August 26, 2014.\n{{Identical|February}}", - "timeslider.month.march": "Example usage: Saved on August 26, 2014.\n{{Identical|March}}", - "timeslider.month.april": "Example usage: Saved on August 26, 2014.\n{{Identical|April}}", - "timeslider.month.may": "Example usage: Saved on August 26, 2014.\n{{Identical|May}}", - "timeslider.month.june": "Example usage: Saved on August 26, 2014.\n{{Identical|June}}", - "timeslider.month.july": "Example usage: Saved on August 26, 2014.\n{{Identical|July}}", - "timeslider.month.august": "Example usage: Saved on August 26, 2014.\n{{Identical|August}}", - "timeslider.month.september": "Example usage: Saved on August 26, 2014.\n{{Identical|September}}", - "timeslider.month.october": "Example usage: Saved on August 26, 2014.\n{{Identical|October}}", - "timeslider.month.november": "Example usage: Saved on August 26, 2014.\n{{Identical|November}}", - "timeslider.month.december": "Example usage: Saved on August 26, 2014.\n{{Identical|December}}", - "timeslider.unnamedauthors": "See also:\n* {{msg-etherpadlite|Timeslider.unnamedauthor}}", - "pad.savedrevs.marked": "more like bookmarked, or tagged/starred", - "pad.userlist.entername": "Used as placeholder for the \"Name\" input box in the upper right corner of the screen.", - "pad.userlist.unnamed": "Displayed, if a user has not set a nick yet", - "pad.userlist.guest": "Preceded by the link text which is labeled {{msg-etherpadlite|Pad.userlist.approve}}.\n{{Identical|Guest}}", - "pad.userlist.deny": "Used as link text.\n\nFollowed by the link which is labeled {{msg-etherpadlite|Pad.userlist.approve}}.", - "pad.userlist.approve": "Used as link text.\n\nPreceded by the link which is labeled {{msg-etherpadlite|Pad.userlist.deny}}.\n\nFollowed by the message {{msg-etherpadlite|Pad.userlist.guest}}.\n{{Identical|Approve}}", - "pad.editbar.clearcolors": "Used as confirmation message (JavaScript confirm() function).\n\nThis message means \"Are you sure you want to clear authorship colors on entire document?\".", - "pad.impexp.importbutton": "Used as label for the Submit button.", - "pad.impexp.importing": "Used to indicate that the file is being imported.\n{{Identical|Importing}}", - "pad.impexp.confirmimport": "Used as confirmation message (JavaScript confirm() function).", - "pad.impexp.convertFailed": "Used as error message when importing a file.", - "pad.impexp.uploadFailed": "Used as error message when uploading a file.\n\nThis message means \"The upload has been failed. Please try again.\".", - "pad.impexp.importfailed": "Used as error message.\n\nThis message means \"The import has been failed\".\n\nFollowed by any one of the following messages:\n* {{msg-etherpadlite|Pad.impexp.convertFailed}}\n* {{msg-etherpadlite|Pad.impexp.uploadFailed}}\n* {{msg-etherpadlite|Pad.impexp.copypaste}}", - "pad.impexp.copypaste": "Displayed in case the import failed", - "pad.impexp.exportdisabled": "{{doc-important|Please leave {{type}} parameter untouched. It will be replaced}}" -} diff --git a/sources/src/locales/ro.json b/sources/src/locales/ro.json deleted file mode 100644 index a73bfaf..0000000 --- a/sources/src/locales/ro.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Hedwig", - "ImGelu", - "Minisarm", - "Strainu", - "Wintereu" - ] - }, - "index.newPad": "Pad nou", - "index.createOpenPad": "sau creează/deschide un Pad cu numele:", - "pad.toolbar.bold.title": "Aldin (Ctrl + B)", - "pad.toolbar.italic.title": "Cursiv (Ctrl + I)", - "pad.toolbar.underline.title": "Subliniază (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Taie (Ctrl+5)", - "pad.toolbar.ol.title": "Listă ordonată (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Listă neordonată (Ctrl+Shift+L)", - "pad.toolbar.undo.title": "Anulează (Ctrl+Z)", - "pad.toolbar.redo.title": "Refă (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Curăță culorile autorilor (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importă/Exportă din/în diferite formate", - "pad.toolbar.savedRevision.title": "Salvează revizia", - "pad.toolbar.settings.title": "Setări", - "pad.toolbar.showusers.title": "Arată utilizatorii de pe acest pad", - "pad.colorpicker.save": "Salvează", - "pad.colorpicker.cancel": "Anulează", - "pad.loading": "Se încarcă...", - "pad.passwordRequired": "Ai nevoie de o parolă pentru a accesa acest pad", - "pad.permissionDenied": "Nu ai permisiunea să accesezi acest pad", - "pad.wrongPassword": "Parola ta este greșită", - "pad.settings.padSettings": "Setări pentru Pad", - "pad.settings.stickychat": "Chat-ul întotdeauna pe ecran", - "pad.settings.chatandusers": "Afișează Chat-ul și Utilizatorii", - "pad.settings.colorcheck": "Culorile autorilor", - "pad.settings.linenocheck": "Numere de linie", - "pad.settings.fontType": "Tipul fontului:", - "pad.settings.globalView": "Vedere generală", - "pad.settings.language": "Limbă:", - "pad.importExport.import_export": "Import/Export", - "pad.importExport.import": "Încarcă orice fișier text sau document", - "pad.importExport.importSuccessful": "Succes!", - "pad.importExport.export": "Exportă pad-ul curent ca:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Text brut", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.modals.connected": "Conectat.", - "pad.modals.reconnecting": "Se reconectează la pad-ul dumneavoastră..", - "pad.modals.forcereconnect": "Forțează reconectarea", - "pad.modals.userdup": "Deschis în altă fereastră", - "pad.modals.userdup.advice": "Reconectați-vă dacă doriți să utilizați această fereastră.", - "pad.modals.unauth": "Nu ești autorizat", - "pad.modals.initsocketfail": "Serverul nu este disponibil.", - "pad.modals.initsocketfail.explanation": "Nu s-a putut conecta la serverul de sincronizare.", - "pad.modals.slowcommit.explanation": "Serverul nu răspunde.", - "pad.modals.slowcommit.cause": "Aceasta poate fi cauzată de probleme cu conexiunea la rețea.", - "pad.modals.deleted": "Șters.", - "pad.modals.deleted.explanation": "Acest pad a fost șters.", - "pad.modals.disconnected": "Ai fost deconectat.", - "pad.share": "Distribuie acest pad", - "pad.share.readonly": "Doar în citire", - "pad.share.link": "Legătură", - "pad.share.emebdcode": "Adresa URL încorporată", - "pad.chat": "Chat", - "pad.chat.title": "Deschide chat-ul pentru acest pad.", - "pad.chat.loadmessages": "Încarcă mai multe mesaje", - "timeslider.toolbar.returnbutton": "Înapoi la pad", - "timeslider.toolbar.authors": "Autori:", - "timeslider.toolbar.authorsList": "Niciun autor", - "timeslider.toolbar.exportlink.title": "Exportă", - "timeslider.exportCurrent": "Exportă versiunea curentă ca:", - "timeslider.version": "Versiunea {{version}}", - "timeslider.saved": "Salvat pe {{day}} {{month}} {{year}}", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "ianuarie", - "timeslider.month.february": "februarie", - "timeslider.month.march": "martie", - "timeslider.month.april": "aprilie", - "timeslider.month.may": "mai", - "timeslider.month.june": "iunie", - "timeslider.month.july": "iulie", - "timeslider.month.august": "august", - "timeslider.month.september": "septembrie", - "timeslider.month.october": "octombrie", - "timeslider.month.november": "noiembrie", - "timeslider.month.december": "decembrie", - "pad.userlist.entername": "Introduceți numele dumneavoastră", - "pad.userlist.unnamed": "fără nume", - "pad.userlist.guest": "Oaspete", - "pad.userlist.deny": "Respinge", - "pad.userlist.approve": "Aprobă", - "pad.impexp.importbutton": "Importă acum", - "pad.impexp.importing": "Importare...", - "pad.impexp.importfailed": "Import eșuat" -} diff --git a/sources/src/locales/ru.json b/sources/src/locales/ru.json deleted file mode 100644 index 801ceaa..0000000 --- a/sources/src/locales/ru.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Amire80", - "DCamer", - "Eleferen", - "Okras", - "Volkov", - "Nzeemin", - "Facenapalm", - "Patrick Star" - ] - }, - "index.newPad": "Создать", - "index.createOpenPad": "или создать/открыть документ с именем:", - "pad.toolbar.bold.title": "полужирный (Ctrl-B)", - "pad.toolbar.italic.title": "курсив (Ctrl-I)", - "pad.toolbar.underline.title": "подчёркивание (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Зачёркивание (Ctrl+5)", - "pad.toolbar.ol.title": "Упорядоченный список (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Неупорядоченный список (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Отступ (TAB)", - "pad.toolbar.unindent.title": "Выступ (Shift+TAB)", - "pad.toolbar.undo.title": "Отменить (Ctrl-Z)", - "pad.toolbar.redo.title": "Вернуть (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Очистить цвета документа (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Импорт/экспорт с использованием различных форматов файлов", - "pad.toolbar.timeslider.title": "Шкала времени", - "pad.toolbar.savedRevision.title": "Сохранить версию", - "pad.toolbar.settings.title": "Настройки", - "pad.toolbar.embed.title": "Поделиться и встроить этот документ", - "pad.toolbar.showusers.title": "Показать пользователей в документе", - "pad.colorpicker.save": "Сохранить", - "pad.colorpicker.cancel": "Отмена", - "pad.loading": "Загрузка...", - "pad.noCookie": "Куки не найдены. Пожалуйста, включите куки в вашем браузере!", - "pad.passwordRequired": "Вам нужен пароль для доступа", - "pad.permissionDenied": "У вас нет разрешения на доступ", - "pad.wrongPassword": "Неправильный пароль", - "pad.settings.padSettings": "Настройки документа", - "pad.settings.myView": "Мой вид", - "pad.settings.stickychat": "Всегда отображать чат", - "pad.settings.chatandusers": "Показать чат и пользователей", - "pad.settings.colorcheck": "Цвета документа", - "pad.settings.linenocheck": "Номера строк", - "pad.settings.rtlcheck": "Читать содержимое справа налево?", - "pad.settings.fontType": "Тип шрифта:", - "pad.settings.fontType.normal": "Обычный", - "pad.settings.fontType.monospaced": "Моноширинный", - "pad.settings.globalView": "Общий вид", - "pad.settings.language": "Язык:", - "pad.importExport.import_export": "Импорт/экспорт", - "pad.importExport.import": "Загрузить любой текстовый файл или документ", - "pad.importExport.importSuccessful": "Успешно!", - "pad.importExport.export": "Экспортировать текущий документ как:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Обычный текст", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (документ OpenOffice)", - "pad.importExport.abiword.innerHTML": "Вы можете импортировать только из обычного текста или HTML. Для более продвинутых функций импорта, пожалуйста, установите AbiWord.", - "pad.modals.connected": "Подключен.", - "pad.modals.reconnecting": "Повторное подключение к вашему документу", - "pad.modals.forcereconnect": "Принудительное переподключение", - "pad.modals.reconnecttimer": "Попытка переподключения", - "pad.modals.cancel": "Отмена", - "pad.modals.userdup": "Открыто в другом окне", - "pad.modals.userdup.explanation": "Документ, возможно, открыт более чем в одном окне браузера на этом компьютере.", - "pad.modals.userdup.advice": "Повторно подключить с использованием этого окна.", - "pad.modals.unauth": "Не авторизован", - "pad.modals.unauth.explanation": "Ваши разрешения были изменены во время просмотра этой страницы. Попробуйте подключиться повторно.", - "pad.modals.looping.explanation": "Проблемы связи с сервером синхронизации.", - "pad.modals.looping.cause": "Возможно, вы подключились через несовместимый брандмауэр или прокси.", - "pad.modals.initsocketfail": "Сервер недоступен.", - "pad.modals.initsocketfail.explanation": "Не удалось подключиться к серверу синхронизации.", - "pad.modals.initsocketfail.cause": "Вероятно, это вызвано проблемами с вашим браузером или интернет-соединением.", - "pad.modals.slowcommit.explanation": "Сервер не отвечает.", - "pad.modals.slowcommit.cause": "Это может быть вызвано проблемами с сетевым подключением.", - "pad.modals.badChangeset.explanation": "Правка, которую вы сделали, была классифицирована сервером синхронизации как недопустимая.", - "pad.modals.badChangeset.cause": "Это может быть из-за неправильной конфигурации сервера или некоторых других неожиданных действий. Пожалуйста, свяжитесь с администратором службы, если вы считаете, что это ошибка. Попробуйте переподключиться для того, чтобы продолжить редактирование.", - "pad.modals.corruptPad.explanation": "Документ, к которому вы пытаетесь получить доступ, повреждён.", - "pad.modals.corruptPad.cause": "Это может быть из-за неправильной конфигурации сервера или некоторых других неожиданных действий. Пожалуйста, свяжитесь с администратором службы.", - "pad.modals.deleted": "Удален.", - "pad.modals.deleted.explanation": "Этот документ был удален.", - "pad.modals.disconnected": "Соединение разорвано.", - "pad.modals.disconnected.explanation": "Подключение к серверу потеряно", - "pad.modals.disconnected.cause": "Сервер, возможно, недоступен. Пожалуйста, сообщите администратору службы, если проблема будет повторятся.", - "pad.share": "Поделиться", - "pad.share.readonly": "Только чтение", - "pad.share.link": "Ссылка", - "pad.share.emebdcode": "Вставить URL", - "pad.chat": "Чат", - "pad.chat.title": "Открыть чат для этого документа.", - "pad.chat.loadmessages": "Еще сообщения", - "timeslider.pageTitle": "Временная шкала {{appTitle}}", - "timeslider.toolbar.returnbutton": "К документу", - "timeslider.toolbar.authors": "Авторы:", - "timeslider.toolbar.authorsList": "Нет авторов", - "timeslider.toolbar.exportlink.title": "Экспорт", - "timeslider.exportCurrent": "Экспортировать текущую версию как:", - "timeslider.version": "Версия {{version}}", - "timeslider.saved": "Сохранено {{day}}.{{month}}.{{year}}", - "timeslider.playPause": "Воспроизведение / Пауза содержимого документа", - "timeslider.backRevision": "Назад на одну версию документа", - "timeslider.forwardRevision": "Вперёд на одну версию документа", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "январь", - "timeslider.month.february": "февраль", - "timeslider.month.march": "март", - "timeslider.month.april": "апрель", - "timeslider.month.may": "май", - "timeslider.month.june": "июнь", - "timeslider.month.july": "июль", - "timeslider.month.august": "август", - "timeslider.month.september": "сентябрь", - "timeslider.month.october": "октябрь", - "timeslider.month.november": "ноябрь", - "timeslider.month.december": "декабрь", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: безымянный автор, few: безымянных автора, many: безымянных авторов, other: безымянных авторов]}", - "pad.savedrevs.marked": "Эта версия теперь помечена как сохраненная", - "pad.savedrevs.timeslider": "Вы можете увидеть сохранённые версии на шкале времени", - "pad.userlist.entername": "Введите ваше имя", - "pad.userlist.unnamed": "безымянный", - "pad.userlist.guest": "Гость", - "pad.userlist.deny": "Отклонить", - "pad.userlist.approve": "Утвердить", - "pad.editbar.clearcolors": "Очистить авторские цвета во всем документе?", - "pad.impexp.importbutton": "Импортировать сейчас", - "pad.impexp.importing": "Импортирование…", - "pad.impexp.confirmimport": "Импорт файла перезапишет текущий текст. Вы уверены, что вы хотите продолжить?", - "pad.impexp.convertFailed": "Не удалось импортировать этот файл. Пожалуйста, используйте другой формат или скопируйте вручную", - "pad.impexp.padHasData": "Не получилось импортировать этот файл, потому что этот документ уже имеет изменения, пожалуйста, импортируйте в новый документ", - "pad.impexp.uploadFailed": "Загрузка не удалась, пожалуйста, попробуйте ещё раз", - "pad.impexp.importfailed": "Ошибка при импорте", - "pad.impexp.copypaste": "Пожалуйста, скопируйте", - "pad.impexp.exportdisabled": "Экспорт в формате {{type}} отключен. Для подробной информации обратитесь к системному администратору." -} diff --git a/sources/src/locales/sco.json b/sources/src/locales/sco.json deleted file mode 100644 index 274a85b..0000000 --- a/sources/src/locales/sco.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "@metadata": { - "authors": [ - "John Reid", - "AmaryllisGardener" - ] - }, - "index.newPad": "New Pad", - "index.createOpenPad": "or mak/apen ae Pad wi the name:", - "pad.toolbar.bold.title": "Bold (Ctrl-B)", - "pad.toolbar.italic.title": "Italic (Ctrl-I)", - "pad.toolbar.underline.title": "Underline (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Strikethrou (Ctrl+5)", - "pad.toolbar.ol.title": "Ordered leet (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Unordered Leet (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Indent (TAB)", - "pad.toolbar.unindent.title": "Ootdent (Shift+TAB)", - "pad.toolbar.undo.title": "Ondae (Ctrl-Z)", - "pad.toolbar.redo.title": "Redae (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Clear Authorship Colours (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Import/Export fae/til different file formats", - "pad.toolbar.timeslider.title": "Timeslider", - "pad.toolbar.savedRevision.title": "Hain Reveesion", - "pad.toolbar.settings.title": "Settins", - "pad.toolbar.embed.title": "Shair n Embed this pad", - "pad.toolbar.showusers.title": "Shaw the uisers oan this pad", - "pad.colorpicker.save": "Hain", - "pad.colorpicker.cancel": "Cancel", - "pad.loading": "Laidin...", - "pad.noCookie": "Cookie could nae be foond. Please allae cookies in yer brouser!", - "pad.passwordRequired": "Ye need ae passwaird fer tae access this pad", - "pad.permissionDenied": "Ye dinna hae permeession tae access this pad", - "pad.wrongPassword": "Yer password wis wrang", - "pad.settings.padSettings": "Pad Settins", - "pad.settings.myView": "Ma Luik", - "pad.settings.stickychat": "Tauk aye oan screen", - "pad.settings.chatandusers": "Shaw Chat an Uisers", - "pad.settings.colorcheck": "Authorship colours", - "pad.settings.linenocheck": "Line nummers", - "pad.settings.rtlcheck": "Read content fae richt til cair?", - "pad.settings.fontType": "Font type:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "The Global Luik", - "pad.settings.language": "Leid:", - "pad.importExport.import_export": "Import/Export", - "pad.importExport.import": "Upload oni tex file or document", - "pad.importExport.importSuccessful": "Success!", - "pad.importExport.export": "Export current pad as:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Plain tex", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Ye can yinly import fae plain tex or HTML formats. Fer mair advanced import features please install abiword.", - "pad.modals.connected": "Connected.", - "pad.modals.reconnecting": "Reconnectin til yer pad..", - "pad.modals.forcereconnect": "Force reconnect", - "pad.modals.userdup": "Apened in anither windae", - "pad.modals.userdup.explanation": "This pad seems tae be apened in mair than yin brouser windae on this computer.", - "pad.modals.userdup.advice": "Reconnect fer tae uise this windae instead.", - "pad.modals.unauth": "Naw authorized", - "pad.modals.unauth.explanation": "Yer permeessions hae chynged while viewing this page. Try tae reconnect.", - "pad.modals.looping.explanation": "Thaur ar communication proablems wi the synchronization server.", - "pad.modals.looping.cause": "Meyhaps ye connected through aen incompatible firewa or proxy.", - "pad.modals.initsocketfail": "Server canna be reached.", - "pad.modals.initsocketfail.explanation": "Coudna connect til the synchronization server.", - "pad.modals.initsocketfail.cause": "This is possably cause o ae problem wi yer brouser or yer wab connection.", - "pad.modals.slowcommit.explanation": "The server isna respondin.", - "pad.modals.slowcommit.cause": "This coud be cause o problems wi netwairk connecteevitie.", - "pad.modals.badChangeset.explanation": "Aen eedit that ye'v makit wis classeefied aes onlegal bi the synchronization server.", - "pad.modals.badChangeset.cause": "This coud be cause o ae wrang server confeeguration or some ither onexpected behavior. Please contact the service admeenistrator, gif ye feel that this is ae mistak. Try tae reconnect in order tae continue editing.", - "pad.modals.corruptPad.explanation": "The pad ye'r trying te access is mingin.", - "pad.modals.corruptPad.cause": "This micht be cause o ae wrang server confeeguration or some ither onexpected behavior. Please contact the service admeenistrater.", - "pad.modals.deleted": "Delytit.", - "pad.modals.deleted.explanation": "This pad has been hif't.", - "pad.modals.disconnected": "Ye'v been disconnected.", - "pad.modals.disconnected.explanation": "The connection til the server wis loast", - "pad.modals.disconnected.cause": "The server micht be onavailable. Please notify the service admeenistrater gif this continues tae happen.", - "pad.share": "Share this pad", - "pad.share.readonly": "Read yinly", - "pad.share.link": "Airtin", - "pad.share.emebdcode": "Embed URL", - "pad.chat": "Chait", - "pad.chat.title": "Apen the tauk fer this pad.", - "pad.chat.loadmessages": "Laid mair messages", - "timeslider.pageTitle": "{{appTitle}} Timeslider", - "timeslider.toolbar.returnbutton": "Return til pad", - "timeslider.toolbar.authors": "Authers:", - "timeslider.toolbar.authorsList": "Nae Authers", - "timeslider.toolbar.exportlink.title": "Export", - "timeslider.exportCurrent": "Export current version as:", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Saved {{day}} {{month}}, {{year}}", - "timeslider.playPause": "Playback / Pause Pad Contents", - "timeslider.backRevision": "Gae back a reveesion in this Pad", - "timeslider.forwardRevision": "Gae forwart a reveesion in this Pad", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januair", - "timeslider.month.february": "Febuair", - "timeslider.month.march": "Mairch", - "timeslider.month.april": "Apryle", - "timeslider.month.may": "Mey", - "timeslider.month.june": "Juin", - "timeslider.month.july": "Julie", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "October", - "timeslider.month.november": "November", - "timeslider.month.december": "Dizember", - "timeslider.unnamedauthors": "{{num}} onnamed {[plural(num) one: writer, other: writers ]}", - "pad.savedrevs.marked": "This reveesion is nou tagged aes ae hained reveesion", - "pad.savedrevs.timeslider": "Ye can see saved reveesions bi veesitin the timeslider", - "pad.userlist.entername": "Enter yer name", - "pad.userlist.unnamed": "onnamed", - "pad.userlist.guest": "Guest", - "pad.userlist.deny": "Bar", - "pad.userlist.approve": "Appruiv", - "pad.editbar.clearcolors": "Clear authership colours oan the entire document?", - "pad.impexp.importbutton": "Import Nou", - "pad.impexp.importing": "Importing...", - "pad.impexp.confirmimport": "Importin ae file will owerwrite the current tex o the pad. Ar ye sair ye want tae proceed?", - "pad.impexp.convertFailed": "We coudna import this file. Please uise ae different document format or copy paste manually", - "pad.impexp.padHasData": "We war nae able tae import this file acause this Pad haes awready haed chynges, please import tae a new pad", - "pad.impexp.uploadFailed": "The upload failed, please try again", - "pad.impexp.importfailed": "The import failed", - "pad.impexp.copypaste": "Please copy paste", - "pad.impexp.exportdisabled": "Exporting as {{type}} format is disabled. Please contact yer system admeenistrator fer details." -} diff --git a/sources/src/locales/sd.json b/sources/src/locales/sd.json deleted file mode 100644 index bf8a36e..0000000 --- a/sources/src/locales/sd.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Mehtab ahmed" - ] - }, - "index.newPad": "نئين پٽي", - "index.createOpenPad": "يا نالي سان ڪا پٽي تخليق ڪريو\\کوليو:", - "pad.toolbar.bold.title": "وزني (Ctrl+B)", - "pad.toolbar.italic.title": "اطالوي (Ctrl+I)", - "pad.toolbar.underline.title": "هيٺان سٽ ڏيو (Ctrl+U)", - "pad.toolbar.strikethrough.title": "ليڪو ڏيو (Ctrl+5)", - "pad.toolbar.ol.title": "ترتيب وار فهرست (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "ٻي ترتيب فهرست (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "وڌايو (TAB)", - "pad.toolbar.unindent.title": "گھٽايو (Shift+TAB)", - "pad.toolbar.undo.title": "اڻ ڪريو (Ctrl+Z)", - "pad.toolbar.redo.title": "ٻيهر ڪريو (Ctrl+Y)", - "pad.toolbar.timeslider.title": "وقت ڦيرڻو", - "pad.toolbar.savedRevision.title": "نظرثاني سانڍيو", - "pad.toolbar.settings.title": "ترتيبون", - "pad.colorpicker.save": "سانڍيو", - "pad.colorpicker.cancel": "رد", - "pad.loading": "لاهيندي...", - "pad.wrongPassword": "توهان جو ڳجھو لفظ غلط هيو", - "pad.settings.padSettings": "پٽي جو ترتيبون", - "pad.settings.myView": "منهنجو نظارو", - "pad.settings.stickychat": "ڳالھ ٻولھ هميشه پردي تي ڪريو", - "pad.settings.chatandusers": "ڳالھ ٻولھ ۽ يوزر ڏيکاريو", - "pad.settings.linenocheck": "سٽ جا انگ", - "pad.settings.rtlcheck": "مواد ساڄي کان کاٻي طرف پڙهندئو؟", - "pad.settings.fontType": "اکرن جو قسم:", - "pad.settings.globalView": "عالمي نظارو", - "pad.settings.language": "ٻولي:", - "pad.importExport.import_export": "درآمد ڪريو\\برآمد ڪريو", - "pad.importExport.import": "ڪو به متن وارو فائيل يا دستاويز چاڙهيو", - "pad.importExport.importSuccessful": "ڪامياب!", - "pad.importExport.export": "هاڻوڪي پٽي برآمد ڪريو جي طور:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "سادو متن", - "pad.importExport.exportword": "مائيڪرسافٽ ورڊ", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (کليل دستاويز فارميٽ)", - "pad.modals.connected": "ڳنڍيل.", - "pad.modals.reconnecting": "توهان جي پٽي سان ٻيهر ڳنڍي رهيو آهي...", - "pad.modals.forcereconnect": "جبري طور ٻيهر ڳنڍيو", - "pad.modals.userdup": "هڪ ٻي دري ۾ کليل", - "pad.modals.unauth": "اختيار نه آهي", - "pad.modals.initsocketfail": "سَروَرَ کي پڄي نٿو سگھجي.", - "pad.modals.slowcommit.explanation": "سَروَر جواب نٿو ڏي.", - "pad.modals.corruptPad.explanation": "جيڪا پٽي توهان حاصل ڪرڻ چاهيو ٿا اها بدعنوان آهي.", - "pad.modals.deleted": "ختم ڪيل.", - "pad.modals.deleted.explanation": "هي پٽي هٽائجي چڪي آهي.", - "pad.modals.disconnected": "توهان سان ڳانڍاپو ختم ڪيو ويو آهي.", - "pad.share": "هي پٽي ونڊيو", - "pad.share.readonly": "صرف پڙهو", - "pad.share.link": "ڳنڍڻو", - "pad.chat": "ڳالھ ٻولھ", - "pad.chat.title": "هن پٽي لاءِ ڳالھ ٻولھ کوليو.", - "pad.chat.loadmessages": "وڌيڪ پيغام لوڊ ڪريو", - "timeslider.pageTitle": "{{appTitle}} وقت ڦيرڻو", - "timeslider.toolbar.returnbutton": "پٽي ڏانهن ورو", - "timeslider.toolbar.authors": "ليکڪ:", - "timeslider.toolbar.authorsList": "ڪوبه ليکڪ ناهي", - "timeslider.toolbar.exportlink.title": "برآمد ڪريو", - "timeslider.version": "ورزن {{version}}", - "timeslider.saved": "شانڍيل {{مهينو}} {{ڏينهن}}, {{سال}}", - "timeslider.dateformat": "{{مهينو}}/{{ڏينهن}}/{{سال}} {{ڪلاڪ}}:{{منٽ}}:{{سيڪنڊ}}", - "timeslider.month.january": "جنوري", - "timeslider.month.february": "فيبروري", - "timeslider.month.march": "مارچ", - "timeslider.month.april": "اپريل", - "timeslider.month.may": "مئي", - "timeslider.month.june": "جون", - "timeslider.month.july": "جولاءِ", - "timeslider.month.august": "آگسٽ", - "timeslider.month.september": "سيپٽمبر", - "timeslider.month.october": "آڪٽوبر", - "timeslider.month.november": "نومبر", - "timeslider.month.december": "ڊسمبر", - "pad.userlist.entername": "پنهنجو نالو داخل ڪريو", - "pad.userlist.unnamed": "بينام", - "pad.userlist.guest": "مهمان", - "pad.userlist.deny": "انڪار ڪريو", - "pad.userlist.approve": "قبول ڪريو", - "pad.impexp.importbutton": "هاڻي درآمد ڪريو", - "pad.impexp.importing": "درآمد ڪندي...", - "pad.impexp.uploadFailed": "چاڙھ ناڪام ويو، براءِ مهرباني ٻيهر ڪوشش ڪريو", - "pad.impexp.importfailed": "درآمد ناڪام", - "pad.impexp.copypaste": "براءِ مهرباني ڪاپي ڪري لڳايو" -} diff --git a/sources/src/locales/shn.json b/sources/src/locales/shn.json deleted file mode 100644 index 434ef49..0000000 --- a/sources/src/locales/shn.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Saosukham" - ] - }, - "index.newPad": "ၽႅတ်ႉမႂ်ႇ", - "index.createOpenPad": "ဢမ်ႇၼၼ် ၶူင်မႂ်ႇ/ပိုတ်ႇၽႅတ်ႉၵိုၵ်းၸိုဝ်ႈ", - "pad.toolbar.bold.title": "လမ် (Ctrl+B)", - "pad.toolbar.italic.title": "ၵိူင်း (Ctrl+I)", - "pad.toolbar.underline.title": "ထတ်းထႅဝ်တႂ်ႈ (Ctrl+U)", - "pad.toolbar.strikethrough.title": "လတ်းၵၢင် (Ctrl+5)", - "pad.toolbar.ol.title": "ၵုမ်းသဵၼ်ႈ (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "ဢမ်ႇၵုမ်းသဵၼ်ႈ (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "ၶၼ်ႈ (TAB)", - "pad.toolbar.unindent.title": "ၶၼ်ႈႁၢင်ႇ (Shift+TAB)", - "pad.toolbar.undo.title": "ၶိုၼ်းဢမ်ႇႁဵတ်း (Ctrl+Z)", - "pad.toolbar.redo.title": "ၶိုၼ်းႁဵတ်း (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "သၢင်းလၢင်းပႅတ်ႈ သီဢၼ်မီးဝႆႉၵဝ်ႇ (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "သူင်ႇၶဝ်ႈ/သူင်ႇဢွၵ်ႇ တမ်ႈတီႈ/ထိုင် ၾၢႆႇၾေႃးမိတ်ႉ ဢၼ်ဢမ်ႇမိူၼ်ၵၼ်ၸိူဝ်းၼၼ်ႉ", - "pad.toolbar.timeslider.title": "ၶၢဝ်းယၢမ်းထွၵ်ႇလၢႆႈ", - "pad.toolbar.savedRevision.title": "သိမ်းလွင်ႈၶိုၼ်းမႄး", - "pad.toolbar.settings.title": "ပိူင်ႁႅၼ်း", - "pad.toolbar.embed.title": "ၽႄပၼ်ၽႅတ်ႉဢၼ်ၼႆႉသေ ၽိူမ်ႉပၼ်", - "pad.toolbar.showusers.title": "ၼႄပၼ်ၵေႃႉၸႂ်ႉ တီႈၼိူဝ်ၽႅတ်ႉၼႆႉ", - "pad.colorpicker.save": "ၵဵပ်းသိမ်း", - "pad.colorpicker.cancel": "ဢမ်ႇႁဵတ်း", - "pad.loading": "တိုၵ်ႉလူတ်ႇ", - "pad.noCookie": "ၶုၵ်းၶီး ဢမ်ႇႁၼ်လႆႈ။ ၶႅၼ်းတေႃႈ ၶႂၢင်းပၼ် ၶုၵ်းၶီး တီႈၼႂ်း ပရၢဝ်ႇသႃႇၸဝ်ႈၵဝ်ႇ", - "pad.passwordRequired": "တႃႇၶဝ်ႈတီႈၽႅတ်ႉၼႆႉ ၸဝ်ႈၵဝ်ႇ လူဝ်ႇမီး မၢႆလပ်ႉ", - "pad.permissionDenied": "ၸဝ်ႈၵဝ်ႇ ဢမ်ႇမီးၶေႃႈၶႂၢင်ႉ တႃႇၶဝ်ႈၼႂ်းၽႅတ်ႉၼႆႉ", - "pad.wrongPassword": "မၢႆလပ်ႉၸဝ်ႈၵဝ်ႇ ၽိတ်း", - "pad.settings.padSettings": "ပိူင်သၢင်ႈၽႅတ်ႉ", - "pad.settings.myView": "ဝိဝ်းၵဝ်", - "pad.settings.stickychat": "ၶျၢတ်ႉၼိူဝ်ၼႃႈၽိဝ် တႃႇသေႇ", - "pad.settings.chatandusers": "ၼႄၶျၢတ်ႉဢိၵ်ႇၵေႃႉၸႂ်ႉ", - "pad.settings.colorcheck": "သီၸိူဝ်းမီးဝႆႉၵဝ်ႇၵဝ်ႇ", - "pad.settings.linenocheck": "တူဝ်လိၵ်ႈႁေႈႁၢႆး", - "pad.settings.rtlcheck": "လူၵႂၢမ်းၼၢမ်း တႄႇၶႂႃတေႃႇသၢႆႉ", - "pad.settings.fontType": "ၾွၼ်ႉတူဝ်လိၵ်ႈ", - "pad.settings.globalView": "ဝိဝ်းတင်းလူၵ်ႈ", - "pad.settings.language": "ၽႃႇသႃႇၵႂၢမ်း:", - "pad.importExport.import_export": "သူင်ႇၶဝ်/သူင်ႇဢွၵ်ႇ", - "pad.importExport.import": "လူတ်ႇၶိုၼ်ႈ ၾၢႆႇလိၵ်ႈၵမ်ႈၽွင်ႈ ဢမ်ႇၼၼ် ပွင်ႈလိၵ်ႈ", - "pad.importExport.importSuccessful": "ဢွင်ႇယဝ်ႉ!", - "pad.importExport.export": "ဢဝ်ဢွၵ်ႇၽႅတ်ႉဢၼ်ပိူၼ်ႈသူင် ၸိူင်ႉၼင်ႇ:", - "pad.importExport.exportetherpad": "ၽႅတ်ႉပဝ်ႇ", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "တူဝ်လိၵ်ႈပဝ်ႇ", - "pad.importExport.exportword": "မၢႆႇၶရူဝ်ႇသွပ်ႉဝၢတ်ႉ", - "pad.importExport.exportpdf": "ၽီႇတီႇဢႅပ်ႉၾ်", - "pad.importExport.exportopen": "ဢူဝ်တီႇဢႅပ်ႉၾ် (Open Document Format)", - "pad.importExport.abiword.innerHTML": "ၸဝ်ႈၵဝ်ႇၸၢင်ႈလုၵ်ႉတီႈ လိၵ်ႈပဝ်ႇသေ သူင်ႇၶဝ်ႈၵႂႃႇ ဢမ်ႇၼၼ် ပိူင်လၢႆႈ HTML. ပုၼ်ႈတႃႇ ၸိူဝ်းပိူင်မႂ်ႇ ဢၼ်သူင်ႇၶဝ်ႈမႃးၼၼ်ႉ ၶွပ်ႈၸႂ်သေ install abiword.", - "pad.modals.connected": "ၵွင်ႉသၢၼ်ယဝ်ႉ", - "pad.modals.reconnecting": "ၶိုၼ်းၵွင်ႉသၢၼ်ၸူး ၽႅတ်ႉၸဝ်ႈၵဝ်ႇယူႇ", - "pad.modals.forcereconnect": "တဵၵ်းၸႂ်ႉ ၶိုၼ်းၵွင်ႉသၢၼ်", - "pad.modals.userdup": "ပိုတ်ႇတမ်ႈတီႈ ၼႃႈတူမႂ်ႇ", - "pad.modals.userdup.explanation": "တမ်ႈတီႈၼႂ်းၶွမ်းတၢင်ႇဢၼ်ၼၼ်ႉ ၽႅတ်ႉဢၼ်ၼႆႉ လႅပ်ႉပိုတ်ႇဝႆႉ တမ်ႈတီႈ ပရၢဝ်ႇသႃႇတၢင်ႇတီႈယူႇ", - "pad.modals.userdup.advice": "ၶိုၼ်းၵွင်ႉသၢၼ်တၢင် တမ်ႈတီႈ ဝိၼ်းတူဝ်းၼႆႉ", - "pad.modals.unauth": "ဢမ်ႇမီးသုၼ်ႇႁဵတ်း", - "pad.modals.unauth.explanation": "ၽွင်းၼႄၼႃႈလိၵ်ႈၼႆႉယူႇၼၼ်ႉ ၶေႃႈၶႂၢင်းၸဝ်ႈၵဝ်ႇ လႅၵ်ႈလၢႆႉယဝ်ႉယဝ်ႉ။ ၶတ်းၸႂ် ၶိုၼ်းၵွင်ႉသၢၼ်တႅင်ႈ", - "pad.modals.looping.explanation": "ၸိူဝ်းၼႆႉ မီးဝႆႉပၼ်ႁႃ သၢႆတိတ်းတေႃႇ ၵိုၵ်းလူၺ်ႈ သႃႇဝႃႇ ဢၼ်ၸၼ်ထိင်းဝႆႉ", - "pad.modals.looping.cause": "သင်ပဵၼ်လႆႈ မႂ်းၶဝ်ႈၵွင်ႉသၢၼ် ၾၢႆးယႃးဝေႃး ဢမ်ႇၼၼ် ပရွၵ်ႉသီႇ ဢၼ်ဢမ်ႇငၢမ်ႇၵၼ်", - "pad.modals.initsocketfail": "သႃႇဝႃႇ ဢမ်ႇၵွင်ႉလႆႈ", - "pad.modals.initsocketfail.explanation": "ဢမ်ႇၵွင်ႉၸူးလႆႈ သႃႇဝႃႇဢၼ်ၸၼ်ထိင်းဝႆႉ", - "pad.modals.initsocketfail.cause": "ၼႆႉပဵၼ်ပၼ်ႁႃၶိုၵ်ႉလူင် ၵိုၵ်းလူၺ်ႈ ပရၢဝ်ႇသႃႇၸဝ်ႈၵဝ်ႇ ဢမ်ႇၼၼ် သၢႆၼႅင်ႈၸဝ်ႈၵဝ်ႇ", - "pad.modals.slowcommit.explanation": "သႃႇဝႃႇ ဢမ်ႇတွပ်ႇပၼ်", - "pad.modals.slowcommit.cause": "ၼႆႉပူပ်ႉၺႃး ပၼ်ႁႃ ၵိုၵ်းလူၺ်ႈ သၢႆၼႅင်ႈၵွင်ႉသၢၼ်", - "pad.modals.badChangeset.explanation": "ၶေႃႈထတ်း ဢၼ်ၸဝ်ႈၵဝ်ႇႁဵတ်းၼၼ်ႉ မၼ်းဢမ်ႇႁူမ်ႈၶဝ်ႈၶႂၢင်ႇ ၸွမ်းၼင်ႇ သႃႇဝႃႇဢၼ် ၸၼ်ထိင်းဝႆႉ", - "pad.modals.corruptPad.explanation": "ၽႅတ်ႉဢၼ်ၸဝ်ႈၵဝ်ႇပေႃႉၼၼ်ႉ ၶဝ်ႈၽိတ်းဝႆႉ", - "pad.modals.corruptPad.cause": "ဢၼ်ၼႆႉ သႃႇဝႃႇဢၼ်ၸၼ်ထိင်းမၼ်း ၽိတ်းဝႆႉ ဢမ်ႇၼၼ် ဢမ်ႇမုင်ႈမွင်းသေ ၽိတ်းပိူင်ႈဝႆႉယဝ်ႉ။ ၶႅၼ်းတေႃႈ ၵပ်းသိုပ်ႇတမ်ႈတီႈ ၽူႈၵုမ်းၵၢၼ်.", - "pad.modals.deleted": "ယႃႉ", - "pad.modals.deleted.explanation": "ၽႅတ်ႉဢၼ်ၼႆႉ ၶၢႆႉပႅတ်ႈယဝ်ႉ", - "pad.modals.disconnected": "ၸဝ်ႈၵဝ်ႇ ဢမ်ႇၵွင်ႉသၢၼ်ဝႆႉ", - "pad.modals.disconnected.explanation": "လွင်ႈၵွင်ႉသၢၼ် ၵႂႃႇၸူးသႃႇဝႃႇၼၼ်ႉ ႁၢႆဝႆႉ", - "pad.modals.disconnected.cause": "သႃႇဝႃႇတေဢမ်ႇၸၢင်ႈယိပ်းတိုဝ်း။ တႃႇႁႂ်ႈသိုပ်ႇပဵၼ်ၵၢၼ်ၵႂႃႇၼၼ်ႉ ၶႅၼ်းတေႃႈ ပွင်ႇၶၢဝ်ႇ တမ်ႈတီႈ ၽူႈၵုမ်းၵၢၼ်", - "pad.share": "ၽႄၽႅတ်ႉၼႆႉ", - "pad.share.readonly": "လူလၢႆလၢႆ", - "pad.share.link": "ၵွင်ႉ", - "pad.share.emebdcode": "သႂ်ႇ URL", - "pad.chat": "ၶျၢတ်ႉ", - "pad.chat.title": "ပိုတ်ႇၶျၢတ်ႉ တႃႇၽႅတ်ႉၼႆႉ", - "pad.chat.loadmessages": "လူတ်ႇၶေႃႈၶၢဝ်ႇ လိူဝ်", - "timeslider.pageTitle": "{{appTitle}} ၶၢဝ်းယၢမ်းထေႃပူၼ်ႉ", - "timeslider.toolbar.returnbutton": "ၶိုၼ်းၵႂႃႇၸူး ၽႅတ်ႉ", - "timeslider.toolbar.authors": "ၽူႈတႅမ်ႈလိၵ်ႈ", - "timeslider.toolbar.authorsList": "ဢမ်ႇၸႂ်ႈ ၽူႈတႅမ်ႈလိၵ်ႈ", - "timeslider.toolbar.exportlink.title": "သူင်ႇဢွၵ်ႇ", - "timeslider.exportCurrent": "သူင်ႇဢွၵ်ႇ လုၼ်ႈပၢၼ်မႂ်ႇ ၼင်ႇ:", - "timeslider.version": "လုၼ်ႈ {{version}}", - "timeslider.saved": "သိမ်းယဝ်ႉ{{month}} {{day}}, {{year}}", - "timeslider.playPause": "လဵၼ်ႈလင်/ၵိုတ်းသဝ်း ၵႂၢမ်းၼၢမ်း ၽႅတ်ႉ", - "timeslider.backRevision": "ႁူၼ်လင် ၶိုၼ်းမႄး ၽႅတ်ႉၼႆႉ", - "timeslider.forwardRevision": "ၵႂႃႇၼႃႈ ၶိုၼ်းမႄး ၽႅတ်ႉၼႆႉ", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "ၵျၼ်ႇၼိဝ်ႇရီႇ", - "timeslider.month.february": "ၾႅပ်ႇဝႃႇရီႇ", - "timeslider.month.march": "မၢတ်ႉၶျ်", - "timeslider.month.april": "ဢေႇပရႄႇ", - "timeslider.month.may": "မေႇ", - "timeslider.month.june": "ၵျုၼ်ႇ", - "timeslider.month.july": "ၵျူႇလၢႆႇ", - "timeslider.month.august": "ဢေႃးၵၢတ်ႉ", - "timeslider.month.september": "သႅပ်ႉထိမ်ႇပႃႇ", - "timeslider.month.october": "ဢွၵ်ႇထူဝ်ႇပႃႇ", - "timeslider.month.november": "ၼူဝ်ႇ​ဝႅမ်ႇ​ပႃႇ", - "timeslider.month.december": "တီႇသႅမ်ႇပႃႇ", - "timeslider.unnamedauthors": "{{num}} ဢမ်ႇသႂ်ႇၸိုဝ်ႈ {[plural(num) ၼိုင်ႈ: ၽူႈတႅမ်ႈလိၵ်ႈ, တၢင်ႇၸိူဝ်း: ၽူႈတႅမ်ႈလိၵ်ႈၶဝ် ]}", - "pad.savedrevs.marked": "ဢၼ်မႄးဝႆႉၼႆႉ ယၢမ်းလဵဝ် ၶိုၼ်းမႄး ၵဵပ်းသိမ်းဝႆႉ ၸိူင်ႉၼင်ႇဢၼ်ၼိုင်ႈ", - "pad.savedrevs.timeslider": "ၸဝ်ႈၵဝ်ႇတေတူၺ်းလႆႈ ဢၼ်ၶိုၼ်းမႄးသိမ်းဝႆႉၼၼ်ႉယူႇ ပေႃးၶဝ်ႈတူၺ်းတီႈ ၶၢဝ်းယၢမ်းထေႃပူၼ်ႉ", - "pad.userlist.entername": "ပေႃႇသႂ်ႇပၼ် ၸိုဝ်ႈၽူႈၸႂ်ႉတိုဝ်း ၸဝ်ႈၵဝ်ႇ", - "pad.userlist.unnamed": "ဢမ်ႇသႂ်ႇၸိုဝ်ႈ", - "pad.userlist.guest": "ၶႅၵ်ႇ", - "pad.userlist.deny": "ထဵင်", - "pad.userlist.approve": "ၵမ်ႉထႅမ်", - "pad.editbar.clearcolors": "လၢင်ႉပႅတ်ႈသီၵဝ်ႇ တမ်ႈတီႈ ၼိူဝ်ၶေႃႈလိၵ်ႈတင်းသဵင်ႈ", - "pad.impexp.importbutton": "သူင်ႇၶဝ်ႈယၢမ်းလဵဝ်", - "pad.impexp.importing": "တိုၵ်ႉသူင်ႇၶဝ်ႈယူႇ", - "pad.impexp.confirmimport": "ဢဝ်ၾၢႆႇၶဝ်ႈမႃးၼႆႉ တေမႃး တဵင်သႂ်ႇ လိၵ်ႈဢၼ်မီးဝႆႉ တီႈၼႂ်းၽႅတ်ႉၼႆႉယဝ်ႉ။ ၸွင်ႇၸဝ်ႈၵဝ်ႇ လပ်ႉလွင်းဝႃႈ ၸဝ်ႈၵဝ်ႇ တေၶႂ်ႈ ငူပ်ႉငိႁိုဝ်?", - "pad.impexp.convertFailed": "ႁဝ်းဢမ်ႇၸၢင်းႁဵတ်းႁိုဝ် ဢဝ်ၾၢႆႇၼႆႉ သူင်ႇၶဝ်ႈၵႂႃႇ။ ၶႅၼ်းတေႃႈ ၸႂ်ႉတိုဝ်း ၶေႃႈလိၵ်ႈ ဢၼ်ပႅၵ်ႇပိူင်ႈၵၼ် ဢမ်ႇၼၼ် ၵူးထုတ်ႇဝႆႉလႄႈ", - "pad.impexp.padHasData": "ႁဝ်းဢမ်ႇၸၢင်းႁဵတ်းႁိုဝ် ဢဝ်ၾၢႆႇၼႆႉ သူင်ႇၶဝ်ႈၵႂႃႇ ၵွပ်ႈပိူဝ်ႈဝႃႈ ၽႅတ်ႉဢၼ်ၼႆႉ မၼ်းလႅၵ်ႈလၢႆႈၵႂႃႇယဝ်ႉယဝ်ႈ။ ၶွပ်ႈၸႂ် သူင်ႇၶႂ်ႈၼႂ်း ၽႅတ်ႉမႂ်ႇလႄႈ", - "pad.impexp.uploadFailed": "ဢၼ်လူတ်ႇၶိုၼ်ႈ ၶၢတ်ႇတူၵ်းယဝ်ႉ။ ၶႅၼ်းတေႃႈ ၶတ်းၸႂ်ထႅင်ႈ", - "pad.impexp.importfailed": "ဢၼ်သူင်ႇၶဝ်ႈ ၶၢတ်ႇတူၵ်းယဝ်ႉ", - "pad.impexp.copypaste": "ၶႅၼ်းတေႃႈ ၵူးသေ ဢဝ်ဝႆႉတ", - "pad.impexp.exportdisabled": "ၸိူင်ႉၼင်ႇ {{type}} သူင်ႇဢွၵ်ႇ ၾေႃးမဵတ်ႉ ၼၼ်ႉ ဢမ်ႇၸၢင်ႈ။ ၶႅၼ်းတေႃႈ ၵပ်းသိုပ်ႇ ၽူႈၵုမ်းၵၢၼ်ၸၢၵ်ႈ တႃႇႁူဝ်ယွႆႈမၼ်းတ" -} diff --git a/sources/src/locales/sk.json b/sources/src/locales/sk.json deleted file mode 100644 index e199945..0000000 --- a/sources/src/locales/sk.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Teslaton", - "Kusavica", - "Rudko", - "Mark", - "Lexected" - ] - }, - "index.newPad": "Nový Pad", - "index.createOpenPad": "alebo vytvoriť/otvoriť Pad s názvom:", - "pad.toolbar.bold.title": "Tučné (Ctrl-B)", - "pad.toolbar.italic.title": "Kurzíva (Ctrl-I)", - "pad.toolbar.underline.title": "Podčiarknuté (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Prečiarknuté (Ctrl+5)", - "pad.toolbar.ol.title": "Usporiadaný zoznam (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Nezoradený zoznam (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Zväčšiť odsadenie (TAB)", - "pad.toolbar.unindent.title": "Zmenšiť odsadenie (Shift+TAB)", - "pad.toolbar.undo.title": "Späť (Ctrl-Z)", - "pad.toolbar.redo.title": "Znova (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Odstrániť farby autorstva (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Import/export z/do rôznych formátov súborov", - "pad.toolbar.timeslider.title": "Časová os", - "pad.toolbar.savedRevision.title": "Uložiť revíziu", - "pad.toolbar.settings.title": "Nastavenia", - "pad.toolbar.embed.title": "Zdieľať alebo vložiť tento Pad", - "pad.toolbar.showusers.title": "Zobraziť používateľov tohoto Padu", - "pad.colorpicker.save": "Uložiť", - "pad.colorpicker.cancel": "Zrušiť", - "pad.loading": "Načítava sa...", - "pad.noCookie": "Cookie nebolo možné nájsť. Povoľte prosím cookies vo vašom prehliadači.", - "pad.passwordRequired": "Prístup k tomuto Padu je chránený heslom", - "pad.permissionDenied": "Ľutujeme, nemáte oprávnenie pristupovať k tomuto Padu", - "pad.wrongPassword": "Nesprávne heslo", - "pad.settings.padSettings": "Nastavenia Padu", - "pad.settings.myView": "Vlastný pohľad", - "pad.settings.stickychat": "Chat stále na obrazovke", - "pad.settings.chatandusers": "Zobraziť chat a užívateľov", - "pad.settings.colorcheck": "Farby autorstva", - "pad.settings.linenocheck": "Čísla riadkov", - "pad.settings.rtlcheck": "Čítať obsah sprava doľava?", - "pad.settings.fontType": "Typ písma:", - "pad.settings.fontType.normal": "Normálne", - "pad.settings.fontType.monospaced": "Strojové", - "pad.settings.globalView": "Globálny pohľad", - "pad.settings.language": "Jazyk:", - "pad.importExport.import_export": "Import/Export", - "pad.importExport.import": "Nahrať ľubovoľný textový súbor alebo dokument", - "pad.importExport.importSuccessful": "Import úspešný!", - "pad.importExport.export": "Exportovať aktuálny Pad ako:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Čistý text", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Importovať môžete len čistý text alebo HTML. Pre pokročilejšie funkcie importu prosím nainštalujte „AbiWord“.", - "pad.modals.connected": "Pripojené.", - "pad.modals.reconnecting": "Opätovné pripájanie k vášmu Padu...", - "pad.modals.forcereconnect": "Vynútiť znovupripojenie", - "pad.modals.reconnecttimer": "Skúšam sa pripojiť", - "pad.modals.cancel": "Zrušiť", - "pad.modals.userdup": "Otvorené v inom okne", - "pad.modals.userdup.explanation": "Zdá sa, že tento Pad je na tomto počítači otvorený vo viacerých oknách prehliadača.", - "pad.modals.userdup.advice": "Pre použitie tohoto okna se musíte znovu pripojiť.", - "pad.modals.unauth": "Nie ste autorizovaný", - "pad.modals.unauth.explanation": "Vaše oprávnenia sa počas prehliadania tejto stránky zmenili. Skúste sa pripojiť znovu.", - "pad.modals.looping.explanation": "Nastali problémy pri komunikácii so synchronizačným serverom.", - "pad.modals.looping.cause": "Možno ste pripojení cez nekompatibilný firewall alebo proxy server.", - "pad.modals.initsocketfail": "Server je nedostupný.", - "pad.modals.initsocketfail.explanation": "Nepodarilo sa pripojiť k synchronizačnému serveru.", - "pad.modals.initsocketfail.cause": "Príčinou je pravdepodobne problém s prehliadačom alebo internetovým pripojením.", - "pad.modals.slowcommit.explanation": "Server neodpovedá.", - "pad.modals.slowcommit.cause": "Príčinou môže byť problém so sieťovým pripojením.", - "pad.modals.badChangeset.explanation": "Editácia, kterú ste vykonali byla synchronizáciou serveru vyhodnotená ako nepovolená.", - "pad.modals.badChangeset.cause": "To môže byť z dôvodu nesprávnej konfigurácie servera alebo iného neočakávaného správania. Ak máte pocit že došlo k chybe, kontaktuje prosím správcu služby. Pokúste sa pripojiť znova a pokračovať v úpravách.", - "pad.modals.corruptPad.explanation": "Pad ku ktorému sa snažíte získať prístup je poškodený.", - "pad.modals.corruptPad.cause": "To môže byť z dôvodu nesprávnej konfigurácie servera alebo iného neočakávaného správania. Prosím, obráťte sa na správcu služby.", - "pad.modals.deleted": "Odstránené.", - "pad.modals.deleted.explanation": "Tento Pad bol odstránený.", - "pad.modals.disconnected": "Boli ste odpojení.", - "pad.modals.disconnected.explanation": "Spojenie so serverom sa prerušilo", - "pad.modals.disconnected.cause": "Server môže byť nedostupný. Ak by problém pretrvával, informujte správcu služby.", - "pad.share": "Zdieľať tento Pad", - "pad.share.readonly": "Len na čítanie", - "pad.share.link": "Odkaz", - "pad.share.emebdcode": "Vložiť URL", - "pad.chat": "Chat", - "pad.chat.title": "Otvoriť chat tohoto Padu.", - "pad.chat.loadmessages": "Načítať ďalšie správy", - "timeslider.pageTitle": "Časová os {{appTitle}}", - "timeslider.toolbar.returnbutton": "Návrat do Padu", - "timeslider.toolbar.authors": "Autori:", - "timeslider.toolbar.authorsList": "Bez autorov", - "timeslider.toolbar.exportlink.title": "Export", - "timeslider.exportCurrent": "Exportovať aktuálnu verziu ako:", - "timeslider.version": "Verzia {{version}}", - "timeslider.saved": "Uložené {{day}}. {{month}} {{year}}", - "timeslider.playPause": "Pustiť / Pozastaviť obsah padu", - "timeslider.backRevision": "Ísť v tomto pade a revíziu späť", - "timeslider.forwardRevision": "Ísť v tomto pade o revíziu vpred", - "timeslider.dateformat": "{{day}}. {{month}} {{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "januára", - "timeslider.month.february": "februára", - "timeslider.month.march": "marca", - "timeslider.month.april": "apríla", - "timeslider.month.may": "mája", - "timeslider.month.june": "júna", - "timeslider.month.july": "júla", - "timeslider.month.august": "augusta", - "timeslider.month.september": "septembra", - "timeslider.month.october": "októbra", - "timeslider.month.november": "novembra", - "timeslider.month.december": "decembra", - "timeslider.unnamedauthors": "{{num}} {[ plural(num) one: nemenovaný autor, few: nemenovaní autori, other: nemenovaných autorov ]}", - "pad.savedrevs.marked": "Táto revízia bola označená ako uložená", - "pad.savedrevs.timeslider": "Návštevou časovej osi môžete zobraziť uložené revízie", - "pad.userlist.entername": "Zadajte svoje meno", - "pad.userlist.unnamed": "nemenovaný", - "pad.userlist.guest": "Hosť", - "pad.userlist.deny": "Zakázať", - "pad.userlist.approve": "Schváliť", - "pad.editbar.clearcolors": "Skutočne odstrániť autorské farby z celého dokumentu?", - "pad.impexp.importbutton": "Importovať", - "pad.impexp.importing": "Prebieha import...", - "pad.impexp.confirmimport": "Import súboru prepíše celý súčasný obsah Padu. Skutočne si želáte vykonať túto akciu?", - "pad.impexp.convertFailed": "Tento súbor nie je možné importovať. Použite prosím iný formát súboru alebo nakopírujte text manuálne", - "pad.impexp.padHasData": "Nebolo možné importovať tento súbor, pretože tento pad už bol pozmenený. Importujte prosím súbor do nového padu", - "pad.impexp.uploadFailed": "Nahrávanie zlyhalo, skúste to prosím znovu", - "pad.impexp.importfailed": "Import zlyhal", - "pad.impexp.copypaste": "Vložte prosím kópiu cez schránku", - "pad.impexp.exportdisabled": "Export do formátu {{type}} nie je povolený. Kontaktujte prosím administrátora pre zistenie detailov." -} diff --git a/sources/src/locales/skr-arab.json b/sources/src/locales/skr-arab.json deleted file mode 100644 index 833d341..0000000 --- a/sources/src/locales/skr-arab.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Saraiki" - ] - }, - "index.newPad": "نواں پیڈ", - "pad.toolbar.bold.title": "بولڈ(Ctrl+B)", - "pad.toolbar.italic.title": "ترچھے (Ctrl+I)", - "pad.toolbar.underline.title": "ہیٹھ لکیر (Ctrl+U)", - "pad.toolbar.savedRevision.title": "رویژن بچاؤ", - "pad.toolbar.settings.title": "ترتیباں", - "pad.colorpicker.save": "بچاؤ", - "pad.colorpicker.cancel": "منسوخ", - "pad.loading": "لوڈ تھیندا پئے۔۔۔", - "pad.wrongPassword": "تہاݙ پاسورڈ غلط ہے", - "pad.settings.padSettings": "پیڈ ترتیباں", - "pad.settings.fontType": "فونٹ قسم:", - "pad.settings.globalView": "عالمی منظر", - "pad.settings.language": "زبان:", - "pad.importExport.importSuccessful": "کامیاب!", - "pad.importExport.exportetherpad": "ایتھرپیڈ", - "pad.importExport.exporthtml": "ایچ ٹی ایم ایل", - "pad.importExport.exportplain": "سادہ متن", - "pad.importExport.exportword": "مائیکروسافٹ ورڈ", - "pad.importExport.exportpdf": "پی ڈی ایف", - "pad.modals.connected": "ڄُڑ ڳیا۔", - "pad.modals.cancel": "منسوخ", - "pad.modals.unauth": "اجازت کائنی", - "pad.modals.initsocketfail": "سرور تائیں پہنچݨ ممکن کائنی", - "pad.modals.slowcommit.explanation": "سرور توں جواب کائنی امدا پیا", - "pad.modals.deleted": "مٹا ݙتے", - "pad.modals.deleted.explanation": "ایہ پیڈ ہٹا ݙتا ڳئے۔", - "pad.modals.disconnected": "تہاݙا کنکشن مُک ڳئے", - "pad.share": "ایہ پیڈ شیئر کرو", - "pad.share.readonly": "صرف پڑھو", - "pad.share.link": "ربط", - "pad.share.emebdcode": "امنیڈ یو آر ایل", - "pad.chat": "چیٹ", - "pad.chat.loadmessages": "ٻئے سنیہے لوڈ کرو", - "timeslider.toolbar.returnbutton": "واپس پیڈ تے ونڄو", - "timeslider.toolbar.authors": "مصنف:", - "timeslider.toolbar.authorsList": "کوئی مصنف کائنی", - "timeslider.toolbar.exportlink.title": "ٻاہر بھیڄو", - "timeslider.version": "ورژن {{version}}", - "timeslider.saved": "محفوظ تھیا {{month}} {{day}}, {{year}}", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "جنوری", - "timeslider.month.february": "فروری", - "timeslider.month.march": "مارچ", - "timeslider.month.april": "اپريل", - "timeslider.month.may": "مئی", - "timeslider.month.june": "جون", - "timeslider.month.july": "جولائی", - "timeslider.month.august": "اگست", - "timeslider.month.september": "ستمبر", - "timeslider.month.october": "اکتوبر", - "timeslider.month.november": "نومبر", - "timeslider.month.december": "دسمبر", - "pad.userlist.entername": "آپݨا ناں درج کرو", - "pad.userlist.unnamed": "بغیر ناں", - "pad.userlist.guest": "پرہاݨاں", - "pad.userlist.deny": "انکار", - "pad.userlist.approve": "منظور", - "pad.impexp.importbutton": "ہݨ ٻاہروں گھن آؤ", - "pad.impexp.importing": "اندر آندا پئے۔۔۔", - "pad.impexp.uploadFailed": "فائل اپ لوڈ نی تھی سڳی، چڑھاوݨ کیتےولدا کوشش کرو", - "pad.impexp.importfailed": "ٻاہروں آ نی سڳے" -} diff --git a/sources/src/locales/sl.json b/sources/src/locales/sl.json deleted file mode 100644 index 94ccfa7..0000000 --- a/sources/src/locales/sl.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Dbc334", - "Mateju", - "Skalcaa", - "HairyFotr" - ] - }, - "index.newPad": "Nov dokument", - "index.createOpenPad": "ali pa ustvari/odpri dokument z imenom:", - "pad.toolbar.bold.title": "Krepko (Ctrl-B)", - "pad.toolbar.italic.title": "Ležeče (Ctrl-I)", - "pad.toolbar.underline.title": "Podčrtano (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Prečrtano (Ctrl+5)", - "pad.toolbar.ol.title": "Urejen seznam (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Neurejen seznam (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Zamik desno (TAB)", - "pad.toolbar.unindent.title": "Zamik levo (Shift+TAB)", - "pad.toolbar.undo.title": "Razveljavi (Ctrl-Z)", - "pad.toolbar.redo.title": "Ponovno uveljavi (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Počisti barve avtorstva (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Uvozi/Izvozi različne oblike zapisov", - "pad.toolbar.timeslider.title": "Časovni trak", - "pad.toolbar.savedRevision.title": "Shrani redakcijo", - "pad.toolbar.settings.title": "Nastavitve", - "pad.toolbar.embed.title": "Deli in vključi ta dokument", - "pad.toolbar.showusers.title": "Pokaži uporabnike dokumenta", - "pad.colorpicker.save": "Shrani", - "pad.colorpicker.cancel": "Prekliči", - "pad.loading": "Nalaganje ...", - "pad.noCookie": "Piškotka ni bilo mogoče najti. Prosimo, dovolite piškotke v vašem brskalniku!", - "pad.passwordRequired": "Za dostop do dokumenta potrebujete geslo.", - "pad.permissionDenied": "Nimate dovoljenja za dostop do tega dokumenta.", - "pad.wrongPassword": "Vpisano geslo je napačno", - "pad.settings.padSettings": "Nastavitve dokumenta", - "pad.settings.myView": "Moj pogled", - "pad.settings.stickychat": "Vsebina klepeta je vedno na zaslonu", - "pad.settings.chatandusers": "Prikaži klepet in uporabnike", - "pad.settings.colorcheck": "Barve avtorstva", - "pad.settings.linenocheck": "Številke vrstic", - "pad.settings.rtlcheck": "Ali naj se vsebina prebira od desne proti levi?", - "pad.settings.fontType": "Vrsta pisave:", - "pad.settings.fontType.normal": "Običajno", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Splošni pogled", - "pad.settings.language": "Jezik:", - "pad.importExport.import_export": "Uvoz/Izvoz", - "pad.importExport.import": "Naloži katerokoli besedilno datoteko ali dokument.", - "pad.importExport.importSuccessful": "Opravilo je uspešno končano!", - "pad.importExport.export": "Izvozi trenutni dokument kot:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML (oblikovano besedilo)", - "pad.importExport.exportplain": "TXT (neoblikovano besedilo)", - "pad.importExport.exportword": "DOC (zapis Microsoft Word)", - "pad.importExport.exportpdf": "PDF (zapis Acrobat PDF)", - "pad.importExport.exportopen": "ODF (zapis Open Document)", - "pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le običajno neoblikovano besedilo in zapise HTML. Za naprednejše zmožnosti namestite program AbiWord.", - "pad.modals.connected": "Povezano.", - "pad.modals.reconnecting": "Poteka povezovanje z dokumentom ...", - "pad.modals.forcereconnect": "Vsili ponovno povezavo", - "pad.modals.reconnecttimer": "Poskus ponovne vzpostavitve povezave čez", - "pad.modals.cancel": "Prekliči", - "pad.modals.userdup": "Dokument je že odprt v v drugem oknu", - "pad.modals.userdup.explanation": "Videti je, da je ta dokument odprt v več kot enem oknu brskalnika na tem računalniku.", - "pad.modals.userdup.advice": "Ponovno vzpostavite povezavo in uporabljajte to okno.", - "pad.modals.unauth": "Nepooblaščen dostop", - "pad.modals.unauth.explanation": "Med pregledovanjem te strani so se dovoljenja za ogled spremenila. Poskusite se ponovno povezati.", - "pad.modals.looping.explanation": "Zaznane so težave pri komunikaciji s strežnikom za usklajevanje.", - "pad.modals.looping.cause": "Morda ste se povezali preko neustrezno nastavljenega požarnega zidu ali posredniškega strežnika.", - "pad.modals.initsocketfail": "Strežnika je nedosegljiv.", - "pad.modals.initsocketfail.explanation": "Povezava s strežnikom za usklajevanje ni mogoča.", - "pad.modals.initsocketfail.cause": "Najverjetneje gre za težavo z vašim brskalnikom, ali internetno povezavo.", - "pad.modals.slowcommit.explanation": "Strežnik se ne odziva.", - "pad.modals.slowcommit.cause": "Možen vzrok so težave z omrežno povezljivostjo.", - "pad.modals.badChangeset.explanation": "Urejanje, ki ste ga naredili, je strežnik za usklajevanje označil kot nedovoljeno.", - "pad.modals.badChangeset.cause": "Razlog za to je morda napačna konfiguracija strežnika ali neko drugo nepričakovano vedenje. Prosimo, stopite v stik z skrbnikom storitve, če menite, da gre za napako. Poskusite se ponovno povezati, da nadaljujete z urejanjem.", - "pad.modals.corruptPad.explanation": "Dokument, do katerega želite dostopati, je poškodovan.", - "pad.modals.corruptPad.cause": "Razlog za to je morda napačna konfiguracija strežnika ali neko drugo nepričakovano vedenje. Prosimo, stopite v stik s skrbnikom storitve.", - "pad.modals.deleted": "Izbrisano.", - "pad.modals.deleted.explanation": "Dokument je bil odstranjen.", - "pad.modals.disconnected": "Vaša povezava je bila prekinjena.", - "pad.modals.disconnected.explanation": "Povezava s strežnikom je bila izgubljena.", - "pad.modals.disconnected.cause": "Strežnik morda ni na voljo. Prosimo, obvestite skrbnika storitve, če se to zgodi večkrat.", - "pad.share": "Določi souporabo dokumenta", - "pad.share.readonly": "Le za branje", - "pad.share.link": "Povezava", - "pad.share.emebdcode": "URL za vključitev", - "pad.chat": "Klepet", - "pad.chat.title": "Odpri klepetalno okno dokumenta.", - "pad.chat.loadmessages": "Naloži več sporočil", - "timeslider.pageTitle": "Časovni trak {{appTitle}}", - "timeslider.toolbar.returnbutton": "Vrni se na dokument", - "timeslider.toolbar.authors": "Avtorji:", - "timeslider.toolbar.authorsList": "Ni določenih avtorjev", - "timeslider.toolbar.exportlink.title": "Izvozi", - "timeslider.exportCurrent": "Izvozi trenutno različico kot:", - "timeslider.version": "Različica {{version}}", - "timeslider.saved": "Shranjeno {{day}}.{{month}}.{{year}}", - "timeslider.playPause": "Predvajaj/začasno ustavi vsebino dokumenta", - "timeslider.backRevision": "Pojdi eno redakcijo nazaj v tem dokumentu", - "timeslider.forwardRevision": "Pojdi eno redakcijo naprej v tem dokumentu", - "timeslider.dateformat": "{{day}}.{{month}}.{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Januar", - "timeslider.month.february": "Februar", - "timeslider.month.march": "Marec", - "timeslider.month.april": "April", - "timeslider.month.may": "Maj", - "timeslider.month.june": "Junij", - "timeslider.month.july": "Julij", - "timeslider.month.august": "August", - "timeslider.month.september": "September", - "timeslider.month.october": "Oktober", - "timeslider.month.november": "November", - "timeslider.month.december": "December", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovan avtor, plural(num) two: neimenovana avtorja, plural(num) few: neimenovani avtorji, other: neimenovanih avtorjev ]}", - "pad.savedrevs.marked": "Ta redakcija je zdaj označena kot shranjena redakcija", - "pad.savedrevs.timeslider": "Shranjene redakcije si lahko ogledate s pomočjo časovnega traku", - "pad.userlist.entername": "Vnesite svoje ime", - "pad.userlist.unnamed": "neimenovana oseba", - "pad.userlist.guest": "Gost", - "pad.userlist.deny": "Zavrni", - "pad.userlist.approve": "Odobri", - "pad.editbar.clearcolors": "Ali naj se počistijo barve avtorstva v celotnem dokumentu?", - "pad.impexp.importbutton": "Uvozi takoj", - "pad.impexp.importing": "Poteka uvažanje ...", - "pad.impexp.confirmimport": "Uvoz datoteke prepiše obstoječe besedilo dokumenta. Ali ste prepričani, da želite nadaljevati?", - "pad.impexp.convertFailed": "Datoteke ni bilo mogoče uvoziti. Prosimo uporabite drug podprt zapis dokumenta ali pa vsebino prilepite ročno", - "pad.impexp.padHasData": "Nismo mogli uvoziti datoteke, ker dokument že vsebuje spremembe. Prosimo, uvozite datoteko v nov dokument", - "pad.impexp.uploadFailed": "Nalaganje je spodletelo, prosimo poskusite znova", - "pad.impexp.importfailed": "Uvoz je spodletel", - "pad.impexp.copypaste": "Vsebino kopirajte in prilepite", - "pad.impexp.exportdisabled": "Izvoz v zapis {{type}} je onemogočen. Za več podrobnosti stopite v stik s skrbnikom." -} diff --git a/sources/src/locales/sq.json b/sources/src/locales/sq.json deleted file mode 100644 index 28485b3..0000000 --- a/sources/src/locales/sq.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Besnik b", - "Kosovastar" - ] - }, - "index.newPad": "Bllok i ri", - "index.createOpenPad": "ose krijoni/hapni një Bllok me emrin:", - "pad.toolbar.bold.title": "Të trasha (Ctrl-B)", - "pad.toolbar.italic.title": "Të pjerrëta (Ctrl-I)", - "pad.toolbar.underline.title": "Të nënvizuara (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Hequr vije (Ctrl+5)", - "pad.toolbar.ol.title": "Listë e renditur (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Listë e parenditur (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Brendazi (TAB)", - "pad.toolbar.unindent.title": "Jashtazi (Shift+TAB)", - "pad.toolbar.undo.title": "Zhbëje (Ctrl-Z)", - "pad.toolbar.redo.title": "Ribëje (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Hiqu Ngjyra Autorësish (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importoni/Eksportoni nga/në formate të tjera kartelash", - "pad.toolbar.timeslider.title": "Rrjedha kohore", - "pad.toolbar.savedRevision.title": "Ruaje rishikimin", - "pad.toolbar.settings.title": "Rregullime", - "pad.toolbar.embed.title": "Ndajeni me të tjerët dhe Trupëzojeni këtë bllok", - "pad.toolbar.showusers.title": "Shfaq përdoruesit në këtë bllok", - "pad.colorpicker.save": "Ruaje", - "pad.colorpicker.cancel": "Anuloje", - "pad.loading": "Po ngarkohet…", - "pad.noCookie": "S’u gjet dot cookie. Ju lutemi, lejoni cookie-t te shfletuesi juaj!", - "pad.passwordRequired": "Ju duhet një fjalëkalim që të mund të përdorni këtë bllok", - "pad.permissionDenied": "S’keni leje të hyni në këtë bllok", - "pad.wrongPassword": "Fjalëkalimi juaj qe gabim", - "pad.settings.padSettings": "Rregullime Blloku", - "pad.settings.myView": "Pamja ime", - "pad.settings.stickychat": "Fjalosje përherë në ekran", - "pad.settings.chatandusers": "Shfaq Fjalosje dhe Përdorues", - "pad.settings.colorcheck": "Ngjyra autorësish", - "pad.settings.linenocheck": "Numra rreshtash", - "pad.settings.rtlcheck": "Të lexohet lënda nga e djathta në të majtë?", - "pad.settings.fontType": "Lloj shkronjash:", - "pad.settings.fontType.normal": "Normale", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Pamje e Përgjithshme", - "pad.settings.language": "Gjuhë:", - "pad.importExport.import_export": "Import/Eksport", - "pad.importExport.import": "Ngarkoni cilëndo kartelë teksti ose dokument", - "pad.importExport.importSuccessful": "Me sukses!", - "pad.importExport.export": "Eksportojeni bllokun e tanishëm si:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Tekst të thjeshtë", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Mund të importoni vetëm prej formati tekst i thjeshtë ose html. Për veçori më të thelluara importimi, ju lutemi, instaloni Abiword-in.", - "pad.modals.connected": "I lidhur.", - "pad.modals.reconnecting": "Po rilidheni te blloku juaj…", - "pad.modals.forcereconnect": "Rilidhje e detyruar", - "pad.modals.userdup": "Hapur në një tjetër dritare", - "pad.modals.userdup.explanation": "Ky bllok duket se gjendet i hapur në më shumë se një dritare shfletuesi në këtë kompjuter.", - "pad.modals.userdup.advice": "Rilidhuni që të përdoret kjo dritare.", - "pad.modals.unauth": "I paautorizuar", - "pad.modals.unauth.explanation": "Lejet tuaja ndryshuan teksa shihnit këtë dritare. Provoni të rilidheni.", - "pad.modals.looping.explanation": "Ka probleme komunikimi me shërbyesin e njëkohësimit.", - "pad.modals.looping.cause": "Ndoshta jeni lidhur përmes një firewall-i ose ndërmjetësi të papërputhshëm.", - "pad.modals.initsocketfail": "Shërbyesi është i pakapshëm.", - "pad.modals.initsocketfail.explanation": "S’u lidh dot te shërbyesi i njëkohësimit.", - "pad.modals.initsocketfail.cause": "Ka gjasa që kjo vjen për shkak të një problemi me shfletuesin tuaj ose lidhjen tuaj në internet.", - "pad.modals.slowcommit.explanation": "Shërbyesi nuk po përgjigjet.", - "pad.modals.slowcommit.cause": "Kjo mund të vijë për shkak problemesh lidhjeje me rrjetin.", - "pad.modals.badChangeset.explanation": "Një përpunim që keni bërë u vlerësua si i paligjshëm nga shërbyesi i njëkohësimit.", - "pad.modals.badChangeset.cause": "Kjo mund të jetë për shkak të një formësimi të gabuar të shërbyesit ose ndonjë tjetër sjelljeje të papritur. Ju lutemi, lidhuni me përgjegjësin e shërbimit, nëse mendoni që ky është një gabim. Provoni të rilidheni që të vazhdoni përpunimin.", - "pad.modals.corruptPad.explanation": "Blloku te i cili po përpiqeni të hyni është i dëmtuar.", - "pad.modals.corruptPad.cause": "Kjo mund të vijë nga një formësim i gabuar shërbyesi ose ndonjë tjetër sjellje e papritur. Ju lutemi, lidhuni me përgjegjësin e shërbimit.", - "pad.modals.deleted": "I fshirë.", - "pad.modals.deleted.explanation": "Ky bllok është hequr.", - "pad.modals.disconnected": "Jeni shkëputur.", - "pad.modals.disconnected.explanation": "U ndërpre lidhja me shërbyesin", - "pad.modals.disconnected.cause": "Shërbyesi mund të mos jetë në punë. Ju lutemi, njoftoni përgjegjësin e shërbimit, nëse kjo vazhdon të ndodhë.", - "pad.share": "Ndajeni këtë bllok me të tjerët", - "pad.share.readonly": "Vetëm për lexim", - "pad.share.link": "Lidhje", - "pad.share.emebdcode": "URL trupëzimi", - "pad.chat": "Fjalosje", - "pad.chat.title": "Hapni fjalosjen për këtë bllok.", - "pad.chat.loadmessages": "Ngarko më tepër mesazhe", - "timeslider.pageTitle": "Rrjedhë kohore e {{appTitle}}", - "timeslider.toolbar.returnbutton": "Rikthehuni te blloku", - "timeslider.toolbar.authors": "Autorë:", - "timeslider.toolbar.authorsList": "S’ka autorë", - "timeslider.toolbar.exportlink.title": "Eksportoje", - "timeslider.exportCurrent": "Eksportojeni versionin e tanishëm si:", - "timeslider.version": "Versioni {{version}}", - "timeslider.saved": "Ruajtur më {{day}} {{month}}, {{year}}", - "timeslider.playPause": "Luaj / Pusho Lëndë Blloku", - "timeslider.backRevision": "Kalo një rishikim mbrapsht në këtë Bllok", - "timeslider.forwardRevision": "Kalo një rishikim përpara në këtë Bllok", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Janar", - "timeslider.month.february": "Shkurt", - "timeslider.month.march": "Mars", - "timeslider.month.april": "Prill", - "timeslider.month.may": "Maj", - "timeslider.month.june": "Qershor", - "timeslider.month.july": "Korrik", - "timeslider.month.august": "Gusht", - "timeslider.month.september": "Shtator", - "timeslider.month.october": "Tetor", - "timeslider.month.november": "Nëntor", - "timeslider.month.december": "Dhjetor", - "timeslider.unnamedauthors": "{{num}} i paemër {[plural(num) një: autor, tjetër:{{num}} autorë ]}", - "pad.savedrevs.marked": "Ky rishikim tani është shënuar si rishikim i ruajtur", - "pad.savedrevs.timeslider": "Rishikimet e ruajtura mund t’i shihni duke vizituar rrjedhën kohore", - "pad.userlist.entername": "Jepni emrin tuaj", - "pad.userlist.unnamed": "pa emër", - "pad.userlist.guest": "Vizitor", - "pad.userlist.deny": "Hidhe poshtë", - "pad.userlist.approve": "Miratoje", - "pad.editbar.clearcolors": "Të hiqen ngjyra autorësish në krejt dokumentin?", - "pad.impexp.importbutton": "Importoje Tani", - "pad.impexp.importing": "Po importohet…", - "pad.impexp.confirmimport": "Importimi i një kartele do të mbishkruajë tekstin e tanishëm të bllokut. Jeni i sigurt se doni të vazhdohet?", - "pad.impexp.convertFailed": "Nuk qemë në gjendje ta importonim këtë kartelë. Ju lutemi, përdorni një format tjetër dokumentesh ose kopjojeni dhe hidheni dorazi", - "pad.impexp.padHasData": "S’qemë në gjendje të importojmë këtë kartelë, ngaqë ky Bllok kish tashmë ndryshime, ju lutemi, importojeni tek një bllok i ri", - "pad.impexp.uploadFailed": "Ngarkimi dështoi, ju lutemi, riprovoni", - "pad.impexp.importfailed": "Importimi dështoi", - "pad.impexp.copypaste": "Ju lutemi, kopjojeni dhe ngjiteni", - "pad.impexp.exportdisabled": "Eksportimi në formatin {{type}} është i çaktivizuar. Për hollësi, ju lutemi, lidhuni me administratorin e sistemit." -} diff --git a/sources/src/locales/sr-ec.json b/sources/src/locales/sr-ec.json deleted file mode 100644 index 59f77ef..0000000 --- a/sources/src/locales/sr-ec.json +++ /dev/null @@ -1,136 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Aktron", - "Milicevic01", - "Милан Јелисавчић", - "Srdjan m", - "Obsuser", - "Acamicamacaraca" - ] - }, - "index.newPad": "Нови Пад", - "index.createOpenPad": "или направите/отворите пад следећег назива:", - "pad.toolbar.bold.title": "Подебљано (Ctrl+B)", - "pad.toolbar.italic.title": "Искошено (Ctrl+I)", - "pad.toolbar.underline.title": "Подвучено (Ctrl+U)", - "pad.toolbar.strikethrough.title": "Прецртано (Ctrl+5)", - "pad.toolbar.ol.title": "Уређен списак (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Неуређен списак (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Увлачење (TAB)", - "pad.toolbar.unindent.title": "Извлачење (Shift+TAB)", - "pad.toolbar.undo.title": "Опозови (Ctrl+Z)", - "pad.toolbar.redo.title": "Понови (Ctrl+Z)", - "pad.toolbar.clearAuthorship.title": "Очисти ауторске боје (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Увези/извези из/на друге датотечне формате", - "pad.toolbar.timeslider.title": "Временска линија", - "pad.toolbar.savedRevision.title": "Сачувај верзију", - "pad.toolbar.settings.title": "Подешавања", - "pad.toolbar.embed.title": "Сачувај и угради овај пад", - "pad.toolbar.showusers.title": "Прикажи кориснике на овом паду", - "pad.colorpicker.save": "Сачувај", - "pad.colorpicker.cancel": "Откажи", - "pad.loading": "Учитавам…", - "pad.noCookie": "Колачић није пронађен. Молимо да укључите колачиће у вашем прегледавачу!", - "pad.passwordRequired": "Требате имати лозинку како бисте приступили овом паду", - "pad.permissionDenied": "Немате дозволу да приступите овом паду", - "pad.wrongPassword": "Ваша лозинка није исправна", - "pad.settings.padSettings": "Подешавања пада", - "pad.settings.myView": "Мој приказ", - "pad.settings.stickychat": "Ћаскање увек на екрану", - "pad.settings.chatandusers": "Прикажи ћаскање и кориснике", - "pad.settings.colorcheck": "Ауторске боје", - "pad.settings.linenocheck": "Бројеви редова", - "pad.settings.rtlcheck": "Читај садржај с десна на лево?", - "pad.settings.fontType": "Врста фонта:", - "pad.settings.fontType.normal": "Нормално", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Глобални приказ", - "pad.settings.language": "Језик:", - "pad.importExport.import_export": "Увоз/извоз", - "pad.importExport.import": "Отпремите било коју текстуалну датотеку или документ", - "pad.importExport.importSuccessful": "Успешно!", - "pad.importExport.export": "Извези тренутни пад као:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Чист текст", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Једино можете увести са једноставног текстуалног формата или HTML формата. За компликованије функције о увозу, молимо да инсталирате AbiWord.", - "pad.modals.connected": "Повезано.", - "pad.modals.reconnecting": "Поново се повезујем на ваш пад..", - "pad.modals.forcereconnect": "Присилно се поново повежи", - "pad.modals.reconnecttimer": "Покушавам се поново повезати", - "pad.modals.cancel": "Откажи", - "pad.modals.userdup": "Отворено у другом прозору", - "pad.modals.userdup.explanation": "Изгледа да је овај пад отворен у два или више прозора на овом рачунару.", - "pad.modals.userdup.advice": "Поново се повежите на овој прозор.", - "pad.modals.unauth": "Нисте овлашћени", - "pad.modals.unauth.explanation": "Ваша допуштења се се променила док сте прегледавали страницу. Покушајте се поново повезати.", - "pad.modals.looping.explanation": "Постоје комуникацијски проблеми са синхронизационим сервером.", - "pad.modals.looping.cause": "Можда сте се повезали преко неподржаног заштитног зида или проксија.", - "pad.modals.initsocketfail": "Сервер је недоступан.", - "pad.modals.initsocketfail.explanation": "Не могу се повезати на синхронизациони сервер.", - "pad.modals.initsocketfail.cause": "Највероватније је дошло до проблем са вашим прегледачем или вашом интернетском везом.", - "pad.modals.slowcommit.explanation": "Сервер не одговара.", - "pad.modals.slowcommit.cause": "Највероватније је дошло до проблема са мрежном повезаношћу.", - "pad.modals.badChangeset.explanation": "Синхронизациони сервер је уређивање које сте начили означио као неисправно.", - "pad.modals.badChangeset.cause": "Могуће да је дошло до погрешне конфигурације сервера или неког другог неочекиваног догађаја. Молимо вас да контактирате сервисног администратора ако мислите да је ово грешка. Покушајте се поново повезати како бисте наставили с уређивањем.", - "pad.modals.corruptPad.explanation": "Пад којем покушавате приступити је оштећен.", - "pad.modals.corruptPad.cause": "Могуће да је дошло до погрешне конфигурације сервера или неког другог неочекиваног догађаја. Молимо вас да контактирате сервисног администратора.", - "pad.modals.deleted": "Обрисано.", - "pad.modals.deleted.explanation": "Овај пад је уклоњен.", - "pad.modals.disconnected": "Веза је прекинута.", - "pad.modals.disconnected.explanation": "Изгубљена је веза са сервером", - "pad.modals.disconnected.cause": "Сервер није доступан. Обавестите сервисног администратора ако се ово настави дешавати.", - "pad.share": "Пофели овај пад", - "pad.share.readonly": "Само за читање", - "pad.share.link": "Веза", - "pad.share.emebdcode": "Угради везу", - "pad.chat": "Ћаскање", - "pad.chat.title": "Отворите ћаскање за овај пад.", - "pad.chat.loadmessages": "Учитај више порука", - "timeslider.pageTitle": "{{appTitle}} временска линија", - "timeslider.toolbar.returnbutton": "Врати се на пад", - "timeslider.toolbar.authors": "Аутори:", - "timeslider.toolbar.authorsList": "Нема аутора", - "timeslider.toolbar.exportlink.title": "Извези", - "timeslider.exportCurrent": "Извези тренутну верзију као:", - "timeslider.version": "Издање {{version}}", - "timeslider.saved": "Сачувано на {{day}}. {{month}}. {{year}}", - "timeslider.playPause": "Пусти/паузирај садржај пада", - "timeslider.backRevision": "Иди на претходну верзију овог пада", - "timeslider.forwardRevision": "Иди на следеће издање пада", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "јануар", - "timeslider.month.february": "фебруар", - "timeslider.month.march": "март", - "timeslider.month.april": "април", - "timeslider.month.may": "мај", - "timeslider.month.june": "јун", - "timeslider.month.july": "јул", - "timeslider.month.august": "август", - "timeslider.month.september": "септембар", - "timeslider.month.october": "октобар", - "timeslider.month.november": "новембар", - "timeslider.month.december": "децембар", - "timeslider.unnamedauthors": "{{num}} неименован(и) {[plural(num) one: аутор, other: аутори ]}", - "pad.savedrevs.marked": "Ова измена је сада означена као сачувана", - "pad.savedrevs.timeslider": "Можете видети сачуване измене користећи се временском линијом", - "pad.userlist.entername": "Упишите своје име", - "pad.userlist.unnamed": "неименован", - "pad.userlist.guest": "Гост", - "pad.userlist.deny": "Одбиј", - "pad.userlist.approve": "Одобри", - "pad.editbar.clearcolors": "Очисти ауторске боје за цели документ?", - "pad.impexp.importbutton": "Увези одмах", - "pad.impexp.importing": "Увозим...", - "pad.impexp.confirmimport": "Увоз датотеке ће преписати тренутни текст пада. Да ли сте сигурни да желите наставити?", - "pad.impexp.convertFailed": "Не могу да увезем ову датотеку. Молимо да користите други формат документа или да документ копирате ручно", - "pad.impexp.padHasData": "Не могу да увезем ову датотеку зато што је већ било промена на овом паду, молимо да увезете нови пад", - "pad.impexp.uploadFailed": "Нисам успео да отпремим, молимо покушате поново", - "pad.impexp.importfailed": "Нисам успео да увезем", - "pad.impexp.copypaste": "Копирајте и залепите", - "pad.impexp.exportdisabled": "Извоз у формату {{type}} није дозвољен. Контактирајте системског администратора за детаље." -} diff --git a/sources/src/locales/sv.json b/sources/src/locales/sv.json deleted file mode 100644 index e73c3e7..0000000 --- a/sources/src/locales/sv.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Lokal Profil", - "WikiPhoenix", - "Jopparn" - ] - }, - "index.newPad": "Nytt block", - "index.createOpenPad": "eller skapa/öppna ett block med namnet:", - "pad.toolbar.bold.title": "Fet (Ctrl-B)", - "pad.toolbar.italic.title": "Kursiv (Ctrl-I)", - "pad.toolbar.underline.title": "Understruken (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Genomstruken (Ctrl+5)", - "pad.toolbar.ol.title": "Numrerad lista (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Onumrerad lista (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Öka indrag (TABB)", - "pad.toolbar.unindent.title": "Minska indrag (Shift+TABB)", - "pad.toolbar.undo.title": "Ångra (Ctrl-Z)", - "pad.toolbar.redo.title": "Gör om (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Rensa författarfärger (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Importera/exportera från/till olika filformat", - "pad.toolbar.timeslider.title": "Tidsreglage", - "pad.toolbar.savedRevision.title": "Spara version", - "pad.toolbar.settings.title": "Inställningar", - "pad.toolbar.embed.title": "Dela och bädda in detta block", - "pad.toolbar.showusers.title": "Visa användarna på detta block", - "pad.colorpicker.save": "Spara", - "pad.colorpicker.cancel": "Avbryt", - "pad.loading": "Läser in...", - "pad.noCookie": "Kunde inte hitta några kakor. Var god tillåt kakor i din webbläsare!", - "pad.passwordRequired": "Du behöver ett lösenord för att få tillgång till detta block", - "pad.permissionDenied": "Du har inte åtkomstbehörighet för detta block", - "pad.wrongPassword": "Ditt lösenord var fel", - "pad.settings.padSettings": "Blockinställningar", - "pad.settings.myView": "Min vy", - "pad.settings.stickychat": "Chatten alltid på skärmen", - "pad.settings.chatandusers": "Visa chatt och användare", - "pad.settings.colorcheck": "Författarskapsfärger", - "pad.settings.linenocheck": "Radnummer", - "pad.settings.rtlcheck": "Vill du läsa innehållet från höger till vänster?", - "pad.settings.fontType": "Typsnitt:", - "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Fast breddsteg", - "pad.settings.globalView": "Global vy", - "pad.settings.language": "Språk:", - "pad.importExport.import_export": "Importera/Exportera", - "pad.importExport.import": "Ladda upp textfiler eller dokument", - "pad.importExport.importSuccessful": "Åtgärden slutfördes!", - "pad.importExport.export": "Export aktuellt block som:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Oformaterad text", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "Du kan endast importera från oformaterad text eller HTML-format. För mer avancerade importfunktioner, var god installera AbiWord.", - "pad.modals.connected": "Ansluten.", - "pad.modals.reconnecting": "Återansluter till ditt block...", - "pad.modals.forcereconnect": "Tvinga återanslutning", - "pad.modals.reconnecttimer": "Försöker ansluta igen", - "pad.modals.cancel": "Avbryt", - "pad.modals.userdup": "Öppnades i ett nytt fönster", - "pad.modals.userdup.explanation": "Detta block verkar vara öppet i mer än ett fönster på denna dator.", - "pad.modals.userdup.advice": "Återanslut för att använda detta fönster istället.", - "pad.modals.unauth": "Inte godkänd", - "pad.modals.unauth.explanation": "Din behörighet ändrades medan du visade denna sida. Försök att återansluta.", - "pad.modals.looping.explanation": "Kommunikationsproblem med synkroniseringsservern har uppstått.", - "pad.modals.looping.cause": "Kanske du är ansluten via en inkompatibel brandvägg eller proxy.", - "pad.modals.initsocketfail": "Servern kan inte nås.", - "pad.modals.initsocketfail.explanation": "Det gick inte att ansluta till synkroniseringsservern.", - "pad.modals.initsocketfail.cause": "Detta beror troligen på ett problem med din webbläsare eller din internetanslutning.", - "pad.modals.slowcommit.explanation": "Servern svarar inte.", - "pad.modals.slowcommit.cause": "Detta kan bero på problem med nätverksanslutningen.", - "pad.modals.badChangeset.explanation": "En redigering som du gjort klassificerades som otillåten av synkroniseringsservern.", - "pad.modals.badChangeset.cause": "Detta kan bero på en felaktig konfiguration av servern eller något annat oväntad beteende. Var god kontakta tjänsteadministratören om du upplever att detta är ett fel. Försök att ansluta igen för att fortsätta redigera.", - "pad.modals.corruptPad.explanation": "Blocket du försöker komma åt är skadat.", - "pad.modals.corruptPad.cause": "Detta kan bero på en felaktig konfiguration av servern eller något annat oväntad beteende. Var god kontakta tjänstadministratören.", - "pad.modals.deleted": "Raderad.", - "pad.modals.deleted.explanation": "Detta block har tagits bort.", - "pad.modals.disconnected": "Du har blivit frånkopplad.", - "pad.modals.disconnected.explanation": "Anslutningen till servern avbröts", - "pad.modals.disconnected.cause": "Servern kanske är otillgänglig. Var god meddela tjänstadministratören om detta fortsätter att hända.", - "pad.share": "Dela detta block", - "pad.share.readonly": "Skrivskyddad", - "pad.share.link": "Länk", - "pad.share.emebdcode": "Bädda in URL", - "pad.chat": "Chatt", - "pad.chat.title": "Öppna chatten för detta block.", - "pad.chat.loadmessages": "Läs in fler meddelanden", - "timeslider.pageTitle": "{{appTitle}} tidsreglage", - "timeslider.toolbar.returnbutton": "Återvänd till blocket", - "timeslider.toolbar.authors": "Författare:", - "timeslider.toolbar.authorsList": "Inga författare", - "timeslider.toolbar.exportlink.title": "Exportera", - "timeslider.exportCurrent": "Exportera aktuell version som:", - "timeslider.version": "Version {{version}}", - "timeslider.saved": "Sparades den {{day}} {{month}} {{year}}", - "timeslider.playPause": "Spela upp/pausa blockets innehåll", - "timeslider.backRevision": "Gå tillbaka en version av detta block", - "timeslider.forwardRevision": "Gå framåt en version av detta block", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "januari", - "timeslider.month.february": "februari", - "timeslider.month.march": "mars", - "timeslider.month.april": "april", - "timeslider.month.may": "maj", - "timeslider.month.june": "juni", - "timeslider.month.july": "juli", - "timeslider.month.august": "augusti", - "timeslider.month.september": "september", - "timeslider.month.october": "oktober", - "timeslider.month.november": "november", - "timeslider.month.december": "december", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: namnlös författare, other: namnlösa författare]}", - "pad.savedrevs.marked": "Denna version är nu markerad som en sparad version", - "pad.savedrevs.timeslider": "Du kan se sparade versioner med tidsreglaget", - "pad.userlist.entername": "Ange ditt namn", - "pad.userlist.unnamed": "namnlös", - "pad.userlist.guest": "Gäst", - "pad.userlist.deny": "Neka", - "pad.userlist.approve": "Godkänn", - "pad.editbar.clearcolors": "Rensa författarfärger på hela dokumentet?", - "pad.impexp.importbutton": "Importera nu", - "pad.impexp.importing": "Importerar...", - "pad.impexp.confirmimport": "Att importera en fil kommer att skriva över den aktuella texten i blocket. Är du säker på att du vill fortsätta?", - "pad.impexp.convertFailed": "Vi kunde inte importera denna fil. Var god använd ett annat dokumentformat eller kopiera och klistra in den manuellt", - "pad.impexp.padHasData": "Vi kunde inte importera denna fil eftersom detta block redan har redigerats. Importera den till ett nytt block.", - "pad.impexp.uploadFailed": "Uppladdningen misslyckades, var god försök igen", - "pad.impexp.importfailed": "Importering misslyckades", - "pad.impexp.copypaste": "Var god kopiera och klistra in", - "pad.impexp.exportdisabled": "Exportering av formatet {{type}} är inaktiverad. Var god kontakta din systemadministratör för mer information." -} diff --git a/sources/src/locales/ta.json b/sources/src/locales/ta.json deleted file mode 100644 index c0a7cdc..0000000 --- a/sources/src/locales/ta.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Balajijagadesh", - "ElangoRamanujam", - "Sank" - ] - }, - "index.newPad": "புதிய அட்டை", - "index.createOpenPad": "அல்லது பெயருடன் ஒரு அட்டையை உருவாக்கு/திற", - "pad.toolbar.bold.title": "தடித்த (Ctrl+B)", - "pad.toolbar.italic.title": "சாய்ந்த (Ctrl+l)", - "pad.toolbar.underline.title": "அடிக்கோடு (Ctrl-U)", - "pad.toolbar.strikethrough.title": "குறுக்குக்கோடு (Ctrl+5)", - "pad.toolbar.timeslider.title": "நேர வழுக்கி", - "pad.toolbar.settings.title": "அமைப்புகள்", - "pad.toolbar.embed.title": "இவ்வட்டையை பகிர் மற்றும் பதி", - "pad.toolbar.showusers.title": "இவ்வட்டையின் பயனர்களை காட்டவும்", - "pad.colorpicker.save": "சேமி", - "pad.colorpicker.cancel": "இரத்து செய்", - "pad.loading": "ஏற்றப்படுகிறது...", - "pad.passwordRequired": "இவ்வட்டையை அணுக தங்களுக்கு ஒரு கடவுச்சொல் தேவைப்படும்", - "pad.permissionDenied": "இவ்வட்டையை அணுக தங்களுக்கு அனுமதி இல்லை", - "pad.wrongPassword": "தங்கள் கடவுச்சொல் தவறானது", - "pad.settings.padSettings": "அட்டை அமைவுகள்", - "pad.settings.myView": "என் பார்வை", - "pad.settings.stickychat": "திரையில் எப்பொழுதும் அரட்டை", - "pad.settings.chatandusers": "அரட்டை மற்றும் பயனர்களை காட்டுக", - "pad.settings.colorcheck": "ஆசிரியர் நிறங்கள்", - "pad.settings.linenocheck": "வரி எண்கள்", - "pad.settings.fontType": "எழுத்துரு வகை:", - "pad.settings.globalView": "உலக பார்வை", - "pad.settings.language": "மொழி:", - "pad.importExport.import_export": "இறக்குமதி/ஏற்றுமதி", - "pad.importExport.importSuccessful": "வெற்றி!", - "pad.modals.connected": "இணைக்கப்பட்டது.", - "pad.modals.initsocketfail": "வழங்கியை தொடர்பு கொள்ளமுடியவில்லை", - "pad.modals.deleted": "நீக்கப்பட்டது", - "pad.modals.deleted.explanation": "இந்த அட்டை நீக்கப்பட்டது.", - "pad.modals.disconnected": "தாங்கள் துண்டிக்கப்பட்டுள்ளீர்கள்", - "pad.modals.disconnected.explanation": "வழங்கியின் தொடர்பு தொலைந்து", - "pad.share": "இவ்வட்டையை பகிர்க", - "pad.share.readonly": "வாசிக்க மாத்திரம்", - "pad.share.link": "இணைப்பு", - "pad.share.emebdcode": "உரலியை பதிக", - "pad.chat": "அரட்டை", - "pad.chat.title": "இவ்வட்டைக்கு அரட்டையை திறக்கவும்", - "pad.chat.loadmessages": "மேலும் தகவல்களை பதிவேற்றவும்", - "timeslider.pageTitle": "{{appTitle}} நேரவழுக்கி", - "timeslider.toolbar.returnbutton": "அட்டைக்கு திரும்பவும்", - "timeslider.toolbar.authors": "ஆசிரியர்கள்:", - "timeslider.toolbar.authorsList": "ஆசிரியர்கள் இல்லை", - "timeslider.toolbar.exportlink.title": "ஏற்றுமதி செய்க", - "timeslider.version": "பதிப்பு {{version}}", - "timeslider.month.january": "சனவரி", - "timeslider.month.february": "பெப்ரவரி", - "timeslider.month.march": "மார்ச்", - "timeslider.month.april": "ஏப்ரல்", - "timeslider.month.may": "மே", - "timeslider.month.june": "சூன்", - "timeslider.month.july": "சூலை", - "timeslider.month.august": "ஆகஸ்ட்", - "timeslider.month.september": "செப்டம்பர்", - "timeslider.month.october": "அக்டோபர்", - "timeslider.month.november": "நவம்பர்", - "timeslider.month.december": "டிசம்பர்", - "pad.userlist.entername": "உங்கள் பெயரை உள்ளிடுக", - "pad.userlist.unnamed": "பெயரிடப்படாதது", - "pad.userlist.guest": "விருந்தினர்", - "pad.userlist.deny": "மறுக்கவும்", - "pad.userlist.approve": "ஒப்புதல் அளிக்கவும்", - "pad.impexp.importbutton": "இப்பொழுது இறக்குக", - "pad.impexp.importing": "இறக்குகிறது...", - "pad.impexp.uploadFailed": "பதிவேற்றம் தோல்வியடைந்தது, தயவுசெய்து மீண்டும் முயலவும்.", - "pad.impexp.importfailed": "இறக்குமதி தோல்வியடைந்தது", - "pad.impexp.copypaste": "படியெடுத்து ஒட்டுக" -} diff --git a/sources/src/locales/tcy.json b/sources/src/locales/tcy.json deleted file mode 100644 index 3cd815b..0000000 --- a/sources/src/locales/tcy.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "@metadata": { - "authors": [ - "BHARATHESHA ALASANDEMAJALU", - "VASANTH S.N." - ] - }, - "index.newPad": "ಪೊಸ ಪ್ಯಾಡ್", - "index.createOpenPad": "ಅತಂಡ ಈ ಪುದರ್ತ ಪ್ಯಾಡನ್ನು ಉಂಡು ಮನ್ಪು/ತೋಜಾಲ:", - "pad.toolbar.bold.title": "ದಪ್ಪೊ(Ctrl+B)", - "pad.toolbar.italic.title": "ಓರೆ (Ctrl-I)", - "pad.toolbar.underline.title": "ಅಡಿಗೆರೆ(Ctrl-U)", - "pad.toolbar.indent.title": "Indent (TAB)", - "pad.toolbar.undo.title": "ಪಿರವುತ(Ctrl+Z)", - "pad.toolbar.redo.title": "ದುಂಬುತ್ತ(Ctrl+Y)", - "pad.toolbar.settings.title": "ಸಂಯೋಜನೆಲು", - "pad.toolbar.showusers.title": "ಈ ಪ್ಯಾಡ್ ಟ್ ಗಲಸುನಾಯಾನ್ ತೋಜಾಲೆ", - "pad.colorpicker.save": "ಒರಿಪಾಲೆ", - "pad.colorpicker.cancel": "ವಜಾ ಮಲ್ಪುಲೆ", - "pad.loading": "ದಿಂಜಾವೊಂದುಂಡು......", - "pad.wrongPassword": "ಇರೇನಾ ಪಾಸ್ ವರ್ಡ್ ತಪ್ಪತುಂಡ್", - "pad.settings.padSettings": "ಪ್ಯಾಡ್ ಸಂಯೋಜನೆ", - "pad.settings.language": "ಬಾಸೆ:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportpdf": "PDF", - "pad.modals.connected": "ನೆಟ್ ವರ್ಕ್ ತಿಕೊಂತುಂಡು.", - "pad.modals.cancel": "ವಜಾ ಮಲ್ಪುಲೆ", - "pad.modals.deleted": "ಮಾಜಾಯಿನ.", - "pad.share.readonly": "ಓದ್ಯರಾ ಮಾತ್ರ", - "pad.share.link": "ಕೊಂಡಿಲು", - "timeslider.month.january": "ಜನವರಿ", - "timeslider.month.february": "ಪೆಬ್ರವರಿ", - "timeslider.month.march": "ಮಾರ್ಚಿ", - "timeslider.month.april": "ಎಪ್ರಿಲ್", - "timeslider.month.may": "ಮೇ", - "timeslider.month.june": "ಜೂನ್", - "timeslider.month.july": "ಜುಲಾಯಿ", - "timeslider.month.august": "ಆಗೋಸ್ಟು", - "timeslider.month.september": "ಸಪ್ಟಂಬರೊ", - "timeslider.month.october": "ಅಕ್ಟೋಬರ", - "timeslider.month.november": "ನವಂಬರೊ", - "timeslider.month.december": "ದಸಂಬರೊ", - "pad.userlist.entername": "ಈರೆನೆ ಪುದರ್ ಬರೆಲೆ", - "pad.userlist.unnamed": "ಪುದರ್ ಇಜ್ಜಂತಿನವು", - "pad.userlist.guest": "ಬಿನ್ನೆರ್", - "pad.userlist.approve": "ಒಪ್ಪಂದ ಅಂಡ್" -} diff --git a/sources/src/locales/te.json b/sources/src/locales/te.json deleted file mode 100644 index 13af397..0000000 --- a/sources/src/locales/te.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "@metadata": { - "authors": [ - "JVRKPRASAD", - "Malkum", - "Veeven", - "Chaduvari", - "Ravichandra", - "Kiranmayee" - ] - }, - "index.newPad": "కొత్త పలక", - "index.createOpenPad": "ఒక పేరుతో పలకని సృష్టించండి లేదా అదే పేరుతో ఉన్న పలకని తెరవండి", - "pad.toolbar.bold.title": "బొద్దు (Ctrl+B)", - "pad.toolbar.italic.title": "వాలు (Ctrl+I)", - "pad.toolbar.underline.title": "క్రిందగీత", - "pad.toolbar.strikethrough.title": "కొట్టివేత (Ctrl+5)", - "pad.toolbar.ol.title": "క్రమ జాబితా (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "బిందు జాబితా (Ctrl+Shift+L)", - "pad.toolbar.undo.title": "చేయవద్దు", - "pad.toolbar.redo.title": "తిరిగిచెయ్యి", - "pad.toolbar.clearAuthorship.title": "మూలకర్తపు వర్ణాలను తీసివేయండి", - "pad.toolbar.import_export.title": "భిన్నమైన రూపలావన్యాలను బయట నుండి దిగుమతి లేదా బయటకు ఎగుమతి చేయండి", - "pad.toolbar.timeslider.title": "పనిసమయ సూచిక పరికరం", - "pad.toolbar.savedRevision.title": "పునరుచ్చరణలు దాచు", - "pad.toolbar.settings.title": "అమరికలు", - "pad.toolbar.embed.title": "ఈ పలకని పొదగించి పంచిపెట్టండి", - "pad.toolbar.showusers.title": "ఈ పలక యొక్క వినియోగదారులను చూపించు", - "pad.colorpicker.save": "భద్రపరచు", - "pad.colorpicker.cancel": "రద్దుచేయి", - "pad.loading": "లోడవుతోంది...", - "pad.permissionDenied": "ఈ పేజీని చూడడానికి మీరు అనుమతి లేదు.", - "pad.wrongPassword": "మీ సంకేతపదం తప్పు", - "pad.settings.padSettings": "పలక అమరికలు", - "pad.settings.myView": "నా ఉద్దేశ్యము", - "pad.settings.stickychat": "తెరపైనే మాటామంతిని ఎల్లపుడు చేయుము", - "pad.settings.colorcheck": "రచయితలకు రంగులు", - "pad.settings.linenocheck": "వరుస సంఖ్యలు", - "pad.settings.fontType": "అక్షరశైలి రకం:", - "pad.settings.fontType.normal": "సాధారణ", - "pad.settings.fontType.monospaced": "మోనోస్పేస్", - "pad.settings.globalView": "బయటకి దర్శనం", - "pad.settings.language": "భాష", - "pad.importExport.import_export": "దిగుమతి/ఎగుమతి", - "pad.importExport.import": "పాఠము దస్త్రము లేదా పత్రమును దిగుమతి చేయుము", - "pad.importExport.importSuccessful": "విజయవంతం!", - "pad.importExport.export": "ప్రస్తుత పలకని ఈ విధముగా ఎగుమతి చేయుము:", - "pad.importExport.exporthtml": "హెచ్ టి ఎం ఎల్", - "pad.importExport.exportplain": "సాదా పాఠ్యం", - "pad.importExport.exportword": "మైక్రోసాఫ్ట్ వర్డ్", - "pad.importExport.exportpdf": "పీ డి ఎఫ్", - "pad.importExport.exportopen": "ఓ డి ఎఫ్ (ఓపెన్ డాక్యుమెంట్ ఫార్మాట్)", - "pad.modals.connected": "సంబంధం కుదిరింది.", - "pad.modals.reconnecting": "మీ పలకకు మరల సంబంధం కలుపుతుంది...", - "pad.modals.forcereconnect": "బలవంతంగానైనా సంబంధం కుదిరించు", - "pad.modals.cancel": "రద్దుచేయి", - "pad.modals.userdup.explanation": "ఈ పలక, ఈ కంప్యూటర్లో ఒకటికన్న ఎక్కువ గవాక్షములలో తెరుచుకున్నట్లు అనిపిస్తుంది.", - "pad.modals.userdup.advice": "బదులుగా ఈ గవాక్షమును వాడడానికి మరల సంబంధం కలపండి", - "pad.modals.unauth": "అధికారం లేదు", - "pad.modals.unauth.explanation": "మీరు ఈ పుటను చూస్తూన్నప్పుడు మీ అనుమతులు మారాయి. మరల సంబంధం కలపడానికి ప్రయత్నించండి.", - "pad.modals.initsocketfail": "సర్వరు అందుబాటులో లేదు.", - "pad.modals.slowcommit.explanation": "సర్వరు స్పందించడం లేదు.", - "pad.modals.deleted": "తొలగించబడింది ( తొలగించినది )", - "pad.share": "ఈ పలకను పంచుకొను", - "pad.share.readonly": "చదువుటకు మాత్రమే", - "pad.share.link": "లంకె", - "pad.share.emebdcode": "యు ఆర్ ఎల్ ను పొదగించండి", - "pad.chat": "మాటామంతి", - "pad.chat.title": "ఈ పలకకు మాటామంతిని తెరిచి ఉంచండి.", - "pad.chat.loadmessages": "మరిన్ని సందేశాలు తీసుకురా", - "timeslider.pageTitle": "{{appTitle}} పనిసమయ సూచిక పరికరం", - "timeslider.toolbar.returnbutton": "పలకకి తిరిగి వెళ్ళండి", - "timeslider.toolbar.authors": "రచయితలు:", - "timeslider.toolbar.authorsList": "రచయితలు లేరు", - "timeslider.toolbar.exportlink.title": "ఎగుమతి చెయ్యి", - "timeslider.exportCurrent": "ప్రస్తుత అవతారాన్ని ఈ విధంగా ఎగుమతి చేయుము:", - "timeslider.saved": "{{year}}, {{month}} {{day}} న భద్రపరచబడింది", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "జనవరి", - "timeslider.month.february": "ఫిబ్రవరి", - "timeslider.month.march": "మార్చి", - "timeslider.month.april": "ఏప్రిల్", - "timeslider.month.may": "మే", - "timeslider.month.june": "జూన్", - "timeslider.month.july": "జూలై", - "timeslider.month.august": "ఆగష్టు", - "timeslider.month.september": "సెప్టెంబరు", - "timeslider.month.october": "అక్టోబరు", - "timeslider.month.november": "నవంబరు", - "timeslider.month.december": "డిసెంబరు", - "pad.userlist.entername": "మీ పేరు ఇవ్వండి", - "pad.userlist.unnamed": "అనామకం", - "pad.userlist.guest": "అతిథి", - "pad.userlist.deny": "తిరస్కరించు", - "pad.userlist.approve": "ఆమోదించు", - "pad.impexp.importbutton": "దిగుమతి చేసెయ్యి", - "pad.impexp.importing": "దిగుమతి చేస్తున్నాం...", - "pad.impexp.confirmimport": "దిగుమతి చేసుకోవడం వల్ల ప్యాడ్ లోఉన్న పాఠ్యం తుడిచిపెట్టుకుపోతుంది. ఇది మీకు అంగీకారమేనా?", - "pad.impexp.convertFailed": "ఈ ఫైలును దిగుమతి చేసుకోలేకపోయాం. వేరే డాక్యుమెంట్ ఫార్మాటును వాడండి లేదా మీరే కాపీ చేసి అతికించండి", - "pad.impexp.uploadFailed": "ఎక్కింపు విఫలమైంది, మళ్ళీ ప్రయత్నించండి.", - "pad.impexp.importfailed": "దిగుమతి విఫలమైంది", - "pad.impexp.copypaste": "నకలు చేసి అతికించండి" -} diff --git a/sources/src/locales/th.json b/sources/src/locales/th.json deleted file mode 100644 index d5c2437..0000000 --- a/sources/src/locales/th.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Aefgh39622" - ] - }, - "index.newPad": "สร้างแผ่นจดบันทึกใหม่", - "index.createOpenPad": "หรือสร้าง/เปิดแผ่นจดบันทึกที่มีชื่อ:", - "pad.toolbar.bold.title": "ตัวหนา (Ctrl+B)", - "pad.toolbar.italic.title": "ตัวเอียง (Ctrl+I)", - "pad.toolbar.underline.title": "ขีดเส้นใต้ (Ctrl+U)", - "pad.toolbar.strikethrough.title": "ขีดทับ (Ctrl+5)", - "pad.toolbar.ol.title": "รายการที่เรียงลำดับ (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "รายการที่ไม่เรียงลำดับ (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "เยื้องเข้า (TAB)", - "pad.toolbar.unindent.title": "เยื้องออก (Shift+TAB)", - "pad.toolbar.undo.title": "เลิกทำ (Ctrl+Z)", - "pad.toolbar.redo.title": "ทำซ้ำ (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "ลบสีผู้เขียน (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "นำเข้า/ส่งออกไฟล์จาก/เป็นรูปแบบต่าง ๆ", - "pad.toolbar.timeslider.title": "ตัวเลื่อนเวลา", - "pad.toolbar.savedRevision.title": "บันทึกรุ่นแก้ไข", - "pad.toolbar.settings.title": "การตั้งค่า", - "pad.toolbar.embed.title": "แชร์และฝังแผ่นจดบันทึกนี้", - "pad.toolbar.showusers.title": "แสดงผู้ใช้บนแผ่นจดบันทึกนี้", - "pad.colorpicker.save": "บันทึก", - "pad.colorpicker.cancel": "ยกเลิก", - "pad.loading": "กำลังโหลด...", - "pad.noCookie": "ไม่พบคุกกี้ โปรดเปิดใช้งานคุกกี้ในเบราว์เซอร์ของคุณ!", - "pad.passwordRequired": "คุณต้องใช้รหัสผ่านเพื่อเข้าถึงแผ่นจดบันทึกนี้", - "pad.permissionDenied": "คุณไม่มีสิทธิ์เข้าถึงแผ่นจดบันทึกนี้", - "pad.wrongPassword": "รหัสผ่านของคุณผิด", - "pad.settings.padSettings": "การตั้งค่าแผ่นจดบันทึก", - "pad.settings.myView": "มุมมองของฉัน", - "pad.settings.stickychat": "แสดงการแชทบนหน้าจอเสมอ", - "pad.settings.chatandusers": "แสดงการแชทและผู้ใช้", - "pad.settings.colorcheck": "สีผู้เขียน", - "pad.settings.linenocheck": "เลขบรรทัด", - "pad.settings.rtlcheck": "อ่านเนื้อหาจากขวาไปซ้ายหรือไม่?", - "pad.settings.fontType": "ชนิดแบบอักษร:", - "pad.settings.globalView": "มุมมองสากล", - "pad.settings.language": "ภาษา:", - "pad.importExport.import_export": "นำเข้า/ส่งออก", - "pad.importExport.import": "อัปโหลดไฟล์ข้อความหรือเอกสารใดๆ", - "pad.importExport.importSuccessful": "สำเร็จ!", - "pad.importExport.export": "ส่งออกแผ่นจดบันทึกปัจจุบันเป็น:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "ข้อความธรรมดา", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "คุณสามารถนำเข้าได้จากรูปแบบ HTML หรือข้อความธรรมดาเท่านั้น สำหรับคุณสมบัติการนำเข้าขั้นสูงเพิ่มเติม โปรดติดตั้ง AbiWord", - "pad.modals.connected": "เชื่อมต่อแล้ว", - "pad.modals.reconnecting": "กำลังเชื่อมต่อกับแผ่นจดบันทึกของคุณใหม่..", - "pad.modals.forcereconnect": "บังคับเชื่อมต่อใหม่", - "pad.modals.reconnecttimer": "กำลังพยายามเชื่อมต่อใหม่ใน", - "pad.modals.cancel": "ยกเลิก", - "pad.modals.userdup": "เปิดในหน้าต่างอื่นแล้ว", - "pad.modals.userdup.explanation": "แผ่นจดบันทึกนี้ดูเหมือนว่าจะถูกเปิดในหน้าต่างเบราว์เซอร์มากกว่าหนึ่งหน้าต่างบนคอมพิวเตอร์นี้", - "pad.modals.userdup.advice": "เชื่อมต่อใหม่เพื่อใช้หน้าต่างนี้แทน", - "pad.modals.unauth": "ไม่ได้รับอนุญาต", - "pad.modals.unauth.explanation": "สิทธิของคุณถูกเปลี่ยนขณะที่คุณดูหน้านี้อยู่ พยายามเชื่อมต่อใหม่", - "pad.modals.looping.explanation": "มีปัญหาการสื่อสารกับเซิร์ฟเวอร์การซิงค์ข้อมูล", - "pad.modals.looping.cause": "บางทีอาจเป็นเพราะคุณเชื่อมต่อกับไฟร์วอลล์หรือพร็อกซีที่เข้ากันไม่ได้", - "pad.modals.initsocketfail": "เซิร์ฟเวอร์ไม่สามารถเข้าถึงได้", - "pad.modals.initsocketfail.explanation": "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์การซิงค์ข้อมูล", - "pad.modals.initsocketfail.cause": "อาจเป็นเนื่องจากเบราว์เซอร์ของคุณหรือการเชื่อมต่ออินเทอร์เน็ตของคุณมีปัญหา", - "pad.modals.slowcommit.explanation": "เซิร์ฟเวอร์ไม่ตอบสนอง", - "pad.modals.slowcommit.cause": "อาจเป็นเนื่องจากปัญหาเกี่ยวกับการเชื่อมต่อเครือข่าย", - "pad.modals.badChangeset.explanation": "การแก้ไขที่คุณกระทำถูกจัดว่าไม่เหมาะสมโดยเซิร์ฟเวอร์การซิงค์ข้อมูล", - "pad.modals.badChangeset.cause": "อาจเป็นเนื่องจากการกำหนดค่าเซิร์ฟเวอร์ไม่ถูกต้องหรือมีลักษณะการทำงานอื่นๆ บางอย่างที่ไม่คาดคิด โปรดติดต่อผู้ดูแลการให้บริการ ถ้าคุณรู้สึกว่านี่คือข้อผิดพลาด โปรดทำการเชื่อมต่อใหม่อีกครั้งเพื่อทำการแก้ไขต่อไป", - "pad.modals.corruptPad.explanation": "แผ่นจดบันทึกที่คุณกำลังพยายามเข้าถึงเสียหาย", - "pad.modals.corruptPad.cause": "อาจเป็นเนื่องจากการกำหนดค่าเซิร์ฟเวอร์ไม่ถูกต้องหรือมีลักษณะการทำงานอื่นๆ บางอย่างที่ไม่คาดคิด โปรดติดต่อผู้ดูแลการให้บริการ", - "pad.modals.deleted": "ลบแล้ว", - "pad.modals.deleted.explanation": "แผ่นจดบันทึกนี้ได้ถูกลบออกแล้ว", - "pad.modals.disconnected": "คุณได้ตัดการเชื่อมต่อแล้ว", - "pad.modals.disconnected.explanation": "การเชื่อมต่อกับเซิร์ฟเวอร์ถูกตัด", - "pad.modals.disconnected.cause": "เซิร์ฟเวอร์อาจใช้ไม่ได้ชั่วคราว โปรดแจ้งให้ผู้ดูแลการให้บริการทราบถ้าปัญหานี้ยังคงเกิดขึ้น", - "pad.share": "แชร์แผ่นจดบันทึกนี้", - "pad.share.readonly": "อ่านเท่านั้น", - "pad.share.link": "ลิงก์", - "pad.share.emebdcode": "URL แบบฝังตัว", - "pad.chat": "แชท", - "pad.chat.title": "เปิดการแชทสำหรับแผ่นจดบันทึกนี้", - "pad.chat.loadmessages": "โหลดข้อความเพิ่มเติม", - "timeslider.pageTitle": "ตัวเลื่อนเวลา {{appTitle}}", - "timeslider.toolbar.returnbutton": "กลับไปแผ่นจดบันทึก", - "timeslider.toolbar.authors": "ผู้เขียน:", - "timeslider.toolbar.authorsList": "ไม่มีผู้เขียน", - "timeslider.toolbar.exportlink.title": "ส่งออก", - "timeslider.exportCurrent": "ส่งออกรุ่นปัจจุบันเป็น:", - "timeslider.version": "รุ่น {{version}}", - "timeslider.saved": "บันทึกแล้วเมื่อ {{day}} {{month}} {{year}}", - "timeslider.playPause": "เล่น / พักเนื้อหาแผ่นจดบันทึก", - "timeslider.backRevision": "กลับไปรุ่นแก้ไขเก่าของแผ่นจดบันทึกนี้", - "timeslider.forwardRevision": "ไปยังรุ่นแก้ไขใหม่ของแผ่นจดบันทึกนี้", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "มกราคม", - "timeslider.month.february": "กุมภาพันธ์", - "timeslider.month.march": "มีนาคม", - "timeslider.month.april": "เมษายน", - "timeslider.month.may": "พฤษภาคม", - "timeslider.month.june": "มิถุนายน", - "timeslider.month.july": "กรกฎาคม", - "timeslider.month.august": "สิงหาคม", - "timeslider.month.september": "กันยายน", - "timeslider.month.october": "ตุลาคม", - "timeslider.month.november": "พฤศจิกายน", - "timeslider.month.december": "ธันวาคม", - "timeslider.unnamedauthors": "{{num}} ผู้เขียนที่ไม่มีชื่อ", - "pad.savedrevs.marked": "รุ่นแก้ไขนี้ถูกทำเครื่องหมายเป็นรุ่นแก้ไขที่บันทึกแล้ว", - "pad.savedrevs.timeslider": "คุณสามารถดูรุ่นแก้ไขที่บันทึกแล้วโดยเยี่ยมชมตัวเลื่อนเวลา", - "pad.userlist.entername": "กรอกชื่อของคุณ", - "pad.userlist.unnamed": "ไม่มีชื่อ", - "pad.userlist.guest": "ผู้เยี่ยมชม", - "pad.userlist.deny": "ปฏิเสธ", - "pad.userlist.approve": "อนุมัติ", - "pad.editbar.clearcolors": "ล้างสีผู้เขียนบนทั้งเอกสารหรือไม่?", - "pad.impexp.importbutton": "นำเข้าเดี๋ยวนี้", - "pad.impexp.importing": "กำลังนำเข้า...", - "pad.impexp.confirmimport": "การนำเข้าไฟล์จะเป็นการเขียนทับข้อความปัจจุบันบนแผ่นจดบันทึก คุณแน่ใจหรือว่าคุณต้องการดำเนินการต่อ?", - "pad.impexp.convertFailed": "เราไม่สามารถนำเข้าไฟล์นี้ได้ โปรดใช้รูปแบบเอกสารอื่นหรือคัดลอกแล้ววางด้วยตนเอง", - "pad.impexp.padHasData": "เราไม่สามารถนำเข้าไฟล์นี้ได้เนื่องจากแผ่นจดบันทึกนี้มีการเปลี่ยนแปลงอยู่แล้ว โปรดนำเข้าไปแผ่นจดบันทึกใหม่แทน", - "pad.impexp.uploadFailed": "การอัปโหลดล้มเหลว โปรดลองอีกครั้ง", - "pad.impexp.importfailed": "การนำเข้าล้มเหลว", - "pad.impexp.copypaste": "โปรดคัดลอกแล้ววาง", - "pad.impexp.exportdisabled": "การส่งออกเป็นรูปแบบ {{type}} ถูกปิดใช้งาน โปรดติดต่อผู้ดูแลระบบของคุณสำหรับรายละเอียดเพิ่มเติม" -} diff --git a/sources/src/locales/tr.json b/sources/src/locales/tr.json deleted file mode 100644 index 0be2588..0000000 --- a/sources/src/locales/tr.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Emperyan", - "Erdemaslancan", - "Joseph", - "Meelo", - "Trockya", - "McAang", - "Vito Genovese" - ] - }, - "index.newPad": "Yeni Bloknot", - "index.createOpenPad": "ya da şu isimle bir Bloknot oluştur/aç:", - "pad.toolbar.bold.title": "Kalın (Ctrl-B)", - "pad.toolbar.italic.title": "Eğik (Ctrl-I)", - "pad.toolbar.underline.title": "Altı Çizili (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Üstü Çizili (Ctrl+5)", - "pad.toolbar.ol.title": "Sıralı liste (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Sırasız Liste (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Girintiyi arttır (TAB)", - "pad.toolbar.unindent.title": "Girintiyi azalt (Shift+TAB)", - "pad.toolbar.undo.title": "Geri Al (Ctrl-Z)", - "pad.toolbar.redo.title": "Yinele (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "Yazarlık Renklerini Temizle (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Farklı dosya biçimlerini içeri/dışarı aktar", - "pad.toolbar.timeslider.title": "Zaman Çizelgesi", - "pad.toolbar.savedRevision.title": "Düzeltmeyi Kaydet", - "pad.toolbar.settings.title": "Ayarlar", - "pad.toolbar.embed.title": "Bu bloknotu Paylaş ve Göm", - "pad.toolbar.showusers.title": "Kullanıcıları bu bloknotta göster", - "pad.colorpicker.save": "Kaydet", - "pad.colorpicker.cancel": "İptal", - "pad.loading": "Yükleniyor...", - "pad.noCookie": "Çerez bulunamadı. Lütfen tarayıcınızda çerezlere izin veriniz!", - "pad.passwordRequired": "Bu bloknota erişebilmeniz için parolaya ihtiyacınız var", - "pad.permissionDenied": "Bu bloknota erişmeye izniniz yok", - "pad.wrongPassword": "Parolanız yanlış", - "pad.settings.padSettings": "Bloknot Ayarları", - "pad.settings.myView": "Görünümüm", - "pad.settings.stickychat": "Sohbeti her zaman ekranda yap", - "pad.settings.chatandusers": "Sohbeti ve Kullanıcıları Göster", - "pad.settings.colorcheck": "Yazarlık renkleri", - "pad.settings.linenocheck": "Satır numaraları", - "pad.settings.rtlcheck": "İçerik sağdan sola doğru okunsun mu?", - "pad.settings.fontType": "Yazı tipi:", - "pad.settings.fontType.normal": "Olağan", - "pad.settings.fontType.monospaced": "Tek aralıklı", - "pad.settings.globalView": "Genel Görünüm", - "pad.settings.language": "Dil:", - "pad.importExport.import_export": "İçerik/Dışarı Aktar", - "pad.importExport.import": "Herhangi bir metin dosyası ya da belgesi yükle", - "pad.importExport.importSuccessful": "Başarılı!", - "pad.importExport.export": "Mevcut bloknotu şu olarak dışa aktar:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Düz metin", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (Açık Doküman Biçimi)", - "pad.importExport.abiword.innerHTML": "Yalnızca düz metin ya da HTML biçimlerini içe aktarabilirsiniz. Daha fazla gelişmiş içe aktarım özellikleri için lütfen AbiWord'ü yükleyin.", - "pad.modals.connected": "Bağlandı.", - "pad.modals.reconnecting": "Bloknotunuza tekrar bağlanılıyor...", - "pad.modals.forcereconnect": "Yeniden bağlanmaya zorla", - "pad.modals.reconnecttimer": "Yeniden bağlanmaya çalışılıyor", - "pad.modals.cancel": "İptal", - "pad.modals.userdup": "Başka pencerede açıldı", - "pad.modals.userdup.explanation": "Bu bloknot bu bilgisayarda birden fazla tarayıcı penceresinde açılmış gibi görünüyor.", - "pad.modals.userdup.advice": "Bu pencereden kullanmak için yeniden bağlanın.", - "pad.modals.unauth": "Yetkili değil", - "pad.modals.unauth.explanation": "Bu sayfayı görüntülerken izinleriniz değiştirildi. Tekrar bağlanmayı deneyin.", - "pad.modals.looping.explanation": "Eşitleme sunucusu ile iletişim sorunları yaşanıyor.", - "pad.modals.looping.cause": "Belki de uygun olmayan güvenlik duvarı ya da vekil sunucu (proxy) ile bağlanmaya çalışıyorsunuz.", - "pad.modals.initsocketfail": "Sunucuya erişilemiyor.", - "pad.modals.initsocketfail.explanation": "Eşitleme sunucusuna bağlantı kurulamıyor.", - "pad.modals.initsocketfail.cause": "Bu sorun muhtemelen, tarayıcınızdan ya da internet bağlantınızdan kaynaklanıyor.", - "pad.modals.slowcommit.explanation": "Sunucu yanıt vermiyor.", - "pad.modals.slowcommit.cause": "Bu hata ağ bağlantısı sebebiyle olabilir.", - "pad.modals.badChangeset.explanation": "Yaptığınız bir düzenleme eşitleme sunucusu tarafından kullanışsız/kural dışı olarak sınıflandırıldı.", - "pad.modals.badChangeset.cause": "Bu, yanlış sunucu yapılandırması ya da başka bir beklenmedik davranışlar sonucunda olmuş olabilir. Bu size bir hataymış gibi geliyorsa lütfen servis yöneticisiyle iletişime geçin. Düzenlemeye devam etmek için yeniden bağlanmayı deneyin.", - "pad.modals.corruptPad.explanation": "Erişmeye çalıştığınız bloknot bozuk.", - "pad.modals.corruptPad.cause": "Bu, yanlış sunucu yapılandırması ya da başka bir beklenmedik davranışlardan kaynaklanabilir. Lütfen servis yöneticisiyle iletişime geçin.", - "pad.modals.deleted": "Silindi.", - "pad.modals.deleted.explanation": "Bu bloknot kaldırılmış.", - "pad.modals.disconnected": "Bağlantınız koptu.", - "pad.modals.disconnected.explanation": "Sunucu bağlantısı kaybedildi", - "pad.modals.disconnected.cause": "Sunucu kullanılamıyor olabilir. Bunun devam etmesi durumunda servis yöneticisine bildirin.", - "pad.share": "Bu bloknotu paylaş", - "pad.share.readonly": "Salt okunur", - "pad.share.link": "Bağlantı", - "pad.share.emebdcode": "URL'yi göm", - "pad.chat": "Sohbet", - "pad.chat.title": "Bu bloknot için sohbeti açın.", - "pad.chat.loadmessages": "Daha fazla mesaj yükle", - "timeslider.pageTitle": "{{appTitle}} Zaman Çizelgesi", - "timeslider.toolbar.returnbutton": "Bloknota geri dön", - "timeslider.toolbar.authors": "Yazarlar:", - "timeslider.toolbar.authorsList": "Yazar Yok", - "timeslider.toolbar.exportlink.title": "Dışa aktar", - "timeslider.exportCurrent": "Mevcut sürümü şu olarak dışa aktar:", - "timeslider.version": "{{version}} sürümü", - "timeslider.saved": "{{day}} {{month}} {{year}} tarihinde kaydedildi", - "timeslider.playPause": "Bloknot İçeriğini Oynat / Durdur", - "timeslider.backRevision": "Bu bloknottaki bir revizyona geri git", - "timeslider.forwardRevision": "Bu bloknatta sonraki revizyona git", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Ocak", - "timeslider.month.february": "Şubat", - "timeslider.month.march": "Mart", - "timeslider.month.april": "Nisan", - "timeslider.month.may": "Mayıs", - "timeslider.month.june": "Haziran", - "timeslider.month.july": "Temmuz", - "timeslider.month.august": "Ağustos", - "timeslider.month.september": "Eylül", - "timeslider.month.october": "Ekim", - "timeslider.month.november": "Kasım", - "timeslider.month.december": "Aralık", - "timeslider.unnamedauthors": "{{num}} isimsiz {[plural(num) one: yazar, other: yazar ]}", - "pad.savedrevs.marked": "Bu düzenleme artık kayıtlı bir düzeltme olarak işaretlendi", - "pad.savedrevs.timeslider": "Zaman kaydırıcısını ziyaret ederek kaydedilen revizyonları görebilirsiniz", - "pad.userlist.entername": "Adınızı girin", - "pad.userlist.unnamed": "isimsiz", - "pad.userlist.guest": "Misafir", - "pad.userlist.deny": "Reddet", - "pad.userlist.approve": "Onayla", - "pad.editbar.clearcolors": "Bütün belgedeki yazarlık renkleri silinsin mi?", - "pad.impexp.importbutton": "Şimdi İçe Aktar", - "pad.impexp.importing": "İçe aktarıyor...", - "pad.impexp.confirmimport": "Bir dosya içe aktarılırken bloknotun mevcut metninin üzerine yazdırılır. Devam etmek istediğinizden emin misiniz?", - "pad.impexp.convertFailed": "Bu dosyayı içe aktarmak mümkün değil. Lütfen farklı bir belge biçimi kullanın ya da elle kopyala yapıştır yapın", - "pad.impexp.padHasData": "Biz bu dosyayı içe aktaramadık çünkü bu Bloknot zaten değiştirilmiş, lütfen yeni bir bloknot içe aktarın.", - "pad.impexp.uploadFailed": "Yükleme başarısız, lütfen tekrar deneyin", - "pad.impexp.importfailed": "İçe aktarım başarısız oldu", - "pad.impexp.copypaste": "Lütfen kopyala yapıştır yapın", - "pad.impexp.exportdisabled": "{{type}} biçimiyle dışa aktarma devre dışı bırakıldı. Ayrıntılar için sistem yöneticinizle iletişime geçiniz." -} diff --git a/sources/src/locales/uk.json b/sources/src/locales/uk.json deleted file mode 100644 index 9f89e50..0000000 --- a/sources/src/locales/uk.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Andriykopanytsia", - "Base", - "Olvin", - "Steve.rusyn", - "SteveR", - "Lxlalexlxl", - "Григорій Пугач", - "Bunyk", - "Piramidion" - ] - }, - "index.newPad": "Створити", - "index.createOpenPad": "або створити/відкрити документ з назвою:", - "pad.toolbar.bold.title": "Напівжирний (Ctrl-B)", - "pad.toolbar.italic.title": "Курсив (Ctrl-I)", - "pad.toolbar.underline.title": "Підкреслення (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Закреслення (Ctrl+5)", - "pad.toolbar.ol.title": "Упорядкований список (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Неупорядкований список (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Відступ (TAB)", - "pad.toolbar.unindent.title": "Виступ (Shift+TAB)", - "pad.toolbar.undo.title": "Скасувати (Ctrl-Z)", - "pad.toolbar.redo.title": "Повторити (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Очистити кольори документу (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Імпорт/Експорт з використанням різних форматів файлів", - "pad.toolbar.timeslider.title": "Шкала часу", - "pad.toolbar.savedRevision.title": "Зберегти версію", - "pad.toolbar.settings.title": "Налаштування", - "pad.toolbar.embed.title": "Поділитись та вбудувати цей документ", - "pad.toolbar.showusers.title": "Показати користувачів цього документу", - "pad.colorpicker.save": "Зберегти", - "pad.colorpicker.cancel": "Скасувати", - "pad.loading": "Завантаження…", - "pad.noCookie": "Реп'яшки не знайдено. Будь-ласка, увімкніть реп'яшки у вашому браузері!", - "pad.passwordRequired": "Вам необхідний пароль для доступу до цього документу", - "pad.permissionDenied": "Ви не має дозволу для доступу до цього документу", - "pad.wrongPassword": "Неправильний пароль", - "pad.settings.padSettings": "Налаштування документу", - "pad.settings.myView": "Мій Вигляд", - "pad.settings.stickychat": "Завжди відображувати чат", - "pad.settings.chatandusers": "Показати чат і користувачів", - "pad.settings.colorcheck": "Кольори документу", - "pad.settings.linenocheck": "Номери рядків", - "pad.settings.rtlcheck": "Читати вміст з права на ліво?", - "pad.settings.fontType": "Тип шрифту:", - "pad.settings.fontType.normal": "Звичайний", - "pad.settings.fontType.monospaced": "Моноширинний", - "pad.settings.globalView": "Загальний вигляд", - "pad.settings.language": "Мова:", - "pad.importExport.import_export": "Імпорт/Експорт", - "pad.importExport.import": "Завантажити будь-який текстовий файл або документ", - "pad.importExport.importSuccessful": "Успішно!", - "pad.importExport.export": "Експортувати поточний документ як:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Звичайний текст", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF (документ OpenOffice)", - "pad.importExport.abiword.innerHTML": "Ви можете імпортувати лище формати простого тексту або html. Для більш просунутих способів імпорту встановіть abiword.", - "pad.modals.connected": "З'єднано.", - "pad.modals.reconnecting": "Перепідлючення до Вашого документу..", - "pad.modals.forcereconnect": "Примусове перепідключення", - "pad.modals.reconnecttimer": "Триває спроба відновлення з'єднання", - "pad.modals.cancel": "Скасувати", - "pad.modals.userdup": "Відкрито в іншому вікні", - "pad.modals.userdup.explanation": "Документ, можливо, відкрито більш ніж в одному вікні браузера на цьому комп'ютері.", - "pad.modals.userdup.advice": "Перепідключитись використовуючи це вікно.", - "pad.modals.unauth": "Не авторизовано", - "pad.modals.unauth.explanation": "Ваші права було змінено під час перегляду цієї сторінк. Спробуйте перепідключитись.", - "pad.modals.looping.explanation": "Проблеми зв'єзку з сервером синхронізації.", - "pad.modals.looping.cause": "Можливо, підключились через несумісний брандмауер або проксі-сервер.", - "pad.modals.initsocketfail": "Сервер недоступний.", - "pad.modals.initsocketfail.explanation": "Не вдалося підключитися до сервера синхронізації.", - "pad.modals.initsocketfail.cause": "Ймовірно, це пов'язано з Вашим браузером або інтернет-з'єднанням.", - "pad.modals.slowcommit.explanation": "Сервер не відповідає.", - "pad.modals.slowcommit.cause": "Це може бути через проблем з підключенням до мережі.", - "pad.modals.badChangeset.explanation": "Редагування, яке ви зробили, було класифіковане як незаконний шлях доступу до сервера синхронізації.", - "pad.modals.badChangeset.cause": "Причиною може бути неправильна конфігурація сервера або інші непередбачувані поведінки. Зверніться до адміністратора служби, якщо ви відчуваєте, що це помилка. Спробуйте підключитися повторно для того, щоб продовжити редагування.", - "pad.modals.corruptPad.explanation": "Пошкоджено документ, до якого ви хочете одержати доступ.", - "pad.modals.corruptPad.cause": "Це може бути через неправильну конфігурацію сервера або іншу непередбачувану поведінку. Зверніться до адміністратора служби.", - "pad.modals.deleted": "Вилучено.", - "pad.modals.deleted.explanation": "Цей документ було вилучено.", - "pad.modals.disconnected": "Вас було від'єднано.", - "pad.modals.disconnected.explanation": "З'єднання з сервером втрачено", - "pad.modals.disconnected.cause": "Сервер, можливо, недоступний. Будь ласка, повідомте адміністратора служби, якщо це повторюватиметься.", - "pad.share": "Поділитись", - "pad.share.readonly": "Тільки читання", - "pad.share.link": "Посилання", - "pad.share.emebdcode": "Вставити URL", - "pad.chat": "Чат", - "pad.chat.title": "Відкрити чат для цього документу.", - "pad.chat.loadmessages": "Завантажити більше повідомлень", - "timeslider.pageTitle": "Часова шкала {{appTitle}}", - "timeslider.toolbar.returnbutton": "Повернутись до документу", - "timeslider.toolbar.authors": "Автори:", - "timeslider.toolbar.authorsList": "Немає авторів", - "timeslider.toolbar.exportlink.title": "Експорт", - "timeslider.exportCurrent": "Експортувати поточну версію як:", - "timeslider.version": "Версія {{version}}", - "timeslider.saved": "Збережено {{month}} {{day}}, {{year}}", - "timeslider.playPause": "Відтворення / Пауза Панель Зміст", - "timeslider.backRevision": "Переглянути попередню ревізію цієї панелі", - "timeslider.forwardRevision": "Переглянути наступну ревізію цієї панелі", - "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Січень", - "timeslider.month.february": "Лютий", - "timeslider.month.march": "Березень", - "timeslider.month.april": "Квітень", - "timeslider.month.may": "Травень", - "timeslider.month.june": "Червень", - "timeslider.month.july": "Липень", - "timeslider.month.august": "Серпень", - "timeslider.month.september": "Вересень", - "timeslider.month.october": "Жовтень", - "timeslider.month.november": "Листопад", - "timeslider.month.december": "Грудень", - "timeslider.unnamedauthors": "{{num}} {[plural(num) one: безіменний автор, few: безіменні автори, many: безіменних авторів, other: безіменних авторів]}", - "pad.savedrevs.marked": "Цю версію помічено збереженою версією", - "pad.savedrevs.timeslider": "Ви можете побачити збережені ревізії, відвідавши \"Слайдер Змін Ревізій\"", - "pad.userlist.entername": "Введіть Ваше ім'я", - "pad.userlist.unnamed": "безіменний", - "pad.userlist.guest": "Гість", - "pad.userlist.deny": "Заборонити", - "pad.userlist.approve": "Підтвердити", - "pad.editbar.clearcolors": "Очистити кольори у всьому документі?", - "pad.impexp.importbutton": "Імпортувати зараз", - "pad.impexp.importing": "Імпорт...", - "pad.impexp.confirmimport": "Імпортування файлу перезапише поточний текст документу. Ви дійсно хочете продовжити?", - "pad.impexp.convertFailed": "Ми не можемо імпортувати цей файл. Будь ласка, використайте інший формат документу, або прямо скопіюйте та вставте", - "pad.impexp.padHasData": "Ми були не в стані імпортувати цей файл, тому що ця панель, вже відредактована, будь ласка, імпортуйте на нову панель", - "pad.impexp.uploadFailed": "Завантаження не вдалось, будь ласка, спробуйте знову", - "pad.impexp.importfailed": "Помилка при імпортуванні", - "pad.impexp.copypaste": "Будь ласка, скопіюйте та вставте", - "pad.impexp.exportdisabled": "Експорт у формат {{type}} вимкнено. Будь ласка, зв'яжіться із Вашим системним адміністратором за деталями." -} diff --git a/sources/src/locales/vi.json b/sources/src/locales/vi.json deleted file mode 100644 index 57f58e0..0000000 --- a/sources/src/locales/vi.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Baonguyen21022003", - "Minh Nguyen", - "Tuankiet65", - "Max20091" - ] - }, - "index.newPad": "Tạo một Pad mới", - "index.createOpenPad": "hay tạo/mở một Pad với tên:", - "pad.toolbar.bold.title": "In đậm (Ctrl-B)", - "pad.toolbar.italic.title": "In nghiêng (Ctrl-I)", - "pad.toolbar.underline.title": "Gạch chân (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Gạch ngang (Ctrl+5)", - "pad.toolbar.ol.title": "Danh sách Có Đánh số (Ctrl+Shift+N)", - "pad.toolbar.ul.title": "Danh sách Không Đánh số (Ctrl+Shift+L)", - "pad.toolbar.indent.title": "Tăng lề (TAB)", - "pad.toolbar.unindent.title": "Giảm lề (Shift+TAB)", - "pad.toolbar.undo.title": "Hoàn tác (Ctrl-Z)", - "pad.toolbar.redo.title": "Làm lại (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Xóa Màu chỉ Tác giả (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Xuất/Nhập từ/đến các định dạng file khác nhau", - "pad.toolbar.timeslider.title": "Thanh thời gian", - "pad.toolbar.savedRevision.title": "Lưu Phiên bản", - "pad.toolbar.settings.title": "Thiết lập", - "pad.toolbar.embed.title": "Chia sẻ và Nhúng pad này", - "pad.toolbar.showusers.title": "Hiện các người dùng trên pad này", - "pad.colorpicker.save": "Lưu", - "pad.colorpicker.cancel": "Hủy bỏ", - "pad.loading": "Đang tải…", - "pad.passwordRequired": "Bạn cần mật khẩu để truy cập pad này", - "pad.permissionDenied": "Bạn không có quyền truy cập pad này.", - "pad.wrongPassword": "Bạn đã nhập sai mật khẩu", - "pad.settings.padSettings": "Tùy chọn Pad", - "pad.settings.myView": "Chỉ có tôi", - "pad.settings.stickychat": "Luân hiện cửa sổ trò chuyện trên màn hình", - "pad.settings.colorcheck": "Màu chỉ tác giả", - "pad.settings.linenocheck": "Số dòng", - "pad.settings.rtlcheck": "Đọc nội dung từ phải sang trái?", - "pad.settings.fontType": "Kiểu phông chữ:", - "pad.settings.fontType.normal": "Thường", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Toàn cầu", - "pad.settings.language": "Ngôn ngữ:", - "pad.importExport.import_export": "Xuất/Nhập", - "pad.importExport.import": "Tải lên bất kỳ tập tin văn bản hoặc tài liệu", - "pad.importExport.importSuccessful": "Thành công!", - "pad.importExport.export": "Xuất pad hiện tại ra định dạng:", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "Văn bản thuần túy", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF", - "pad.importExport.abiword.innerHTML": "Bạn chỉ có thể nhập vào từ văn bản thuần túy hay định dạng HTML. Nếu muốn có nhiều chức năng nhập hơn xin hãy cài đặt abiword.", - "pad.modals.connected": "Đã kết nối lại.", - "pad.modals.reconnecting": "Kết nối lại tới pad của bạn", - "pad.modals.forcereconnect": "Ép kết nối lại", - "pad.modals.userdup": "Mở trong cửa sổ khác", - "pad.modals.userdup.explanation": "Pad này dường như được mở trên hơn một cửa sổ trình duyệt trên máy tính này.", - "pad.modals.userdup.advice": "Kết nối lại để sử dụng cửa sổ này.", - "pad.modals.unauth": "Không có quyền", - "pad.modals.unauth.explanation": "Quyền của bạn đã thay đổi trong khi bạn đang xem trang này. Hãy thử kết nối lại.", - "pad.modals.looping.explanation": "Có vấn đề khi giao tiếp với máy chủ đồng bộ", - "pad.modals.looping.cause": "Có thể bạn đã kết nối thông qua một tường lửa hay proxy không thích hợp", - "pad.modals.initsocketfail": "Không thể tiếp cận máy chủ", - "pad.modals.initsocketfail.explanation": "Không thể kết nối đến máy chủ đồng bộ.", - "pad.modals.initsocketfail.cause": "Điều này có thể là do một vấn đề với trình duyệt của bạn hay đường truyền internet của bạn.", - "pad.modals.slowcommit.explanation": "Máy chủ không phản hồi.", - "pad.modals.slowcommit.cause": "Điều này có thể là do vấn đề về kết nối mạng.", - "pad.modals.badChangeset.explanation": "Chỉnh sửa bạn đã thực hiện là bất hợp pháp phân loại bởi máy chủ đồng bộ hóa.", - "pad.modals.badChangeset.cause": "Điều này có thể là do một cấu hình máy chủ sai hoặc một số hành vi không mong muốn khác. Xin vui lòng liên hệ với quản trị viên dịch vụ, nếu bạn cảm thấy đây là một lỗi. Cố gắng kết nối lại để tiếp tục chỉnh sửa.", - "pad.modals.corruptPad.explanation": "Các phím bạn đang cố truy cập bị hỏng.", - "pad.modals.corruptPad.cause": "Điều này có thể là do một cấu hình máy chủ sai hoặc một số hành vi không mong muốn khác. Xin vui lòng liên hệ với người quản trị dịch vụ.", - "pad.modals.deleted": "Đã xóa", - "pad.modals.deleted.explanation": "Pad này đã được gỡ", - "pad.modals.disconnected": "Bạn đã ngắt kết nối", - "pad.modals.disconnected.explanation": "Kết nối tới máy chủ đã bị mất", - "pad.modals.disconnected.cause": "Hệ phục vụ có thể không sẵn dùng. Xin vui lòng thông báo cho người quản trị dịch vụ nếu điều này tiếp tục xảy ra.", - "pad.share": "Chia sẻ pad này", - "pad.share.readonly": "Chỉ đọc", - "pad.share.link": "Liên kết", - "pad.share.emebdcode": "URL nhúng", - "pad.chat": "Trò chuyện", - "pad.chat.title": "Mở trò chuyện cho pad này.", - "pad.chat.loadmessages": "Tải thêm tin nhắn", - "timeslider.pageTitle": "Thanh thời gian của {{appTitle}}", - "timeslider.toolbar.returnbutton": "Trở về pad", - "timeslider.toolbar.authors": "Tác giả:", - "timeslider.toolbar.authorsList": "Không có tác giả", - "timeslider.toolbar.exportlink.title": "Xuất", - "timeslider.exportCurrent": "Xuất phiên bản hiện tại thành:", - "timeslider.version": "Phiên bản {{version}}", - "timeslider.saved": "Đã lưu vào ngày {{day}} {{month}} năm {{year}}", - "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Tháng Giêng", - "timeslider.month.february": "Tháng Hai", - "timeslider.month.march": "Tháng Ba", - "timeslider.month.april": "Tháng Tư", - "timeslider.month.may": "Tháng Năm", - "timeslider.month.june": "Tháng Sáu", - "timeslider.month.july": "Tháng Bảy", - "timeslider.month.august": "Tháng Tám", - "timeslider.month.september": "Tháng Chín", - "timeslider.month.october": "Tháng Mười", - "timeslider.month.november": "Tháng Mười Một", - "timeslider.month.december": "Tháng Mười Hai", - "timeslider.unnamedauthors": "Không tên {{in a}} {[plural(num) một: tác giả, khác: tác giả]}", - "pad.savedrevs.marked": "Phiên bản này đã được đánh dấu là một phiên bản đã lưu", - "pad.userlist.entername": "Nhập tên của bạn", - "pad.userlist.unnamed": "Không tên", - "pad.userlist.guest": "Khách", - "pad.userlist.deny": "Chặn", - "pad.userlist.approve": "Chấp nhận", - "pad.editbar.clearcolors": "Xóa màu chỉ tác giả trên toàn bộ tài liệu?", - "pad.impexp.importbutton": "Nhập ngay bây giờ", - "pad.impexp.importing": "Đang nhập…", - "pad.impexp.confirmimport": "Nhập một tập tin sẽ ghi đè nội dung hiện tại của pad. Bạn có muốn làm như vậy không?", - "pad.impexp.convertFailed": "Chúng tôi không thể nhập tập tin này. Hãy sử dụng định dạng tập tin khác hay sao chéo và dán một cách thủ công.", - "pad.impexp.uploadFailed": "Tải lên không thành công, vui lòng thử lại", - "pad.impexp.importfailed": "Nhập thất bại", - "pad.impexp.copypaste": "Xin vui lòng sao chép và dán", - "pad.impexp.exportdisabled": "Xuất ra định dạng {{type}} đã bị vô hiệu hóa. Xin hãy liên hệ với quản trị viên hệ thống để biết thêm thông tin chi tiết." -} diff --git a/sources/src/locales/zh-hans.json b/sources/src/locales/zh-hans.json deleted file mode 100644 index a598d9a..0000000 --- a/sources/src/locales/zh-hans.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Dimension", - "Hydra", - "Hzy980512", - "Liuxinyu970226", - "Qiyue2001", - "Shangkuanlc", - "Shizhao", - "Yfdyh000", - "乌拉跨氪", - "燃玉", - "JuneAugust" - ] - }, - "index.newPad": "新记事本", - "index.createOpenPad": "或者创建/打开带名字的记事本:", - "pad.toolbar.bold.title": "粗体(Ctrl-B)", - "pad.toolbar.italic.title": "斜体(Ctrl-I)", - "pad.toolbar.underline.title": "下划线(Ctrl-U)", - "pad.toolbar.strikethrough.title": "删除线(Ctrl+5)", - "pad.toolbar.ol.title": "有序列表(Ctrl+Shift+N)", - "pad.toolbar.ul.title": "无序列表(Ctrl+Shift+L)", - "pad.toolbar.indent.title": "增加缩进(TAB)", - "pad.toolbar.unindent.title": "减少缩进(Shift+TAB)", - "pad.toolbar.undo.title": "撤消(Ctrl-Z)", - "pad.toolbar.redo.title": "重做(Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "清除作者颜色(Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "从不同的文件格式导入/导出", - "pad.toolbar.timeslider.title": "时间轴", - "pad.toolbar.savedRevision.title": "保存修订", - "pad.toolbar.settings.title": "设置", - "pad.toolbar.embed.title": "共享并嵌入此记事本", - "pad.toolbar.showusers.title": "显示此记事本上的用户", - "pad.colorpicker.save": "保存", - "pad.colorpicker.cancel": "取消", - "pad.loading": "载入中……", - "pad.noCookie": "无法找到Cookie。请在您的浏览器中允许Cookie!", - "pad.passwordRequired": "您需要密码才能访问这个记事本", - "pad.permissionDenied": "您没有访问这个记事本的权限", - "pad.wrongPassword": "您的密码错了", - "pad.settings.padSettings": "记事本设置", - "pad.settings.myView": "我的视窗", - "pad.settings.stickychat": "总是显示聊天屏幕", - "pad.settings.chatandusers": "显示聊天和用户", - "pad.settings.colorcheck": "作者颜色", - "pad.settings.linenocheck": "行号", - "pad.settings.rtlcheck": "从右到左阅读内容吗?", - "pad.settings.fontType": "字体类型:", - "pad.settings.fontType.normal": "正常", - "pad.settings.fontType.monospaced": "等宽字体", - "pad.settings.globalView": "所有人视窗", - "pad.settings.language": "语言:", - "pad.importExport.import_export": "导入/导出", - "pad.importExport.import": "上载任何文本文件或档案", - "pad.importExport.importSuccessful": "成功!", - "pad.importExport.export": "当前记事本导出为:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "纯文本", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF(开放文档格式)", - "pad.importExport.abiword.innerHTML": "您只可以导入纯文本或HTML格式。要获取更高级的导入功能,请安装AbiWord。", - "pad.modals.connected": "已连接。", - "pad.modals.reconnecting": "重新连接到您的记事本...", - "pad.modals.forcereconnect": "强制重新连接", - "pad.modals.reconnecttimer": "尝试重新连入", - "pad.modals.cancel": "取消", - "pad.modals.userdup": "在另一个窗口中打开", - "pad.modals.userdup.explanation": "此记事本似乎在本电脑上的多个浏览器窗口中打开。", - "pad.modals.userdup.advice": "重新连接,使用此窗口。", - "pad.modals.unauth": "未授权", - "pad.modals.unauth.explanation": "您的权限在查看此页面时已改变。尝试重新连接。", - "pad.modals.looping.explanation": "与同步服务器的通信出现问题。", - "pad.modals.looping.cause": "也许您是通过不兼容的防火墙或代理服务器连接。", - "pad.modals.initsocketfail": "无法访问服务器。", - "pad.modals.initsocketfail.explanation": "无法连接到同步服务器。", - "pad.modals.initsocketfail.cause": "这可能是由于您的浏览器或您的互联网连接的问题。", - "pad.modals.slowcommit.explanation": "服务器没有响应。", - "pad.modals.slowcommit.cause": "这可能是由于网络连接问题。", - "pad.modals.badChangeset.explanation": "您的一个编辑被同步服务器分类为非法。", - "pad.modals.badChangeset.cause": "这可能是因为服务器配置的错误或者其他未预料到的行为。如果您认为这是错误,请联系服务管理员。要继续编辑,请尝试重新连接。", - "pad.modals.corruptPad.explanation": "您试图连接的记事本已损坏。", - "pad.modals.corruptPad.cause": "这可能是因为服务器配置的错误或者其他未预料到的行为。请联系服务管理员。", - "pad.modals.deleted": "已删除。", - "pad.modals.deleted.explanation": "此记事本已被移除。", - "pad.modals.disconnected": "您已断开连接。", - "pad.modals.disconnected.explanation": "到服务器的连接已丢失", - "pad.modals.disconnected.cause": "服务器可能无法使用。若此情况持续发生,请通知服务器管理员。", - "pad.share": "分享此记事本", - "pad.share.readonly": "只读", - "pad.share.link": "链接", - "pad.share.emebdcode": "嵌入网址", - "pad.chat": "聊天", - "pad.chat.title": "打开此记事本的聊天窗口。", - "pad.chat.loadmessages": "加载更多信息", - "timeslider.pageTitle": "{{appTitle}} 时间轴", - "timeslider.toolbar.returnbutton": "返回记事本", - "timeslider.toolbar.authors": "作者:", - "timeslider.toolbar.authorsList": "没有作者", - "timeslider.toolbar.exportlink.title": "导出", - "timeslider.exportCurrent": "当前版本导出为:", - "timeslider.version": "版本 {{version}}", - "timeslider.saved": "在{{year}}年{{month}}{{day}}日保存", - "timeslider.playPause": "回放 / 暂停Pad内容", - "timeslider.backRevision": "返回此Pad的一次修订", - "timeslider.forwardRevision": "前往此Pad的一次修订", - "timeslider.dateformat": "{{year}}年{{month}}月{{day}}日 {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "1月", - "timeslider.month.february": "2月", - "timeslider.month.march": "3月", - "timeslider.month.april": "4月", - "timeslider.month.may": "5月", - "timeslider.month.june": "6月", - "timeslider.month.july": "7月", - "timeslider.month.august": "8月", - "timeslider.month.september": "9月", - "timeslider.month.october": "10月", - "timeslider.month.november": "11月", - "timeslider.month.december": "12月", - "timeslider.unnamedauthors": "{{num}}个匿名作者", - "pad.savedrevs.marked": "这一修订现在被标记为已保存的修订版本", - "pad.savedrevs.timeslider": "您可以使用时间滑块查阅已保存的版本", - "pad.userlist.entername": "输入您的姓名", - "pad.userlist.unnamed": "匿名", - "pad.userlist.guest": "访客", - "pad.userlist.deny": "拒绝", - "pad.userlist.approve": "批准", - "pad.editbar.clearcolors": "清除整个文档的作者颜色吗?", - "pad.impexp.importbutton": "现在导入", - "pad.impexp.importing": "正在导入...", - "pad.impexp.confirmimport": "导入的文件将覆盖记事本的当前文本。你确定要继续吗?", - "pad.impexp.convertFailed": "我们无法导入此文档。请使用其他文档格式或手动复制贴上。", - "pad.impexp.padHasData": "我们无法导入此文件,因为此记事本已经变更,请导入到一个新的记事本中", - "pad.impexp.uploadFailed": "上载失败,请重试", - "pad.impexp.importfailed": "导入失败", - "pad.impexp.copypaste": "请复制粘贴", - "pad.impexp.exportdisabled": "{{type}} 格式的导出被禁用。有关详情,请与您的系统管理员联系。" -} diff --git a/sources/src/locales/zh-hant.json b/sources/src/locales/zh-hant.json deleted file mode 100644 index 2a7d6d1..0000000 --- a/sources/src/locales/zh-hant.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Justincheng12345", - "Liuxinyu970226", - "Shangkuanlc", - "Shirayuki", - "Simon Shek", - "LNDDYL", - "Wehwei", - "Kly" - ] - }, - "index.newPad": "新記事本", - "index.createOpenPad": "或創建/開啟以下名稱的記事本:", - "pad.toolbar.bold.title": "粗體(Ctrl-B)", - "pad.toolbar.italic.title": "斜體(Ctrl-I)", - "pad.toolbar.underline.title": "底線(Ctrl-U)", - "pad.toolbar.strikethrough.title": "刪除線(Ctrl+5)", - "pad.toolbar.ol.title": "有序清單(Ctrl+Shift+N)", - "pad.toolbar.ul.title": "無序清單(Ctrl+Shift+L)", - "pad.toolbar.indent.title": "縮排(TAB)", - "pad.toolbar.unindent.title": "凸排(Shift+TAB)", - "pad.toolbar.undo.title": "撤銷(Ctrl-Z)", - "pad.toolbar.redo.title": "重做 (Ctrl+Y)", - "pad.toolbar.clearAuthorship.title": "清除協作者顏色區別 (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "以其他檔案格式匯入/匯出", - "pad.toolbar.timeslider.title": "時間軸", - "pad.toolbar.savedRevision.title": "儲存修訂", - "pad.toolbar.settings.title": "設定", - "pad.toolbar.embed.title": "分享和嵌入此記事本", - "pad.toolbar.showusers.title": "顯示此記事本的使用者", - "pad.colorpicker.save": "儲存", - "pad.colorpicker.cancel": "取消", - "pad.loading": "載入中...", - "pad.noCookie": "找不到 Cookie。請讓你的瀏覽器允許 Cookie!", - "pad.passwordRequired": "您需要密碼才能訪問這個記事本", - "pad.permissionDenied": "你沒有訪問這個記事本的權限", - "pad.wrongPassword": "密碼錯誤", - "pad.settings.padSettings": "記事本設定", - "pad.settings.myView": "我的視窗", - "pad.settings.stickychat": "永遠在屏幕上顯示聊天", - "pad.settings.chatandusers": "顯示聊天與使用者", - "pad.settings.colorcheck": "協作者顏色", - "pad.settings.linenocheck": "行號", - "pad.settings.rtlcheck": "從右至左讀取內容?", - "pad.settings.fontType": "字體類型:", - "pad.settings.fontType.normal": "正常", - "pad.settings.fontType.monospaced": "等寬", - "pad.settings.globalView": "所有人的視窗", - "pad.settings.language": "語言:", - "pad.importExport.import_export": "匯入/匯出", - "pad.importExport.import": "上載任何文字檔或文件", - "pad.importExport.importSuccessful": "完成!", - "pad.importExport.export": "匯出目前的記事本為:", - "pad.importExport.exportetherpad": "Etherpad", - "pad.importExport.exporthtml": "HTML", - "pad.importExport.exportplain": "純文字", - "pad.importExport.exportword": "Microsoft Word", - "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportopen": "ODF(開放文件格式)", - "pad.importExport.abiword.innerHTML": "您只可以純文字或 HTML 格式檔匯入。安裝\n AbiWord 取得更多進階的匯入功能。", - "pad.modals.connected": "已連線。", - "pad.modals.reconnecting": "重新連接到您的記事本...", - "pad.modals.forcereconnect": "強制重新連線", - "pad.modals.reconnecttimer": "嘗試重新連接在", - "pad.modals.cancel": "取消", - "pad.modals.userdup": "在另一個視窗中開啟", - "pad.modals.userdup.explanation": "此記事本似乎在此電腦上的多個瀏覽器視窗中開啟。", - "pad.modals.userdup.advice": "重新連接到此視窗。", - "pad.modals.unauth": "未授權", - "pad.modals.unauth.explanation": "您的權限在查看此頁時發生更改。請嘗試重新連接。", - "pad.modals.looping.explanation": "與同步伺服器間有通信問題。", - "pad.modals.looping.cause": "也許您是通過不相容的防火牆或代理伺服器連線。", - "pad.modals.initsocketfail": "無法訪問伺服器。", - "pad.modals.initsocketfail.explanation": "無法連接到同步伺服器。", - "pad.modals.initsocketfail.cause": "這可能是因為瀏覽器或網際網路連線問題所造成。", - "pad.modals.slowcommit.explanation": "伺服器沒有回應。", - "pad.modals.slowcommit.cause": "這可能是因為網路連線問題所造成。", - "pad.modals.badChangeset.explanation": "您的一個編輯被同步伺服器類為非法。", - "pad.modals.badChangeset.cause": "這可能由於伺服器的配置錯誤或遇到意外問題。若您認為這是錯誤,請聯繫伺服器管理員。如要繼續編輯,請嘗試重新連接。", - "pad.modals.corruptPad.explanation": "您試圖存取的記事本已損壞。", - "pad.modals.corruptPad.cause": "這可能由於伺服器的配置錯誤或遇到意外問題。請聯繫伺服器管理員。", - "pad.modals.deleted": "已刪除。", - "pad.modals.deleted.explanation": "此記事本已被移除。", - "pad.modals.disconnected": "您已中斷連線。", - "pad.modals.disconnected.explanation": "伺服器連接曾中斷", - "pad.modals.disconnected.cause": "伺服器可能無法使用。若此情況持續發生,請通知伺服器管理員。", - "pad.share": "分享此記事本", - "pad.share.readonly": "唯讀", - "pad.share.link": "連結", - "pad.share.emebdcode": "嵌入網址", - "pad.chat": "聊天功能", - "pad.chat.title": "打開記事本聊天功能", - "pad.chat.loadmessages": "載入更多訊息", - "timeslider.pageTitle": "{{appTitle}}時間軸", - "timeslider.toolbar.returnbutton": "返回到記事本", - "timeslider.toolbar.authors": "協作者:", - "timeslider.toolbar.authorsList": "無協作者", - "timeslider.toolbar.exportlink.title": "匯出", - "timeslider.exportCurrent": "匯出當前版本為:", - "timeslider.version": "版本{{version}}", - "timeslider.saved": "{{year}}年{{month}}{{day}}日儲存", - "timeslider.playPause": "放送 / 暫停記事本內容", - "timeslider.backRevision": "返回此記事本的前一次修訂", - "timeslider.forwardRevision": "前往此記事本的前一次修訂", - "timeslider.dateformat": "{{year}}年{{month}}月{{day}}日 {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "1月", - "timeslider.month.february": "2月", - "timeslider.month.march": "3月", - "timeslider.month.april": "4月", - "timeslider.month.may": "5月", - "timeslider.month.june": "6月", - "timeslider.month.july": "7月", - "timeslider.month.august": "8月", - "timeslider.month.september": "9月", - "timeslider.month.october": "10月", - "timeslider.month.november": "11月", - "timeslider.month.december": "12月", - "timeslider.unnamedauthors": "{{num}} 個匿名{[plural(num) one:作者, other:作者]}", - "pad.savedrevs.marked": "標記此修訂版本為已儲存修訂版本。", - "pad.savedrevs.timeslider": "您可使用時段滑標來查看先前保存的版本內容", - "pad.userlist.entername": "輸入您的姓名", - "pad.userlist.unnamed": "未命名", - "pad.userlist.guest": "訪客", - "pad.userlist.deny": "拒絕", - "pad.userlist.approve": "批准", - "pad.editbar.clearcolors": "清除整個文檔的協作者顏色區別嗎?", - "pad.impexp.importbutton": "現在匯入", - "pad.impexp.importing": "匯入中...", - "pad.impexp.confirmimport": "匯入的檔案將會覆蓋記事本內目前的文字。您確定要繼續嗎?", - "pad.impexp.convertFailed": "未能匯入此檔案。請以其他檔案格式或手動複製貼上匯入。", - "pad.impexp.padHasData": "此記事本已異動過所以無法匯入該檔案,請匯入至另一個記事本試試。", - "pad.impexp.uploadFailed": "上載失敗,請重試", - "pad.impexp.importfailed": "匯入失敗", - "pad.impexp.copypaste": "請複製貼上", - "pad.impexp.exportdisabled": "{{type}}格式的匯出被禁用。有關詳情,請與您的系統管理員聯繫。" -} diff --git a/sources/src/node/README.md b/sources/src/node/README.md deleted file mode 100644 index 4b44328..0000000 --- a/sources/src/node/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# About the folder structure - -* **db** - all modules that are accesing the data structure and are communicating directly to the database -* **handler** - all modules that responds directly to requests/messages of the browser -* **utils** - helper modules - -# Module name conventions - -Module file names start with a capital letter and uses camelCase - -# Where does it start? - -server.js is started directly diff --git a/sources/src/node/db/API.js b/sources/src/node/db/API.js deleted file mode 100644 index be3e734..0000000 --- a/sources/src/node/db/API.js +++ /dev/null @@ -1,1301 +0,0 @@ -/** - * This module provides all API functions - */ - -/* - * 2011 Peter 'Pita' Martischka (Primary Technology Ltd) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var ERR = require("async-stacktrace"); -var customError = require("../utils/customError"); -var padManager = require("./PadManager"); -var padMessageHandler = require("../handler/PadMessageHandler"); -var readOnlyManager = require("./ReadOnlyManager"); -var groupManager = require("./GroupManager"); -var authorManager = require("./AuthorManager"); -var sessionManager = require("./SessionManager"); -var async = require("async"); -var exportHtml = require("../utils/ExportHtml"); -var exportTxt = require("../utils/ExportTxt"); -var importHtml = require("../utils/ImportHtml"); -var cleanText = require("./Pad").cleanText; -var PadDiff = require("../utils/padDiff"); - -/**********************/ -/**GROUP FUNCTIONS*****/ -/**********************/ - -exports.listAllGroups = groupManager.listAllGroups; -exports.createGroup = groupManager.createGroup; -exports.createGroupIfNotExistsFor = groupManager.createGroupIfNotExistsFor; -exports.deleteGroup = groupManager.deleteGroup; -exports.listPads = groupManager.listPads; -exports.createGroupPad = groupManager.createGroupPad; - -/**********************/ -/**PADLIST FUNCTION****/ -/**********************/ - -exports.listAllPads = padManager.listAllPads; - -/**********************/ -/**AUTHOR FUNCTIONS****/ -/**********************/ - -exports.createAuthor = authorManager.createAuthor; -exports.createAuthorIfNotExistsFor = authorManager.createAuthorIfNotExistsFor; -exports.getAuthorName = authorManager.getAuthorName; -exports.listPadsOfAuthor = authorManager.listPadsOfAuthor; -exports.padUsers = padMessageHandler.padUsers; -exports.padUsersCount = padMessageHandler.padUsersCount; - -/**********************/ -/**SESSION FUNCTIONS***/ -/**********************/ - -exports.createSession = sessionManager.createSession; -exports.deleteSession = sessionManager.deleteSession; -exports.getSessionInfo = sessionManager.getSessionInfo; -exports.listSessionsOfGroup = sessionManager.listSessionsOfGroup; -exports.listSessionsOfAuthor = sessionManager.listSessionsOfAuthor; - -/************************/ -/**PAD CONTENT FUNCTIONS*/ -/************************/ - -/** -getAttributePool(padID) returns the attribute pool of a pad - -Example returns: -{ - "code":0, - "message":"ok", - "data": { - "pool":{ - "numToAttrib":{ - "0":["author","a.X4m8bBWJBZJnWGSh"], - "1":["author","a.TotfBPzov54ihMdH"], - "2":["author","a.StiblqrzgeNTbK05"], - "3":["bold","true"] - }, - "attribToNum":{ - "author,a.X4m8bBWJBZJnWGSh":0, - "author,a.TotfBPzov54ihMdH":1, - "author,a.StiblqrzgeNTbK05":2, - "bold,true":3 - }, - "nextNum":4 - } - } -} - -*/ -exports.getAttributePool = function (padID, callback) -{ - getPadSafe(padID, true, function(err, pad) - { - if (ERR(err, callback)) return; - callback(null, {pool: pad.pool}); - }); -} - -/** -getRevisionChangeset (padID, [rev]) - -get the changeset at a given revision, or last revision if 'rev' is not defined. - -Example returns: -{ - "code" : 0, - "message" : "ok", - "data" : "Z:1>6b|5+6b$Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http://etherpad.org\n" -} - -*/ -exports.getRevisionChangeset = function(padID, rev, callback) -{ - // check if rev is set - if (typeof rev === "function") - { - callback = rev; - rev = undefined; - } - - // check if rev is a number - if (rev !== undefined && typeof rev !== "number") - { - // try to parse the number - if (!isNaN(parseInt(rev))) - { - rev = parseInt(rev); - } - else - { - callback(new customError("rev is not a number", "apierror")); - return; - } - } - - // ensure this is not a negative number - if (rev !== undefined && rev < 0) - { - callback(new customError("rev is not a negative number", "apierror")); - return; - } - - // ensure this is not a float value - if (rev !== undefined && !is_int(rev)) - { - callback(new customError("rev is a float value", "apierror")); - return; - } - - // get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - //the client asked for a special revision - if(rev !== undefined) - { - //check if this is a valid revision - if(rev > pad.getHeadRevisionNumber()) - { - callback(new customError("rev is higher than the head revision of the pad","apierror")); - return; - } - - //get the changeset for this revision - pad.getRevisionChangeset(rev, function(err, changeset) - { - if(ERR(err, callback)) return; - - callback(null, changeset); - }) - } - //the client wants the latest changeset, lets return it to him - else - { - pad.getRevisionChangeset(pad.getHeadRevisionNumber(), function(err, changeset) - { - if(ERR(err, callback)) return; - - callback(null, changeset); - }) - } - }); -} - -/** -getText(padID, [rev]) returns the text of a pad - -Example returns: - -{code: 0, message:"ok", data: {text:"Welcome Text"}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.getText = function(padID, rev, callback) -{ - //check if rev is set - if(typeof rev == "function") - { - callback = rev; - rev = undefined; - } - - //check if rev is a number - if(rev !== undefined && typeof rev != "number") - { - //try to parse the number - if(!isNaN(parseInt(rev))) - { - rev = parseInt(rev); - } - else - { - callback(new customError("rev is not a number", "apierror")); - return; - } - } - - //ensure this is not a negativ number - if(rev !== undefined && rev < 0) - { - callback(new customError("rev is a negativ number","apierror")); - return; - } - - //ensure this is not a float value - if(rev !== undefined && !is_int(rev)) - { - callback(new customError("rev is a float value","apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - //the client asked for a special revision - if(rev !== undefined) - { - //check if this is a valid revision - if(rev > pad.getHeadRevisionNumber()) - { - callback(new customError("rev is higher than the head revision of the pad","apierror")); - return; - } - - //get the text of this revision - pad.getInternalRevisionAText(rev, function(err, atext) - { - if(ERR(err, callback)) return; - - var data = {text: atext.text}; - - callback(null, data); - }) - } - //the client wants the latest text, lets return it to him - else - { - var padText = exportTxt.getTXTFromAtext(pad, pad.atext); - callback(null, {"text": padText}); - } - }); -} - -/** -setText(padID, text) sets the text of a pad - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"padID does not exist", data: null} -{code: 1, message:"text too long", data: null} -*/ -exports.setText = function(padID, text, callback) -{ - //text is required - if(typeof text != "string") - { - callback(new customError("text is no string","apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - //set the text - pad.setText(text); - - //update the clients on the pad - padMessageHandler.updatePadClients(pad, callback); - }); -} - -/** -appendText(padID, text) appends text to a pad - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"padID does not exist", data: null} -{code: 1, message:"text too long", data: null} -*/ -exports.appendText = function(padID, text, callback) -{ - //text is required - if(typeof text != "string") - { - callback(new customError("text is no string","apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - pad.appendText(text); - - //update the clients on the pad - padMessageHandler.updatePadClients(pad, callback); - }); -}; - - - -/** -getHTML(padID, [rev]) returns the html of a pad - -Example returns: - -{code: 0, message:"ok", data: {text:"Welcome Text"}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.getHTML = function(padID, rev, callback) -{ - if(typeof rev == "function") - { - callback = rev; - rev = undefined; - } - - if (rev !== undefined && typeof rev != "number") - { - if (!isNaN(parseInt(rev))) - { - rev = parseInt(rev); - } - else - { - callback(new customError("rev is not a number","apierror")); - return; - } - } - - if(rev !== undefined && rev < 0) - { - callback(new customError("rev is a negative number","apierror")); - return; - } - - if(rev !== undefined && !is_int(rev)) - { - callback(new customError("rev is a float value","apierror")); - return; - } - - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - //the client asked for a special revision - if(rev !== undefined) - { - //check if this is a valid revision - if(rev > pad.getHeadRevisionNumber()) - { - callback(new customError("rev is higher than the head revision of the pad","apierror")); - return; - } - - //get the html of this revision - exportHtml.getPadHTML(pad, rev, function(err, html) - { - if(ERR(err, callback)) return; - html = "" +html; // adds HTML head - html += ""; - var data = {html: html}; - callback(null, data); - }); - } - //the client wants the latest text, lets return it to him - else - { - exportHtml.getPadHTML(pad, undefined, function (err, html) - { - if(ERR(err, callback)) return; - html = "" +html; // adds HTML head - html += ""; - var data = {html: html}; - callback(null, data); - }); - } - }); -} - -/** -setHTML(padID, html) sets the text of a pad based on HTML - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.setHTML = function(padID, html, callback) -{ - //html is required - if(typeof html != "string") - { - callback(new customError("html is no string","apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - // add a new changeset with the new html to the pad - importHtml.setPadHTML(pad, cleanText(html), function(e){ - if(e){ - callback(new customError("HTML is malformed","apierror")); - return; - }else{ - //update the clients on the pad - padMessageHandler.updatePadClients(pad, callback); - return; - } - }); - }); -} - -/******************/ -/**CHAT FUNCTIONS */ -/******************/ - -/** -getChatHistory(padId, start, end), returns a part of or the whole chat-history of this pad - -Example returns: - -{"code":0,"message":"ok","data":{"messages":[{"text":"foo","authorID":"a.foo","time":1359199533759,"userName":"test"}, - {"text":"bar","authorID":"a.foo","time":1359199534622,"userName":"test"}]}} - -{code: 1, message:"start is higher or equal to the current chatHead", data: null} - -{code: 1, message:"padID does not exist", data: null} -*/ -exports.getChatHistory = function(padID, start, end, callback) -{ - if(start && end) - { - if(start < 0) - { - callback(new customError("start is below zero","apierror")); - return; - } - if(end < 0) - { - callback(new customError("end is below zero","apierror")); - return; - } - if(start > end) - { - callback(new customError("start is higher than end","apierror")); - return; - } - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - var chatHead = pad.chatHead; - - // fall back to getting the whole chat-history if a parameter is missing - if(!start || !end) - { - start = 0; - end = pad.chatHead; - } - - if(start > chatHead) - { - callback(new customError("start is higher than the current chatHead","apierror")); - return; - } - if(end > chatHead) - { - callback(new customError("end is higher than the current chatHead","apierror")); - return; - } - - // the the whole message-log and return it to the client - pad.getChatMessages(start, end, - function(err, msgs) - { - if(ERR(err, callback)) return; - callback(null, {messages: msgs}); - }); - }); -} - -/** -appendChatMessage(padID, text, authorID, time), creates a chat message for the pad id, time is a timestamp - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.appendChatMessage = function(padID, text, authorID, time, callback) -{ - //text is required - if(typeof text != "string") - { - callback(new customError("text is no string","apierror")); - return; - } - - // if time is not an integer value - if(time === undefined || !is_int(time)) - { - // set time to current timestamp - time = new Date().getTime(); - } - - var padMessage = require("ep_etherpad-lite/node/handler/PadMessageHandler.js"); - // save chat message to database and send message to all connected clients - padMessage.sendChatMessageToPadClients(parseInt(time), authorID, text, padID); - - callback(); -} - -/*****************/ -/**PAD FUNCTIONS */ -/*****************/ - -/** -getRevisionsCount(padID) returns the number of revisions of this pad - -Example returns: - -{code: 0, message:"ok", data: {revisions: 56}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.getRevisionsCount = function(padID, callback) -{ - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - callback(null, {revisions: pad.getHeadRevisionNumber()}); - }); -} - -/** -getSavedRevisionsCount(padID) returns the number of saved revisions of this pad - -Example returns: - -{code: 0, message:"ok", data: {savedRevisions: 42}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.getSavedRevisionsCount = function(padID, callback) -{ - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - callback(null, {savedRevisions: pad.getSavedRevisionsNumber()}); - }); -} - -/** -listSavedRevisions(padID) returns the list of saved revisions of this pad - -Example returns: - -{code: 0, message:"ok", data: {savedRevisions: [2, 42, 1337]}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.listSavedRevisions = function(padID, callback) -{ - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - callback(null, {savedRevisions: pad.getSavedRevisionsList()}); - }); -} - -/** -saveRevision(padID) returns the list of saved revisions of this pad - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.saveRevision = function(padID, rev, callback) -{ - //check if rev is set - if(typeof rev == "function") - { - callback = rev; - rev = undefined; - } - - //check if rev is a number - if(rev !== undefined && typeof rev != "number") - { - //try to parse the number - if(!isNaN(parseInt(rev))) - { - rev = parseInt(rev); - } - else - { - callback(new customError("rev is not a number", "apierror")); - return; - } - } - - //ensure this is not a negativ number - if(rev !== undefined && rev < 0) - { - callback(new customError("rev is a negativ number","apierror")); - return; - } - - //ensure this is not a float value - if(rev !== undefined && !is_int(rev)) - { - callback(new customError("rev is a float value","apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - //the client asked for a special revision - if(rev !== undefined) - { - //check if this is a valid revision - if(rev > pad.getHeadRevisionNumber()) - { - callback(new customError("rev is higher than the head revision of the pad","apierror")); - return; - } - } else { - rev = pad.getHeadRevisionNumber(); - } - - authorManager.createAuthor('API', function(err, author) { - if(ERR(err, callback)) return; - - pad.addSavedRevision(rev, author.authorID, 'Saved through API call'); - callback(); - }); - }); -} - -/** -getLastEdited(padID) returns the timestamp of the last revision of the pad - -Example returns: - -{code: 0, message:"ok", data: {lastEdited: 1340815946602}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.getLastEdited = function(padID, callback) -{ - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - pad.getLastEdit(function(err, value) { - if(ERR(err, callback)) return; - callback(null, {lastEdited: value}); - }); - }); -} - -/** -createPad(padName [, text]) creates a new pad in this group - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"pad does already exist", data: null} -*/ -exports.createPad = function(padID, text, callback) -{ - //ensure there is no $ in the padID - if(padID) - { - if(padID.indexOf("$") != -1) - { - callback(new customError("createPad can't create group pads","apierror")); - return; - } - //check for url special characters - else if(padID.match(/(\/|\?|&|#)/)) - { - callback(new customError("malformed padID: Remove special characters","apierror")); - return; - } - } - - //create pad - getPadSafe(padID, false, text, function(err) - { - if(ERR(err, callback)) return; - callback(); - }); -} - -/** -deletePad(padID) deletes a pad - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.deletePad = function(padID, callback) -{ - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - pad.remove(callback); - }); -} -/** - restoreRevision(padID, [rev]) Restores revision from past as new changeset - - Example returns: - - {code:0, message:"ok", data:null} - {code: 1, message:"padID does not exist", data: null} - */ -exports.restoreRevision = function (padID, rev, callback) -{ - var Changeset = require("ep_etherpad-lite/static/js/Changeset"); - var padMessage = require("ep_etherpad-lite/node/handler/PadMessageHandler.js"); - - //check if rev is a number - if (rev !== undefined && typeof rev != "number") - { - //try to parse the number - if (!isNaN(parseInt(rev))) - { - rev = parseInt(rev); - } - else - { - callback(new customError("rev is not a number", "apierror")); - return; - } - } - - //ensure this is not a negativ number - if (rev !== undefined && rev < 0) - { - callback(new customError("rev is a negativ number", "apierror")); - return; - } - - //ensure this is not a float value - if (rev !== undefined && !is_int(rev)) - { - callback(new customError("rev is a float value", "apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function (err, pad) - { - if (ERR(err, callback)) return; - - - //check if this is a valid revision - if (rev > pad.getHeadRevisionNumber()) - { - callback(new customError("rev is higher than the head revision of the pad", "apierror")); - return; - } - - pad.getInternalRevisionAText(rev, function (err, atext) - { - if (ERR(err, callback)) return; - - var oldText = pad.text(); - atext.text += "\n"; - function eachAttribRun(attribs, func) - { - var attribsIter = Changeset.opIterator(attribs); - var textIndex = 0; - var newTextStart = 0; - var newTextEnd = atext.text.length; - while (attribsIter.hasNext()) - { - var op = attribsIter.next(); - var nextIndex = textIndex + op.chars; - if (!(nextIndex <= newTextStart || textIndex >= newTextEnd)) - { - func(Math.max(newTextStart, textIndex), Math.min(newTextEnd, nextIndex), op.attribs); - } - textIndex = nextIndex; - } - } - - // create a new changeset with a helper builder object - var builder = Changeset.builder(oldText.length); - - // assemble each line into the builder - eachAttribRun(atext.attribs, function (start, end, attribs) - { - builder.insert(atext.text.substring(start, end), attribs); - }); - - var lastNewlinePos = oldText.lastIndexOf('\n'); - if (lastNewlinePos < 0) - { - builder.remove(oldText.length - 1, 0); - } else - { - builder.remove(lastNewlinePos, oldText.match(/\n/g).length - 1); - builder.remove(oldText.length - lastNewlinePos - 1, 0); - } - - var changeset = builder.toString(); - - //append the changeset - pad.appendRevision(changeset); - // - padMessage.updatePadClients(pad, function () - { - }); - callback(null, null); - }); - - }); -}; - -/** -copyPad(sourceID, destinationID[, force=false]) copies a pad. If force is true, - the destination will be overwritten if it exists. - -Example returns: - -{code: 0, message:"ok", data: {padID: destinationID}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.copyPad = function(sourceID, destinationID, force, callback) -{ - getPadSafe(sourceID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - pad.copy(destinationID, force, callback); - }); -} - -/** -movePad(sourceID, destinationID[, force=false]) moves a pad. If force is true, - the destination will be overwritten if it exists. - -Example returns: - -{code: 0, message:"ok", data: {padID: destinationID}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.movePad = function(sourceID, destinationID, force, callback) -{ - getPadSafe(sourceID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - pad.copy(destinationID, force, function(err) { - if(ERR(err, callback)) return; - pad.remove(callback); - }); - }); -} -/** -getReadOnlyLink(padID) returns the read only link of a pad - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.getReadOnlyID = function(padID, callback) -{ - //we don't need the pad object, but this function does all the security stuff for us - getPadSafe(padID, true, function(err) - { - if(ERR(err, callback)) return; - - //get the readonlyId - readOnlyManager.getReadOnlyId(padID, function(err, readOnlyId) - { - if(ERR(err, callback)) return; - callback(null, {readOnlyID: readOnlyId}); - }); - }); -} - -/** -getPadID(roID) returns the padID of a pad based on the readonlyID(roID) - -Example returns: - -{code: 0, message:"ok", data: {padID: padID}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.getPadID = function(roID, callback) -{ - //get the PadId - readOnlyManager.getPadId(roID, function(err, retrievedPadID) - { - if(ERR(err, callback)) return; - - if(retrievedPadID == null) - { - callback(new customError("padID does not exist","apierror")); - } - else - { - callback(null, {padID: retrievedPadID}); - } - }); -} - -/** -setPublicStatus(padID, publicStatus) sets a boolean for the public status of a pad - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.setPublicStatus = function(padID, publicStatus, callback) -{ - //ensure this is a group pad - if(padID && padID.indexOf("$") == -1) - { - callback(new customError("You can only get/set the publicStatus of pads that belong to a group","apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - //convert string to boolean - if(typeof publicStatus == "string") - publicStatus = publicStatus == "true" ? true : false; - - //set the password - pad.setPublicStatus(publicStatus); - - callback(); - }); -} - -/** -getPublicStatus(padID) return true of false - -Example returns: - -{code: 0, message:"ok", data: {publicStatus: true}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.getPublicStatus = function(padID, callback) -{ - //ensure this is a group pad - if(padID && padID.indexOf("$") == -1) - { - callback(new customError("You can only get/set the publicStatus of pads that belong to a group","apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - callback(null, {publicStatus: pad.getPublicStatus()}); - }); -} - -/** -setPassword(padID, password) returns ok or a error message - -Example returns: - -{code: 0, message:"ok", data: null} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.setPassword = function(padID, password, callback) -{ - //ensure this is a group pad - if(padID && padID.indexOf("$") == -1) - { - callback(new customError("You can only get/set the password of pads that belong to a group","apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - //set the password - pad.setPassword(password == "" ? null : password); - - callback(); - }); -} - -/** -isPasswordProtected(padID) returns true or false - -Example returns: - -{code: 0, message:"ok", data: {passwordProtection: true}} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.isPasswordProtected = function(padID, callback) -{ - //ensure this is a group pad - if(padID && padID.indexOf("$") == -1) - { - callback(new customError("You can only get/set the password of pads that belong to a group","apierror")); - return; - } - - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - callback(null, {isPasswordProtected: pad.isPasswordProtected()}); - }); -} - -/** -listAuthorsOfPad(padID) returns an array of authors who contributed to this pad - -Example returns: - -{code: 0, message:"ok", data: {authorIDs : ["a.s8oes9dhwrvt0zif", "a.akf8finncvomlqva"]} -{code: 1, message:"padID does not exist", data: null} -*/ -exports.listAuthorsOfPad = function(padID, callback) -{ - //get the pad - getPadSafe(padID, true, function(err, pad) - { - if(ERR(err, callback)) return; - - callback(null, {authorIDs: pad.getAllAuthors()}); - }); -} - -/** -sendClientsMessage(padID, msg) sends a message to all clients connected to the -pad, possibly for the purpose of signalling a plugin. - -Note, this will only accept strings from the HTTP API, so sending bogus changes -or chat messages will probably not be possible. - -The resulting message will be structured like so: - -{ - type: 'COLLABROOM', - data: { - type: , - time:

      ')); - } - lists.length = 0; - pieces.push(lineContent, '
      '); - } - else - { - console.log('trace 2'); - pieces.push('

      '); - } - }*/ - else//means we are getting closer to the lowest level of indentation or are at the same level - { - var toClose = lists.length > 0 ? listLevels[listLevels.length - 2] - line.listLevel : 0 - if( toClose > 0){ - pieces.push('') - if(lists[lists.length - 1][1] == "number") - { - pieces.push(new Array(toClose+1).join('
    ')) - pieces.push('
  1. ', lineContent || '
    '); - } - else - { - pieces.push(new Array(toClose+1).join('')) - pieces.push('
  2. ', lineContent || '
    '); - } - lists = lists.slice(0,whichList+1) - } else { - pieces.push('
  3. ', lineContent || '
    '); - } - } - } - else//outside any list, need to close line.listLevel of lists - { - if(lists.length > 0){ - if(lists[lists.length - 1][1] == "number"){ - pieces.push('
'); - pieces.push(new Array(listLevels[listLevels.length - 2]).join('')) - } else { - pieces.push(''); - pieces.push(new Array(listLevels[listLevels.length - 2]).join('')) - } - } - lists = [] - - var context = { - line: line, - lineContent: lineContent, - apool: apool, - attribLine: attribLines[i], - text: textLines[i], - padId: pad.id - } - - var lineContentFromHook = hooks.callAllStr("getLineHTMLForExport", context, " ", " ", ""); - - if (lineContentFromHook) - { - pieces.push(lineContentFromHook, ''); - } - else - { - pieces.push(lineContent, '
'); - } - } - } - - for (var k = lists.length - 1; k >= 0; k--) - { - if(lists[k][1] == "number") - { - pieces.push(''); - } - else - { - pieces.push(''); - } - } - - return pieces.join(''); -} - -exports.getPadHTMLDocument = function (padId, revNum, callback) -{ - padManager.getPad(padId, function (err, pad) - { - if(ERR(err, callback)) return; - - var stylesForExportCSS = ""; - // Include some Styles into the Head for Export - hooks.aCallAll("stylesForExport", padId, function(err, stylesForExport){ - stylesForExport.forEach(function(css){ - stylesForExportCSS += css; - }); - - getPadHTML(pad, revNum, function (err, html) - { - if(ERR(err, callback)) return; - var exportedDoc = eejs.require("ep_etherpad-lite/templates/export_html.html", { - body: html, - padId: Security.escapeHTML(padId), - extraCSS: stylesForExportCSS - }); - callback(null, exportedDoc); - }); - }); - }); -}; - -// copied from ACE -var _REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/; -var _REGEX_SPACE = /\s/; -var _REGEX_URLCHAR = new RegExp('(' + /[-:@a-zA-Z0-9_.,~%+\/\\?=&#;()$]/.source + '|' + _REGEX_WORDCHAR.source + ')'); -var _REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man|gopher|txmt):\/\/|mailto:)/.source + _REGEX_URLCHAR.source + '*(?![:.,;])' + _REGEX_URLCHAR.source, 'g'); - -// returns null if no URLs, or [[startIndex1, url1], [startIndex2, url2], ...] - - -function _findURLs(text) -{ - _REGEX_URL.lastIndex = 0; - var urls = null; - var execResult; - while ((execResult = _REGEX_URL.exec(text))) - { - urls = (urls || []); - var startIndex = execResult.index; - var url = execResult[0]; - urls.push([startIndex, url]); - } - - return urls; -} - - -// copied from ACE -function _processSpaces(s){ - var doesWrap = true; - if (s.indexOf("<") < 0 && !doesWrap){ - // short-cut - return s.replace(/ /g, ' '); - } - var parts = []; - s.replace(/<[^>]*>?| |[^ <]+/g, function (m){ - parts.push(m); - }); - if (doesWrap){ - var endOfLine = true; - var beforeSpace = false; - // last space in a run is normal, others are nbsp, - // end of line is nbsp - for (var i = parts.length - 1; i >= 0; i--){ - var p = parts[i]; - if (p == " "){ - if (endOfLine || beforeSpace) parts[i] = ' '; - endOfLine = false; - beforeSpace = true; - } - else if (p.charAt(0) != "<"){ - endOfLine = false; - beforeSpace = false; - } - } - // beginning of line is nbsp - for (i = 0; i < parts.length; i++){ - p = parts[i]; - if (p == " "){ - parts[i] = ' '; - break; - } - else if (p.charAt(0) != "<"){ - break; - } - } - } - else - { - for (i = 0; i < parts.length; i++){ - p = parts[i]; - if (p == " "){ - parts[i] = ' '; - } - } - } - return parts.join(''); -} diff --git a/sources/src/node/utils/ExportTxt.js b/sources/src/node/utils/ExportTxt.js deleted file mode 100644 index e3ce015..0000000 --- a/sources/src/node/utils/ExportTxt.js +++ /dev/null @@ -1,286 +0,0 @@ -/** - * TXT export - */ - -/* - * 2013 John McLear - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var async = require("async"); -var Changeset = require("ep_etherpad-lite/static/js/Changeset"); -var padManager = require("../db/PadManager"); -var ERR = require("async-stacktrace"); -var _analyzeLine = require('./ExportHelper')._analyzeLine; - -// This is slightly different than the HTML method as it passes the output to getTXTFromAText -function getPadTXT(pad, revNum, callback) -{ - var atext = pad.atext; - var html; - async.waterfall([ - // fetch revision atext - - - function (callback) - { - if (revNum != undefined) - { - pad.getInternalRevisionAText(revNum, function (err, revisionAtext) - { - if(ERR(err, callback)) return; - atext = revisionAtext; - callback(); - }); - } - else - { - callback(null); - } - }, - - // convert atext to html - - - function (callback) - { - html = getTXTFromAtext(pad, atext); // only this line is different to the HTML function - callback(null); - }], - // run final callback - - - function (err) - { - if(ERR(err, callback)) return; - callback(null, html); - }); -} - -exports.getPadTXT = getPadTXT; - - -// This is different than the functionality provided in ExportHtml as it provides formatting -// functionality that is designed specifically for TXT exports -function getTXTFromAtext(pad, atext, authorColors) -{ - var apool = pad.apool(); - var textLines = atext.text.slice(0, -1).split('\n'); - var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text); - - var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough']; - var anumMap = {}; - var css = ""; - - props.forEach(function (propName, i) - { - var propTrueNum = apool.putAttrib([propName, true], true); - if (propTrueNum >= 0) - { - anumMap[propTrueNum] = i; - } - }); - - function getLineTXT(text, attribs) - { - var propVals = [false, false, false]; - var ENTER = 1; - var STAY = 2; - var LEAVE = 0; - - // Use order of tags (b/i/u) as order of nesting, for simplicity - // and decent nesting. For example, - // Just bold Bold and italics Just italics - // becomes - // Just bold Bold and italics Just italics - var taker = Changeset.stringIterator(text); - var assem = Changeset.stringAssembler(); - - var idx = 0; - - function processNextChars(numChars) - { - if (numChars <= 0) - { - return; - } - - var iter = Changeset.opIterator(Changeset.subattribution(attribs, idx, idx + numChars)); - idx += numChars; - - while (iter.hasNext()) - { - var o = iter.next(); - var propChanged = false; - Changeset.eachAttribNumber(o.attribs, function (a) - { - if (a in anumMap) - { - var i = anumMap[a]; // i = 0 => bold, etc. - if (!propVals[i]) - { - propVals[i] = ENTER; - propChanged = true; - } - else - { - propVals[i] = STAY; - } - } - }); - for (var i = 0; i < propVals.length; i++) - { - if (propVals[i] === true) - { - propVals[i] = LEAVE; - propChanged = true; - } - else if (propVals[i] === STAY) - { - propVals[i] = true; // set it back - } - } - // now each member of propVal is in {false,LEAVE,ENTER,true} - // according to what happens at start of span - if (propChanged) - { - // leaving bold (e.g.) also leaves italics, etc. - var left = false; - for (var i = 0; i < propVals.length; i++) - { - var v = propVals[i]; - if (!left) - { - if (v === LEAVE) - { - left = true; - } - } - else - { - if (v === true) - { - propVals[i] = STAY; // tag will be closed and re-opened - } - } - } - - var tags2close = []; - - for (var i = propVals.length - 1; i >= 0; i--) - { - if (propVals[i] === LEAVE) - { - //emitCloseTag(i); - tags2close.push(i); - propVals[i] = false; - } - else if (propVals[i] === STAY) - { - //emitCloseTag(i); - tags2close.push(i); - } - } - - for (var i = 0; i < propVals.length; i++) - { - if (propVals[i] === ENTER || propVals[i] === STAY) - { - propVals[i] = true; - } - } - // propVals is now all {true,false} again - } // end if (propChanged) - - var chars = o.chars; - if (o.lines) - { - chars--; // exclude newline at end of line, if present - } - - var s = taker.take(chars); - - // removes the characters with the code 12. Don't know where they come - // from but they break the abiword parser and are completly useless - // s = s.replace(String.fromCharCode(12), ""); - - // remove * from s, it's just not needed on a blank line.. This stops - // plugins from being able to display * at the beginning of a line - // s = s.replace("*", ""); // Then remove it - - assem.append(s); - } // end iteration over spans in line - - var tags2close = []; - for (var i = propVals.length - 1; i >= 0; i--) - { - if (propVals[i]) - { - tags2close.push(i); - propVals[i] = false; - } - } - - } // end processNextChars - processNextChars(text.length - idx); - return(assem.toString()); - } // end getLineHTML - var pieces = [css]; - - // Need to deal with constraints imposed on HTML lists; can - // only gain one level of nesting at once, can't change type - // mid-list, etc. - // People might use weird indenting, e.g. skip a level, - // so we want to do something reasonable there. We also - // want to deal gracefully with blank lines. - // => keeps track of the parents level of indentation - for (var i = 0; i < textLines.length; i++) - { - var line = _analyzeLine(textLines[i], attribLines[i], apool); - var lineContent = getLineTXT(line.text, line.aline); - if(line.listTypeName == "bullet"){ - lineContent = "* " + lineContent; // add a bullet - } - if(line.listLevel > 0){ - for (var j = line.listLevel - 1; j >= 0; j--){ - pieces.push('\t'); - } - if(line.listTypeName == "number"){ - pieces.push(line.listLevel + ". "); - // This is bad because it doesn't truly reflect what the user - // sees because browsers do magic on nested
  1. s - } - pieces.push(lineContent, '\n'); - }else{ - pieces.push(lineContent, '\n'); - } - } - - return pieces.join(''); -} -exports.getTXTFromAtext = getTXTFromAtext; - -exports.getPadTXTDocument = function (padId, revNum, callback) -{ - padManager.getPad(padId, function (err, pad) - { - if(ERR(err, callback)) return; - - getPadTXT(pad, revNum, function (err, html) - { - if(ERR(err, callback)) return; - callback(null, html); - }); - }); -}; diff --git a/sources/src/node/utils/ImportEtherpad.js b/sources/src/node/utils/ImportEtherpad.js deleted file mode 100644 index bf1129c..0000000 --- a/sources/src/node/utils/ImportEtherpad.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * 2014 John McLear (Etherpad Foundation / McLear Ltd) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var log4js = require('log4js'); -var async = require("async"); -var db = require("../db/DB").db; - -exports.setPadRaw = function(padId, records, callback){ - records = JSON.parse(records); - - async.eachSeries(Object.keys(records), function(key, cb){ - var value = records[key] - - if(!value){ - return setImmediate(cb); - } - - // Author data - if(value.padIDs){ - // rewrite author pad ids - value.padIDs[padId] = 1; - var newKey = key; - - // Does this author already exist? - db.get(key, function(err, author){ - if(author){ - // Yes, add the padID to the author.. - if( Object.prototype.toString.call(author) === '[object Array]'){ - author.padIDs.push(padId); - } - value = author; - }else{ - // No, create a new array with the author info in - value.padIDs = [padId]; - } - }); - - // Not author data, probably pad data - }else{ - // we can split it to look to see if its pad data - var oldPadId = key.split(":"); - - // we know its pad data.. - if(oldPadId[0] === "pad"){ - - // so set the new pad id for the author - oldPadId[1] = padId; - - // and create the value - var newKey = oldPadId.join(":"); // create the new key - } - - } - // Write the value to the server - db.set(newKey, value); - - setImmediate(cb); - }, function(){ - callback(null, true); - }); -} diff --git a/sources/src/node/utils/ImportHtml.js b/sources/src/node/utils/ImportHtml.js deleted file mode 100644 index d71e272..0000000 --- a/sources/src/node/utils/ImportHtml.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright Yaco Sistemas S.L. 2011. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var log4js = require('log4js'); -var Changeset = require("ep_etherpad-lite/static/js/Changeset"); -var contentcollector = require("ep_etherpad-lite/static/js/contentcollector"); -var cheerio = require("cheerio"); - -function setPadHTML(pad, html, callback) -{ - var apiLogger = log4js.getLogger("ImportHtml"); - - var $ = cheerio.load(html); - - // Appends a line break, used by Etherpad to ensure a caret is available - // below the last line of an import - $('body').append("

    "); - - var doc = $('html')[0]; - apiLogger.debug('html:'); - apiLogger.debug(html); - - // Convert a dom tree into a list of lines and attribute liens - // using the content collector object - var cc = contentcollector.makeContentCollector(true, null, pad.pool); - try{ // we use a try here because if the HTML is bad it will blow up - cc.collectContent(doc); - }catch(e){ - apiLogger.warn("HTML was not properly formed", e); - return callback(e); // We don't process the HTML because it was bad.. - } - - var result = cc.finish(); - - apiLogger.debug('Lines:'); - var i; - for (i = 0; i < result.lines.length; i += 1) - { - apiLogger.debug('Line ' + (i + 1) + ' text: ' + result.lines[i]); - apiLogger.debug('Line ' + (i + 1) + ' attributes: ' + result.lineAttribs[i]); - } - - // Get the new plain text and its attributes - var newText = result.lines.join('\n'); - apiLogger.debug('newText:'); - apiLogger.debug(newText); - var newAttribs = result.lineAttribs.join('|1+1') + '|1+1'; - - function eachAttribRun(attribs, func /*(startInNewText, endInNewText, attribs)*/ ) - { - var attribsIter = Changeset.opIterator(attribs); - var textIndex = 0; - var newTextStart = 0; - var newTextEnd = newText.length; - while (attribsIter.hasNext()) - { - var op = attribsIter.next(); - var nextIndex = textIndex + op.chars; - if (!(nextIndex <= newTextStart || textIndex >= newTextEnd)) - { - func(Math.max(newTextStart, textIndex), Math.min(newTextEnd, nextIndex), op.attribs); - } - textIndex = nextIndex; - } - } - - // create a new changeset with a helper builder object - var builder = Changeset.builder(1); - - // assemble each line into the builder - eachAttribRun(newAttribs, function(start, end, attribs) - { - builder.insert(newText.substring(start, end), attribs); - }); - - // the changeset is ready! - var theChangeset = builder.toString(); - apiLogger.debug('The changeset: ' + theChangeset); - pad.setText("\n"); - pad.appendRevision(theChangeset); - callback(null); -} - -exports.setPadHTML = setPadHTML; diff --git a/sources/src/node/utils/LibreOffice.js b/sources/src/node/utils/LibreOffice.js deleted file mode 100644 index 3cf63e1..0000000 --- a/sources/src/node/utils/LibreOffice.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Controls the communication with LibreOffice - */ - -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var async = require("async"); -var fs = require("fs"); -var os = require("os"); -var path = require("path"); -var settings = require("./Settings"); -var spawn = require("child_process").spawn; - -// Conversion tasks will be queued up, so we don't overload the system -var queue = async.queue(doConvertTask, 1); - -/** - * Convert a file from one type to another - * - * @param {String} srcFile The path on disk to convert - * @param {String} destFile The path on disk where the converted file should be stored - * @param {String} type The type to convert into - * @param {Function} callback Standard callback function - */ -exports.convertFile = function(srcFile, destFile, type, callback) { - // soffice can't convert from html to doc directly (verified with LO 5 and 6) - // we need to convert to odt first, then to doc - // to avoid `Error: no export filter for /tmp/xxxx.doc` error - if (type === 'doc') { - queue.push({ - "srcFile": srcFile, - "destFile": destFile.replace(/\.doc$/, '.odt'), - "type": 'odt', - "callback": function () { - queue.push({"srcFile": srcFile.replace(/\.html$/, '.odt'), "destFile": destFile, "type": type, "callback": callback}); - } - }); - } else { - queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback}); - } -}; - -function doConvertTask(task, callback) { - var tmpDir = os.tmpdir(); - - async.series([ - // Generate a PDF file with LibreOffice - function(callback) { - var soffice = spawn(settings.soffice, [ - '--headless', - '--invisible', - '--nologo', - '--nolockcheck', - '--convert-to', task.type, - task.srcFile, - '--outdir', tmpDir - ]); - - var stdoutBuffer = ''; - - // Delegate the processing of stdout to another function - soffice.stdout.on('data', function(data) { - stdoutBuffer += data.toString(); - }); - - // Append error messages to the buffer - soffice.stderr.on('data', function(data) { - stdoutBuffer += data.toString(); - }); - - // Throw an exception if libreoffice failed - soffice.on('exit', function(code) { - if (code != 0) { - return callback("LibreOffice died with exit code " + code + " and message: " + stdoutBuffer); - } - - callback(); - }) - }, - - // Move the PDF file to the correct place - function(callback) { - var filename = path.basename(task.srcFile); - var pdfFilename = filename.substr(0, filename.lastIndexOf('.')) + '.' + task.type; - var pdfPath = path.join(tmpDir, pdfFilename); - fs.rename(pdfPath, task.destFile, callback); - } - ], function(err) { - // Invoke the callback for the local queue - callback(); - - // Invoke the callback for the task - task.callback(err); - }); -} diff --git a/sources/src/node/utils/Minify.js b/sources/src/node/utils/Minify.js deleted file mode 100644 index a56e347..0000000 --- a/sources/src/node/utils/Minify.js +++ /dev/null @@ -1,430 +0,0 @@ -/** - * This Module manages all /minified/* requests. It controls the - * minification && compression of Javascript and CSS. - */ - -/* - * 2011 Peter 'Pita' Martischka (Primary Technology Ltd) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var ERR = require("async-stacktrace"); -var settings = require('./Settings'); -var async = require('async'); -var fs = require('fs'); -var StringDecoder = require('string_decoder').StringDecoder; -var CleanCSS = require('clean-css'); -var uglifyJS = require("uglify-js"); -var path = require('path'); -var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins"); -var RequireKernel = require('etherpad-require-kernel'); -var urlutil = require('url'); - -var ROOT_DIR = path.normalize(__dirname + "/../../static/"); -var TAR_PATH = path.join(__dirname, 'tar.json'); -var tar = JSON.parse(fs.readFileSync(TAR_PATH, 'utf8')); - - -var LIBRARY_WHITELIST = [ - 'async' - , 'security' - , 'tinycon' - , 'underscore' - , 'unorm' - ]; - -// Rewrite tar to include modules with no extensions and proper rooted paths. -var LIBRARY_PREFIX = 'ep_etherpad-lite/static/js'; -exports.tar = {}; -function prefixLocalLibraryPath(path) { - if (path.charAt(0) == '$') { - return path.slice(1); - } else { - return LIBRARY_PREFIX + '/' + path; - } -} - -for (var key in tar) { - exports.tar[prefixLocalLibraryPath(key)] = - tar[key].map(prefixLocalLibraryPath).concat( - tar[key].map(prefixLocalLibraryPath).map(function (p) { - return p.replace(/\.js$/, ''); - }) - ).concat( - tar[key].map(prefixLocalLibraryPath).map(function (p) { - return p.replace(/\.js$/, '') + '/index.js'; - }) - ); -} - -// What follows is a terrible hack to avoid loop-back within the server. -// TODO: Serve files from another service, or directly from the file system. -function requestURI(url, method, headers, callback, redirectCount) { - var parsedURL = urlutil.parse(url); - - var status = 500, headers = {}, content = []; - - var mockRequest = { - url: url - , method: method - , params: {filename: parsedURL.path.replace(/^\/static\//, '')} - , headers: headers - }; - var mockResponse = { - writeHead: function (_status, _headers) { - status = _status; - for (var header in _headers) { - if (Object.prototype.hasOwnProperty.call(_headers, header)) { - headers[header] = _headers[header]; - } - } - } - , setHeader: function (header, value) { - headers[header.toLowerCase()] = value.toString(); - } - , header: function (header, value) { - headers[header.toLowerCase()] = value.toString(); - } - , write: function (_content) { - _content && content.push(_content); - } - , end: function (_content) { - _content && content.push(_content); - callback(status, headers, content.join('')); - } - }; - - minify(mockRequest, mockResponse); -} -function requestURIs(locations, method, headers, callback) { - var pendingRequests = locations.length; - var responses = []; - - function respondFor(i) { - return function (status, headers, content) { - responses[i] = [status, headers, content]; - if (--pendingRequests == 0) { - completed(); - } - }; - } - - for (var i = 0, ii = locations.length; i < ii; i++) { - requestURI(locations[i], method, headers, respondFor(i)); - } - - function completed() { - var statuss = responses.map(function (x) {return x[0];}); - var headerss = responses.map(function (x) {return x[1];}); - var contentss = responses.map(function (x) {return x[2];}); - callback(statuss, headerss, contentss); - } -} - -/** - * creates the minifed javascript for the given minified name - * @param req the Express request - * @param res the Express response - */ -function minify(req, res, next) -{ - var filename = req.params['filename']; - - // No relative paths, especially if they may go up the file hierarchy. - filename = path.normalize(path.join(ROOT_DIR, filename)); - filename = filename.replace(/\.\./g, '') - - if (filename.indexOf(ROOT_DIR) == 0) { - filename = filename.slice(ROOT_DIR.length); - filename = filename.replace(/\\/g, '/') - } else { - res.writeHead(404, {}); - res.end(); - return; - } - - /* Handle static files for plugins/libraries: - paths like "plugins/ep_myplugin/static/js/test.js" - are rewritten into ROOT_PATH_OF_MYPLUGIN/static/js/test.js, - commonly ETHERPAD_ROOT/node_modules/ep_myplugin/static/js/test.js - */ - var match = filename.match(/^plugins\/([^\/]+)(\/(?:(static\/.*)|.*))?$/); - if (match) { - var library = match[1]; - var libraryPath = match[2] || ''; - - if (plugins.plugins[library] && match[3]) { - var plugin = plugins.plugins[library]; - var pluginPath = plugin.package.realPath; - filename = path.relative(ROOT_DIR, pluginPath + libraryPath); - filename = filename.replace(/\\/g, '/'); // windows path fix - } else if (LIBRARY_WHITELIST.indexOf(library) != -1) { - // Go straight into node_modules - // Avoid `require.resolve()`, since 'mustache' and 'mustache/index.js' - // would end up resolving to logically distinct resources. - filename = '../node_modules/' + library + libraryPath; - } - } - - // What content type should this be? - // TODO: This should use a MIME module. - var contentType; - if (filename.match(/\.js$/)) { - contentType = "text/javascript"; - } else if (filename.match(/\.css$/)) { - contentType = "text/css"; - } else if (filename.match(/\.html$/)) { - contentType = "text/html"; - } else if (filename.match(/\.txt$/)) { - contentType = "text/plain"; - } else if (filename.match(/\.png$/)) { - contentType = "image/png"; - } else if (filename.match(/\.gif$/)) { - contentType = "image/gif"; - } else if (filename.match(/\.ico$/)) { - contentType = "image/x-icon"; - } else { - contentType = "application/octet-stream"; - } - - statFile(filename, function (error, date, exists) { - if (date) { - date = new Date(date); - res.setHeader('last-modified', date.toUTCString()); - res.setHeader('date', (new Date()).toUTCString()); - if (settings.maxAge !== undefined) { - var expiresDate = new Date((new Date()).getTime()+settings.maxAge*1000); - res.setHeader('expires', expiresDate.toUTCString()); - res.setHeader('cache-control', 'max-age=' + settings.maxAge); - } - } - - if (error) { - res.writeHead(500, {}); - res.end(); - } else if (!exists) { - res.writeHead(404, {}); - res.end(); - } else if (new Date(req.headers['if-modified-since']) >= date) { - res.writeHead(304, {}); - res.end(); - } else { - if (req.method == 'HEAD') { - res.header("Content-Type", contentType); - res.writeHead(200, {}); - res.end(); - } else if (req.method == 'GET') { - getFileCompressed(filename, contentType, function (error, content) { - if(ERR(error, function(){ - res.writeHead(500, {}); - res.end(); - })) return; - res.header("Content-Type", contentType); - res.writeHead(200, {}); - res.write(content); - res.end(); - }); - } else { - res.writeHead(405, {'allow': 'HEAD, GET'}); - res.end(); - } - } - }); -} - -// find all includes in ace.js and embed them. -function getAceFile(callback) { - fs.readFile(ROOT_DIR + 'js/ace.js', "utf8", function(err, data) { - if(ERR(err, callback)) return; - - // Find all includes in ace.js and embed them - var founds = data.match(/\$\$INCLUDE_[a-zA-Z_]+\("[^"]*"\)/gi); - if (!settings.minify) { - founds = []; - } - // Always include the require kernel. - founds.push('$$INCLUDE_JS("../static/js/require-kernel.js")'); - - data += ';\n'; - data += 'Ace2Editor.EMBEDED = Ace2Editor.EMBEDED || {};\n'; - - // Request the contents of the included file on the server-side and write - // them into the file. - async.forEach(founds, function (item, callback) { - var filename = item.match(/"([^"]*)"/)[1]; - - var baseURI = 'http://localhost:' + settings.port; - var resourceURI = baseURI + path.normalize(path.join('/static/', filename)); - resourceURI = resourceURI.replace(/\\/g, '/'); // Windows (safe generally?) - - requestURI(resourceURI, 'GET', {}, function (status, headers, body) { - var error = !(status == 200 || status == 404); - if (!error) { - data += 'Ace2Editor.EMBEDED[' + JSON.stringify(filename) + '] = ' - + JSON.stringify(status == 200 ? body || '' : null) + ';\n'; - } else { - // Silence? - } - callback(); - }); - }, function(error) { - callback(error, data); - }); - }); -} - -// Check for the existance of the file and get the last modification date. -function statFile(filename, callback, dirStatLimit) { - if (typeof dirStatLimit === 'undefined') { - dirStatLimit = 3; - } - - if (dirStatLimit < 1 || filename == '' || filename == '/') { - callback(null, null, false); - } else if (filename == 'js/ace.js') { - // Sometimes static assets are inlined into this file, so we have to stat - // everything. - lastModifiedDateOfEverything(function (error, date) { - callback(error, date, !error); - }); - } else if (filename == 'js/require-kernel.js') { - callback(null, requireLastModified(), true); - } else { - fs.stat(ROOT_DIR + filename, function (error, stats) { - if (error) { - if (error.code == "ENOENT") { - // Stat the directory instead. - statFile(path.dirname(filename), function (error, date, exists) { - callback(error, date, false); - }, dirStatLimit-1); - } else { - callback(error); - } - } else if (stats.isFile()) { - callback(null, stats.mtime.getTime(), true); - } else { - callback(null, stats.mtime.getTime(), false); - } - }); - } -} -function lastModifiedDateOfEverything(callback) { - var folders2check = [ROOT_DIR + 'js/', ROOT_DIR + 'css/']; - var latestModification = 0; - //go trough this two folders - async.forEach(folders2check, function(path, callback) - { - //read the files in the folder - fs.readdir(path, function(err, files) - { - if(ERR(err, callback)) return; - - //we wanna check the directory itself for changes too - files.push("."); - - //go trough all files in this folder - async.forEach(files, function(filename, callback) - { - //get the stat data of this file - fs.stat(path + "/" + filename, function(err, stats) - { - if(ERR(err, callback)) return; - - //get the modification time - var modificationTime = stats.mtime.getTime(); - - //compare the modification time to the highest found - if(modificationTime > latestModification) - { - latestModification = modificationTime; - } - - callback(); - }); - }, callback); - }); - }, function () { - callback(null, latestModification); - }); -} - -// This should be provided by the module, but until then, just use startup -// time. -var _requireLastModified = new Date(); -function requireLastModified() { - return _requireLastModified.toUTCString(); -} -function requireDefinition() { - return 'var require = ' + RequireKernel.kernelSource + ';\n'; -} - -function getFileCompressed(filename, contentType, callback) { - getFile(filename, function (error, content) { - if (error || !content || !settings.minify) { - callback(error, content); - } else if (contentType == 'text/javascript') { - try { - content = compressJS(content); - } catch (error) { - // silence - } - callback(null, content); - } else if (contentType == 'text/css') { - compressCSS(filename, content, callback); - } else { - callback(null, content); - } - }); -} - -function getFile(filename, callback) { - if (filename == 'js/ace.js') { - getAceFile(callback); - } else if (filename == 'js/require-kernel.js') { - callback(undefined, requireDefinition()); - } else { - fs.readFile(ROOT_DIR + filename, callback); - } -} - -function compressJS(content) -{ - var decoder = new StringDecoder('utf8'); - var code = decoder.write(content); // convert from buffer to string - var codeMinified = uglifyJS.minify(code, {fromString: true}).code; - return codeMinified; -} - -function compressCSS(filename, content, callback) -{ - try { - var base = path.join(ROOT_DIR, path.dirname(filename)); - new CleanCSS({relativeTo: base}).minify(content, function (errors, minified) { - if (errors) { - // On error, just yield the un-minified original. - callback(null, content); - } else { - callback(null, minified.styles); - } - }); - } catch (error) { - // On error, just yield the un-minified original. - callback(null, content); - } -} - -exports.minify = minify; - -exports.requestURI = requestURI; -exports.requestURIs = requestURIs; diff --git a/sources/src/node/utils/RemoteAddress.js b/sources/src/node/utils/RemoteAddress.js deleted file mode 100644 index 86a4a5b..0000000 --- a/sources/src/node/utils/RemoteAddress.js +++ /dev/null @@ -1 +0,0 @@ -exports.remoteAddress = {}; diff --git a/sources/src/node/utils/Settings.js b/sources/src/node/utils/Settings.js deleted file mode 100644 index 08ace60..0000000 --- a/sources/src/node/utils/Settings.js +++ /dev/null @@ -1,502 +0,0 @@ -/** - * The Settings Modul reads the settings out of settings.json and provides - * this information to the other modules - */ - -/* - * 2011 Peter 'Pita' Martischka (Primary Technology Ltd) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var fs = require("fs"); -var os = require("os"); -var path = require('path'); -var argv = require('./Cli').argv; -var npm = require("npm/lib/npm.js"); -var jsonminify = require("jsonminify"); -var log4js = require("log4js"); -var randomString = require("./randomstring"); -var suppressDisableMsg = " -- To suppress these warning messages change suppressErrorsInPadText to true in your settings.json\n"; -var _ = require("underscore"); - -/* Root path of the installation */ -exports.root = path.normalize(path.join(npm.dir, "..")); - -/** - * The app title, visible e.g. in the browser window - */ -exports.title = "Etherpad"; - -/** - * The app favicon fully specified url, visible e.g. in the browser window - */ -exports.favicon = "favicon.ico"; -exports.faviconPad = "../" + exports.favicon; -exports.faviconTimeslider = "../../" + exports.favicon; - -/** - * The IP ep-lite should listen to - */ -exports.ip = "0.0.0.0"; - -/** - * The Port ep-lite should listen to - */ -exports.port = process.env.PORT || 9001; - -/** - * Should we suppress Error messages from being in Pad Contents - */ -exports.suppressErrorsInPadText = false; - -/** - * The SSL signed server key and the Certificate Authority's own certificate - * default case: ep-lite does *not* use SSL. A signed server key is not required in this case. - */ -exports.ssl = false; - -/** - * socket.io transport methods - **/ -exports.socketTransportProtocols = ['xhr-polling', 'jsonp-polling', 'htmlfile']; - -/* - * The Type of the database - */ -exports.dbType = "dirty"; -/** - * This setting is passed with dbType to ueberDB to set up the database - */ -exports.dbSettings = { "filename" : path.join(exports.root, "dirty.db") }; - -/** - * The default Text of a new pad - */ -exports.defaultPadText = "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nEtherpad on Github: https:\/\/github.com\/ether\/etherpad-lite\n"; - -/** - * The default Pad Settings for a user (Can be overridden by changing the setting - */ -exports.padOptions = { - "noColors": false, - "showControls": true, - "showChat": true, - "showLineNumbers": true, - "useMonospaceFont": false, - "userName": false, - "userColor": false, - "rtl": false, - "alwaysShowChat": false, - "chatAndUsers": false, - "lang": "en-gb" -}, - -/** - * Whether certain shortcut keys are enabled for a user in the pad - */ -exports.padShortcutEnabled = { - "altF9" : true, - "altC" : true, - "delete" : true, - "cmdShift2" : true, - "return" : true, - "esc" : true, - "cmdS" : true, - "tab" : true, - "cmdZ" : true, - "cmdY" : true, - "cmdB" : true, - "cmdI" : true, - "cmdU" : true, - "cmd5" : true, - "cmdShiftL" : true, - "cmdShiftN" : true, - "cmdShift1" : true, - "cmdShiftC" : true, - "cmdH" : true, - "ctrlHome" : true, - "pageUp" : true, - "pageDown" : true, -}, - -/** - * The toolbar buttons and order. - */ -exports.toolbar = { - left: [ - ["bold", "italic", "underline", "strikethrough"], - ["orderedlist", "unorderedlist", "indent", "outdent"], - ["undo", "redo"], - ["clearauthorship"] - ], - right: [ - ["importexport", "timeslider", "savedrevision"], - ["settings", "embed"], - ["showusers"] - ], - timeslider: [ - ["timeslider_export", "timeslider_settings", "timeslider_returnToPad"] - ] -} - -/** - * A flag that requires any user to have a valid session (via the api) before accessing a pad - */ -exports.requireSession = false; - -/** - * A flag that prevents users from creating new pads - */ -exports.editOnly = false; - -/** - * A flag that bypasses password prompts for users with valid sessions - */ -exports.sessionNoPassword = false; - -/** - * Max age that responses will have (affects caching layer). - */ -exports.maxAge = 1000*60*60*6; // 6 hours - -/** - * A flag that shows if minification is enabled or not - */ -exports.minify = true; - -/** - * The path of the abiword executable - */ -exports.abiword = null; - -/** - * The path of the libreoffice executable - */ -exports.soffice = null; - -/** - * The path of the tidy executable - */ -exports.tidyHtml = null; - -/** - * Should we support none natively supported file types on import? - */ -exports.allowUnknownFileEnds = true; - -/** - * The log level of log4js - */ -exports.loglevel = "INFO"; - -/** - * Disable IP logging - */ -exports.disableIPlogging = false; - -/** - * Number of seconds to automatically reconnect pad - */ -exports.automaticReconnectionTimeout = 0; - -/** - * Disable Load Testing - */ -exports.loadTest = false; - -/** - * Enable indentation on new lines - */ -exports.indentationOnNewLine = true; - -/* -* log4js appender configuration -*/ -exports.logconfig = { appenders: [{ type: "console" }]}; - -/* -* Session Key, do not sure this. -*/ -exports.sessionKey = false; - -/* -* Trust Proxy, whether or not trust the x-forwarded-for header. -*/ -exports.trustProxy = false; - -/* This setting is used if you need authentication and/or - * authorization. Note: /admin always requires authentication, and - * either authorization by a module, or a user with is_admin set */ -exports.requireAuthentication = false; -exports.requireAuthorization = false; -exports.users = {}; - -/* -* Show settings in admin page, by default it is true -*/ -exports.showSettingsInAdminPage = true; - -/* -* By default, when caret is moved out of viewport, it scrolls the minimum height needed to make this -* line visible. -*/ -exports.scrollWhenFocusLineIsOutOfViewport = { - /* - * Percentage of viewport height to be additionally scrolled. - */ - "percentage": { - "editionAboveViewport": 0, - "editionBelowViewport": 0 - }, - /* - * Time (in milliseconds) used to animate the scroll transition. Set to 0 to disable animation - */ - "duration": 0, - /* - * Flag to control if it should scroll when user places the caret in the last line of the viewport - */ - /* - * Percentage of viewport height to be additionally scrolled when user presses arrow up - * in the line of the top of the viewport. - */ - "percentageToScrollWhenUserPressesArrowUp": 0, - "scrollWhenCaretIsInTheLastLineOfViewport": false -}; - -//checks if abiword is avaiable -exports.abiwordAvailable = function() -{ - if(exports.abiword != null) - { - return os.type().indexOf("Windows") != -1 ? "withoutPDF" : "yes"; - } - else - { - return "no"; - } -}; - -exports.sofficeAvailable = function () { - if(exports.soffice != null) { - return os.type().indexOf("Windows") != -1 ? "withoutPDF": "yes"; - } else { - return "no"; - } -}; - -exports.exportAvailable = function () { - var abiword = exports.abiwordAvailable(); - var soffice = exports.sofficeAvailable(); - - if(abiword == "no" && soffice == "no") { - return "no"; - } else if ((abiword == "withoutPDF" && soffice == "no") || (abiword == "no" && soffice == "withoutPDF")) { - return "withoutPDF"; - } else { - return "yes"; - } -}; - -// Provide git version if available -exports.getGitCommit = function() { - var version = ""; - try - { - var rootPath = path.resolve(npm.dir, '..'); - if (fs.lstatSync(rootPath + '/.git').isFile()) { - rootPath = fs.readFileSync(rootPath + '/.git', "utf8"); - rootPath = rootPath.split(' ').pop().trim(); - } else { - rootPath += '/.git'; - } - var ref = fs.readFileSync(rootPath + "/HEAD", "utf-8"); - var refPath = rootPath + "/" + ref.substring(5, ref.indexOf("\n")); - version = fs.readFileSync(refPath, "utf-8"); - version = version.substring(0, 7); - } - catch(e) - { - console.warn("Can't get git version for server header\n" + e.message) - } - return version; -} - -// Return etherpad version from package.json -exports.getEpVersion = function() { - return require('ep_etherpad-lite/package.json').version; -} - -exports.reloadSettings = function reloadSettings() { - // Discover where the settings file lives - var settingsFilename = argv.settings || "settings.json"; - - // Discover if a credential file exists - var credentialsFilename = argv.credentials || "credentials.json"; - - if (path.resolve(settingsFilename)===settingsFilename) { - settingsFilename = path.resolve(settingsFilename); - } else { - settingsFilename = path.resolve(path.join(exports.root, settingsFilename)); - } - - if (path.resolve(credentialsFilename)===credentialsFilename) { - credentialsFilename = path.resolve(credentialsFilename); - } - - var settingsStr, credentialsStr; - try{ - //read the settings sync - settingsStr = fs.readFileSync(settingsFilename).toString(); - } catch(e){ - console.warn('No settings file found. Continuing using defaults!'); - } - - try{ - //read the credentials sync - credentialsStr = fs.readFileSync(credentialsFilename).toString(); - } catch(e){ - // Doesn't matter if no credentials file found.. - } - - // try to parse the settings - var settings; - var credentials; - try { - if(settingsStr) { - settingsStr = jsonminify(settingsStr).replace(",]","]").replace(",}","}"); - settings = JSON.parse(settingsStr); - } - }catch(e){ - console.error('There was an error processing your settings.json file: '+e.message); - process.exit(1); - } - - if(credentialsStr) { - credentialsStr = jsonminify(credentialsStr).replace(",]","]").replace(",}","}"); - credentials = JSON.parse(credentialsStr); - } - - //loop trough the settings - for(var i in settings) - { - //test if the setting start with a low character - if(i.charAt(0).search("[a-z]") !== 0) - { - console.warn("Settings should start with a low character: '" + i + "'"); - } - - //we know this setting, so we overwrite it - //or it's a settings hash, specific to a plugin - if(exports[i] !== undefined || i.indexOf('ep_')==0) - { - if (_.isObject(settings[i]) && !_.isArray(settings[i])) { - exports[i] = _.defaults(settings[i], exports[i]); - } else { - exports[i] = settings[i]; - } - } - //this setting is unkown, output a warning and throw it away - else - { - console.warn("Unknown Setting: '" + i + "'. This setting doesn't exist or it was removed"); - } - } - - //loop trough the settings - for(var i in credentials) - { - //test if the setting start with a low character - if(i.charAt(0).search("[a-z]") !== 0) - { - console.warn("Settings should start with a low character: '" + i + "'"); - } - - //we know this setting, so we overwrite it - //or it's a settings hash, specific to a plugin - if(exports[i] !== undefined || i.indexOf('ep_')==0) - { - if (_.isObject(credentials[i]) && !_.isArray(credentials[i])) { - exports[i] = _.defaults(credentials[i], exports[i]); - } else { - exports[i] = credentials[i]; - } - } - //this setting is unkown, output a warning and throw it away - else - { - console.warn("Unknown Setting: '" + i + "'. This setting doesn't exist or it was removed"); - } - } - - log4js.configure(exports.logconfig);//Configure the logging appenders - log4js.setGlobalLogLevel(exports.loglevel);//set loglevel - process.env['DEBUG'] = 'socket.io:' + exports.loglevel; // Used by SocketIO for Debug - log4js.replaceConsole(); - - if(exports.abiword){ - // Check abiword actually exists - if(exports.abiword != null) - { - fs.exists(exports.abiword, function(exists) { - if (!exists) { - var abiwordError = "Abiword does not exist at this path, check your settings file"; - if(!exports.suppressErrorsInPadText){ - exports.defaultPadText = exports.defaultPadText + "\nError: " + abiwordError + suppressDisableMsg; - } - console.error(abiwordError); - exports.abiword = null; - } - }); - } - } - - if(exports.soffice) { - fs.exists(exports.soffice, function (exists) { - if(!exists) { - var sofficeError = "SOffice does not exist at this path, check your settings file"; - - if(!exports.suppressErrorsInPadText) { - exports.defaultPadText = exports.defaultPadText + "\nError: " + sofficeError + suppressDisableMsg; - } - console.error(sofficeError); - exports.soffice = null; - } - }); - } - - if (!exports.sessionKey) { - var sessionkeyFilename = argv.sessionkey || "./SESSIONKEY.txt"; - try { - exports.sessionKey = fs.readFileSync(sessionkeyFilename,"utf8"); - } catch(e) { - exports.sessionKey = randomString(32); - fs.writeFileSync(sessionkeyFilename,exports.sessionKey,"utf8"); - } - } else { - console.warn("Declaring the sessionKey in the settings.json is deprecated. This value is auto-generated now. Please remove the setting from the file."); - } - - if(exports.dbType === "dirty"){ - var dirtyWarning = "DirtyDB is used. This is fine for testing but not recommended for production."; - if(!exports.suppressErrorsInPadText){ - exports.defaultPadText = exports.defaultPadText + "\nWarning: " + dirtyWarning + suppressDisableMsg; - } - console.warn(dirtyWarning); - } -}; - -// initially load settings -exports.reloadSettings(); - - diff --git a/sources/src/node/utils/TidyHtml.js b/sources/src/node/utils/TidyHtml.js deleted file mode 100644 index 5d4e6ed..0000000 --- a/sources/src/node/utils/TidyHtml.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Tidy up the HTML in a given file - */ - -var log4js = require('log4js'); -var settings = require('./Settings'); -var spawn = require('child_process').spawn; - -exports.tidy = function(srcFile, callback) { - var logger = log4js.getLogger('TidyHtml'); - - // Don't do anything if Tidy hasn't been enabled - if (!settings.tidyHtml) { - logger.debug('tidyHtml has not been configured yet, ignoring tidy request'); - return callback(null); - } - - var errMessage = ''; - - // Spawn a new tidy instance that cleans up the file inline - logger.debug('Tidying ' + srcFile); - var tidy = spawn(settings.tidyHtml, ['-modify', srcFile]); - - // Keep track of any error messages - tidy.stderr.on('data', function (data) { - errMessage += data.toString(); - }); - - // Wait until Tidy is done - tidy.on('close', function(code) { - // Tidy returns a 0 when no errors occur and a 1 exit code when - // the file could be tidied but a few warnings were generated - if (code === 0 || code === 1) { - logger.debug('Tidied ' + srcFile + ' successfully'); - return callback(null); - } else { - logger.error('Failed to tidy ' + srcFile + '\n' + errMessage); - return callback('Tidy died with exit code ' + code); - } - }); -}; diff --git a/sources/src/node/utils/caching_middleware.js b/sources/src/node/utils/caching_middleware.js deleted file mode 100644 index 65fe5d2..0000000 --- a/sources/src/node/utils/caching_middleware.js +++ /dev/null @@ -1,181 +0,0 @@ -/* - * 2011 Peter 'Pita' Martischka (Primary Technology Ltd) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var async = require('async'); -var Buffer = require('buffer').Buffer; -var fs = require('fs'); -var path = require('path'); -var zlib = require('zlib'); -var settings = require('./Settings'); -var semver = require('semver'); -var existsSync = require('./path_exists'); - -var CACHE_DIR = path.normalize(path.join(settings.root, 'var/')); -CACHE_DIR = existsSync(CACHE_DIR) ? CACHE_DIR : undefined; - -var responseCache = {}; - -/* - This caches and compresses 200 and 404 responses to GET and HEAD requests. - TODO: Caching and compressing are solved problems, a middleware configuration - should replace this. -*/ - -function CachingMiddleware() { -} -CachingMiddleware.prototype = new function () { - function handle(req, res, next) { - if (!(req.method == "GET" || req.method == "HEAD") || !CACHE_DIR) { - return next(undefined, req, res); - } - - var old_req = {}; - var old_res = {}; - - var supportsGzip = - (req.get('Accept-Encoding') || '').indexOf('gzip') != -1; - - var path = require('url').parse(req.url).path; - var cacheKey = (new Buffer(path)).toString('base64').replace(/[\/\+=]/g, ''); - - fs.stat(CACHE_DIR + 'minified_' + cacheKey, function (error, stats) { - var modifiedSince = (req.headers['if-modified-since'] - && new Date(req.headers['if-modified-since'])); - var lastModifiedCache = !error && stats.mtime; - if (lastModifiedCache && responseCache[cacheKey]) { - req.headers['if-modified-since'] = lastModifiedCache.toUTCString(); - } else { - delete req.headers['if-modified-since']; - } - - // Always issue get to downstream. - old_req.method = req.method; - req.method = 'GET'; - - var expirationDate = new Date(((responseCache[cacheKey] || {}).headers || {})['expires']); - if (expirationDate > new Date()) { - // Our cached version is still valid. - return respond(); - } - - var _headers = {}; - old_res.setHeader = res.setHeader; - res.setHeader = function (key, value) { - // Don't set cookies, see issue #707 - if (key.toLowerCase() === 'set-cookie') return; - - _headers[key.toLowerCase()] = value; - old_res.setHeader.call(res, key, value); - }; - - old_res.writeHead = res.writeHead; - res.writeHead = function (status, headers) { - var lastModified = (res.getHeader('last-modified') - && new Date(res.getHeader('last-modified'))); - - res.writeHead = old_res.writeHead; - if (status == 200) { - // Update cache - var buffer = ''; - - Object.keys(headers || {}).forEach(function (key) { - res.setHeader(key, headers[key]); - }); - headers = _headers; - - old_res.write = res.write; - old_res.end = res.end; - res.write = function(data, encoding) { - buffer += data.toString(encoding); - }; - res.end = function(data, encoding) { - async.parallel([ - function (callback) { - var path = CACHE_DIR + 'minified_' + cacheKey; - fs.writeFile(path, buffer, function (error, stats) { - callback(); - }); - } - , function (callback) { - var path = CACHE_DIR + 'minified_' + cacheKey + '.gz'; - zlib.gzip(buffer, function(error, content) { - if (error) { - callback(); - } else { - fs.writeFile(path, content, function (error, stats) { - callback(); - }); - } - }); - } - ], function () { - responseCache[cacheKey] = {statusCode: status, headers: headers}; - respond(); - }); - }; - } else if (status == 304) { - // Nothing new changed from the cached version. - old_res.write = res.write; - old_res.end = res.end; - res.write = function(data, encoding) {}; - res.end = function(data, encoding) { respond(); }; - } else { - res.writeHead(status, headers); - } - }; - - next(undefined, req, res); - - // This handles read/write synchronization as well as its predecessor, - // which is to say, not at all. - // TODO: Implement locking on write or ditch caching of gzip and use - // existing middlewares. - function respond() { - req.method = old_req.method || req.method; - res.write = old_res.write || res.write; - res.end = old_res.end || res.end; - - var headers = responseCache[cacheKey].headers; - var statusCode = responseCache[cacheKey].statusCode; - - var pathStr = CACHE_DIR + 'minified_' + cacheKey; - if (supportsGzip && (headers['content-type'] || '').match(/^text\//)) { - pathStr = pathStr + '.gz'; - headers['content-encoding'] = 'gzip'; - } - - var lastModified = (headers['last-modified'] - && new Date(headers['last-modified'])); - - if (statusCode == 200 && lastModified <= modifiedSince) { - res.writeHead(304, headers); - res.end(); - } else if (req.method == 'GET') { - var readStream = fs.createReadStream(pathStr); - res.writeHead(statusCode, headers); - readStream.pipe(res); - } else { - res.writeHead(statusCode, headers); - res.end(); - } - } - }); - } - - this.handle = handle; -}(); - -module.exports = CachingMiddleware; diff --git a/sources/src/node/utils/customError.js b/sources/src/node/utils/customError.js deleted file mode 100644 index 5ca7a7a..0000000 --- a/sources/src/node/utils/customError.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - This helper modules allows us to create different type of errors we can throw -*/ -function customError(message, errorName) -{ - this.name = errorName || "Error"; - this.message = message; - - var stackParts = new Error().stack.split("\n"); - stackParts.splice(0,2); - stackParts.unshift(this.name + ": " + message); - - this.stack = stackParts.join("\n"); -} -customError.prototype = Error.prototype; - -module.exports = customError; diff --git a/sources/src/node/utils/padDiff.js b/sources/src/node/utils/padDiff.js deleted file mode 100644 index 24d5bb0..0000000 --- a/sources/src/node/utils/padDiff.js +++ /dev/null @@ -1,546 +0,0 @@ -var Changeset = require("../../static/js/Changeset"); -var async = require("async"); -var exportHtml = require('./ExportHtml'); - -function PadDiff (pad, fromRev, toRev){ - //check parameters - if(!pad || !pad.id || !pad.atext || !pad.pool) - { - throw new Error('Invalid pad'); - } - - var range = pad.getValidRevisionRange(fromRev, toRev); - if(!range) { throw new Error('Invalid revision range.' + - ' startRev: ' + fromRev + - ' endRev: ' + toRev); } - - this._pad = pad; - this._fromRev = range.startRev; - this._toRev = range.endRev; - this._html = null; - this._authors = []; -} - -PadDiff.prototype._isClearAuthorship = function(changeset){ - //unpack - var unpacked = Changeset.unpack(changeset); - - //check if there is nothing in the charBank - if(unpacked.charBank !== "") - return false; - - //check if oldLength == newLength - if(unpacked.oldLen !== unpacked.newLen) - return false; - - //lets iterator over the operators - var iterator = Changeset.opIterator(unpacked.ops); - - //get the first operator, this should be a clear operator - var clearOperator = iterator.next(); - - //check if there is only one operator - if(iterator.hasNext() === true) - return false; - - //check if this operator doesn't change text - if(clearOperator.opcode !== "=") - return false; - - //check that this operator applys to the complete text - //if the text ends with a new line, its exactly one character less, else it has the same length - if(clearOperator.chars !== unpacked.oldLen-1 && clearOperator.chars !== unpacked.oldLen) - return false; - - var attributes = []; - Changeset.eachAttribNumber(changeset, function(attrNum){ - attributes.push(attrNum); - }); - - //check that this changeset uses only one attribute - if(attributes.length !== 1) - return false; - - var appliedAttribute = this._pad.pool.getAttrib(attributes[0]); - - //check if the applied attribute is an anonymous author attribute - if(appliedAttribute[0] !== "author" || appliedAttribute[1] !== "") - return false; - - return true; -}; - -PadDiff.prototype._createClearAuthorship = function(rev, callback){ - var self = this; - this._pad.getInternalRevisionAText(rev, function(err, atext){ - if(err){ - return callback(err); - } - - //build clearAuthorship changeset - var builder = Changeset.builder(atext.text.length); - builder.keepText(atext.text, [['author','']], self._pad.pool); - var changeset = builder.toString(); - - callback(null, changeset); - }); -}; - -PadDiff.prototype._createClearStartAtext = function(rev, callback){ - var self = this; - - //get the atext of this revision - this._pad.getInternalRevisionAText(rev, function(err, atext){ - if(err){ - return callback(err); - } - - //create the clearAuthorship changeset - self._createClearAuthorship(rev, function(err, changeset){ - if(err){ - return callback(err); - } - - try { - //apply the clearAuthorship changeset - var newAText = Changeset.applyToAText(changeset, atext, self._pad.pool); - } catch(err) { - return callback(err) - } - - callback(null, newAText); - }); - }); -}; - -PadDiff.prototype._getChangesetsInBulk = function(startRev, count, callback) { - var self = this; - - //find out which revisions we need - var revisions = []; - for(var i=startRev;i<(startRev+count) && i<=this._pad.head;i++){ - revisions.push(i); - } - - var changesets = [], authors = []; - - //get all needed revisions - async.forEach(revisions, function(rev, callback){ - self._pad.getRevision(rev, function(err, revision){ - if(err){ - return callback(err); - } - - var arrayNum = rev-startRev; - - changesets[arrayNum] = revision.changeset; - authors[arrayNum] = revision.meta.author; - - callback(); - }); - }, function(err){ - callback(err, changesets, authors); - }); -}; - -PadDiff.prototype._addAuthors = function(authors) { - var self = this; - //add to array if not in the array - authors.forEach(function(author){ - if(self._authors.indexOf(author) == -1){ - self._authors.push(author); - } - }); -}; - -PadDiff.prototype._createDiffAtext = function(callback) { - var self = this; - var bulkSize = 100; - - //get the cleaned startAText - self._createClearStartAtext(self._fromRev, function(err, atext){ - if(err) { return callback(err); } - - var superChangeset = null; - - var rev = self._fromRev + 1; - - //async while loop - async.whilst( - //loop condition - function () { return rev <= self._toRev; }, - - //loop body - function (callback) { - //get the bulk - self._getChangesetsInBulk(rev,bulkSize,function(err, changesets, authors){ - var addedAuthors = []; - - //run trough all changesets - for(var i=0;i= curChar) { - curLineNextOp.chars -= (curChar - indexIntoLine); - done = true; - } else { - indexIntoLine += curLineNextOp.chars; - } - } - } - - while (numChars > 0) { - if ((!curLineNextOp.chars) && (!curLineOpIter.hasNext())) { - curLine++; - curChar = 0; - curLineOpIterLine = curLine; - curLineNextOp.chars = 0; - curLineOpIter = Changeset.opIterator(alines_get(curLine)); - } - if (!curLineNextOp.chars) { - curLineOpIter.next(curLineNextOp); - } - var charsToUse = Math.min(numChars, curLineNextOp.chars); - func(charsToUse, curLineNextOp.attribs, charsToUse == curLineNextOp.chars && curLineNextOp.lines > 0); - numChars -= charsToUse; - curLineNextOp.chars -= charsToUse; - curChar += charsToUse; - } - - if ((!curLineNextOp.chars) && (!curLineOpIter.hasNext())) { - curLine++; - curChar = 0; - } - } - - function skip(N, L) { - if (L) { - curLine += L; - curChar = 0; - } else { - if (curLineOpIter && curLineOpIterLine == curLine) { - consumeAttribRuns(N, function () {}); - } else { - curChar += N; - } - } - } - - function nextText(numChars) { - var len = 0; - var assem = Changeset.stringAssembler(); - var firstString = lines_get(curLine).substring(curChar); - len += firstString.length; - assem.append(firstString); - - var lineNum = curLine + 1; - while (len < numChars) { - var nextString = lines_get(lineNum); - len += nextString.length; - assem.append(nextString); - lineNum++; - } - - return assem.toString().substring(0, numChars); - } - - function cachedStrFunc(func) { - var cache = {}; - return function (s) { - if (!cache[s]) { - cache[s] = func(s); - } - return cache[s]; - }; - } - - var attribKeys = []; - var attribValues = []; - - //iterate over all operators of this changeset - while (csIter.hasNext()) { - var csOp = csIter.next(); - - if (csOp.opcode == '=') { - var textBank = nextText(csOp.chars); - - // decide if this equal operator is an attribution change or not. We can see this by checkinf if attribs is set. - // If the text this operator applies to is only a star, than this is a false positive and should be ignored - if (csOp.attribs && textBank != "*") { - var deletedAttrib = apool.putAttrib(["removed", true]); - var authorAttrib = apool.putAttrib(["author", ""]); - - attribKeys.length = 0; - attribValues.length = 0; - Changeset.eachAttribNumber(csOp.attribs, function (n) { - attribKeys.push(apool.getAttribKey(n)); - attribValues.push(apool.getAttribValue(n)); - - if(apool.getAttribKey(n) === "author"){ - authorAttrib = n; - } - }); - - var undoBackToAttribs = cachedStrFunc(function (attribs) { - var backAttribs = []; - for (var i = 0; i < attribKeys.length; i++) { - var appliedKey = attribKeys[i]; - var appliedValue = attribValues[i]; - var oldValue = Changeset.attribsAttributeValue(attribs, appliedKey, apool); - if (appliedValue != oldValue) { - backAttribs.push([appliedKey, oldValue]); - } - } - return Changeset.makeAttribsString('=', backAttribs, apool); - }); - - var oldAttribsAddition = "*" + Changeset.numToString(deletedAttrib) + "*" + Changeset.numToString(authorAttrib); - - var textLeftToProcess = textBank; - - while(textLeftToProcess.length > 0){ - //process till the next line break or process only one line break - var lengthToProcess = textLeftToProcess.indexOf("\n"); - var lineBreak = false; - switch(lengthToProcess){ - case -1: - lengthToProcess=textLeftToProcess.length; - break; - case 0: - lineBreak = true; - lengthToProcess=1; - break; - } - - //get the text we want to procceed in this step - var processText = textLeftToProcess.substr(0, lengthToProcess); - textLeftToProcess = textLeftToProcess.substr(lengthToProcess); - - if(lineBreak){ - builder.keep(1, 1); //just skip linebreaks, don't do a insert + keep for a linebreak - - //consume the attributes of this linebreak - consumeAttribRuns(1, function(){}); - } else { - //add the old text via an insert, but add a deletion attribute + the author attribute of the author who deleted it - var textBankIndex = 0; - consumeAttribRuns(lengthToProcess, function (len, attribs, endsLine) { - //get the old attributes back - var attribs = (undoBackToAttribs(attribs) || "") + oldAttribsAddition; - - builder.insert(processText.substr(textBankIndex, len), attribs); - textBankIndex += len; - }); - - builder.keep(lengthToProcess, 0); - } - } - } else { - skip(csOp.chars, csOp.lines); - builder.keep(csOp.chars, csOp.lines); - } - } else if (csOp.opcode == '+') { - builder.keep(csOp.chars, csOp.lines); - } else if (csOp.opcode == '-') { - var textBank = nextText(csOp.chars); - var textBankIndex = 0; - - consumeAttribRuns(csOp.chars, function (len, attribs, endsLine) { - builder.insert(textBank.substr(textBankIndex, len), attribs + csOp.attribs); - textBankIndex += len; - }); - } - } - - return Changeset.checkRep(builder.toString()); -}; - -//export the constructor -module.exports = PadDiff; diff --git a/sources/src/node/utils/path_exists.js b/sources/src/node/utils/path_exists.js deleted file mode 100644 index c2d43f6..0000000 --- a/sources/src/node/utils/path_exists.js +++ /dev/null @@ -1,15 +0,0 @@ -var fs = require('fs'); - -var check = function(path) { - var existsSync = fs.statSync || fs.existsSync || path.existsSync; - - var result; - try { - result = existsSync(path); - } catch (e) { - result = false; - } - return result; -} - -module.exports = check; diff --git a/sources/src/node/utils/randomstring.js b/sources/src/node/utils/randomstring.js deleted file mode 100644 index 3815c66..0000000 --- a/sources/src/node/utils/randomstring.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Generates a random String with the given length. Is needed to generate the Author, Group, readonly, session Ids - */ -var crypto = require('crypto'); - -var randomString = function(len) -{ - return crypto.randomBytes(len).toString('hex') -}; - -module.exports = randomString; diff --git a/sources/src/node/utils/tar.json b/sources/src/node/utils/tar.json deleted file mode 100644 index 05d764a..0000000 --- a/sources/src/node/utils/tar.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "pad.js": [ - "pad.js" - , "pad_utils.js" - , "browser.js" - , "pad_cookie.js" - , "pad_editor.js" - , "pad_editbar.js" - , "pad_docbar.js" - , "pad_modals.js" - , "ace.js" - , "collab_client.js" - , "pad_userlist.js" - , "pad_impexp.js" - , "pad_savedrevs.js" - , "pad_connectionstatus.js" - , "chat.js" - , "gritter.js" - , "$tinycon/tinycon.js" - , "excanvas.js" - , "farbtastic.js" - ] -, "timeslider.js": [ - "timeslider.js" - , "colorutils.js" - , "draggable.js" - , "pad_utils.js" - , "browser.js" - , "pad_cookie.js" - , "pad_editor.js" - , "pad_editbar.js" - , "pad_docbar.js" - , "pad_modals.js" - , "pad_savedrevs.js" - , "pad_impexp.js" - , "AttributePool.js" - , "Changeset.js" - , "domline.js" - , "linestylefilter.js" - , "cssmanager.js" - , "broadcast.js" - , "broadcast_slider.js" - , "broadcast_revisions.js" - ] -, "ace2_inner.js": [ - "ace2_inner.js" - , "browser.js" - , "AttributePool.js" - , "Changeset.js" - , "ChangesetUtils.js" - , "skiplist.js" - , "cssmanager.js" - , "colorutils.js" - , "undomodule.js" - , "$unorm.js" - , "contentcollector.js" - , "changesettracker.js" - , "linestylefilter.js" - , "domline.js" - , "AttributeManager.js" - ] -, "ace2_common.js": [ - "ace2_common.js" - , "browser.js" - , "jquery.js" - , "rjquery.js" - , "$async.js" - , "$async/lib/async.js" - , "underscore.js" - , "$underscore.js" - , "$underscore/underscore.js" - , "security.js" - , "$security.js" - , "json2.js" - , "pluginfw/client_plugins.js" - , "pluginfw/shared.js" - , "pluginfw/hooks.js" - ] -} diff --git a/sources/src/node/utils/toolbar.js b/sources/src/node/utils/toolbar.js deleted file mode 100644 index eaa1d42..0000000 --- a/sources/src/node/utils/toolbar.js +++ /dev/null @@ -1,265 +0,0 @@ -/** - * The Toolbar Module creates and renders the toolbars and buttons - */ -var _ = require("underscore") - , tagAttributes - , tag - , Button - , ButtonsGroup - , Separator - , defaultButtonAttributes - , removeItem; - -removeItem = function(array,what) { - var ax; - while ((ax = array.indexOf(what)) !== -1) { - array.splice(ax, 1); - } - return array; -}; - -defaultButtonAttributes = function (name, overrides) { - return { - command: name, - localizationId: "pad.toolbar." + name + ".title", - class: "buttonicon buttonicon-" + name - }; -}; - -tag = function (name, attributes, contents) { - var aStr = tagAttributes(attributes); - - if (_.isString(contents) && contents.length > 0) { - return '<' + name + aStr + '>' + contents + ''; - } - else { - return '<' + name + aStr + '>'; - } -}; - -tagAttributes = function (attributes) { - attributes = _.reduce(attributes || {}, function (o, val, name) { - if (!_.isUndefined(val)) { - o[name] = val; - } - return o; - }, {}); - - return " " + _.map(attributes, function (val, name) { - return "" + name + '="' + _.escape(val) + '"'; - }).join(" "); -}; - -ButtonsGroup = function () { - this.buttons = []; -}; - -ButtonsGroup.fromArray = function (array) { - var btnGroup = new this; - _.each(array, function (btnName) { - btnGroup.addButton(Button.load(btnName)); - }); - return btnGroup; -}; - -ButtonsGroup.prototype.addButton = function (button) { - this.buttons.push(button); - return this; -}; - -ButtonsGroup.prototype.render = function () { - if (this.buttons.length == 1) { - this.buttons[0].grouping = ""; - } - else { - _.first(this.buttons).grouping = "grouped-left"; - _.last(this.buttons).grouping = "grouped-right"; - _.each(this.buttons.slice(1, -1), function (btn) { - btn.grouping = "grouped-middle" - }); - } - - return _.map(this.buttons, function (btn) { - return btn.render(); - }).join("\n"); -}; - -Button = function (attributes) { - this.attributes = attributes; -}; - -Button.load = function (btnName) { - var button = module.exports.availableButtons[btnName]; - if (button.constructor === Button || button.constructor === SelectButton) { - return button; - } - else { - return new Button(button); - } -}; - -_.extend(Button.prototype, { - grouping: "", - - render: function () { - var liAttributes = { - "data-type": "button", - "data-key": this.attributes.command, - }; - return tag("li", liAttributes, - tag("a", { "class": this.grouping, "data-l10n-id": this.attributes.localizationId }, - tag("button", { "class": " "+ this.attributes.class, "data-l10n-id": this.attributes.localizationId }) - ) - ); - } -}); - - - -SelectButton = function (attributes) { - this.attributes = attributes; - this.options = []; -}; - -_.extend(SelectButton.prototype, Button.prototype, { - addOption: function (value, text, attributes) { - this.options.push({ - value: value, - text: text, - attributes: attributes - }); - return this; - }, - - select: function (attributes) { - var options = []; - - _.each(this.options, function (opt) { - var a = _.extend({ - value: opt.value - }, opt.attributes); - - options.push( tag("option", a, opt.text) ); - }); - return tag("select", attributes, options.join("")); - }, - - render: function () { - var attributes = { - id: this.attributes.id, - "data-key": this.attributes.command, - "data-type": "select" - }; - return tag("li", attributes, - this.select({ id: this.attributes.selectId }) - ); - } -}); - -Separator = function () {}; -Separator.prototype.render = function () { - return tag("li", { "class": "separator" }); -}; - -module.exports = { - availableButtons: { - bold: defaultButtonAttributes("bold"), - italic: defaultButtonAttributes("italic"), - underline: defaultButtonAttributes("underline"), - strikethrough: defaultButtonAttributes("strikethrough"), - - orderedlist: { - command: "insertorderedlist", - localizationId: "pad.toolbar.ol.title", - class: "buttonicon buttonicon-insertorderedlist" - }, - - unorderedlist: { - command: "insertunorderedlist", - localizationId: "pad.toolbar.ul.title", - class: "buttonicon buttonicon-insertunorderedlist" - }, - - indent: defaultButtonAttributes("indent"), - outdent: { - command: "outdent", - localizationId: "pad.toolbar.unindent.title", - class: "buttonicon buttonicon-outdent" - }, - - undo: defaultButtonAttributes("undo"), - redo: defaultButtonAttributes("redo"), - - clearauthorship: { - command: "clearauthorship", - localizationId: "pad.toolbar.clearAuthorship.title", - class: "buttonicon buttonicon-clearauthorship" - }, - - importexport: { - command: "import_export", - localizationId: "pad.toolbar.import_export.title", - class: "buttonicon buttonicon-import_export" - }, - - timeslider: { - command: "showTimeSlider", - localizationId: "pad.toolbar.timeslider.title", - class: "buttonicon buttonicon-history" - }, - - savedrevision: defaultButtonAttributes("savedRevision"), - settings: defaultButtonAttributes("settings"), - embed: defaultButtonAttributes("embed"), - showusers: defaultButtonAttributes("showusers"), - - timeslider_export: { - command: "import_export", - localizationId: "timeslider.toolbar.exportlink.title", - class: "buttonicon buttonicon-import_export" - }, - - timeslider_settings: { - command: "settings", - localizationId: "pad.toolbar.settings.title", - class: "buttonicon buttonicon-settings" - }, - - timeslider_returnToPad: { - command: "timeslider_returnToPad", - localizationId: "timeslider.toolbar.returnbutton", - class: "buttontext" - } - }, - - registerButton: function (buttonName, buttonInfo) { - this.availableButtons[buttonName] = buttonInfo; - }, - - button: function (attributes) { - return new Button(attributes); - }, - separator: function () { - return (new Separator).render(); - }, - selectButton: function (attributes) { - return new SelectButton(attributes); - }, - menu: function (buttons, isReadOnly) { - if(isReadOnly){ - // The best way to detect if it's the left editbar is to check for a bold button - if(buttons[0].indexOf("bold") !== -1){ - // Clear all formatting buttons - buttons = [] - }else{ - // Remove Save Revision from the right menu - removeItem(buttons[0],"savedrevision"); - } - } - - var groups = _.map(buttons, function (group) { - return ButtonsGroup.fromArray(group).render(); - }); - return groups.join(this.separator()); - } -}; diff --git a/sources/src/package.json b/sources/src/package.json deleted file mode 100644 index cb243cc..0000000 --- a/sources/src/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name" : "ep_etherpad-lite", - "description" : "A Etherpad based on node.js", - "homepage" : "http://etherpad.org", - "keywords" : ["etherpad", "realtime", "collaborative", "editor"], - "author" : "Etherpad Foundation", - "contributors" : [ - { "name": "John McLear" }, - { "name": "Hans Pinckaers" }, - { "name": "Robin Buse" }, - { "name": "Marcel Klehr" }, - { "name": "Peter Martischka" } - ], - "dependencies" : { - "etherpad-yajsml" : "0.0.2", - "request" : "2.83.0", - "etherpad-require-kernel" : "1.0.9", - "resolve" : "1.1.7", - "socket.io" : "1.7.3", - "ueberdb2" : "0.3.8", - "express" : "4.13.4", - "express-session" : "1.13.0", - "cookie-parser" : "1.3.4", - "async" : "0.9.0", - "clean-css" : "3.4.19", - "uglify-js" : "2.6.2", - "formidable" : "1.2.1", - "log4js" : "0.6.35", - "cheerio" : "0.20.0", - "async-stacktrace" : "0.0.2", - "npm" : ">=4.0.2", - "ejs" : "2.5.7", - "graceful-fs" : "4.1.3", - "slide" : "1.1.6", - "semver" : "5.1.0", - "security" : "1.0.0", - "tinycon" : "0.0.1", - "underscore" : "1.8.3", - "unorm" : "1.4.1", - "languages4translatewiki" : "0.1.3", - "swagger-node-express" : "2.1.3", - "channels" : "0.0.4", - "jsonminify" : "0.4.1", - "measured" : "1.1.0", - "mocha" : "5.0.5", - "supertest" : "3.0.0" - }, - "bin": { "etherpad-lite": "./node/server.js" }, - "devDependencies": { - "wd" : "1.6.1" - }, - "engines" : { "node" : ">=0.10.0", - "npm" : ">=1.0" - }, - "repository" : { "type" : "git", - "url" : "http://github.com/ether/etherpad-lite.git" - }, - "version" : "1.6.6", - "license" : "Apache-2.0" -} diff --git a/sources/src/static/css/admin.css b/sources/src/static/css/admin.css deleted file mode 100644 index e9ba601..0000000 --- a/sources/src/static/css/admin.css +++ /dev/null @@ -1,287 +0,0 @@ -html, body { - height: 100%; - box-sizing: border-box; -} - -body { - margin: 0; - color: #333; - font: 14px helvetica, sans-serif; - background: #eee; -} - -div.menu { - height: 100%; - padding: 15px; - width: 220px; - border-right: 1px solid #ccc; - position: fixed; -} - -div.menu ul { - padding: 0; -} - -div.menu li { - list-style: none; - margin-left: 3px; - line-height: 3; - border-top: 1px solid #ccc; -} - -div.menu li:last-child { - border-bottom: 1px solid #ccc; -} - -div.innerwrapper { - padding: 15px; - padding-left: 265px; -} - -div.innerwrapper-err { - padding: 15px; - padding-left: 265px; - display: none; -} - -#wrapper { - background: none repeat scroll 0px 0px #FFFFFF; - box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.2); - margin: auto; - max-width: 1150px; - min-height: 101%;/*always display a scrollbar*/ -} - -h1 { - font-size: 29px; -} - -h2 { - font-size: 24px; -} - -.separator { - margin: 10px 0; - height: 1px; - background: #aaa; - background: -webkit-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff); - background: -moz-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff); - background: -ms-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff); - background: -o-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff); -} - -form { - margin-bottom: 0; -} - -#inner { - width: 300px; - margin: 0 auto; -} - -input { - font-weight: bold; - font-size: 15px; -} - -input[type="button"] { - padding: 4px 6px; - margin: 0; -} - -table input[type="button"] { - float: right; - width: 100px; -} - -input[type="text"] { - border-radius: 3px; - box-sizing: border-box; - -moz-box-sizing: border-box; - padding: 10px; - *padding: 0; - /* IE7 hack */ - width: 100%; - outline: none; - border: 1px solid #ddd; - margin: 0 0 5px 0; - max-width: 500px; -} - -.sort { - cursor: pointer; -} -.sort:after { - content: '▲▼' -} -.sort.up:after { - content:'▲' -} -.sort.down:after { - content:'▼' -} - -table { - border: 1px solid #ddd; - border-radius: 3px; - border-spacing: 0; - width: 100%; - margin: 20px 0; - position:relative; /* Allows us to position the loading indicator relative to the table */ -} - -table thead tr { - background: #eee; -} - -td, th { - padding: 5px; -} - -.template { - display: none; -} - -#installed-plugins td>div { - position: relative;/* Allows us to position the loading indicator relative to this row */ - display: inline-block; /*make this fill the whole cell*/ - width:100%; -} - -.messages { - height: 5em; -} -.messages * { - display: none; - text-align: center; -} -.messages .fetching { - display: block; -} - -.progress { - position: absolute; - top: 0; left: 0; bottom:0; right:0; - padding: auto; - - background: rgb(255,255,255); - display: none; -} - -#search-progress.progress { - padding-top: 20%; - background: rgba(255,255,255,0.3); -} - -.progress * { - display: block; - margin: 0 auto; - text-align: center; - color: #666; -} - -.settings { - outline: none; - width: 100%; - min-height: 500px; -} - -#response { - display: inline; -} - -a:link, a:visited, a:hover, a:focus { - color: #333333; - text-decoration: none; -} - -a:focus, a:hover { - text-decoration: underline; -} - -.installed-results a:link, -.search-results a:link, -.installed-results a:visited, -.search-results a:visited, -.installed-results a:hover, -.search-results a:hover, -.installed-results a:focus, -.search-results a:focus { - text-decoration: underline; -} - -.installed-results a:focus, -.search-results a:focus, -.installed-results a:hover, -.search-results a:hover { - text-decoration: none; -} - -pre { - white-space: pre-wrap; - word-wrap: break-word; -} - -@media (max-width: 720px) { - div.innerwrapper { - padding: 0 15px 15px 15px; - } - - div.menu { - padding: 1px 15px 0 15px; - position: static; - height: auto; - border-right: none; - width: auto; - } - - table { - border: none; - } - - table, thead, tbody, td, tr { - display: block; - } - - thead tr { - display: none; - } - - tr { - border: 1px solid #ccc; - margin-bottom: 5px; - border-radius: 3px; - } - - td { - border: none; - border-bottom: 1px solid #eee; - position: relative; - padding-left: 50%; - white-space: normal; - text-align: left; - } - - td.name { - word-wrap: break-word; - } - - td:before { - position: absolute; - top: 6px; - left: 6px; - text-align: left; - padding-right: 10px; - white-space: nowrap; - font-weight: bold; - content: attr(data-label); - } - - td:last-child { - border-bottom: none; - } - - table input[type="button"] { - float: none; - } -} \ No newline at end of file diff --git a/sources/src/static/css/iframe_editor.css b/sources/src/static/css/iframe_editor.css deleted file mode 100644 index 9aa003a..0000000 --- a/sources/src/static/css/iframe_editor.css +++ /dev/null @@ -1,152 +0,0 @@ -/* These CSS rules are included in both the outer and inner ACE iframe. - Also see inner.css, included only in the inner one. -*/ - -@import url('./lists_and_indents.css'); - -html { cursor: text; } /* in Safari, produces text cursor for whole doc (inc. below body) */ -span { cursor: auto; } - -::selection { - background: #acf; -} -::-moz-selection { - background: #acf; -} - -a { - cursor: pointer !important; - white-space:pre-wrap; -} - -body { - margin: 0; - white-space: nowrap; - word-wrap: normal; -} - -#outerdocbody { - background-color: #fff; -} -body.grayedout { background-color: #eee !important } - -#innerdocbody { - font-size: 12px; /* overridden by body.style */ - font-family:Arial, sans-serif; /* overridden by body.style */ - line-height: 16px; /* overridden by body.style */ - background-color: white; - color: black; -} - -body.doesWrap { - /* white-space: pre-wrap; */ - - /* - Must be pre-wrap to keep trailing spaces. Otherwise you get a zombie caret, - walking around your screen (see #1766). - WARNING: Enabling this causes Paste as plain text in Chrome to remove line breaks - this is probably undesirable - WARNING: This causes copy & paste events to lose bold etc. attributes - NOTE: The walking-zombie caret issue seems to have been fixed in FF upstream - so let's try diabling pre-wrap and see how we get on now. - For more details see: https://github.com/ether/etherpad-lite/issues/2574 - */ - word-wrap: break-word; /* fix for issue #1648 - firefox not wrapping long lines (without spaces) correctly */ -} - -.noprewrap{ - white-space: normal; -} - -body.doesWrap:not(.noprewrap) > div{ - /* Related to #1766 */ - white-space: pre-wrap; -} - -#innerdocbody { - padding-top: 1px; /* important for some reason? */ - padding-right: 10px; - padding-bottom: 8px; - padding-left: 1px /* prevents characters from looking chopped off in FF3 -- Removed because it added too much whitespace */; - overflow: hidden; - /* blank 1x1 gif, so that IE8 doesn't consider the body transparent */ - background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==); -} - -#sidediv { - font-size: 11px; - font-family: monospace; - line-height: 16px; /* overridden by sideDiv.style */ - padding-top: 8px; /* EDIT_BODY_PADDING_TOP */ - padding-right: 3px; /* LINE_NUMBER_PADDING_RIGHT - 1 */ - position: absolute; - width: 20px; /* MIN_LINEDIV_WIDTH */ - top: 0; - left: 0; - cursor: default; - color: white; -} - -#sidedivinner { - text-align: right; -} - -.sidedivdelayed { /* class set after sizes are set */ - background-color: #eee; - color: #888 !important; - border-right: 1px solid #ccc; -} -.sidedivhidden { - display: none; -} - -#outerdocbody iframe { - display: block; /* codemirror says it suppresses bugs */ - position: relative; - left: 32px; /* MIN_LINEDIV_WIDTH + LINE_NUMBER_PADDING_RIGHT + EDIT_BODY_PADDING_LEFT */ - top: 7px; /* EDIT_BODY_PADDING_TOP - 1*/ - border: 0; - width: 1px; /* changed programmatically */ - height: 1px; /* changed programmatically */ -} - -#outerdocbody .hotrect { - border: 1px solid #999; - position: absolute; -} - -/* cause "body" area (e.g. where clicks are heard) to grow horizontally with text */ -body.mozilla, body.safari { - display: table-cell; -} - -body.doesWrap { - display: block !important; -} - -.safari div { - /* prevents the caret from disappearing on the longest line of the doc */ - padding-right: 1px; -} - -p { - margin: 0; -} - -#linemetricsdiv { - position: absolute; - left: -1000px; - top: -1000px; - color: white; - z-index: -1; - font-size: 12px; /* overridden by lineMetricsDiv.style */ - font-family: monospace; /* overridden by lineMetricsDiv.style */ -} - -/* Stops super long lines without being spaces such as aaaaaaaaaaaaaa*100 breaking the editor - Commented out because it stops IE from being able to render the document, crazy IE bug is crazy. */ -/* -.ace-line{ - overflow:hidden; -} -*/ diff --git a/sources/src/static/css/lists_and_indents.css b/sources/src/static/css/lists_and_indents.css deleted file mode 100644 index c6348ef..0000000 --- a/sources/src/static/css/lists_and_indents.css +++ /dev/null @@ -1,195 +0,0 @@ -/* - * These are the common definitions for the styling of bulleted lists, numbered - * lists, and plain indented blocks, shared by the editor and timeslider pages. - */ - -ul, ol, li { - padding: 0; - margin: 0; -} - -ul { margin-left: 1.5em; } -ul ul { margin-left: 0 !important; } -ul.list-bullet1 { margin-left: 1.5em; } -ul.list-bullet2 { margin-left: 3em; } -ul.list-bullet3 { margin-left: 4.5em; } -ul.list-bullet4 { margin-left: 6em; } -ul.list-bullet5 { margin-left: 7.5em; } -ul.list-bullet6 { margin-left: 9em; } -ul.list-bullet7 { margin-left: 10.5em; } -ul.list-bullet8 { margin-left: 12em; } -ul.list-bullet9 { margin-left: 13.5em; } -ul.list-bullet10 { margin-left: 15em; } -ul.list-bullet11 { margin-left: 16.5em; } -ul.list-bullet12 { margin-left: 18em; } -ul.list-bullet13 { margin-left: 19.5em; } -ul.list-bullet14 { margin-left: 21em; } -ul.list-bullet15 { margin-left: 22.5em; } -ul.list-bullet16 { margin-left: 24em; } - -ul { list-style-type: disc; } -ul.list-bullet1 { list-style-type: disc; } -ul.list-bullet2 { list-style-type: circle; } -ul.list-bullet3 { list-style-type: square; } -ul.list-bullet4 { list-style-type: disc; } -ul.list-bullet5 { list-style-type: circle; } -ul.list-bullet6 { list-style-type: square; } -ul.list-bullet7 { list-style-type: disc; } -ul.list-bullet8 { list-style-type: circle; } -ul.list-bullet9 { list-style-type: disc; } -ul.list-bullet10 { list-style-type: circle; } -ul.list-bullet11 { list-style-type: square; } -ul.list-bullet12 { list-style-type: disc; } -ul.list-bullet13 { list-style-type: circle; } -ul.list-bullet14 { list-style-type: square; } -ul.list-bullet15 { list-style-type: disc; } -ul.list-bullet16 { list-style-type: circle; } - -ul.list-indent1 { margin-left: 1.5em; } -ul.list-indent2 { margin-left: 3em; } -ul.list-indent3 { margin-left: 4.5em; } -ul.list-indent4 { margin-left: 6em; } -ul.list-indent5 { margin-left: 7.5em; } -ul.list-indent6 { margin-left: 9em; } -ul.list-indent7 { margin-left: 10.5em; } -ul.list-indent8 { margin-left: 12em; } -ul.list-indent9 { margin-left: 13.5em; } -ul.list-indent10 { margin-left: 15em; } -ul.list-indent11 { margin-left: 16.5em; } -ul.list-indent12 { margin-left: 18em; } -ul.list-indent13 { margin-left: 19.5em; } -ul.list-indent14 { margin-left: 21em; } -ul.list-indent15 { margin-left: 22.5em; } -ul.list-indent16 { margin-left: 24em; } - -ul.list-indent1, ul.list-indent2, ul.list-indent3, ul.list-indent4, ul.list-indent5, -ul.list-indent6, ul.list-indent7, ul.list-indent8, ul.list-indent9, ul.list-indent10, -ul.list-indent11, ul.list-indent12, ul.list-indent13, -ul.list-indent14, ul.list-indent15, ul.list-indent16 { list-style-type: none; } - -ol { - list-style-type: decimal; -} - -/* Fixes #2223 and #1836 */ -ol > li { - display:block; -} - -/* Set the indentation */ -ol.list-number1{ text-indent: 0px; } -ol.list-number2{ text-indent: 10px; } -ol.list-number3{ text-indent: 20px; } -ol.list-number4{ text-indent: 30px; } -ol.list-number5{ text-indent: 40px; } -ol.list-number6{ text-indent: 50px; } -ol.list-number7{ text-indent: 60px; } -ol.list-number8{ text-indent: 70px; } -ol.list-number9{ text-indent: 80px; } -ol.list-number10{ text-indent: 90px; } -ol.list-number11{ text-indent: 100px; } -ol.list-number12{ text-indent: 110px; } -ol.list-number13{ text-indent: 120px; } -ol.list-number14{ text-indent: 130px; } -ol.list-number15{ text-indent: 140px; } -ol.list-number16{ text-indent: 150px; } - -/* Add styling to the first item in a list */ - -.list-start-number1 { counter-reset: first second; } -.list-start-number2 { counter-reset: second; } -.list-start-number3 { counter-reset: third; } -.list-start-number4 { counter-reset: fourth; } -.list-start-number5 { counter-reset: fifth; } -.list-start-number6 { counter-reset: sixth; } -.list-start-number7 { counter-reset: seventh; } -.list-start-number8 { counter-reset: eighth; } -.list-start-number9 { counter-reset: ninth; } -.list-start-number10 { counter-reset: tenth; } -.list-start-number11 { counter-reset: eleventh; } -.list-start-number12 { counter-reset: twelfth; } -.list-start-number13 { counter-reset: thirteenth; } -.list-start-number14 { counter-reset: fourteenth; } -.list-start-number15 { counter-reset: fifteenth; } -.list-start-number16 { counter-reset: sixteenth; } - -/* The behavior for incrementing and the prefix */ -.list-number1 li:before { - content: counter(first) ". " ; - counter-increment: first; -} - -.list-number2 li:before { - content: counter(first) "." counter(second) ". "; - counter-increment: second; -} - -.list-number3 li:before { - content: counter(first) "." counter(second) "." counter(third) ". "; - counter-increment: third 1; -} - -.list-number4 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) ". "; - counter-increment: fourth 1; -} - -.list-number5 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) ". "; - counter-increment: fifth 1; -} - -.list-number6 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) ". "; - counter-increment: sixth 1; -} - -.list-number7 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) ". "; - counter-increment: seventh 1; -} - -.list-number8 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) ". " ; - counter-increment: eighth 1; -} - -.list-number9 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) ". "; - counter-increment: ninth 1; -} - -.list-number10 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) "." counter(tenth) ". "; - counter-increment: tenth 1; -} - -.list-number11 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) ". "; - counter-increment: eleventh 1; -} - -.list-number12 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelfth) ". "; - counter-increment: twelfth 1; -} - -.list-number13 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelfth) "." counter(thirteenth) ". "; - counter-increment: thirteenth 1; -} - -.list-number14 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelfth) "." counter(thirteenth) "." counter(fourteenth) ". "; - counter-increment: fourteenth 1; -} - -.list-number15 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelfth) "." counter(thirteenth) "." counter(fourteenth) "." counter(fifteenth) ". "; - counter-increment: fifteenth 1; -} - -.list-number16 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelfth) "." counter(thirteenth) "." counter(fourteenth) "." counter(fifteenth) "." counter(sixteenth) ". "; - counter-increment: sixteenth 1; -} diff --git a/sources/src/static/css/pad.css b/sources/src/static/css/pad.css deleted file mode 100644 index 484e6f2..0000000 --- a/sources/src/static/css/pad.css +++ /dev/null @@ -1,1354 +0,0 @@ -*, -html, -body, -p { - margin: 0; - padding: 0px; -} - -.clear { - clear: both -} -html { - font-size: 62.5%; - width: 100%; -} -body, -textarea { - font-family: Helvetica, Arial, sans-serif -} -iframe { - position: absolute -} -.readonly .acl-write { - display: none; -} - -#users { - background: #f7f7f7; - background: -webkit-linear-gradient( #F7F7F7,#EEE); - background: -moz-linear-gradient( #F7F7F7,#EEE); - background: -ms-linear-gradient( #F7F7F7,#EEE); - background: -o-linear-gradient( #F7F7F7,#EEE); - background: linear-gradient( #F7F7F7,#EEE); - width: 160px; - color: #fff; - padding: 5px; - border-radius: 0 0 6px 6px; - border: 1px solid #ccc; -} -#otherusers { - max-height: 400px; - overflow: auto; -} -a img { - border: 0 -} -/* menu */ -.toolbar { - background: #f7f7f7; - background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: linear-gradient(#f7f7f7, #f1f1f1 80%); - border-bottom: 1px solid #ccc; - overflow: hidden; - padding-top: 4px; - width: 100%; - white-space: nowrap; - height: 32px; -} -.toolbar ul { - position: absolute; - list-style: none; - padding-right: 3px; - padding-left: 1px; - z-index: 2; - overflow: hidden; - float: left -} -.toolbar ul li { - float: left; - margin-left: 2px; - height:32px; -} -.toolbar ul li.separator { - border: inherit; - background: inherit; - visibility: hidden; - width: 0px; - padding: 5px; - height:22px; -} -.toolbar ul li a:hover { - text-decoration: none; -} -.toolbar ul li a:hover { - background: #fff; - background: -webkit-linear-gradient(#f4f4f4, #e4e4e4); - background: -moz-linear-gradient(#f4f4f4, #e4e4e4); - background: -o-linear-gradient(#f4f4f4, #e4e4e4); - background: -ms-linear-gradient(#f4f4f4, #e4e4e4); - background: linear-gradient(#f4f4f4, #e4e4e4); -} -.toolbar ul li a:active { - background: #eee; - background: -webkit-linear-gradient(#ddd, #fff); - background: -moz-linear-gradient(#ddd, #fff); - background: -o-linear-gradient(#ddd, #fff); - background: -ms-linear-gradient(#ddd, #fff); - background: linear-gradient(#ddd, #fff); - -webkit-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - -moz-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - box-shadow: 0 0 8px rgba(0,0,0,.1) inset; -} -.toolbar ul li .activeButton { - background: #eee; - background: -webkit-linear-gradient(#ddd, #fff); - background: -moz-linear-gradient(#ddd, #fff); - background: -o-linear-gradient(#ddd, #fff); - background: -ms-linear-gradient(#ddd, #fff); - background: linear-gradient(#ddd, #fff); - -webkit-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - -moz-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - box-shadow: 0 0 8px rgba(0,0,0,.1) inset; -} -.toolbar ul li a { - background: #fff; - background: -webkit-linear-gradient(#fff, #f0f0f0); - background: -moz-linear-gradient(#fff, #f0f0f0); - background: -o-linear-gradient(#fff, #f0f0f0); - background: -ms-linear-gradient(#fff, #f0f0f0); - background: linear-gradient(#fff, #f0f0f0); - border: 1px solid #ccc; - border-radius: 3px; - color: #ccc; - cursor: pointer; - display: inline-block; - min-height: 18px; - overflow: hidden; - padding: 4px 5px; - text-align: center; - text-decoration: none; - min-width: 18px; -} -.toolbar ul li a .buttonicon { - position: relative; - top: 1px; -} -.toolbar ul li a .buttontext { - color: #666; - font-size: 14px; - border:none; - background:none; - margin-top:1px; - color:#666; -} - -.buttontext::-moz-focus-inner { - padding: 0; - border: 0; -} - -.buttontext:focus{ - /* Not sure why important is required here but it is */ - border: 1px solid #666 !important; -} - -.toolbar ul li a.grouped-left { - border-radius: 3px 0 0 3px; -} -.toolbar ul li a.grouped-middle { - border-radius: 0; - margin-left: -2px; - border-left: 0; -} -.toolbar ul li a.grouped-right { - border-radius: 0 3px 3px 0; - margin-left: -2px; - border-left: 0; -} -.toolbar ul li a.selected { - background: #eee !important; - background: -webkit-linear-gradient(#EEE, #F0F0F0) !important; - background: -moz-linear-gradient(#EEE, #F0F0F0) !important; - background: -o-linear-gradient(#EEE, #F0F0F0) !important; - background: -ms-linear-gradient(#EEE, #F0F0F0) !important; - background: linear-gradient(#EEE, #F0F0F0) !important; -} -.toolbar ul li select { - background: #fff; - padding: 4px; - line-height: 22px; /* fix for safari (win/mac) */ - height: 28px; /* fix for chrome (mac) */ - border-radius: 3px; - border: 1px solid #ccc; - outline: none; -} -.toolbar ul.menu_left { - left:0px; - right:250px; -} - -.toolbar ul.menu_right { - right:0px; -} - -li[data-key=showusers] > a { - min-width: 30px; - text-align: left; -} -li[data-key=showusers] > a #online_count { - color: #777; - font-size: 11px; - position: relative; - top: 2px; - padding-left: 2px; -} -#editbar{ - display:none; -} - -#editorcontainer { - position: absolute; - top: 37px; /* + 1px border */ - left: 0px; - right: 0px; - bottom: 0px; - z-index: 1; - - /* Required to be able to scroll on iOS: */ - -webkit-overflow-scrolling: touch; -} -#editorcontainer iframe { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - left: 0; /* Required for safari fixes RTL */ -} -#editorloadingbox { - padding-top: 100px; - padding-bottom: 100px; - font-size: 2.5em; - color: #aaa; - text-align: center; - position: absolute; - width: 100%; - height: 30px; - z-index: 100; -} - -#editorloadingbox .passForm{ - padding:10px; -} - -#editorloadingbox input{ - padding:10px; -} - -#editorloadingbox button{ - padding:10px; -} - -.loadingAnimation{ - -webkit-animation: loadingAnimation 2s infinite linear; - animation: loadingAnimation 2s infinite linear; - font-family: "fontawesome-etherpad"; - font-size:24px; - z-index:150; - width:25px; - height:25px; -} - -.loadingAnimation:before{ - content: "\e80e"; -} - -@-webkit-keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -#editorcontainerbox { - position: absolute; - bottom: 0; - top: 0; - width: 100%; -} -#padpage { - position: absolute; - top: 0px; - bottom: 0px; - width: 100%; -} -#padmain { - margin-top: 0px; - position: absolute; - top: 63px !important; - left: 0px; - right: 0px; - bottom: 0px; - zoom: 1; -} -#padeditor { - bottom: 0px; - left: 0; - position: absolute; - right: 0px; - top: 0; - zoom: 1; -} -#myswatchbox { - position: absolute; - left: 5px; - top: 5px; - width: 24px; - height: 24px; - border: 1px solid #000; - background: transparent; - cursor: pointer; -} -#myswatch { - width: 100%; - height: 100%; - background: transparent; /*...initially*/ -} -#mycolorpicker { - width: 232px; - height: 265px; - position: absolute; - left: -250px; - top: 0px; - z-index: 101; - display: none; - border-radius: 0 0 6px 6px; - background: #f7f7f7; - border: 1px solid #ccc; - border-top: 0; - padding-left: 10px; - padding-top: 10px; -} -#mycolorpickersave { - left: 10px; - font-weight: bold; -} -#mycolorpickercancel { - left: 85px -} -#mycolorpickersave, -#mycolorpickercancel { - background: #fff; - background: -webkit-linear-gradient(#fff, #ccc); - background: -moz-linear-gradient(#fff, #ccc); - background: -o-linear-gradient(#fff, #ccc); - background: -ms-linear-gradient(#fff, #ccc); - background: linear-gradient(#fff, #ccc); - border: 1px solid #ccc; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - font-size: 12px; - cursor: pointer; - color: #000; - overflow: hidden; - padding: 4px; - top: 240px; - text-align: center; - position: absolute; - width: 60px; -} -#mycolorpickerpreview { - position: absolute; - left: 207px; - top: 240px; - width: 16px; - height: 16px; - padding: 4px; - overflow: hidden; - color: #fff; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} -#myusernameform { - margin-left: 30px -} -#myusernameedit { - font-size: 1.3em; - color: #fff; - padding: 3px; - height: 18px; - margin: 0; - border: 0; - width: 122px; - background: transparent; -} -#myusernameform input.editable { - border: 1px solid #444 -} -#myuser .myusernameedithoverable:hover { - background: white; - color: black; -} -#mystatusform { - margin-left: 35px; - margin-top: 5px; -} -#mystatusedit { - font-size: 1.2em; - color: #777; - font-style: italic; - display: none; - padding: 2px; - height: 14px; - margin: 0; - border: 1px solid #bbb; - width: 199px; - background: transparent; -} -#myusernameform .editactive, -#myusernameform .editempty { - background: white; - border-left: 1px solid #c3c3c3; - border-top: 1px solid #c3c3c3; - border-right: 1px solid #e6e6e6; - border-bottom: 1px solid #e6e6e6; - color: #000; -} -#myusernameform .editempty { - color: #333 -} -#myswatchbox, #myusernameedit, #otheruserstable .swatch { - border: 1px solid #ccc !important; - color: #333; -} -table#otheruserstable { - display: none -} -#nootherusers { - padding: 10px; - font-size: 1.2em; - color: #eee; - font-weight: bold; -} -#nootherusers a { - color: #3C88FF -} -#otheruserstable td { - height: 26px; - vertical-align: middle; - padding: 0 2px; - color: #333; -} -#otheruserstable .swatch { - border: 1px solid #000; - width: 13px; - height: 13px; - overflow: hidden; - margin: 0 4px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.usertdswatch { - width: 1% -} -.usertdname { - font-size: 1.3em; - color: #444; -} -.usertdstatus { - font-size: 1.1em; - font-style: italic; - color: #999; -} -.usertdactivity { - font-size: 1.1em; - color: #777; -} -.usertdname input { - border: 1px solid #bbb; - width: 80px; - padding: 2px; -} -.usertdname input.editactive, -.usertdname input.editempty { - background: white; - border-left: 1px solid #c3c3c3; - border-top: 1px solid #c3c3c3; - border-right: 1px solid #e6e6e6; - border-bottom: 1px solid #e6e6e6; -} -.usertdname input.editempty { - color: #888; - font-style: italic; -} - -#connectivity { - z-index: 600 !important; -} - -#connectivity * { - display: none; -} - -#connectivity .visible, -#connectivity .visible * { - display: block; -} - -/* styles for the automatic reconnection timer: */ -#connectivity .visible.with_reconnect_timer button, -#connectivity .visible.with_reconnect_timer .reconnecttimer * { - display: inline-block; -} - -#connectivity .with_reconnect_timer .hidden, -#connectivity .with_reconnect_timer #defaulttext.hidden, -#connectivity .with_reconnect_timer button.hidden { - display: none; -} - -#connectivity .with_reconnect_timer #cancelreconnect { - margin-left: 10px; -} -/* end of styles for the automatic reconnection timer */ - -#reconnect_form button { - font-size: 12pt; - padding: 5px; -} - -.toolbar #overlay { - z-index: 500; - display: none; - background-repeat: repeat-both; - width: 100%; - position: absolute; - height: inherit; - left: 0; - top: 0; -} -* html #overlay { - /* for IE 6+ */ - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; - filter: alpha(opacity=100); - opacity: 1; /* in case this is looked at */ - background-image: none; - background-repeat: no-repeat; /* scale the image */ -} - -#chatbox { - position: absolute; - bottom: 0px; - right: 20px; - width: 180px; - height: 200px; - z-index: 400; - background-color: #f7f7f7; - border-left: 1px solid #999; - border-right: 1px solid #999; - border-top: 1px solid #999; - padding: 3px; - padding-bottom: 10px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - display: none; -} -#chattext { - background-color: white; - border: 1px solid white; - -ms-overflow-y: scroll; - overflow-y: scroll; - font-size: 12px; - position: absolute; - right: 0px; - left: 0px; - top: 25px; - bottom: 25px; - z-index: 1002; -} -#chattext p { - padding: 3px; - -ms-overflow-x: hidden; - overflow-x: hidden; -} -.chatloadmessages -{ - margin-bottom: 5px; - margin-top: 5px; - margin-left: auto; - margin-right: auto; - display: block; -} -#chatloadmessagesbutton -{ - line-height: 1.8em; -} -#chatloadmessagesball -{ - display: none; -} -#chatinputbox { - padding: 3px 2px; - position: absolute; - bottom: 0px; - right: 0px; - left: 3px; -} -#chatlabel { - font-size: 13px; - font-weight: bold; - color: #555; - text-decoration: none; - margin-right: 3px; - vertical-align: middle; -} -#chatinput { - border: 1px solid #BBBBBB; - width: 100%; - float: right; -} -#chaticon { - z-index: 400; - position: fixed; - bottom: 0px; - right: 20px; - padding: 5px; - border-left: 1px solid #999; - border-right: 1px solid #999; - border-top: 1px solid #999; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - background-color: #fff; - cursor: pointer; -} -#chaticon a { - text-decoration: none -} -#chatcounter { - color: #777; - font-size: 10px; - vertical-align: middle; -} -#titlebar { - line-height: 16px; - font-weight: bold; - color: #555; - position: relative; - bottom: 2px; -} -#titlelabel { - font-size: 13px; - margin: 4px 0 0 4px; - position: absolute; -} -#titlesticky{ - font-size: 10px; - padding-top:2px; - float: right; - text-align: right; - text-decoration: none; - cursor: pointer; - color: #555; -} -#titlecross { - font-size: 25px; - float: right; - text-align: right; - text-decoration: none; - cursor: pointer; - color: #555; -} -.time { - float: right; - color: #333; - font-style: italic; - font-size: 10px; - margin-left: 3px; - margin-right: 3px; - margin-top: 2px; -} -#exportColumn{ - margin-top:20px; -} -.exporttype { - margin-top: 4px; - background-repeat: no-repeat; - padding-left: 25px; - color: #333; - text-decoration: none; - padding-bottom:2px; - display:inline; - padding-left:5px; - font-family: "Arial"; -} -.exportlink{ - font-family: "fontawesome-etherpad"; - display:block; - margin:5px; - color:#666; -} -#exporthtmla:before { - content: "\e826"; -} -#exportplaina:before { - content: "\e802"; -} -#exportworda:before { - content: "\e804"; -} -#exportpdfa:before { - content: "\e803"; -} -#exportetherpada:before { - content: "\e806"; -} -#exportopena:before { - content: "\e805"; -} - -/* hidden element */ -#importstatusball, -#importmessagesuccess, -#importmessageabiword { - display: none; -} - -.throbbold{ - font-weight:bold; -} - -#importmessageabiword { - color: #900; - font-size: small; -} - -#importsubmitinput { - margin-top: 12px; - padding:2px 4px 2px 4px; -} -#chatthrob { - display: none; - position: absolute; - bottom: 40px; - font-size: 14px; - width: 150px; - height: 40px; - right: 20px; - z-index: 200; - background-color: #000; - color: white; - background-color: rgb(0,0,0); - background-color: rgba(0,0,0,0.7); - padding: 10px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; - filter: alpha(opacity=80); - opacity: .8; -} -.buttonicon { - width: 16px; - height: 16px; - display: inline-block; - vertical-align: middle; - border: none; - padding: 0; - background: none; - font-family: "fontawesome-etherpad"; - font-size: 15px; - font-style: normal; - font-weight: normal; - color: #666; - cursor: pointer; -} - -.buttonicon::-moz-focus-inner { - padding: 0; - border: 0 -} - -.buttonicon:focus{ - border: 1px solid #666; -} -.buttonicon-bold:before { - content: "\e81c"; -} -.buttonicon-italic:before { - content: "\e81d"; -} -.buttonicon-underline:before { - content: "\e817"; -} -.buttonicon-strikethrough:before { - content: "\e818"; -} -.buttonicon-insertorderedlist:before { - content: "\e816"; -} -.buttonicon-insertunorderedlist:before { - content: "\e815"; -} -.buttonicon-indent:before { - content: "\e814"; -} -.buttonicon-outdent:before { - content: "\e813"; -} -.buttonicon-undo:before { - content: "\e823"; -} -.buttonicon-redo:before { - content: "\e824"; -} -.buttonicon-clearauthorship:before { - content: "\e80d"; -} -.buttonicon-settings:before { - content: "\e833"; -} -.buttonicon-import_export:before { - content: "\e834"; -} -.buttonicon-embed:before { - content: "\e827"; -} -.buttonicon-history:before { - content: "\e837"; -} -.buttonicon-chat:before { - content: "\e829"; -} -.buttonicon-showusers:before { - content: "\e808"; -} -.buttonicon-savedRevision:before { - content: "\e835"; -} -#focusprotector { - z-index: 100; - position: absolute; - bottom: 0px; - top: 0px; - left: 0px; - right: 0px; - background-color: white; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=1)"; - filter: alpha(opacity=1); - opacity: 0.01; - display: none; -} -.rtl { - direction: RTL -} -#chattext p { - word-wrap: break-word -} -/* fix for misaligned checkboxes */ -input[type=checkbox] { - vertical-align: -1px -} -.right { - float: right -} -.popup { - font-size: 12px; - width: 80%; - max-width: 500px; - padding: 10px; - border-radius: 0 0 6px 6px; - border: 1px solid #ccc; - border-top: none; - background: #f7f7f7; - background: -webkit-linear-gradient(#F7F7F7, #EEE); - background: -moz-linear-gradient(#F7F7F7, #EEE); - background: -ms-linear-gradient(#F7F7F7, #EEE); - background: -o-linear-gradient(#F7F7F7, #EEE); - background: linear-gradient(#F7F7F7, #EEE); - -webkit-box-shadow: 0 0 8px #888; - -moz-box-shadow: 0 0 8px #888; - box-shadow: 0 2px 4px #ddd; - color: #222; -} -.popup input[type=text] { - width: 100%; - padding: 5px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - display: block; - margin-top: 10px; -} -.popup input[type=text], #users input[type=text] { - outline: none; -} -.popup button { - padding: 5px; - font-size: 14px; -} -.popup a { - text-decoration: none -} -.popup h1 { - color: #555; - font-size: 18px -} -.popup h2 { - color: #777; - font-size: 15px -} -.popup p { - margin: 5px 0 -} -.popup select { - background: #fff; - padding: 2px; - height: 24px; - border-radius: 3px; - border: 1px solid #ccc; - outline: none; - width: 120px; -} -.column { - float: left; - width:50%; -} -#settings, -#import_export, -#embed, -#connectivity, -#users { - position: absolute; - top: 38px; - right: 20px; - display: none; - z-index: 500; -} -.stickyChat { - background-color: #f1f1f1 !important; - right: 0px !important; - top: 37px; - -webkit-border-radius: 0px !important; - -moz-border-radius: 0px !important; - border-radius: 0px !important; - height: auto !important; - border: none !important; - border-left: 1px solid #ccc !important; - width: 185px !important; -} -.chatAndUsers{ - display:block !important; - right:0px !important; - border-radius:0px !important; - width:182px !important; -/* Below makes UI look weird when X makes editbar flow onto two lines */ -/* margin:2px 0 0 0 !important;*/ - border: none !important; - border-bottom: 1px solid #ccc !important; - height:155px !important; - border-left: 1px solid #ccc !important; -} -.chatAndUsers > #otherusers{ - max-height: 100px; - overflow-y: auto; -} -.chatAndUsersChat > div > #titlecross{ - display:none; -} -.chatAndUsersChat{ - bottom:0px !important; - padding:0 !important; - margin: 165px 0px 0px 0px; - right:0 !important; - width:182px !important; - border: none !important; - padding:5px !important; - border-left: 1px solid #ccc !important; -} - -@media screen and (max-width: 600px) { - .toolbar ul li.separator { - display: none; - } - .toolbar ul li a { - padding: 4px 1px - } - .toolbar ul.menu_left { - left:0px; - right:150px; - } -} -@media all and (max-width: 400px){ - #gritter-notice-wrapper{ - max-height:172px; - overflow:hidden; - width:100% !important; - background-color: #ccc; - bottom:20px; - left:0px; - right:0px; - color:#000; - } - .gritter-close { - display:block !important; - left: auto !important; - right:5px; - } - #gritter-notice-wrapper.bottom-right{ - left:0px !important; - bottom:30px !important; - right:0px !important; - } - .gritter-item p{ - color:black; - font-size:16px; - } - .gritter-title{ - text-shadow: none !important; - color:black; - } - .gritter-item{ - padding:2px 11px 8px 4px; - } - .gritter-item-wrapper{ - margin:0; - } - .gritter-item-wrapper > div{ - background: none; - } - #editorcontainer { - top: 68px; - } - #editbar { - height: 62px; - } - .toolbar ul.menu_left { - left:0px; - right:100px; - } - - .toolbar ul.menu_right { - right:0px; - } - .popup { - width:100%; - max-width:300px; - top: 72px !important; - } -} - -/* Mobile devices */ -@media only screen and (min-device-width: 320px) and (max-device-width: 720px) { - #users { - top: auto; - right:0px !important; - bottom: 33px; - border-radius: 0px !important; - height: 55px !important; - overflow: auto; - } - #mycolorpicker { - left: 0px; - top:37px !important; - position:fixed; - /* #mycolorpicker: width -#users: width */; - } - #editorcontainer { - margin-bottom: 33px - } - /* cancel non-mobile border (will be defined on ".toolbar ul.menu_left" bellow) */ - .toolbar { - border-bottom: 0; - } - .toolbar ul { - background: #f7f7f7; - background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: linear-gradient(#f7f7f7, #f1f1f1 80%); - width: 100%; - overflow: hidden; - } - .toolbar ul.menu_left { - right:0px; - position: fixed; - top: 0; - padding-top: 4px; - border-bottom: 1px solid #ccc; - z-index: 10; - } - .toolbar ul.menu_right { - right:0px !important; - height: 32px; - position: fixed; - bottom: 0; - border-top: 1px solid #ccc; - } - .toolbar ul.menu_right > li:last-child { - float: right; - } - .toolbar ul.menu_right > li a { - border-radius: 0; - border: none; - background: none; - margin: 0; - padding: 8px; - } - .toolbar ul li a.selected { - background: none !important - } - li[data-key="showusers"] > a { - - margin-top:-10px; - padding-top:2px !important; - line-height:20px; - vertical-align:top !important; - } - #chaticon { - position:fixed; - right:48px; - } - .popup { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - width: 100%; - } - #settings, - #import_export, - #connectivity, - #embed { - top:auto; - left: 0; - bottom: 33px; - right: 0; - } - .toolbar ul li .separator { - display: none - } - #online_count { - line-height: 24px - } - #chatbox{ - position:fixed; - bottom:33px !important; - margin: 65px 0 0 0; - } - #gritter-notice-wrapper{ - bottom:43px !important; - right:10px !important; - } -} - -#passwordRequired{ - display:none; -} - -#permissionDenied{ - display:none; -} - -#wrongPassword{ - display:none; -} - -#noCookie{ - display:none; -} - -/* gritter stuff */ -#gritter-notice-wrapper { - position:fixed; - top:20px; - right:20px; - width:301px; - z-index:9999; - background-color:#666; -} -#gritter-notice-wrapper.bottom-right { - top: auto; - left: auto; - bottom: 20px; - right: 20px; -} -.gritter-item-wrapper { - position:relative; - margin:0 0 10px 0; -} - -.gritter-top { - height:10px; -} -.hover .gritter-top { - background-position:right -30px; -} -.gritter-bottom { - height:8px; - margin:0; -} -.hover .gritter-bottom { - background-position: bottom right; -} -.gritter-item { - display:block; - color:#eee; - padding:2px 11px 8px 11px; - font-size: 11px; - font-family:verdana; -} -.hover .gritter-item { - background-position:right -40px; -} -.gritter-item p { - padding:0; - margin:0; -} -.gritter-close { - display:none; - position:absolute; - top:5px; - left:3px; - cursor:pointer; - width:30px; - height:30px; -} -.gritter-title { - font-size:14px; - font-weight:bold; - padding:0 0 7px 0; - display:block; - text-shadow:1px 1px 0 #000; /* Not supported by IE :( */ -} -.gritter-image { - width:48px; - height:48px; - float:left; -} -.gritter-with-image, -.gritter-without-image { - padding:0 0 5px 0; -} -.gritter-with-image { - width:220px; - float:right; -} -/* for the light (white) version of the gritter notice */ -.gritter-light .gritter-item, -.gritter-light .gritter-bottom, -.gritter-light .gritter-top, -.gritter-close { - color: #222; -} -.gritter-light .gritter-title { - text-shadow: none; -} -/* End of gritter stuff */ - -/* Montserrat Font */ -@font-face { - font-family: "Montserrat"; - src: url("../../static/font/Montserrat-Light.otf") format("opentype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "Montserrat"; - src: url("../../static/font/Montserrat-Regular.otf") format("opentype"); - font-weight: bold; - font-style: normal; -} -/* End of Monterrat Font */ - -@font-face { - font-family: opendyslexic; - src: url("../../static/font/opendyslexic.otf") format("opentype"); -} - -/* Roboto Mono */ -@font-face { - font-family: "RobotoMono"; - src: url("../../static/font/RobotoMono-Regular.ttf") format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "RobotoMono"; - src: url("../../static/font/RobotoMono-Bold.ttf") format("truetype"); - font-weight: bold; - font-style: normal; -} -/* End of Roboto Mono */ - -@font-face { - font-family: "fontawesome-etherpad"; - src:url("../../static/font/fontawesome-etherpad.eot"); - src:url("../../static/font/fontawesome-etherpad.eot?#iefix") format("embedded-opentype"), - url("../../static/font/fontawesome-etherpad.woff") format("woff"), - url("../../static/font/fontawesome-etherpad.ttf") format("truetype"), - url("../../static/font/fontawesome-etherpad.svg#fontawesome-etherpad") format("svg"); - font-weight: normal; - font-style: normal; - -} - -[data-icon]:before { - font-family: "fontawesome-etherpad" !important; - content: attr(data-icon); - font-style: normal !important; - font-weight: normal !important; - font-variant: normal !important; - text-transform: none !important; - speak: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -[class^="icon-"]:before, -[class*=" icon-"]:before { - font-family: "fontawesome-etherpad" !important; - font-style: normal !important; - font-weight: normal !important; - font-variant: normal !important; - text-transform: none !important; - speak: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.hideControlsEditor{ - top:0px !important; -} -.hideControlsEditbar{ - display:none !important; -} diff --git a/sources/src/static/css/timeslider.css b/sources/src/static/css/timeslider.css deleted file mode 100644 index 0311b10..0000000 --- a/sources/src/static/css/timeslider.css +++ /dev/null @@ -1,279 +0,0 @@ -@import url('./lists_and_indents.css'); - -p.pblort { - height: 100px; -} - -#editorcontainerbox { - overflow: auto; - top: 40px; - position: static; -} -#padcontent { - font-size: 12px; - padding: 10px; -} -#timeslider-wrapper { - left: 0; - position: relative; - right: 0; - top: 0; -} -#timeslider-left { - background-color:#fff; - height: 63px; - left: 0; - position: absolute; - width: 134px; -} -#timeslider-right { - background-color:#fff; - height: 63px; - position: absolute; - right: 0; - top: 0; - width: 155px; -} -#timeslider { - height: 63px; - margin: 0 9px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-color:#fff; - /* bgcolor is reuqired so you can't see pad content behind it */ -} -#timeslider #timeslider-slider { - height: 61px; - left: 0; - position: absolute; - top: 1px; - width: 100%; -} -#ui-slider-handle { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - background-color: #666; - cursor: pointer; - height: 61px; - left: 0; - position: absolute; - top: 0; - width: 13px; -} -#ui-slider-bar { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - cursor: pointer; - height: 60px; - margin-left: 5px; - margin-right: 150px; - position: relative; - top: 0px; -} - -#playpause_button, -#playpause_button_icon { - height: 44px; - position: absolute; - width: 44px; - text-align:center; - vertical-align:middle; - background:none; -} -#playpause_button { - right: 77px; - top: 9px; - height:50px; - height:50px; - background: background-linear-gradient( #F7F7F7, #F1F1F1 80%) repeat scroll 0 0 transparent; - border-radius:24px; - cursor:hand; -} -#playpause_button_icon:before { - line-height:44px; - padding-left:2px; - font-family: fontawesome-etherpad; - content: "\e82c"; - font-size:24px; - color:#666; -} - -#playpause_button_icon { - left: 0; - top: 0; - border-radius:48px; - border: solid 1px #666; -} -.pause:before { - line-height:44px; - padding-left:2px; - font-family: fontawesome-etherpad; - content: "\e82e" !important; - font-size:24px; - color:#666; - padding-left:0 !important; -} -#leftstar, -#rightstar, -#leftstep, -#rightstep { - background-color: white; - overflow: hidden; - position: absolute; -} - -.stepper{ - font-family: fontawesome-etherpad; - border-radius:2px; - border: #666 solid 1px; -/* line-height:18px; */ - text-align:center; - height:22px; - color:#666; -} - -stepper:active{ - color:#000; -} - -#leftstep { - right: 38px; - top: 20px; - width: 25px; -} -#leftstep:before{ - content: '\e821'; - vertical-align:middle; -} -#rightstep:before{ - content: "\e822"; - vertical-align:middle; -} - -#rightstep { - right: 12px; - top: 20px; - width: 25px; -} -.star:before{ - font-family: fontawesome-etherpad; - content: "\e835"; - vertical-align:middle; - font-size:16px; -} -#timeslider .star { - cursor: pointer; - height: 16px; - position: absolute; - top: 25px; - width: 15px; -} -#timeslider #timer { - background: linear-gradient(#F7F7F7, #F1F1F1 80%) repeat scroll 0% 0% transparent; - padding:2px; - border-radius:2px; - font-family: Arial, sans-serif; - font-size: 11px; - left: 7px; - position: absolute; - text-align: center; - top: 9px; - width: 122px; -} -.topbarcenter, -#docbar { - display: none -} -#padmain { - top: 0px !important -} -#editbar{ - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.editbarright { - float: right; - text-align: right; - height: 30px !important; -} -.toolbar ul{ - position:relative; - float:right; - height:30px; -} -#import_export, #settings{ - top: 115px; - position: fixed; -} -#import_export .popup { - width: 183px; - border-top: none; - border-right: none; - border-radius: 0 0 0 6px; -} -#import_export { - width: 185px; -} -.timeslider-bar { - background: #f7f7f7; - background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: linear-gradient(#f7f7f7, #f1f1f1 80%); - overflow: hidden; - padding-top: 3px; - width: 100%; -} -.timeslider-bar #editbar { - border-bottom: none; - float: right; - width: auto; -} -.timeslider-bar h1 { - margin: 5px -} -.timeslider-bar p { - margin: 5px -} -#timeslider-top { - width: 100%; - position: fixed; - z-index: 1; -} -#authorsList .author { - padding-left: 0.4em; - padding-right: 0.4em; -} -#authorsList .author-anonymous { - padding-left: 0.6em; - padding-right: 0.6em; -} -#padeditor { - position: static -} - -button{ - margin:0; - padding:0; - cursor:pointer; -} - -button::-moz-focus-inner { - padding: 0; - border: 0 -} - -button:focus{ - border: 1px solid #666; -} diff --git a/sources/src/static/custom/.gitignore b/sources/src/static/custom/.gitignore deleted file mode 100644 index aae16bb..0000000 --- a/sources/src/static/custom/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!.gitignore -!*.template diff --git a/sources/src/static/custom/css.template b/sources/src/static/custom/css.template deleted file mode 100644 index 236251d..0000000 --- a/sources/src/static/custom/css.template +++ /dev/null @@ -1,8 +0,0 @@ -/* - custom css files are loaded after core css files. Simply use the same selector to override a style. - Example: - #editbar LI {border:1px solid #000;} - overrides - #editbar LI {border:1px solid #d5d5d5;} - from pad.css -*/ diff --git a/sources/src/static/custom/js.template b/sources/src/static/custom/js.template deleted file mode 100644 index 152c3d5..0000000 --- a/sources/src/static/custom/js.template +++ /dev/null @@ -1,6 +0,0 @@ -function customStart() -{ - //define your javascript here - //jquery is available - except index.js - //you can load extra scripts with $.getScript http://api.jquery.com/jQuery.getScript/ -} diff --git a/sources/src/static/favicon.ico b/sources/src/static/favicon.ico deleted file mode 100644 index 938e955..0000000 Binary files a/sources/src/static/favicon.ico and /dev/null differ diff --git a/sources/src/static/font/Montserrat-Light.otf b/sources/src/static/font/Montserrat-Light.otf deleted file mode 100755 index f2f0e2d..0000000 Binary files a/sources/src/static/font/Montserrat-Light.otf and /dev/null differ diff --git a/sources/src/static/font/Montserrat-Regular.otf b/sources/src/static/font/Montserrat-Regular.otf deleted file mode 100755 index f61d57e..0000000 Binary files a/sources/src/static/font/Montserrat-Regular.otf and /dev/null differ diff --git a/sources/src/static/font/RobotoMono-Bold.ttf b/sources/src/static/font/RobotoMono-Bold.ttf deleted file mode 100755 index 07ef607..0000000 Binary files a/sources/src/static/font/RobotoMono-Bold.ttf and /dev/null differ diff --git a/sources/src/static/font/RobotoMono-Regular.ttf b/sources/src/static/font/RobotoMono-Regular.ttf deleted file mode 100755 index b158a33..0000000 Binary files a/sources/src/static/font/RobotoMono-Regular.ttf and /dev/null differ diff --git a/sources/src/static/font/config.json b/sources/src/static/font/config.json deleted file mode 100644 index f9c2c3d..0000000 --- a/sources/src/static/font/config.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "name": "fontawesome-etherpad", - "css_prefix_text": "icon-", - "css_use_suffix": false, - "hinting": true, - "units_per_em": 1000, - "ascent": 850, - "glyphs": [ - { - "uid": "bf882b30900da12fca090d9796bc3030", - "css": "mail", - "code": 59402, - "src": "fontawesome" - }, - { - "uid": "474656633f79ea2f1dad59ff63f6bf07", - "css": "star", - "code": 59446, - "src": "fontawesome" - }, - { - "uid": "d17030afaecc1e1c22349b99f3c4992a", - "css": "star-empty", - "code": 59445, - "src": "fontawesome" - }, - { - "uid": "8b80d36d4ef43889db10bc1f0dc9a862", - "css": "user", - "code": 59401, - "src": "fontawesome" - }, - { - "uid": "31972e4e9d080eaa796290349ae6c1fd", - "css": "users", - "code": 59400, - "src": "fontawesome" - }, - { - "uid": "0f99ab40ab0b4d64a74f2d0deeb03e42", - "css": "videocam", - "code": 59403, - "src": "fontawesome" - }, - { - "uid": "381da2c2f7fd51f8de877c044d7f439d", - "css": "picture", - "code": 59404, - "src": "fontawesome" - }, - { - "uid": "7fd683b2c518ceb9e5fa6757f2276faa", - "css": "eye-off", - "code": 59405, - "src": "fontawesome" - }, - { - "uid": "7034e4d22866af82bef811f52fb1ba46", - "css": "code", - "code": 59431, - "src": "fontawesome" - }, - { - "uid": "7277ded7695b2a307a5f9d50097bb64c", - "css": "print", - "code": 59393, - "src": "fontawesome" - }, - { - "uid": "85528017f1e6053b2253785c31047f44", - "css": "comment", - "code": 59448, - "src": "fontawesome" - }, - { - "uid": "dcedf50ab1ede3283d7a6c70e2fe32f3", - "css": "chat", - "code": 59432, - "src": "fontawesome" - }, - { - "uid": "9c1376672bb4f1ed616fdd78a23667e9", - "css": "comment-empty", - "code": 59433, - "src": "fontawesome" - }, - { - "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", - "css": "trash-empty", - "code": 59434, - "src": "fontawesome" - }, - { - "uid": "1b5a5d7b7e3c71437f5a26befdd045ed", - "css": "doc", - "code": 59394, - "src": "fontawesome" - }, - { - "uid": "9daa1fdf0838118518a7e22715e83abc", - "css": "file-pdf", - "code": 59395, - "src": "fontawesome" - }, - { - "uid": "310ffd629da85142bc8669f010556f2d", - "css": "file-word", - "code": 59396, - "src": "fontawesome" - }, - { - "uid": "f761c3bbe16ba2d332914ecb28e7a042", - "css": "file-excel", - "code": 59397, - "src": "fontawesome" - }, - { - "uid": "edcd4022de8d8df266ef7c42d2658ca5", - "css": "file-powerpoint", - "code": 59398, - "src": "fontawesome" - }, - { - "uid": "3c961c1a8d874815856fc6637dc5a13c", - "css": "file-image", - "code": 59399, - "src": "fontawesome" - }, - { - "uid": "26613a2e6bc41593c54bead46f8c8ee3", - "css": "file-code", - "code": 59430, - "src": "fontawesome" - }, - { - "uid": "e99461abfef3923546da8d745372c995", - "css": "cog", - "code": 59443, - "src": "fontawesome" - }, - { - "uid": "19c50c52858a81de58f9db488aba77bc", - "css": "mic", - "code": 59435, - "src": "fontawesome" - }, - { - "uid": "598a5f2bcf3521d1615de8e1881ccd17", - "css": "clock", - "code": 59447, - "src": "fontawesome" - }, - { - "uid": "bc71f4c6e53394d5ba46b063040014f1", - "css": "cw", - "code": 59428, - "src": "fontawesome" - }, - { - "uid": "f9c3205df26e7778abac86183aefdc99", - "css": "ccw", - "code": 59427, - "src": "fontawesome" - }, - { - "uid": "a73c5deb486c8d66249811642e5d719a", - "css": "arrows-cw", - "code": 59429, - "src": "fontawesome" - }, - { - "uid": "6020aff067fc3c119cdd75daa5249220", - "css": "exchange", - "code": 59444, - "src": "fontawesome" - }, - { - "uid": "ce06b5805120d0c2f8d60cd3f1a4fdb5", - "css": "play", - "code": 59436, - "src": "fontawesome" - }, - { - "uid": "b624a1e512819d410ddbee84e6918b9d", - "css": "stop", - "code": 59437, - "src": "fontawesome" - }, - { - "uid": "0b28050bac9d3facf2f0226db643ece0", - "css": "pause", - "code": 59438, - "src": "fontawesome" - }, - { - "uid": "c47efa0e3e74f6ba4c2562c1258fff1f", - "css": "to-end", - "code": 59426, - "src": "fontawesome" - }, - { - "uid": "12052b30d23a1a70d6b32962d5464cae", - "css": "to-start", - "code": 59425, - "src": "fontawesome" - }, - { - "uid": "f9cbf7508cd04145ade2800169959eef", - "css": "font", - "code": 59419, - "src": "fontawesome" - }, - { - "uid": "02cca871bb69da75e8ee286b7055832c", - "css": "bold", - "code": 59420, - "src": "fontawesome" - }, - { - "uid": "a8cb1c217f02b073db3670c061cc54d2", - "css": "italic", - "code": 59421, - "src": "fontawesome" - }, - { - "uid": "0c708edd8fae2376b3370aa56d40cf9e", - "css": "header", - "code": 59422, - "src": "fontawesome" - }, - { - "uid": "c009d417f87d6a27bb5a1cefd30b6cbd", - "css": "text-height", - "code": 59423, - "src": "fontawesome" - }, - { - "uid": "13a971bcccd2dda26d4d4eccd8593f8a", - "css": "text-width", - "code": 59424, - "src": "fontawesome" - }, - { - "uid": "f4f0e849b805be1f6d76b65581cb3b8b", - "css": "align-left", - "code": 59392, - "src": "fontawesome" - }, - { - "uid": "ae6336c46d73af999fe7460c089abb4d", - "css": "align-center", - "code": 59407, - "src": "fontawesome" - }, - { - "uid": "e1e7306b47c3c5e6faecce9d32571381", - "css": "align-right", - "code": 59408, - "src": "fontawesome" - }, - { - "uid": "25a81737628d1e654a30ad412d7d6dd7", - "css": "align-justify", - "code": 59409, - "src": "fontawesome" - }, - { - "uid": "48b87105bd38c20315f1b705b8c7b38c", - "css": "list", - "code": 59410, - "src": "fontawesome" - }, - { - "uid": "594e9271c08ff732c04b3bf3117b9040", - "css": "indent-left", - "code": 59411, - "src": "fontawesome" - }, - { - "uid": "4d2dfc45d8176b1f26aed973fa84a91e", - "css": "indent-right", - "code": 59412, - "src": "fontawesome" - }, - { - "uid": "a2a74f5e7b7d9ba054897d8c795a326a", - "css": "list-bullet", - "code": 59413, - "src": "fontawesome" - }, - { - "uid": "f6766a8b042c2453a4e153af03294383", - "css": "list-numbered", - "code": 59414, - "src": "fontawesome" - }, - { - "uid": "61c242c9e2134d5864d7fdd57b3c9289", - "css": "strike", - "code": 59416, - "src": "fontawesome" - }, - { - "uid": "d4a4a38a40b728f46dad1de4ac950231", - "css": "underline", - "code": 59415, - "src": "fontawesome" - }, - { - "uid": "4e88371fb8857dacc1f66afe6314e426", - "css": "superscript", - "code": 59417, - "src": "fontawesome" - }, - { - "uid": "3d1c929dbc966992185ce749548c1b2c", - "css": "subscript", - "code": 59418, - "src": "fontawesome" - }, - { - "uid": "9396b2d8849e0213a0f11c5fd7fcc522", - "css": "tasks", - "code": 59442, - "src": "fontawesome" - }, - { - "uid": "0bda4bc779d4c32623dec2e43bd67ee8", - "css": "gauge", - "code": 59439, - "src": "fontawesome" - }, - { - "uid": "cda0cdcfd38f5f1d9255e722dad42012", - "css": "spinner", - "code": 59406, - "src": "fontawesome" - }, - { - "uid": "fa9a0b7e788c2d78e24cef1de6b70e80", - "css": "brush", - "code": 59440, - "src": "fontawesome" - }, - { - "uid": "be13b8c668eb18839d5d53107725f1de", - "css": "slideshare", - "code": 59441, - "src": "fontawesome" - } - ] -} \ No newline at end of file diff --git a/sources/src/static/font/fontawesome-etherpad.eot b/sources/src/static/font/fontawesome-etherpad.eot deleted file mode 100644 index 284149e..0000000 Binary files a/sources/src/static/font/fontawesome-etherpad.eot and /dev/null differ diff --git a/sources/src/static/font/fontawesome-etherpad.svg b/sources/src/static/font/fontawesome-etherpad.svg deleted file mode 100644 index a64ba86..0000000 --- a/sources/src/static/font/fontawesome-etherpad.svg +++ /dev/null @@ -1,68 +0,0 @@ - - - -Copyright (C) 2015 by original authors @ fontello.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sources/src/static/font/fontawesome-etherpad.ttf b/sources/src/static/font/fontawesome-etherpad.ttf deleted file mode 100644 index f596b4f..0000000 Binary files a/sources/src/static/font/fontawesome-etherpad.ttf and /dev/null differ diff --git a/sources/src/static/font/fontawesome-etherpad.woff b/sources/src/static/font/fontawesome-etherpad.woff deleted file mode 100644 index ebca7ff..0000000 Binary files a/sources/src/static/font/fontawesome-etherpad.woff and /dev/null differ diff --git a/sources/src/static/font/opendyslexic.otf b/sources/src/static/font/opendyslexic.otf deleted file mode 100644 index 1a7c9d4..0000000 Binary files a/sources/src/static/font/opendyslexic.otf and /dev/null differ diff --git a/sources/src/static/js/AttributeManager.js b/sources/src/static/js/AttributeManager.js deleted file mode 100644 index 53b233e..0000000 --- a/sources/src/static/js/AttributeManager.js +++ /dev/null @@ -1,418 +0,0 @@ -var Changeset = require('./Changeset'); -var ChangesetUtils = require('./ChangesetUtils'); -var _ = require('./underscore'); - -var lineMarkerAttribute = 'lmkr'; - -// If one of these attributes are set to the first character of a -// line it is considered as a line attribute marker i.e. attributes -// set on this marker are applied to the whole line. -// The list attribute is only maintained for compatibility reasons -var lineAttributes = [lineMarkerAttribute,'list']; - -/* - The Attribute manager builds changesets based on a document - representation for setting and removing range or line-based attributes. - - @param rep the document representation to be used - @param applyChangesetCallback this callback will be called - once a changeset has been built. - - - A document representation contains - - an array `alines` containing 1 attributes string for each line - - an Attribute pool `apool` - - a SkipList `lines` containing the text lines of the document. -*/ - -var AttributeManager = function(rep, applyChangesetCallback) -{ - this.rep = rep; - this.applyChangesetCallback = applyChangesetCallback; - this.author = ''; - - // If the first char in a line has one of the following attributes - // it will be considered as a line marker -}; - -AttributeManager.lineAttributes = lineAttributes; - -AttributeManager.prototype = _(AttributeManager.prototype).extend({ - - applyChangeset: function(changeset){ - if(!this.applyChangesetCallback) return changeset; - - var cs = changeset.toString(); - if (!Changeset.isIdentity(cs)) - { - this.applyChangesetCallback(cs); - } - - return changeset; - }, - - /* - Sets attributes on a range - @param start [row, col] tuple pointing to the start of the range - @param end [row, col] tuple pointing to the end of the range - @param attribs: an array of attributes - */ - setAttributesOnRange: function(start, end, attribs) - { - // instead of applying the attributes to the whole range at once, we need to apply them - // line by line, to be able to disregard the "*" used as line marker. For more details, - // see https://github.com/ether/etherpad-lite/issues/2772 - var allChangesets; - for(var row = start[0]; row <= end[0]; row++) { - var rowRange = this._findRowRange(row, start, end); - var startCol = rowRange[0]; - var endCol = rowRange[1]; - - var rowChangeset = this._setAttributesOnRangeByLine(row, startCol, endCol, attribs); - - // compose changesets of all rows into a single changeset, as the range might not be continuous - // due to the presence of line markers on the rows - if (allChangesets) { - allChangesets = Changeset.compose(allChangesets.toString(), rowChangeset.toString(), this.rep.apool); - } else { - allChangesets = rowChangeset; - } - } - - return this.applyChangeset(allChangesets); - }, - - _findRowRange: function(row, start, end) - { - var startCol, endCol; - - var startLineOffset = this.rep.lines.offsetOfIndex(row); - var endLineOffset = this.rep.lines.offsetOfIndex(row+1); - var lineLength = endLineOffset - startLineOffset; - - // find column where range on this row starts - if (row === start[0]) { // are we on the first row of range? - startCol = start[1]; - } else { - startCol = this.lineHasMarker(row) ? 1 : 0; // remove "*" used as line marker - } - - // find column where range on this row ends - if (row === end[0]) { // are we on the last row of range? - endCol = end[1]; // if so, get the end of range, not end of row - } else { - endCol = lineLength - 1; // remove "\n" - } - - return [startCol, endCol]; - }, - - /* - Sets attributes on a range, by line - @param row the row where range is - @param startCol column where range starts - @param endCol column where range ends - @param attribs: an array of attributes - */ - _setAttributesOnRangeByLine: function(row, startCol, endCol, attribs) - { - var builder = Changeset.builder(this.rep.lines.totalWidth()); - ChangesetUtils.buildKeepToStartOfRange(this.rep, builder, [row, startCol]); - ChangesetUtils.buildKeepRange(this.rep, builder, [row, startCol], [row, endCol], attribs, this.rep.apool); - return builder; - }, - - /* - Returns if the line already has a line marker - @param lineNum: the number of the line - */ - lineHasMarker: function(lineNum){ - var that = this; - - return _.find(lineAttributes, function(attribute){ - return that.getAttributeOnLine(lineNum, attribute) != ''; - }) !== undefined; - }, - - /* - Gets a specified attribute on a line - @param lineNum: the number of the line to set the attribute for - @param attributeKey: the name of the attribute to get, e.g. list - */ - getAttributeOnLine: function(lineNum, attributeName){ - // get `attributeName` attribute of first char of line - var aline = this.rep.alines[lineNum]; - if (aline) - { - var opIter = Changeset.opIterator(aline); - if (opIter.hasNext()) - { - return Changeset.opAttributeValue(opIter.next(), attributeName, this.rep.apool) || ''; - } - } - return ''; - }, - - /* - Gets all attributes on a line - @param lineNum: the number of the line to get the attribute for - */ - getAttributesOnLine: function(lineNum){ - // get attributes of first char of line - var aline = this.rep.alines[lineNum]; - var attributes = [] - if (aline) - { - var opIter = Changeset.opIterator(aline) - , op - if (opIter.hasNext()) - { - op = opIter.next() - if(!op.attribs) return [] - - Changeset.eachAttribNumber(op.attribs, function(n) { - attributes.push([this.rep.apool.getAttribKey(n), this.rep.apool.getAttribValue(n)]) - }.bind(this)) - return attributes; - } - } - return []; - }, - - /* - Gets a given attribute on a selection - @param attributeName - @param prevChar - returns true or false if an attribute is visible in range - */ - getAttributeOnSelection: function(attributeName, prevChar){ - var rep = this.rep; - if (!(rep.selStart && rep.selEnd)) return - // If we're looking for the caret attribute not the selection - // has the user already got a selection or is this purely a caret location? - var isNotSelection = (rep.selStart[0] == rep.selEnd[0] && rep.selEnd[1] === rep.selStart[1]); - if(isNotSelection){ - if(prevChar){ - // If it's not the start of the line - if(rep.selStart[1] !== 0){ - rep.selStart[1]--; - } - } - } - - var withIt = Changeset.makeAttribsString('+', [ - [attributeName, 'true'] - ], rep.apool); - var withItRegex = new RegExp(withIt.replace(/\*/g, '\\*') + "(\\*|$)"); - function hasIt(attribs) - { - return withItRegex.test(attribs); - } - - return rangeHasAttrib(rep.selStart, rep.selEnd) - - function rangeHasAttrib(selStart, selEnd) { - // if range is collapsed -> no attribs in range - if(selStart[1] == selEnd[1] && selStart[0] == selEnd[0]) return false - - if(selStart[0] != selEnd[0]) { // -> More than one line selected - var hasAttrib = true - - // from selStart to the end of the first line - hasAttrib = hasAttrib && rangeHasAttrib(selStart, [selStart[0], rep.lines.atIndex(selStart[0]).text.length]) - - // for all lines in between - for(var n=selStart[0]+1; n < selEnd[0]; n++) { - hasAttrib = hasAttrib && rangeHasAttrib([n, 0], [n, rep.lines.atIndex(n).text.length]) - } - - // for the last, potentially partial, line - hasAttrib = hasAttrib && rangeHasAttrib([selEnd[0], 0], [selEnd[0], selEnd[1]]) - - return hasAttrib - } - - // Logic tells us we now have a range on a single line - - var lineNum = selStart[0] - , start = selStart[1] - , end = selEnd[1] - , hasAttrib = true - - // Iterate over attribs on this line - - var opIter = Changeset.opIterator(rep.alines[lineNum]) - , indexIntoLine = 0 - - while (opIter.hasNext()) { - var op = opIter.next(); - var opStartInLine = indexIntoLine; - var opEndInLine = opStartInLine + op.chars; - if (!hasIt(op.attribs)) { - // does op overlap selection? - if (!(opEndInLine <= start || opStartInLine >= end)) { - hasAttrib = false; // since it's overlapping but hasn't got the attrib -> range hasn't got it - break; - } - } - indexIntoLine = opEndInLine; - } - - return hasAttrib - } - }, - - /* - Gets all attributes at a position containing line number and column - @param lineNumber starting with zero - @param column starting with zero - returns a list of attributes in the format - [ ["key","value"], ["key","value"], ... ] - */ - getAttributesOnPosition: function(lineNumber, column){ - // get all attributes of the line - var aline = this.rep.alines[lineNumber]; - - if (!aline) { - return []; - } - // iterate through all operations of a line - var opIter = Changeset.opIterator(aline); - - // we need to sum up how much characters each operations take until the wanted position - var currentPointer = 0; - var attributes = []; - var currentOperation; - - while (opIter.hasNext()) { - currentOperation = opIter.next(); - currentPointer = currentPointer + currentOperation.chars; - - if (currentPointer > column) { - // we got the operation of the wanted position, now collect all its attributes - Changeset.eachAttribNumber(currentOperation.attribs, function (n) { - attributes.push([ - this.rep.apool.getAttribKey(n), - this.rep.apool.getAttribValue(n) - ]); - }.bind(this)); - - // skip the loop - return attributes; - } - } - return attributes; - - }, - - /* - Gets all attributes at caret position - if the user selected a range, the start of the selection is taken - returns a list of attributes in the format - [ ["key","value"], ["key","value"], ... ] - */ - getAttributesOnCaret: function(){ - return this.getAttributesOnPosition(this.rep.selStart[0], this.rep.selStart[1]); - }, - - /* - Sets a specified attribute on a line - @param lineNum: the number of the line to set the attribute for - @param attributeKey: the name of the attribute to set, e.g. list - @param attributeValue: an optional parameter to pass to the attribute (e.g. indention level) - - */ - setAttributeOnLine: function(lineNum, attributeName, attributeValue){ - var loc = [0,0]; - var builder = Changeset.builder(this.rep.lines.totalWidth()); - var hasMarker = this.lineHasMarker(lineNum); - - ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0])); - - if(hasMarker){ - ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 1]), [ - [attributeName, attributeValue] - ], this.rep.apool); - }else{ - // add a line marker - builder.insert('*', [ - ['author', this.author], - ['insertorder', 'first'], - [lineMarkerAttribute, '1'], - [attributeName, attributeValue] - ], this.rep.apool); - } - - return this.applyChangeset(builder); - }, - - /** - * Removes a specified attribute on a line - * @param lineNum the number of the affected line - * @param attributeName the name of the attribute to remove, e.g. list - * @param attributeValue if given only attributes with equal value will be removed - */ - removeAttributeOnLine: function(lineNum, attributeName, attributeValue){ - var builder = Changeset.builder(this.rep.lines.totalWidth()); - var hasMarker = this.lineHasMarker(lineNum); - var found = false; - - var attribs = _(this.getAttributesOnLine(lineNum)).map(function (attrib) { - if (attrib[0] === attributeName && (!attributeValue || attrib[0] === attributeValue)){ - found = true; - return [attributeName, '']; - }else if (attrib[0] === 'author'){ - // update last author to make changes to line attributes on this line - return [attributeName, this.author]; - } - return attrib; - }); - - if (!found) { - return; - } - - ChangesetUtils.buildKeepToStartOfRange(this.rep, builder, [lineNum, 0]); - - var countAttribsWithMarker = _.chain(attribs).filter(function(a){return !!a[1];}) - .map(function(a){return a[0];}).difference(['author', 'lmkr', 'insertorder', 'start']).size().value(); - - //if we have marker and any of attributes don't need to have marker. we need delete it - if(hasMarker && !countAttribsWithMarker){ - ChangesetUtils.buildRemoveRange(this.rep, builder, [lineNum, 0], [lineNum, 1]); - }else{ - ChangesetUtils.buildKeepRange(this.rep, builder, [lineNum, 0], [lineNum, 1], attribs, this.rep.apool); - } - - return this.applyChangeset(builder); - }, - - /* - Toggles a line attribute for the specified line number - If a line attribute with the specified name exists with any value it will be removed - Otherwise it will be set to the given value - @param lineNum: the number of the line to toggle the attribute for - @param attributeKey: the name of the attribute to toggle, e.g. list - @param attributeValue: the value to pass to the attribute (e.g. indention level) - */ - toggleAttributeOnLine: function(lineNum, attributeName, attributeValue) { - return this.getAttributeOnLine(lineNum, attributeName) ? - this.removeAttributeOnLine(lineNum, attributeName) : - this.setAttributeOnLine(lineNum, attributeName, attributeValue); - - }, - - hasAttributeOnSelectionOrCaretPosition: function(attributeName) { - var hasSelection = ((this.rep.selStart[0] !== this.rep.selEnd[0]) || (this.rep.selEnd[1] !== this.rep.selStart[1])); - var hasAttrib; - if (hasSelection) { - hasAttrib = this.getAttributeOnSelection(attributeName); - }else { - var attributesOnCaretPosition = this.getAttributesOnCaret(); - hasAttrib = _.contains(_.flatten(attributesOnCaretPosition), attributeName); - } - return hasAttrib; - }, -}); - -module.exports = AttributeManager; diff --git a/sources/src/static/js/AttributePool.js b/sources/src/static/js/AttributePool.js deleted file mode 100644 index 96ea9b0..0000000 --- a/sources/src/static/js/AttributePool.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * This code represents the Attribute Pool Object of the original Etherpad. - * 90% of the code is still like in the original Etherpad - * Look at https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js - * You can find a explanation what a attribute pool is here: - * https://github.com/ether/etherpad-lite/blob/master/doc/easysync/easysync-notes.txt - */ - -/* - * Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - An AttributePool maintains a mapping from [key,value] Pairs called - Attributes to Numbers (unsigened integers) and vice versa. These numbers are - used to reference Attributes in Changesets. -*/ - -var AttributePool = function () { - this.numToAttrib = {}; // e.g. {0: ['foo','bar']} - this.attribToNum = {}; // e.g. {'foo,bar': 0} - this.nextNum = 0; -}; - -AttributePool.prototype.putAttrib = function (attrib, dontAddIfAbsent) { - var str = String(attrib); - if (str in this.attribToNum) { - return this.attribToNum[str]; - } - if (dontAddIfAbsent) { - return -1; - } - var num = this.nextNum++; - this.attribToNum[str] = num; - this.numToAttrib[num] = [String(attrib[0] || ''), String(attrib[1] || '')]; - return num; -}; - -AttributePool.prototype.getAttrib = function (num) { - var pair = this.numToAttrib[num]; - if (!pair) { - return pair; - } - return [pair[0], pair[1]]; // return a mutable copy -}; - -AttributePool.prototype.getAttribKey = function (num) { - var pair = this.numToAttrib[num]; - if (!pair) return ''; - return pair[0]; -}; - -AttributePool.prototype.getAttribValue = function (num) { - var pair = this.numToAttrib[num]; - if (!pair) return ''; - return pair[1]; -}; - -AttributePool.prototype.eachAttrib = function (func) { - for (var n in this.numToAttrib) { - var pair = this.numToAttrib[n]; - func(pair[0], pair[1]); - } -}; - -AttributePool.prototype.toJsonable = function () { - return { - numToAttrib: this.numToAttrib, - nextNum: this.nextNum - }; -}; - -AttributePool.prototype.fromJsonable = function (obj) { - this.numToAttrib = obj.numToAttrib; - this.nextNum = obj.nextNum; - this.attribToNum = {}; - for (var n in this.numToAttrib) { - this.attribToNum[String(this.numToAttrib[n])] = Number(n); - } - return this; -}; - - -module.exports = AttributePool; \ No newline at end of file diff --git a/sources/src/static/js/Changeset.js b/sources/src/static/js/Changeset.js deleted file mode 100644 index 6f6e7d0..0000000 --- a/sources/src/static/js/Changeset.js +++ /dev/null @@ -1,2313 +0,0 @@ -/* - * This is the Changeset library copied from the old Etherpad with some modifications to use it in node.js - * Can be found in https://github.com/ether/pad/blob/master/infrastructure/ace/www/easysync2.js - */ - -/** - * This code is mostly from the old Etherpad. Please help us to comment this code. - * This helps other people to understand this code better and helps them to improve it. - * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED - */ - -/* - * Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var AttributePool = require("./AttributePool"); - -/** - * ==================== General Util Functions ======================= - */ - -/** - * This method is called whenever there is an error in the sync process - * @param msg {string} Just some message - */ -exports.error = function error(msg) { - var e = new Error(msg); - e.easysync = true; - throw e; -}; - -/** - * This method is used for assertions with Messages - * if assert fails, the error function is called. - * @param b {boolean} assertion condition - * @param msgParts {string} error to be passed if it fails - */ -exports.assert = function assert(b, msgParts) { - if (!b) { - var msg = Array.prototype.slice.call(arguments, 1).join(''); - exports.error("Failed assertion: " + msg); - } -}; - -/** - * Parses a number from string base 36 - * @param str {string} string of the number in base 36 - * @returns {int} number - */ -exports.parseNum = function (str) { - return parseInt(str, 36); -}; - -/** - * Writes a number in base 36 and puts it in a string - * @param num {int} number - * @returns {string} string - */ -exports.numToString = function (num) { - return num.toString(36).toLowerCase(); -}; - -/** - * Converts stuff before $ to base 10 - * @obsolete not really used anywhere?? - * @param cs {string} the string - * @return integer - */ -exports.toBaseTen = function (cs) { - var dollarIndex = cs.indexOf('$'); - var beforeDollar = cs.substring(0, dollarIndex); - var fromDollar = cs.substring(dollarIndex); - return beforeDollar.replace(/[0-9a-z]+/g, function (s) { - return String(exports.parseNum(s)); - }) + fromDollar; -}; - - -/** - * ==================== Changeset Functions ======================= - */ - -/** - * returns the required length of the text before changeset - * can be applied - * @param cs {string} String representation of the Changeset - */ -exports.oldLen = function (cs) { - return exports.unpack(cs).oldLen; -}; - -/** - * returns the length of the text after changeset is applied - * @param cs {string} String representation of the Changeset - */ -exports.newLen = function (cs) { - return exports.unpack(cs).newLen; -}; - -/** - * this function creates an iterator which decodes string changeset operations - * @param opsStr {string} String encoding of the change operations to be performed - * @param optStartIndex {int} from where in the string should the iterator start - * @return {Op} type object iterator - */ -exports.opIterator = function (opsStr, optStartIndex) { - //print(opsStr); - var regex = /((?:\*[0-9a-z]+)*)(?:\|([0-9a-z]+))?([-+=])([0-9a-z]+)|\?|/g; - var startIndex = (optStartIndex || 0); - var curIndex = startIndex; - var prevIndex = curIndex; - - function nextRegexMatch() { - prevIndex = curIndex; - var result; - regex.lastIndex = curIndex; - result = regex.exec(opsStr); - curIndex = regex.lastIndex; - if (result[0] == '?') { - exports.error("Hit error opcode in op stream"); - } - - return result; - } - var regexResult = nextRegexMatch(); - var obj = exports.newOp(); - - function next(optObj) { - var op = (optObj || obj); - if (regexResult[0]) { - op.attribs = regexResult[1]; - op.lines = exports.parseNum(regexResult[2] || 0); - op.opcode = regexResult[3]; - op.chars = exports.parseNum(regexResult[4]); - regexResult = nextRegexMatch(); - } else { - exports.clearOp(op); - } - return op; - } - - function hasNext() { - return !!(regexResult[0]); - } - - function lastIndex() { - return prevIndex; - } - return { - next: next, - hasNext: hasNext, - lastIndex: lastIndex - }; -}; - -/** - * Cleans an Op object - * @param {Op} object to be cleared - */ -exports.clearOp = function (op) { - op.opcode = ''; - op.chars = 0; - op.lines = 0; - op.attribs = ''; -}; - -/** - * Creates a new Op object - * @param optOpcode the type operation of the Op object - */ -exports.newOp = function (optOpcode) { - return { - opcode: (optOpcode || ''), - chars: 0, - lines: 0, - attribs: '' - }; -}; - -/** - * Clones an Op - * @param op Op to be cloned - */ -exports.cloneOp = function (op) { - return { - opcode: op.opcode, - chars: op.chars, - lines: op.lines, - attribs: op.attribs - }; -}; - -/** - * Copies op1 to op2 - * @param op1 src Op - * @param op2 dest Op - */ -exports.copyOp = function (op1, op2) { - op2.opcode = op1.opcode; - op2.chars = op1.chars; - op2.lines = op1.lines; - op2.attribs = op1.attribs; -}; - -/** - * Writes the Op in a string the way that changesets need it - */ -exports.opString = function (op) { - // just for debugging - if (!op.opcode) return 'null'; - var assem = exports.opAssembler(); - assem.append(op); - return assem.toString(); -}; - -/** - * Used just for debugging - */ -exports.stringOp = function (str) { - // just for debugging - return exports.opIterator(str).next(); -}; - -/** - * Used to check if a Changeset if valid - * @param cs {Changeset} Changeset to be checked - */ -exports.checkRep = function (cs) { - // doesn't check things that require access to attrib pool (e.g. attribute order) - // or original string (e.g. newline positions) - var unpacked = exports.unpack(cs); - var oldLen = unpacked.oldLen; - var newLen = unpacked.newLen; - var ops = unpacked.ops; - var charBank = unpacked.charBank; - - var assem = exports.smartOpAssembler(); - var oldPos = 0; - var calcNewLen = 0; - var numInserted = 0; - var iter = exports.opIterator(ops); - while (iter.hasNext()) { - var o = iter.next(); - switch (o.opcode) { - case '=': - oldPos += o.chars; - calcNewLen += o.chars; - break; - case '-': - oldPos += o.chars; - exports.assert(oldPos <= oldLen, oldPos, " > ", oldLen, " in ", cs); - break; - case '+': - { - calcNewLen += o.chars; - numInserted += o.chars; - exports.assert(calcNewLen <= newLen, calcNewLen, " > ", newLen, " in ", cs); - break; - } - } - assem.append(o); - } - - calcNewLen += oldLen - oldPos; - charBank = charBank.substring(0, numInserted); - while (charBank.length < numInserted) { - charBank += "?"; - } - - assem.endDocument(); - var normalized = exports.pack(oldLen, calcNewLen, assem.toString(), charBank); - exports.assert(normalized == cs, 'Invalid changeset (checkRep failed)'); - - return cs; -} - - -/** - * ==================== Util Functions ======================= - */ - -/** - * creates an object that allows you to append operations (type Op) and also - * compresses them if possible - */ -exports.smartOpAssembler = function () { - // Like opAssembler but able to produce conforming exportss - // from slightly looser input, at the cost of speed. - // Specifically: - // - merges consecutive operations that can be merged - // - strips final "=" - // - ignores 0-length changes - // - reorders consecutive + and - (which margingOpAssembler doesn't do) - var minusAssem = exports.mergingOpAssembler(); - var plusAssem = exports.mergingOpAssembler(); - var keepAssem = exports.mergingOpAssembler(); - var assem = exports.stringAssembler(); - var lastOpcode = ''; - var lengthChange = 0; - - function flushKeeps() { - assem.append(keepAssem.toString()); - keepAssem.clear(); - } - - function flushPlusMinus() { - assem.append(minusAssem.toString()); - minusAssem.clear(); - assem.append(plusAssem.toString()); - plusAssem.clear(); - } - - function append(op) { - if (!op.opcode) return; - if (!op.chars) return; - - if (op.opcode == '-') { - if (lastOpcode == '=') { - flushKeeps(); - } - minusAssem.append(op); - lengthChange -= op.chars; - } else if (op.opcode == '+') { - if (lastOpcode == '=') { - flushKeeps(); - } - plusAssem.append(op); - lengthChange += op.chars; - } else if (op.opcode == '=') { - if (lastOpcode != '=') { - flushPlusMinus(); - } - keepAssem.append(op); - } - lastOpcode = op.opcode; - } - - function appendOpWithText(opcode, text, attribs, pool) { - var op = exports.newOp(opcode); - op.attribs = exports.makeAttribsString(opcode, attribs, pool); - var lastNewlinePos = text.lastIndexOf('\n'); - if (lastNewlinePos < 0) { - op.chars = text.length; - op.lines = 0; - append(op); - } else { - op.chars = lastNewlinePos + 1; - op.lines = text.match(/\n/g).length; - append(op); - op.chars = text.length - (lastNewlinePos + 1); - op.lines = 0; - append(op); - } - } - - function toString() { - flushPlusMinus(); - flushKeeps(); - return assem.toString(); - } - - function clear() { - minusAssem.clear(); - plusAssem.clear(); - keepAssem.clear(); - assem.clear(); - lengthChange = 0; - } - - function endDocument() { - keepAssem.endDocument(); - } - - function getLengthChange() { - return lengthChange; - } - - return { - append: append, - toString: toString, - clear: clear, - endDocument: endDocument, - appendOpWithText: appendOpWithText, - getLengthChange: getLengthChange - }; -}; - - -exports.mergingOpAssembler = function () { - // This assembler can be used in production; it efficiently - // merges consecutive operations that are mergeable, ignores - // no-ops, and drops final pure "keeps". It does not re-order - // operations. - var assem = exports.opAssembler(); - var bufOp = exports.newOp(); - - // If we get, for example, insertions [xxx\n,yyy], those don't merge, - // but if we get [xxx\n,yyy,zzz\n], that merges to [xxx\nyyyzzz\n]. - // This variable stores the length of yyy and any other newline-less - // ops immediately after it. - var bufOpAdditionalCharsAfterNewline = 0; - - function flush(isEndDocument) { - if (bufOp.opcode) { - if (isEndDocument && bufOp.opcode == '=' && !bufOp.attribs) { - // final merged keep, leave it implicit - } else { - assem.append(bufOp); - if (bufOpAdditionalCharsAfterNewline) { - bufOp.chars = bufOpAdditionalCharsAfterNewline; - bufOp.lines = 0; - assem.append(bufOp); - bufOpAdditionalCharsAfterNewline = 0; - } - } - bufOp.opcode = ''; - } - } - - function append(op) { - if (op.chars > 0) { - if (bufOp.opcode == op.opcode && bufOp.attribs == op.attribs) { - if (op.lines > 0) { - // bufOp and additional chars are all mergeable into a multi-line op - bufOp.chars += bufOpAdditionalCharsAfterNewline + op.chars; - bufOp.lines += op.lines; - bufOpAdditionalCharsAfterNewline = 0; - } else if (bufOp.lines == 0) { - // both bufOp and op are in-line - bufOp.chars += op.chars; - } else { - // append in-line text to multi-line bufOp - bufOpAdditionalCharsAfterNewline += op.chars; - } - } else { - flush(); - exports.copyOp(op, bufOp); - } - } - } - - function endDocument() { - flush(true); - } - - function toString() { - flush(); - return assem.toString(); - } - - function clear() { - assem.clear(); - exports.clearOp(bufOp); - } - return { - append: append, - toString: toString, - clear: clear, - endDocument: endDocument - }; -}; - - - -exports.opAssembler = function () { - var pieces = []; - // this function allows op to be mutated later (doesn't keep a ref) - - function append(op) { - pieces.push(op.attribs); - if (op.lines) { - pieces.push('|', exports.numToString(op.lines)); - } - pieces.push(op.opcode); - pieces.push(exports.numToString(op.chars)); - } - - function toString() { - return pieces.join(''); - } - - function clear() { - pieces.length = 0; - } - return { - append: append, - toString: toString, - clear: clear - }; -}; - -/** - * A custom made String Iterator - * @param str {string} String to be iterated over - */ -exports.stringIterator = function (str) { - var curIndex = 0; - // newLines is the number of \n between curIndex and str.length - var newLines = str.split("\n").length - 1 - function getnewLines(){ - return newLines - } - - function assertRemaining(n) { - exports.assert(n <= remaining(), "!(", n, " <= ", remaining(), ")"); - } - - function take(n) { - assertRemaining(n); - var s = str.substr(curIndex, n); - newLines -= s.split("\n").length - 1 - curIndex += n; - return s; - } - - function peek(n) { - assertRemaining(n); - var s = str.substr(curIndex, n); - return s; - } - - function skip(n) { - assertRemaining(n); - curIndex += n; - } - - function remaining() { - return str.length - curIndex; - } - return { - take: take, - skip: skip, - remaining: remaining, - peek: peek, - newlines: getnewLines - }; -}; - -/** - * A custom made StringBuffer - */ -exports.stringAssembler = function () { - var pieces = []; - - function append(x) { - pieces.push(String(x)); - } - - function toString() { - return pieces.join(''); - } - return { - append: append, - toString: toString - }; -}; - -/** - * This class allows to iterate and modify texts which have several lines - * It is used for applying Changesets on arrays of lines - * Note from prev docs: "lines" need not be an array as long as it supports certain calls (lines_foo inside). - */ -exports.textLinesMutator = function (lines) { - // Mutates lines, an array of strings, in place. - // Mutation operations have the same constraints as exports operations - // with respect to newlines, but not the other additional constraints - // (i.e. ins/del ordering, forbidden no-ops, non-mergeability, final newline). - // Can be used to mutate lists of strings where the last char of each string - // is not actually a newline, but for the purposes of N and L values, - // the caller should pretend it is, and for things to work right in that case, the input - // to insert() should be a single line with no newlines. - var curSplice = [0, 0]; - var inSplice = false; - // position in document after curSplice is applied: - var curLine = 0, - curCol = 0; - // invariant: if (inSplice) then (curLine is in curSplice[0] + curSplice.length - {2,3}) && - // curLine >= curSplice[0] - // invariant: if (inSplice && (curLine >= curSplice[0] + curSplice.length - 2)) then - // curCol == 0 - - function lines_applySplice(s) { - lines.splice.apply(lines, s); - } - - function lines_toSource() { - return lines.toSource(); - } - - function lines_get(idx) { - if (lines.get) { - return lines.get(idx); - } else { - return lines[idx]; - } - } - // can be unimplemented if removeLines's return value not needed - - function lines_slice(start, end) { - if (lines.slice) { - return lines.slice(start, end); - } else { - return []; - } - } - - function lines_length() { - if ((typeof lines.length) == "number") { - return lines.length; - } else { - return lines.length(); - } - } - - function enterSplice() { - curSplice[0] = curLine; - curSplice[1] = 0; - if (curCol > 0) { - putCurLineInSplice(); - } - inSplice = true; - } - - function leaveSplice() { - lines_applySplice(curSplice); - curSplice.length = 2; - curSplice[0] = curSplice[1] = 0; - inSplice = false; - } - - function isCurLineInSplice() { - return (curLine - curSplice[0] < (curSplice.length - 2)); - } - - function debugPrint(typ) { - print(typ + ": " + curSplice.toSource() + " / " + curLine + "," + curCol + " / " + lines_toSource()); - } - - function putCurLineInSplice() { - if (!isCurLineInSplice()) { - curSplice.push(lines_get(curSplice[0] + curSplice[1])); - curSplice[1]++; - } - return 2 + curLine - curSplice[0]; - } - - function skipLines(L, includeInSplice) { - if (L) { - if (includeInSplice) { - if (!inSplice) { - enterSplice(); - } - for (var i = 0; i < L; i++) { - curCol = 0; - putCurLineInSplice(); - curLine++; - } - } else { - if (inSplice) { - if (L > 1) { - leaveSplice(); - } else { - putCurLineInSplice(); - } - } - curLine += L; - curCol = 0; - } - //print(inSplice+" / "+isCurLineInSplice()+" / "+curSplice[0]+" / "+curSplice[1]+" / "+lines.length); -/*if (inSplice && (! isCurLineInSplice()) && (curSplice[0] + curSplice[1] < lines.length)) { - print("BLAH"); - putCurLineInSplice(); -}*/ - // tests case foo in remove(), which isn't otherwise covered in current impl - } - //debugPrint("skip"); - } - - function skip(N, L, includeInSplice) { - if (N) { - if (L) { - skipLines(L, includeInSplice); - } else { - if (includeInSplice && !inSplice) { - enterSplice(); - } - if (inSplice) { - putCurLineInSplice(); - } - curCol += N; - //debugPrint("skip"); - } - } - } - - function removeLines(L) { - var removed = ''; - if (L) { - if (!inSplice) { - enterSplice(); - } - - function nextKLinesText(k) { - var m = curSplice[0] + curSplice[1]; - return lines_slice(m, m + k).join(''); - } - if (isCurLineInSplice()) { - //print(curCol); - if (curCol == 0) { - removed = curSplice[curSplice.length - 1]; - // print("FOO"); // case foo - curSplice.length--; - removed += nextKLinesText(L - 1); - curSplice[1] += L - 1; - } else { - removed = nextKLinesText(L - 1); - curSplice[1] += L - 1; - var sline = curSplice.length - 1; - removed = curSplice[sline].substring(curCol) + removed; - curSplice[sline] = curSplice[sline].substring(0, curCol) + lines_get(curSplice[0] + curSplice[1]); - curSplice[1] += 1; - } - } else { - removed = nextKLinesText(L); - curSplice[1] += L; - } - //debugPrint("remove"); - } - return removed; - } - - function remove(N, L) { - var removed = ''; - if (N) { - if (L) { - return removeLines(L); - } else { - if (!inSplice) { - enterSplice(); - } - var sline = putCurLineInSplice(); - removed = curSplice[sline].substring(curCol, curCol + N); - curSplice[sline] = curSplice[sline].substring(0, curCol) + curSplice[sline].substring(curCol + N); - //debugPrint("remove"); - } - } - return removed; - } - - function insert(text, L) { - if (text) { - if (!inSplice) { - enterSplice(); - } - if (L) { - var newLines = exports.splitTextLines(text); - if (isCurLineInSplice()) { - //if (curCol == 0) { - //curSplice.length--; - //curSplice[1]--; - //Array.prototype.push.apply(curSplice, newLines); - //curLine += newLines.length; - //} - //else { - var sline = curSplice.length - 1; - var theLine = curSplice[sline]; - var lineCol = curCol; - curSplice[sline] = theLine.substring(0, lineCol) + newLines[0]; - curLine++; - newLines.splice(0, 1); - Array.prototype.push.apply(curSplice, newLines); - curLine += newLines.length; - curSplice.push(theLine.substring(lineCol)); - curCol = 0; - //} - } else { - Array.prototype.push.apply(curSplice, newLines); - curLine += newLines.length; - } - } else { - var sline = putCurLineInSplice(); - curSplice[sline] = curSplice[sline].substring(0, curCol) + text + curSplice[sline].substring(curCol); - curCol += text.length; - } - //debugPrint("insert"); - } - } - - function hasMore() { - //print(lines.length+" / "+inSplice+" / "+(curSplice.length - 2)+" / "+curSplice[1]); - var docLines = lines_length(); - if (inSplice) { - docLines += curSplice.length - 2 - curSplice[1]; - } - return curLine < docLines; - } - - function close() { - if (inSplice) { - leaveSplice(); - } - //debugPrint("close"); - } - - var self = { - skip: skip, - remove: remove, - insert: insert, - close: close, - hasMore: hasMore, - removeLines: removeLines, - skipLines: skipLines - }; - return self; -}; - -/** - * Function allowing iterating over two Op strings. - * @params in1 {string} first Op string - * @params idx1 {int} integer where 1st iterator should start - * @params in2 {string} second Op string - * @params idx2 {int} integer where 2nd iterator should start - * @params func {function} which decides how 1st or 2nd iterator - * advances. When opX.opcode = 0, iterator X advances to - * next element - * func has signature f(op1, op2, opOut) - * op1 - current operation of the first iterator - * op2 - current operation of the second iterator - * opOut - result operator to be put into Changeset - * @return {string} the integrated changeset - */ -exports.applyZip = function (in1, idx1, in2, idx2, func) { - var iter1 = exports.opIterator(in1, idx1); - var iter2 = exports.opIterator(in2, idx2); - var assem = exports.smartOpAssembler(); - var op1 = exports.newOp(); - var op2 = exports.newOp(); - var opOut = exports.newOp(); - while (op1.opcode || iter1.hasNext() || op2.opcode || iter2.hasNext()) { - if ((!op1.opcode) && iter1.hasNext()) iter1.next(op1); - if ((!op2.opcode) && iter2.hasNext()) iter2.next(op2); - func(op1, op2, opOut); - if (opOut.opcode) { - //print(opOut.toSource()); - assem.append(opOut); - opOut.opcode = ''; - } - } - assem.endDocument(); - return assem.toString(); -}; - -/** - * Unpacks a string encoded Changeset into a proper Changeset object - * @params cs {string} String encoded Changeset - * @returns {Changeset} a Changeset class - */ -exports.unpack = function (cs) { - var headerRegex = /Z:([0-9a-z]+)([><])([0-9a-z]+)|/; - var headerMatch = headerRegex.exec(cs); - if ((!headerMatch) || (!headerMatch[0])) { - exports.error("Not a exports: " + cs); - } - var oldLen = exports.parseNum(headerMatch[1]); - var changeSign = (headerMatch[2] == '>') ? 1 : -1; - var changeMag = exports.parseNum(headerMatch[3]); - var newLen = oldLen + changeSign * changeMag; - var opsStart = headerMatch[0].length; - var opsEnd = cs.indexOf("$"); - if (opsEnd < 0) opsEnd = cs.length; - return { - oldLen: oldLen, - newLen: newLen, - ops: cs.substring(opsStart, opsEnd), - charBank: cs.substring(opsEnd + 1) - }; -}; - -/** - * Packs Changeset object into a string - * @params oldLen {int} Old length of the Changeset - * @params newLen {int] New length of the Changeset - * @params opsStr {string} String encoding of the changes to be made - * @params bank {string} Charbank of the Changeset - * @returns {Changeset} a Changeset class - */ -exports.pack = function (oldLen, newLen, opsStr, bank) { - var lenDiff = newLen - oldLen; - var lenDiffStr = (lenDiff >= 0 ? '>' + exports.numToString(lenDiff) : '<' + exports.numToString(-lenDiff)); - var a = []; - a.push('Z:', exports.numToString(oldLen), lenDiffStr, opsStr, '$', bank); - return a.join(''); -}; - -/** - * Applies a Changeset to a string - * @params cs {string} String encoded Changeset - * @params str {string} String to which a Changeset should be applied - */ -exports.applyToText = function (cs, str) { - var unpacked = exports.unpack(cs); - exports.assert(str.length == unpacked.oldLen, "mismatched apply: ", str.length, " / ", unpacked.oldLen); - var csIter = exports.opIterator(unpacked.ops); - var bankIter = exports.stringIterator(unpacked.charBank); - var strIter = exports.stringIterator(str); - var assem = exports.stringAssembler(); - while (csIter.hasNext()) { - var op = csIter.next(); - switch (op.opcode) { - case '+': - //op is + and op.lines 0: no newlines must be in op.chars - //op is + and op.lines >0: op.chars must include op.lines newlines - if(op.lines != bankIter.peek(op.chars).split("\n").length - 1){ - throw new Error("newline count is wrong in op +; cs:"+cs+" and text:"+str); - } - assem.append(bankIter.take(op.chars)); - break; - case '-': - //op is - and op.lines 0: no newlines must be in the deleted string - //op is - and op.lines >0: op.lines newlines must be in the deleted string - if(op.lines != strIter.peek(op.chars).split("\n").length - 1){ - throw new Error("newline count is wrong in op -; cs:"+cs+" and text:"+str); - } - strIter.skip(op.chars); - break; - case '=': - //op is = and op.lines 0: no newlines must be in the copied string - //op is = and op.lines >0: op.lines newlines must be in the copied string - if(op.lines != strIter.peek(op.chars).split("\n").length - 1){ - throw new Error("newline count is wrong in op =; cs:"+cs+" and text:"+str); - } - assem.append(strIter.take(op.chars)); - break; - } - } - assem.append(strIter.take(strIter.remaining())); - return assem.toString(); -}; - -/** - * applies a changeset on an array of lines - * @param CS {Changeset} the changeset to be applied - * @param lines The lines to which the changeset needs to be applied - */ -exports.mutateTextLines = function (cs, lines) { - var unpacked = exports.unpack(cs); - var csIter = exports.opIterator(unpacked.ops); - var bankIter = exports.stringIterator(unpacked.charBank); - var mut = exports.textLinesMutator(lines); - while (csIter.hasNext()) { - var op = csIter.next(); - switch (op.opcode) { - case '+': - mut.insert(bankIter.take(op.chars), op.lines); - break; - case '-': - mut.remove(op.chars, op.lines); - break; - case '=': - mut.skip(op.chars, op.lines, ( !! op.attribs)); - break; - } - } - mut.close(); -}; - -/** - * Composes two attribute strings (see below) into one. - * @param att1 {string} first attribute string - * @param att2 {string} second attribue string - * @param resultIsMutaton {boolean} - * @param pool {AttribPool} attribute pool - */ -exports.composeAttributes = function (att1, att2, resultIsMutation, pool) { - // att1 and att2 are strings like "*3*f*1c", asMutation is a boolean. - // Sometimes attribute (key,value) pairs are treated as attribute presence - // information, while other times they are treated as operations that - // mutate a set of attributes, and this affects whether an empty value - // is a deletion or a change. - // Examples, of the form (att1Items, att2Items, resultIsMutation) -> result - // ([], [(bold, )], true) -> [(bold, )] - // ([], [(bold, )], false) -> [] - // ([], [(bold, true)], true) -> [(bold, true)] - // ([], [(bold, true)], false) -> [(bold, true)] - // ([(bold, true)], [(bold, )], true) -> [(bold, )] - // ([(bold, true)], [(bold, )], false) -> [] - // pool can be null if att2 has no attributes. - if ((!att1) && resultIsMutation) { - // In the case of a mutation (i.e. composing two exportss), - // an att2 composed with an empy att1 is just att2. If att1 - // is part of an attribution string, then att2 may remove - // attributes that are already gone, so don't do this optimization. - return att2; - } - if (!att2) return att1; - var atts = []; - att1.replace(/\*([0-9a-z]+)/g, function (_, a) { - atts.push(pool.getAttrib(exports.parseNum(a))); - return ''; - }); - att2.replace(/\*([0-9a-z]+)/g, function (_, a) { - var pair = pool.getAttrib(exports.parseNum(a)); - var found = false; - for (var i = 0; i < atts.length; i++) { - var oldPair = atts[i]; - if (oldPair[0] == pair[0]) { - if (pair[1] || resultIsMutation) { - oldPair[1] = pair[1]; - } else { - atts.splice(i, 1); - } - found = true; - break; - } - } - if ((!found) && (pair[1] || resultIsMutation)) { - atts.push(pair); - } - return ''; - }); - atts.sort(); - var buf = exports.stringAssembler(); - for (var i = 0; i < atts.length; i++) { - buf.append('*'); - buf.append(exports.numToString(pool.putAttrib(atts[i]))); - } - //print(att1+" / "+att2+" / "+buf.toString()); - return buf.toString(); -}; - -/** - * Function used as parameter for applyZip to apply a Changeset to an - * attribute - */ -exports._slicerZipperFunc = function (attOp, csOp, opOut, pool) { - // attOp is the op from the sequence that is being operated on, either an - // attribution string or the earlier of two exportss being composed. - // pool can be null if definitely not needed. - //print(csOp.toSource()+" "+attOp.toSource()+" "+opOut.toSource()); - if (attOp.opcode == '-') { - exports.copyOp(attOp, opOut); - attOp.opcode = ''; - } else if (!attOp.opcode) { - exports.copyOp(csOp, opOut); - csOp.opcode = ''; - } else { - switch (csOp.opcode) { - case '-': - { - if (csOp.chars <= attOp.chars) { - // delete or delete part - if (attOp.opcode == '=') { - opOut.opcode = '-'; - opOut.chars = csOp.chars; - opOut.lines = csOp.lines; - opOut.attribs = ''; - } - attOp.chars -= csOp.chars; - attOp.lines -= csOp.lines; - csOp.opcode = ''; - if (!attOp.chars) { - attOp.opcode = ''; - } - } else { - // delete and keep going - if (attOp.opcode == '=') { - opOut.opcode = '-'; - opOut.chars = attOp.chars; - opOut.lines = attOp.lines; - opOut.attribs = ''; - } - csOp.chars -= attOp.chars; - csOp.lines -= attOp.lines; - attOp.opcode = ''; - } - break; - } - case '+': - { - // insert - exports.copyOp(csOp, opOut); - csOp.opcode = ''; - break; - } - case '=': - { - if (csOp.chars <= attOp.chars) { - // keep or keep part - opOut.opcode = attOp.opcode; - opOut.chars = csOp.chars; - opOut.lines = csOp.lines; - opOut.attribs = exports.composeAttributes(attOp.attribs, csOp.attribs, attOp.opcode == '=', pool); - csOp.opcode = ''; - attOp.chars -= csOp.chars; - attOp.lines -= csOp.lines; - if (!attOp.chars) { - attOp.opcode = ''; - } - } else { - // keep and keep going - opOut.opcode = attOp.opcode; - opOut.chars = attOp.chars; - opOut.lines = attOp.lines; - opOut.attribs = exports.composeAttributes(attOp.attribs, csOp.attribs, attOp.opcode == '=', pool); - attOp.opcode = ''; - csOp.chars -= attOp.chars; - csOp.lines -= attOp.lines; - } - break; - } - case '': - { - exports.copyOp(attOp, opOut); - attOp.opcode = ''; - break; - } - } - } -}; - -/** - * Applies a Changeset to the attribs string of a AText. - * @param cs {string} Changeset - * @param astr {string} the attribs string of a AText - * @param pool {AttribsPool} the attibutes pool - */ -exports.applyToAttribution = function (cs, astr, pool) { - var unpacked = exports.unpack(cs); - - return exports.applyZip(astr, 0, unpacked.ops, 0, function (op1, op2, opOut) { - return exports._slicerZipperFunc(op1, op2, opOut, pool); - }); -}; - -/*exports.oneInsertedLineAtATimeOpIterator = function(opsStr, optStartIndex, charBank) { - var iter = exports.opIterator(opsStr, optStartIndex); - var bankIndex = 0; - -};*/ - -exports.mutateAttributionLines = function (cs, lines, pool) { - //dmesg(cs); - //dmesg(lines.toSource()+" ->"); - var unpacked = exports.unpack(cs); - var csIter = exports.opIterator(unpacked.ops); - var csBank = unpacked.charBank; - var csBankIndex = 0; - // treat the attribution lines as text lines, mutating a line at a time - var mut = exports.textLinesMutator(lines); - - var lineIter = null; - - function isNextMutOp() { - return (lineIter && lineIter.hasNext()) || mut.hasMore(); - } - - function nextMutOp(destOp) { - if ((!(lineIter && lineIter.hasNext())) && mut.hasMore()) { - var line = mut.removeLines(1); - lineIter = exports.opIterator(line); - } - if (lineIter && lineIter.hasNext()) { - lineIter.next(destOp); - } else { - destOp.opcode = ''; - } - } - var lineAssem = null; - - function outputMutOp(op) { - //print("outputMutOp: "+op.toSource()); - if (!lineAssem) { - lineAssem = exports.mergingOpAssembler(); - } - lineAssem.append(op); - if (op.lines > 0) { - exports.assert(op.lines == 1, "Can't have op.lines of ", op.lines, " in attribution lines"); - // ship it to the mut - mut.insert(lineAssem.toString(), 1); - lineAssem = null; - } - } - - var csOp = exports.newOp(); - var attOp = exports.newOp(); - var opOut = exports.newOp(); - while (csOp.opcode || csIter.hasNext() || attOp.opcode || isNextMutOp()) { - if ((!csOp.opcode) && csIter.hasNext()) { - csIter.next(csOp); - } - //print(csOp.toSource()+" "+attOp.toSource()+" "+opOut.toSource()); - //print(csOp.opcode+"/"+csOp.lines+"/"+csOp.attribs+"/"+lineAssem+"/"+lineIter+"/"+(lineIter?lineIter.hasNext():null)); - //print("csOp: "+csOp.toSource()); - if ((!csOp.opcode) && (!attOp.opcode) && (!lineAssem) && (!(lineIter && lineIter.hasNext()))) { - break; // done - } else if (csOp.opcode == '=' && csOp.lines > 0 && (!csOp.attribs) && (!attOp.opcode) && (!lineAssem) && (!(lineIter && lineIter.hasNext()))) { - // skip multiple lines; this is what makes small changes not order of the document size - mut.skipLines(csOp.lines); - //print("skipped: "+csOp.lines); - csOp.opcode = ''; - } else if (csOp.opcode == '+') { - if (csOp.lines > 1) { - var firstLineLen = csBank.indexOf('\n', csBankIndex) + 1 - csBankIndex; - exports.copyOp(csOp, opOut); - csOp.chars -= firstLineLen; - csOp.lines--; - opOut.lines = 1; - opOut.chars = firstLineLen; - } else { - exports.copyOp(csOp, opOut); - csOp.opcode = ''; - } - outputMutOp(opOut); - csBankIndex += opOut.chars; - opOut.opcode = ''; - } else { - if ((!attOp.opcode) && isNextMutOp()) { - nextMutOp(attOp); - } - //print("attOp: "+attOp.toSource()); - exports._slicerZipperFunc(attOp, csOp, opOut, pool); - if (opOut.opcode) { - outputMutOp(opOut); - opOut.opcode = ''; - } - } - } - - exports.assert(!lineAssem, "line assembler not finished:"+cs); - mut.close(); - - //dmesg("-> "+lines.toSource()); -}; - -/** - * joins several Attribution lines - * @param theAlines collection of Attribution lines - * @returns {string} joined Attribution lines - */ -exports.joinAttributionLines = function (theAlines) { - var assem = exports.mergingOpAssembler(); - for (var i = 0; i < theAlines.length; i++) { - var aline = theAlines[i]; - var iter = exports.opIterator(aline); - while (iter.hasNext()) { - assem.append(iter.next()); - } - } - return assem.toString(); -}; - -exports.splitAttributionLines = function (attrOps, text) { - var iter = exports.opIterator(attrOps); - var assem = exports.mergingOpAssembler(); - var lines = []; - var pos = 0; - - function appendOp(op) { - assem.append(op); - if (op.lines > 0) { - lines.push(assem.toString()); - assem.clear(); - } - pos += op.chars; - } - - while (iter.hasNext()) { - var op = iter.next(); - var numChars = op.chars; - var numLines = op.lines; - while (numLines > 1) { - var newlineEnd = text.indexOf('\n', pos) + 1; - exports.assert(newlineEnd > 0, "newlineEnd <= 0 in splitAttributionLines"); - op.chars = newlineEnd - pos; - op.lines = 1; - appendOp(op); - numChars -= op.chars; - numLines -= op.lines; - } - if (numLines == 1) { - op.chars = numChars; - op.lines = 1; - } - appendOp(op); - } - - return lines; -}; - -/** - * splits text into lines - * @param {string} text to be splitted - */ -exports.splitTextLines = function (text) { - return text.match(/[^\n]*(?:\n|[^\n]$)/g); -}; - -/** - * compose two Changesets - * @param cs1 {Changeset} first Changeset - * @param cs2 {Changeset} second Changeset - * @param pool {AtribsPool} Attribs pool - */ -exports.compose = function (cs1, cs2, pool) { - var unpacked1 = exports.unpack(cs1); - var unpacked2 = exports.unpack(cs2); - var len1 = unpacked1.oldLen; - var len2 = unpacked1.newLen; - exports.assert(len2 == unpacked2.oldLen, "mismatched composition of two changesets"); - var len3 = unpacked2.newLen; - var bankIter1 = exports.stringIterator(unpacked1.charBank); - var bankIter2 = exports.stringIterator(unpacked2.charBank); - var bankAssem = exports.stringAssembler(); - - var newOps = exports.applyZip(unpacked1.ops, 0, unpacked2.ops, 0, function (op1, op2, opOut) { - //var debugBuilder = exports.stringAssembler(); - //debugBuilder.append(exports.opString(op1)); - //debugBuilder.append(','); - //debugBuilder.append(exports.opString(op2)); - //debugBuilder.append(' / '); - var op1code = op1.opcode; - var op2code = op2.opcode; - if (op1code == '+' && op2code == '-') { - bankIter1.skip(Math.min(op1.chars, op2.chars)); - } - exports._slicerZipperFunc(op1, op2, opOut, pool); - if (opOut.opcode == '+') { - if (op2code == '+') { - bankAssem.append(bankIter2.take(opOut.chars)); - } else { - bankAssem.append(bankIter1.take(opOut.chars)); - } - } - - //debugBuilder.append(exports.opString(op1)); - //debugBuilder.append(','); - //debugBuilder.append(exports.opString(op2)); - //debugBuilder.append(' -> '); - //debugBuilder.append(exports.opString(opOut)); - //print(debugBuilder.toString()); - }); - - return exports.pack(len1, len3, newOps, bankAssem.toString()); -}; - -/** - * returns a function that tests if a string of attributes - * (e.g. *3*4) contains a given attribute key,value that - * is already present in the pool. - * @param attribPair array [key,value] of the attribute - * @param pool {AttribPool} Attribute pool - */ -exports.attributeTester = function (attribPair, pool) { - if (!pool) { - return never; - } - var attribNum = pool.putAttrib(attribPair, true); - if (attribNum < 0) { - return never; - } else { - var re = new RegExp('\\*' + exports.numToString(attribNum) + '(?!\\w)'); - return function (attribs) { - return re.test(attribs); - }; - } - - function never(attribs) { - return false; - } -}; - -/** - * creates the identity Changeset of length N - * @param N {int} length of the identity changeset - */ -exports.identity = function (N) { - return exports.pack(N, N, "", ""); -}; - - -/** - * creates a Changeset which works on oldFullText and removes text - * from spliceStart to spliceStart+numRemoved and inserts newText - * instead. Also gives possibility to add attributes optNewTextAPairs - * for the new text. - * @param oldFullText {string} old text - * @param spliecStart {int} where splicing starts - * @param numRemoved {int} number of characters to be removed - * @param newText {string} string to be inserted - * @param optNewTextAPairs {string} new pairs to be inserted - * @param pool {AttribPool} Attribution Pool - */ -exports.makeSplice = function (oldFullText, spliceStart, numRemoved, newText, optNewTextAPairs, pool) { - var oldLen = oldFullText.length; - - if (spliceStart >= oldLen) { - spliceStart = oldLen - 1; - } - if (numRemoved > oldFullText.length - spliceStart) { - numRemoved = oldFullText.length - spliceStart; - } - var oldText = oldFullText.substring(spliceStart, spliceStart + numRemoved); - var newLen = oldLen + newText.length - oldText.length; - - var assem = exports.smartOpAssembler(); - assem.appendOpWithText('=', oldFullText.substring(0, spliceStart)); - assem.appendOpWithText('-', oldText); - assem.appendOpWithText('+', newText, optNewTextAPairs, pool); - assem.endDocument(); - return exports.pack(oldLen, newLen, assem.toString(), newText); -}; - -/** - * Transforms a changeset into a list of splices in the form - * [startChar, endChar, newText] meaning replace text from - * startChar to endChar with newText - * @param cs Changeset - */ -exports.toSplices = function (cs) { - // - var unpacked = exports.unpack(cs); - var splices = []; - - var oldPos = 0; - var iter = exports.opIterator(unpacked.ops); - var charIter = exports.stringIterator(unpacked.charBank); - var inSplice = false; - while (iter.hasNext()) { - var op = iter.next(); - if (op.opcode == '=') { - oldPos += op.chars; - inSplice = false; - } else { - if (!inSplice) { - splices.push([oldPos, oldPos, ""]); - inSplice = true; - } - if (op.opcode == '-') { - oldPos += op.chars; - splices[splices.length - 1][1] += op.chars; - } else if (op.opcode == '+') { - splices[splices.length - 1][2] += charIter.take(op.chars); - } - } - } - - return splices; -}; - -/** - * - */ -exports.characterRangeFollow = function (cs, startChar, endChar, insertionsAfter) { - var newStartChar = startChar; - var newEndChar = endChar; - var splices = exports.toSplices(cs); - var lengthChangeSoFar = 0; - for (var i = 0; i < splices.length; i++) { - var splice = splices[i]; - var spliceStart = splice[0] + lengthChangeSoFar; - var spliceEnd = splice[1] + lengthChangeSoFar; - var newTextLength = splice[2].length; - var thisLengthChange = newTextLength - (spliceEnd - spliceStart); - - if (spliceStart <= newStartChar && spliceEnd >= newEndChar) { - // splice fully replaces/deletes range - // (also case that handles insertion at a collapsed selection) - if (insertionsAfter) { - newStartChar = newEndChar = spliceStart; - } else { - newStartChar = newEndChar = spliceStart + newTextLength; - } - } else if (spliceEnd <= newStartChar) { - // splice is before range - newStartChar += thisLengthChange; - newEndChar += thisLengthChange; - } else if (spliceStart >= newEndChar) { - // splice is after range - } else if (spliceStart >= newStartChar && spliceEnd <= newEndChar) { - // splice is inside range - newEndChar += thisLengthChange; - } else if (spliceEnd < newEndChar) { - // splice overlaps beginning of range - newStartChar = spliceStart + newTextLength; - newEndChar += thisLengthChange; - } else { - // splice overlaps end of range - newEndChar = spliceStart; - } - - lengthChangeSoFar += thisLengthChange; - } - - return [newStartChar, newEndChar]; -}; - -/** - * Iterate over attributes in a changeset and move them from - * oldPool to newPool - * @param cs {Changeset} Chageset/attribution string to be iterated over - * @param oldPool {AttribPool} old attributes pool - * @param newPool {AttribPool} new attributes pool - * @return {string} the new Changeset - */ -exports.moveOpsToNewPool = function (cs, oldPool, newPool) { - // works on exports or attribution string - var dollarPos = cs.indexOf('$'); - if (dollarPos < 0) { - dollarPos = cs.length; - } - var upToDollar = cs.substring(0, dollarPos); - var fromDollar = cs.substring(dollarPos); - // order of attribs stays the same - return upToDollar.replace(/\*([0-9a-z]+)/g, function (_, a) { - var oldNum = exports.parseNum(a); - var pair = oldPool.getAttrib(oldNum); - if(!pair) exports.error('Can\'t copy unknown attrib (reference attrib string to non-existant pool entry). Inconsistent attrib state!'); - var newNum = newPool.putAttrib(pair); - return '*' + exports.numToString(newNum); - }) + fromDollar; -}; - -/** - * create an attribution inserting a text - * @param text {string} text to be inserted - */ -exports.makeAttribution = function (text) { - var assem = exports.smartOpAssembler(); - assem.appendOpWithText('+', text); - return assem.toString(); -}; - -/** - * Iterates over attributes in exports, attribution string, or attribs property of an op - * and runs function func on them - * @param cs {Changeset} changeset - * @param func {function} function to be called - */ -exports.eachAttribNumber = function (cs, func) { - var dollarPos = cs.indexOf('$'); - if (dollarPos < 0) { - dollarPos = cs.length; - } - var upToDollar = cs.substring(0, dollarPos); - - upToDollar.replace(/\*([0-9a-z]+)/g, function (_, a) { - func(exports.parseNum(a)); - return ''; - }); -}; - -/** - * Filter attributes which should remain in a Changeset - * callable on a exports, attribution string, or attribs property of an op, - * though it may easily create adjacent ops that can be merged. - * @param cs {Changeset} changeset to be filtered - * @param filter {function} fnc which returns true if an - * attribute X (int) should be kept in the Changeset - */ -exports.filterAttribNumbers = function (cs, filter) { - return exports.mapAttribNumbers(cs, filter); -}; - -/** - * does exactly the same as exports.filterAttribNumbers - */ -exports.mapAttribNumbers = function (cs, func) { - var dollarPos = cs.indexOf('$'); - if (dollarPos < 0) { - dollarPos = cs.length; - } - var upToDollar = cs.substring(0, dollarPos); - - var newUpToDollar = upToDollar.replace(/\*([0-9a-z]+)/g, function (s, a) { - var n = func(exports.parseNum(a)); - if (n === true) { - return s; - } else if ((typeof n) === "number") { - return '*' + exports.numToString(n); - } else { - return ''; - } - }); - - return newUpToDollar + cs.substring(dollarPos); -}; - -/** - * Create a Changeset going from Identity to a certain state - * @params text {string} text of the final change - * @attribs attribs {string} optional, operations which insert - * the text and also puts the right attributes - */ -exports.makeAText = function (text, attribs) { - return { - text: text, - attribs: (attribs || exports.makeAttribution(text)) - }; -}; - -/** - * Apply a Changeset to a AText - * @param cs {Changeset} Changeset to be applied - * @param atext {AText} - * @param pool {AttribPool} Attribute Pool to add to - */ -exports.applyToAText = function (cs, atext, pool) { - return { - text: exports.applyToText(cs, atext.text), - attribs: exports.applyToAttribution(cs, atext.attribs, pool) - }; -}; - -/** - * Clones a AText structure - * @param atext {AText} - */ -exports.cloneAText = function (atext) { - if (atext) { - return { - text: atext.text, - attribs: atext.attribs - } - } else exports.error("atext is null"); -}; - -/** - * Copies a AText structure from atext1 to atext2 - * @param atext {AText} - */ -exports.copyAText = function (atext1, atext2) { - atext2.text = atext1.text; - atext2.attribs = atext1.attribs; -}; - -/** - * Append the set of operations from atext to an assembler - * @param atext {AText} - * @param assem Assembler like smartOpAssembler - */ -exports.appendATextToAssembler = function (atext, assem) { - // intentionally skips last newline char of atext - var iter = exports.opIterator(atext.attribs); - var op = exports.newOp(); - while (iter.hasNext()) { - iter.next(op); - if (!iter.hasNext()) { - // last op, exclude final newline - if (op.lines <= 1) { - op.lines = 0; - op.chars--; - if (op.chars) { - assem.append(op); - } - } else { - var nextToLastNewlineEnd = - atext.text.lastIndexOf('\n', atext.text.length - 2) + 1; - var lastLineLength = atext.text.length - nextToLastNewlineEnd - 1; - op.lines--; - op.chars -= (lastLineLength + 1); - assem.append(op); - op.lines = 0; - op.chars = lastLineLength; - if (op.chars) { - assem.append(op); - } - } - } else { - assem.append(op); - } - } -}; - -/** - * Creates a clone of a Changeset and it's APool - * @param cs {Changeset} - * @param pool {AtributePool} - */ -exports.prepareForWire = function (cs, pool) { - var newPool = new AttributePool(); - var newCs = exports.moveOpsToNewPool(cs, pool, newPool); - return { - translated: newCs, - pool: newPool - }; -}; - -/** - * Checks if a changeset s the identity changeset - */ -exports.isIdentity = function (cs) { - var unpacked = exports.unpack(cs); - return unpacked.ops == "" && unpacked.oldLen == unpacked.newLen; -}; - -/** - * returns all the values of attributes with a certain key - * in an Op attribs string - * @param attribs {string} Attribute string of a Op - * @param key {string} string to be seached for - * @param pool {AttribPool} attribute pool - */ -exports.opAttributeValue = function (op, key, pool) { - return exports.attribsAttributeValue(op.attribs, key, pool); -}; - -/** - * returns all the values of attributes with a certain key - * in an attribs string - * @param attribs {string} Attribute string - * @param key {string} string to be seached for - * @param pool {AttribPool} attribute pool - */ -exports.attribsAttributeValue = function (attribs, key, pool) { - var value = ''; - if (attribs) { - exports.eachAttribNumber(attribs, function (n) { - if (pool.getAttribKey(n) == key) { - value = pool.getAttribValue(n); - } - }); - } - return value; -}; - -/** - * Creates a Changeset builder for a string with initial - * length oldLen. Allows to add/remove parts of it - * @param oldLen {int} Old length - */ -exports.builder = function (oldLen) { - var assem = exports.smartOpAssembler(); - var o = exports.newOp(); - var charBank = exports.stringAssembler(); - - var self = { - // attribs are [[key1,value1],[key2,value2],...] or '*0*1...' (no pool needed in latter case) - keep: function (N, L, attribs, pool) { - o.opcode = '='; - o.attribs = (attribs && exports.makeAttribsString('=', attribs, pool)) || ''; - o.chars = N; - o.lines = (L || 0); - assem.append(o); - return self; - }, - keepText: function (text, attribs, pool) { - assem.appendOpWithText('=', text, attribs, pool); - return self; - }, - insert: function (text, attribs, pool) { - assem.appendOpWithText('+', text, attribs, pool); - charBank.append(text); - return self; - }, - remove: function (N, L) { - o.opcode = '-'; - o.attribs = ''; - o.chars = N; - o.lines = (L || 0); - assem.append(o); - return self; - }, - toString: function () { - assem.endDocument(); - var newLen = oldLen + assem.getLengthChange(); - return exports.pack(oldLen, newLen, assem.toString(), charBank.toString()); - } - }; - - return self; -}; - -exports.makeAttribsString = function (opcode, attribs, pool) { - // makeAttribsString(opcode, '*3') or makeAttribsString(opcode, [['foo','bar']], myPool) work - if (!attribs) { - return ''; - } else if ((typeof attribs) == "string") { - return attribs; - } else if (pool && attribs && attribs.length) { - if (attribs.length > 1) { - attribs = attribs.slice(); - attribs.sort(); - } - var result = []; - for (var i = 0; i < attribs.length; i++) { - var pair = attribs[i]; - if (opcode == '=' || (opcode == '+' && pair[1])) { - result.push('*' + exports.numToString(pool.putAttrib(pair))); - } - } - return result.join(''); - } -}; - -// like "substring" but on a single-line attribution string -exports.subattribution = function (astr, start, optEnd) { - var iter = exports.opIterator(astr, 0); - var assem = exports.smartOpAssembler(); - var attOp = exports.newOp(); - var csOp = exports.newOp(); - var opOut = exports.newOp(); - - function doCsOp() { - if (csOp.chars) { - while (csOp.opcode && (attOp.opcode || iter.hasNext())) { - if (!attOp.opcode) iter.next(attOp); - - if (csOp.opcode && attOp.opcode && csOp.chars >= attOp.chars && attOp.lines > 0 && csOp.lines <= 0) { - csOp.lines++; - } - - exports._slicerZipperFunc(attOp, csOp, opOut, null); - if (opOut.opcode) { - assem.append(opOut); - opOut.opcode = ''; - } - } - } - } - - csOp.opcode = '-'; - csOp.chars = start; - - doCsOp(); - - if (optEnd === undefined) { - if (attOp.opcode) { - assem.append(attOp); - } - while (iter.hasNext()) { - iter.next(attOp); - assem.append(attOp); - } - } else { - csOp.opcode = '='; - csOp.chars = optEnd - start; - doCsOp(); - } - - return assem.toString(); -}; - -exports.inverse = function (cs, lines, alines, pool) { - // lines and alines are what the exports is meant to apply to. - // They may be arrays or objects with .get(i) and .length methods. - // They include final newlines on lines. - - function lines_get(idx) { - if (lines.get) { - return lines.get(idx); - } else { - return lines[idx]; - } - } - - function alines_get(idx) { - if (alines.get) { - return alines.get(idx); - } else { - return alines[idx]; - } - } - - var curLine = 0; - var curChar = 0; - var curLineOpIter = null; - var curLineOpIterLine; - var curLineNextOp = exports.newOp('+'); - - var unpacked = exports.unpack(cs); - var csIter = exports.opIterator(unpacked.ops); - var builder = exports.builder(unpacked.newLen); - - function consumeAttribRuns(numChars, func /*(len, attribs, endsLine)*/ ) { - - if ((!curLineOpIter) || (curLineOpIterLine != curLine)) { - // create curLineOpIter and advance it to curChar - curLineOpIter = exports.opIterator(alines_get(curLine)); - curLineOpIterLine = curLine; - var indexIntoLine = 0; - var done = false; - while (!done && curLineOpIter.hasNext()) { - curLineOpIter.next(curLineNextOp); - if (indexIntoLine + curLineNextOp.chars >= curChar) { - curLineNextOp.chars -= (curChar - indexIntoLine); - done = true; - } else { - indexIntoLine += curLineNextOp.chars; - } - } - } - - while (numChars > 0) { - if ((!curLineNextOp.chars) && (!curLineOpIter.hasNext())) { - curLine++; - curChar = 0; - curLineOpIterLine = curLine; - curLineNextOp.chars = 0; - curLineOpIter = exports.opIterator(alines_get(curLine)); - } - if (!curLineNextOp.chars) { - curLineOpIter.next(curLineNextOp); - } - var charsToUse = Math.min(numChars, curLineNextOp.chars); - func(charsToUse, curLineNextOp.attribs, charsToUse == curLineNextOp.chars && curLineNextOp.lines > 0); - numChars -= charsToUse; - curLineNextOp.chars -= charsToUse; - curChar += charsToUse; - } - - if ((!curLineNextOp.chars) && (!curLineOpIter.hasNext())) { - curLine++; - curChar = 0; - } - } - - function skip(N, L) { - if (L) { - curLine += L; - curChar = 0; - } else { - if (curLineOpIter && curLineOpIterLine == curLine) { - consumeAttribRuns(N, function () {}); - } else { - curChar += N; - } - } - } - - function nextText(numChars) { - var len = 0; - var assem = exports.stringAssembler(); - var firstString = lines_get(curLine).substring(curChar); - len += firstString.length; - assem.append(firstString); - - var lineNum = curLine + 1; - while (len < numChars) { - var nextString = lines_get(lineNum); - len += nextString.length; - assem.append(nextString); - lineNum++; - } - - return assem.toString().substring(0, numChars); - } - - function cachedStrFunc(func) { - var cache = {}; - return function (s) { - if (!cache[s]) { - cache[s] = func(s); - } - return cache[s]; - }; - } - - var attribKeys = []; - var attribValues = []; - while (csIter.hasNext()) { - var csOp = csIter.next(); - if (csOp.opcode == '=') { - if (csOp.attribs) { - attribKeys.length = 0; - attribValues.length = 0; - exports.eachAttribNumber(csOp.attribs, function (n) { - attribKeys.push(pool.getAttribKey(n)); - attribValues.push(pool.getAttribValue(n)); - }); - var undoBackToAttribs = cachedStrFunc(function (attribs) { - var backAttribs = []; - for (var i = 0; i < attribKeys.length; i++) { - var appliedKey = attribKeys[i]; - var appliedValue = attribValues[i]; - var oldValue = exports.attribsAttributeValue(attribs, appliedKey, pool); - if (appliedValue != oldValue) { - backAttribs.push([appliedKey, oldValue]); - } - } - return exports.makeAttribsString('=', backAttribs, pool); - }); - consumeAttribRuns(csOp.chars, function (len, attribs, endsLine) { - builder.keep(len, endsLine ? 1 : 0, undoBackToAttribs(attribs)); - }); - } else { - skip(csOp.chars, csOp.lines); - builder.keep(csOp.chars, csOp.lines); - } - } else if (csOp.opcode == '+') { - builder.remove(csOp.chars, csOp.lines); - } else if (csOp.opcode == '-') { - var textBank = nextText(csOp.chars); - var textBankIndex = 0; - consumeAttribRuns(csOp.chars, function (len, attribs, endsLine) { - builder.insert(textBank.substr(textBankIndex, len), attribs); - textBankIndex += len; - }); - } - } - - return exports.checkRep(builder.toString()); -}; - -// %CLIENT FILE ENDS HERE% -exports.follow = function (cs1, cs2, reverseInsertOrder, pool) { - var unpacked1 = exports.unpack(cs1); - var unpacked2 = exports.unpack(cs2); - var len1 = unpacked1.oldLen; - var len2 = unpacked2.oldLen; - exports.assert(len1 == len2, "mismatched follow - cannot transform cs1 on top of cs2"); - var chars1 = exports.stringIterator(unpacked1.charBank); - var chars2 = exports.stringIterator(unpacked2.charBank); - - var oldLen = unpacked1.newLen; - var oldPos = 0; - var newLen = 0; - - var hasInsertFirst = exports.attributeTester(['insertorder', 'first'], pool); - - var newOps = exports.applyZip(unpacked1.ops, 0, unpacked2.ops, 0, function (op1, op2, opOut) { - if (op1.opcode == '+' || op2.opcode == '+') { - var whichToDo; - if (op2.opcode != '+') { - whichToDo = 1; - } else if (op1.opcode != '+') { - whichToDo = 2; - } else { - // both + - var firstChar1 = chars1.peek(1); - var firstChar2 = chars2.peek(1); - var insertFirst1 = hasInsertFirst(op1.attribs); - var insertFirst2 = hasInsertFirst(op2.attribs); - if (insertFirst1 && !insertFirst2) { - whichToDo = 1; - } else if (insertFirst2 && !insertFirst1) { - whichToDo = 2; - } - // insert string that doesn't start with a newline first so as not to break up lines - else if (firstChar1 == '\n' && firstChar2 != '\n') { - whichToDo = 2; - } else if (firstChar1 != '\n' && firstChar2 == '\n') { - whichToDo = 1; - } - // break symmetry: - else if (reverseInsertOrder) { - whichToDo = 2; - } else { - whichToDo = 1; - } - } - if (whichToDo == 1) { - chars1.skip(op1.chars); - opOut.opcode = '='; - opOut.lines = op1.lines; - opOut.chars = op1.chars; - opOut.attribs = ''; - op1.opcode = ''; - } else { - // whichToDo == 2 - chars2.skip(op2.chars); - exports.copyOp(op2, opOut); - op2.opcode = ''; - } - } else if (op1.opcode == '-') { - if (!op2.opcode) { - op1.opcode = ''; - } else { - if (op1.chars <= op2.chars) { - op2.chars -= op1.chars; - op2.lines -= op1.lines; - op1.opcode = ''; - if (!op2.chars) { - op2.opcode = ''; - } - } else { - op1.chars -= op2.chars; - op1.lines -= op2.lines; - op2.opcode = ''; - } - } - } else if (op2.opcode == '-') { - exports.copyOp(op2, opOut); - if (!op1.opcode) { - op2.opcode = ''; - } else if (op2.chars <= op1.chars) { - // delete part or all of a keep - op1.chars -= op2.chars; - op1.lines -= op2.lines; - op2.opcode = ''; - if (!op1.chars) { - op1.opcode = ''; - } - } else { - // delete all of a keep, and keep going - opOut.lines = op1.lines; - opOut.chars = op1.chars; - op2.lines -= op1.lines; - op2.chars -= op1.chars; - op1.opcode = ''; - } - } else if (!op1.opcode) { - exports.copyOp(op2, opOut); - op2.opcode = ''; - } else if (!op2.opcode) { - // @NOTE: Critical bugfix for EPL issue #1625. We do not copy op1 here - // in order to prevent attributes from leaking into result changesets. - // exports.copyOp(op1, opOut); - op1.opcode = ''; - } else { - // both keeps - opOut.opcode = '='; - opOut.attribs = exports.followAttributes(op1.attribs, op2.attribs, pool); - if (op1.chars <= op2.chars) { - opOut.chars = op1.chars; - opOut.lines = op1.lines; - op2.chars -= op1.chars; - op2.lines -= op1.lines; - op1.opcode = ''; - if (!op2.chars) { - op2.opcode = ''; - } - } else { - opOut.chars = op2.chars; - opOut.lines = op2.lines; - op1.chars -= op2.chars; - op1.lines -= op2.lines; - op2.opcode = ''; - } - } - switch (opOut.opcode) { - case '=': - oldPos += opOut.chars; - newLen += opOut.chars; - break; - case '-': - oldPos += opOut.chars; - break; - case '+': - newLen += opOut.chars; - break; - } - }); - newLen += oldLen - oldPos; - - return exports.pack(oldLen, newLen, newOps, unpacked2.charBank); -}; - -exports.followAttributes = function (att1, att2, pool) { - // The merge of two sets of attribute changes to the same text - // takes the lexically-earlier value if there are two values - // for the same key. Otherwise, all key/value changes from - // both attribute sets are taken. This operation is the "follow", - // so a set of changes is produced that can be applied to att1 - // to produce the merged set. - if ((!att2) || (!pool)) return ''; - if (!att1) return att2; - var atts = []; - att2.replace(/\*([0-9a-z]+)/g, function (_, a) { - atts.push(pool.getAttrib(exports.parseNum(a))); - return ''; - }); - att1.replace(/\*([0-9a-z]+)/g, function (_, a) { - var pair1 = pool.getAttrib(exports.parseNum(a)); - for (var i = 0; i < atts.length; i++) { - var pair2 = atts[i]; - if (pair1[0] == pair2[0]) { - if (pair1[1] <= pair2[1]) { - // winner of merge is pair1, delete this attribute - atts.splice(i, 1); - } - break; - } - } - return ''; - }); - // we've only removed attributes, so they're already sorted - var buf = exports.stringAssembler(); - for (var i = 0; i < atts.length; i++) { - buf.append('*'); - buf.append(exports.numToString(pool.putAttrib(atts[i]))); - } - return buf.toString(); -}; - -exports.composeWithDeletions = function (cs1, cs2, pool) { - var unpacked1 = exports.unpack(cs1); - var unpacked2 = exports.unpack(cs2); - var len1 = unpacked1.oldLen; - var len2 = unpacked1.newLen; - exports.assert(len2 == unpacked2.oldLen, "mismatched composition of two changesets"); - var len3 = unpacked2.newLen; - var bankIter1 = exports.stringIterator(unpacked1.charBank); - var bankIter2 = exports.stringIterator(unpacked2.charBank); - var bankAssem = exports.stringAssembler(); - - var newOps = exports.applyZip(unpacked1.ops, 0, unpacked2.ops, 0, function (op1, op2, opOut) { - var op1code = op1.opcode; - var op2code = op2.opcode; - if (op1code == '+' && op2code == '-') { - bankIter1.skip(Math.min(op1.chars, op2.chars)); - } - exports._slicerZipperFuncWithDeletions(op1, op2, opOut, pool); - if (opOut.opcode == '+') { - if (op2code == '+') { - bankAssem.append(bankIter2.take(opOut.chars)); - } else { - bankAssem.append(bankIter1.take(opOut.chars)); - } - } - }); - - return exports.pack(len1, len3, newOps, bankAssem.toString()); -}; - -// This function is 95% like _slicerZipperFunc, we just changed two lines to ensure it merges the attribs of deletions properly. -// This is necassary for correct paddiff. But to ensure these changes doesn't affect anything else, we've created a seperate function only used for paddiffs -exports._slicerZipperFuncWithDeletions= function (attOp, csOp, opOut, pool) { - // attOp is the op from the sequence that is being operated on, either an - // attribution string or the earlier of two exportss being composed. - // pool can be null if definitely not needed. - //print(csOp.toSource()+" "+attOp.toSource()+" "+opOut.toSource()); - if (attOp.opcode == '-') { - exports.copyOp(attOp, opOut); - attOp.opcode = ''; - } else if (!attOp.opcode) { - exports.copyOp(csOp, opOut); - csOp.opcode = ''; - } else { - switch (csOp.opcode) { - case '-': - { - if (csOp.chars <= attOp.chars) { - // delete or delete part - if (attOp.opcode == '=') { - opOut.opcode = '-'; - opOut.chars = csOp.chars; - opOut.lines = csOp.lines; - opOut.attribs = csOp.attribs; //changed by yammer - } - attOp.chars -= csOp.chars; - attOp.lines -= csOp.lines; - csOp.opcode = ''; - if (!attOp.chars) { - attOp.opcode = ''; - } - } else { - // delete and keep going - if (attOp.opcode == '=') { - opOut.opcode = '-'; - opOut.chars = attOp.chars; - opOut.lines = attOp.lines; - opOut.attribs = csOp.attribs; //changed by yammer - } - csOp.chars -= attOp.chars; - csOp.lines -= attOp.lines; - attOp.opcode = ''; - } - break; - } - case '+': - { - // insert - exports.copyOp(csOp, opOut); - csOp.opcode = ''; - break; - } - case '=': - { - if (csOp.chars <= attOp.chars) { - // keep or keep part - opOut.opcode = attOp.opcode; - opOut.chars = csOp.chars; - opOut.lines = csOp.lines; - opOut.attribs = exports.composeAttributes(attOp.attribs, csOp.attribs, attOp.opcode == '=', pool); - csOp.opcode = ''; - attOp.chars -= csOp.chars; - attOp.lines -= csOp.lines; - if (!attOp.chars) { - attOp.opcode = ''; - } - } else { - // keep and keep going - opOut.opcode = attOp.opcode; - opOut.chars = attOp.chars; - opOut.lines = attOp.lines; - opOut.attribs = exports.composeAttributes(attOp.attribs, csOp.attribs, attOp.opcode == '=', pool); - attOp.opcode = ''; - csOp.chars -= attOp.chars; - csOp.lines -= attOp.lines; - } - break; - } - case '': - { - exports.copyOp(attOp, opOut); - attOp.opcode = ''; - break; - } - } - } -}; diff --git a/sources/src/static/js/ChangesetUtils.js b/sources/src/static/js/ChangesetUtils.js deleted file mode 100644 index e0b6788..0000000 --- a/sources/src/static/js/ChangesetUtils.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * This module contains several helper Functions to build Changesets - * based on a SkipList - */ - -/** - * Copyright 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -exports.buildRemoveRange = function(rep, builder, start, end) -{ - var startLineOffset = rep.lines.offsetOfIndex(start[0]); - var endLineOffset = rep.lines.offsetOfIndex(end[0]); - - if (end[0] > start[0]) - { - builder.remove(endLineOffset - startLineOffset - start[1], end[0] - start[0]); - builder.remove(end[1]); - } - else - { - builder.remove(end[1] - start[1]); - } -} - -exports.buildKeepRange = function(rep, builder, start, end, attribs, pool) -{ - var startLineOffset = rep.lines.offsetOfIndex(start[0]); - var endLineOffset = rep.lines.offsetOfIndex(end[0]); - - if (end[0] > start[0]) - { - builder.keep(endLineOffset - startLineOffset - start[1], end[0] - start[0], attribs, pool); - builder.keep(end[1], 0, attribs, pool); - } - else - { - builder.keep(end[1] - start[1], 0, attribs, pool); - } -} - -exports.buildKeepToStartOfRange = function(rep, builder, start) -{ - var startLineOffset = rep.lines.offsetOfIndex(start[0]); - - builder.keep(startLineOffset, start[0]); - builder.keep(start[1]); -} - diff --git a/sources/src/static/js/ace.js b/sources/src/static/js/ace.js deleted file mode 100644 index 9f219e6..0000000 --- a/sources/src/static/js/ace.js +++ /dev/null @@ -1,352 +0,0 @@ -/** - * This code is mostly from the old Etherpad. Please help us to comment this code. - * This helps other people to understand this code better and helps them to improve it. - * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED - */ - -/** - * Copyright 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// requires: top -// requires: plugins -// requires: undefined - -var KERNEL_SOURCE = '../static/js/require-kernel.js'; - -Ace2Editor.registry = { - nextId: 1 -}; - -var hooks = require('./pluginfw/hooks'); -var _ = require('./underscore'); - -function scriptTag(source) { - return ( - '' - ) -} - -function Ace2Editor() -{ - var ace2 = Ace2Editor; - - var editor = {}; - var info = { - editor: editor, - id: (ace2.registry.nextId++) - }; - var loaded = false; - - var actionsPendingInit = []; - - function pendingInit(func, optDoNow) - { - return function() - { - var that = this; - var args = arguments; - var action = function() - { - func.apply(that, args); - } - if (optDoNow) - { - optDoNow.apply(that, args); - } - if (loaded) - { - action(); - } - else - { - actionsPendingInit.push(action); - } - }; - } - - function doActionsPendingInit() - { - _.each(actionsPendingInit, function(fn,i){ - fn() - }); - actionsPendingInit = []; - } - - ace2.registry[info.id] = info; - - // The following functions (prefixed by 'ace_') are exposed by editor, but - // execution is delayed until init is complete - var aceFunctionsPendingInit = ['importText', 'importAText', 'focus', - 'setEditable', 'getFormattedCode', 'setOnKeyPress', 'setOnKeyDown', - 'setNotifyDirty', 'setProperty', 'setBaseText', 'setBaseAttributedText', - 'applyChangesToBase', 'applyPreparedChangesetToBase', - 'setUserChangeNotificationCallback', 'setAuthorInfo', - 'setAuthorSelectionRange', 'callWithAce', 'execCommand', 'replaceRange']; - - _.each(aceFunctionsPendingInit, function(fnName,i){ - var prefix = 'ace_'; - var name = prefix + fnName; - editor[fnName] = pendingInit(function(){ - info[prefix + fnName].apply(this, arguments); - }); - }); - - editor.exportText = function() - { - if (!loaded) return "(awaiting init)\n"; - return info.ace_exportText(); - }; - - editor.getFrame = function() - { - return info.frame || null; - }; - - editor.getDebugProperty = function(prop) - { - return info.ace_getDebugProperty(prop); - }; - - editor.getInInternationalComposition = function() - { - if (!loaded) return false; - return info.ace_getInInternationalComposition(); - }; - - // prepareUserChangeset: - // Returns null if no new changes or ACE not ready. Otherwise, bundles up all user changes - // to the latest base text into a Changeset, which is returned (as a string if encodeAsString). - // If this method returns a truthy value, then applyPreparedChangesetToBase can be called - // at some later point to consider these changes part of the base, after which prepareUserChangeset - // must be called again before applyPreparedChangesetToBase. Multiple consecutive calls - // to prepareUserChangeset will return an updated changeset that takes into account the - // latest user changes, and modify the changeset to be applied by applyPreparedChangesetToBase - // accordingly. - editor.prepareUserChangeset = function() - { - if (!loaded) return null; - return info.ace_prepareUserChangeset(); - }; - - editor.getUnhandledErrors = function() - { - if (!loaded) return []; - // returns array of {error: , time: +new Date()} - return info.ace_getUnhandledErrors(); - }; - - - - function sortFilesByEmbeded(files) { - var embededFiles = []; - var remoteFiles = []; - - if (Ace2Editor.EMBEDED) { - for (var i = 0, ii = files.length; i < ii; i++) { - var file = files[i]; - if (Object.prototype.hasOwnProperty.call(Ace2Editor.EMBEDED, file)) { - embededFiles.push(file); - } else { - remoteFiles.push(file); - } - } - } else { - remoteFiles = files; - } - - return {embeded: embededFiles, remote: remoteFiles}; - } - function pushStyleTagsFor(buffer, files) { - var sorted = sortFilesByEmbeded(files); - var embededFiles = sorted.embeded; - var remoteFiles = sorted.remote; - - if (embededFiles.length > 0) { - buffer.push(''); - - hooks.callAll("aceInitInnerdocbodyHead", { - iframeHTML: iframeHTML - }); - - iframeHTML.push(' '); - - // Expose myself to global for my child frame. - var thisFunctionsName = "ChildAccessibleAce2Editor"; - (function () {return this}())[thisFunctionsName] = Ace2Editor; - - var outerScript = '\ -editorId = ' + JSON.stringify(info.id) + ';\n\ -editorInfo = parent[' + JSON.stringify(thisFunctionsName) + '].registry[editorId];\n\ -window.onload = function () {\n\ - window.onload = null;\n\ - setTimeout(function () {\n\ - var iframe = document.createElement("IFRAME");\n\ - iframe.name = "ace_inner";\n\ - iframe.title = "pad";\n\ - iframe.scrolling = "no";\n\ - var outerdocbody = document.getElementById("outerdocbody");\n\ - iframe.frameBorder = 0;\n\ - iframe.allowTransparency = true; // for IE\n\ - outerdocbody.insertBefore(iframe, outerdocbody.firstChild);\n\ - iframe.ace_outerWin = window;\n\ - readyFunc = function () {\n\ - editorInfo.onEditorReady();\n\ - readyFunc = null;\n\ - editorInfo = null;\n\ - };\n\ - var doc = iframe.contentWindow.document;\n\ - doc.open();\n\ - var text = (' + JSON.stringify(iframeHTML.join('\n')) + ');\n\ - doc.write(text);\n\ - doc.close();\n\ - }, 0);\n\ -}'; - - var outerHTML = [doctype, ''] - - var includedCSS = []; - var $$INCLUDE_CSS = function(filename) {includedCSS.push(filename)}; - $$INCLUDE_CSS("../static/css/iframe_editor.css"); - $$INCLUDE_CSS("../static/css/pad.css"); - $$INCLUDE_CSS("../static/custom/pad.css"); - - - var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ - if (path.match(/\/\//)) { // Allow urls to external CSS - http(s):// and //some/path.css - return path; - } - return '../static/plugins/' + path } - ); - includedCSS = includedCSS.concat(additionalCSS); - - pushStyleTagsFor(outerHTML, includedCSS); - - // bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly - // (throbs busy while typing) - outerHTML.push('', '', scriptTag(outerScript), '
    x
    '); - - var outerFrame = document.createElement("IFRAME"); - outerFrame.name = "ace_outer"; - outerFrame.frameBorder = 0; // for IE - outerFrame.title = "Ether"; - info.frame = outerFrame; - document.getElementById(containerId).appendChild(outerFrame); - - var editorDocument = outerFrame.contentWindow.document; - - editorDocument.open(); - editorDocument.write(outerHTML.join('')); - editorDocument.close(); - })(); - }; - - return editor; -} - -exports.Ace2Editor = Ace2Editor; diff --git a/sources/src/static/js/ace2_common.js b/sources/src/static/js/ace2_common.js deleted file mode 100644 index 7ad7ba0..0000000 --- a/sources/src/static/js/ace2_common.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * This code is mostly from the old Etherpad. Please help us to comment this code. - * This helps other people to understand this code better and helps them to improve it. - * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED - */ - -/** - * Copyright 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -var Security = require('./security'); - -function isNodeText(node) -{ - return (node.nodeType == 3); -} - -function object(o) -{ - var f = function(){}; - f.prototype = o; - return new f(); -} - -function getAssoc(obj, name) -{ - return obj["_magicdom_" + name]; -} - -function setAssoc(obj, name, value) -{ - // note that in IE designMode, properties of a node can get - // copied to new nodes that are spawned during editing; also, - // properties representable in HTML text can survive copy-and-paste - obj["_magicdom_" + name] = value; -} - -// "func" is a function over 0..(numItems-1) that is monotonically -// "increasing" with index (false, then true). Finds the boundary -// between false and true, a number between 0 and numItems inclusive. - - -function binarySearch(numItems, func) -{ - if (numItems < 1) return 0; - if (func(0)) return 0; - if (!func(numItems - 1)) return numItems; - var low = 0; // func(low) is always false - var high = numItems - 1; // func(high) is always true - while ((high - low) > 1) - { - var x = Math.floor((low + high) / 2); // x != low, x != high - if (func(x)) high = x; - else low = x; - } - return high; -} - -function binarySearchInfinite(expectedLength, func) -{ - var i = 0; - while (!func(i)) i += expectedLength; - return binarySearch(i, func); -} - -function htmlPrettyEscape(str) -{ - return Security.escapeHTML(str).replace(/\r?\n/g, '\\n'); -} - -var noop = function(){}; - -exports.isNodeText = isNodeText; -exports.object = object; -exports.getAssoc = getAssoc; -exports.setAssoc = setAssoc; -exports.binarySearch = binarySearch; -exports.binarySearchInfinite = binarySearchInfinite; -exports.htmlPrettyEscape = htmlPrettyEscape; -exports.noop = noop; diff --git a/sources/src/static/js/ace2_inner.js b/sources/src/static/js/ace2_inner.js deleted file mode 100644 index 90cefa5..0000000 --- a/sources/src/static/js/ace2_inner.js +++ /dev/null @@ -1,5521 +0,0 @@ -/** - * This code is mostly from the old Etherpad. Please help us to comment this code. - * This helps other people to understand this code better and helps them to improve it. - * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED - */ - -/** - * Copyright 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS-IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -var _, $, jQuery, plugins, Ace2Common; -var browser = require('./browser'); -if(browser.msie){ - // Honestly fuck IE royally. - // Basically every hack we have since V11 causes a problem - if(parseInt(browser.version) >= 11){ - delete browser.msie; - browser.chrome = true; - browser.modernIE = true; - } -} - -Ace2Common = require('./ace2_common'); - -plugins = require('ep_etherpad-lite/static/js/pluginfw/client_plugins'); -$ = jQuery = require('./rjquery').$; -_ = require("./underscore"); - -var isNodeText = Ace2Common.isNodeText, - getAssoc = Ace2Common.getAssoc, - setAssoc = Ace2Common.setAssoc, - isTextNode = Ace2Common.isTextNode, - binarySearchInfinite = Ace2Common.binarySearchInfinite, - htmlPrettyEscape = Ace2Common.htmlPrettyEscape, - noop = Ace2Common.noop; -var hooks = require('./pluginfw/hooks'); - -function Ace2Inner(){ - - var makeChangesetTracker = require('./changesettracker').makeChangesetTracker; - var colorutils = require('./colorutils').colorutils; - var makeContentCollector = require('./contentcollector').makeContentCollector; - var makeCSSManager = require('./cssmanager').makeCSSManager; - var domline = require('./domline').domline; - var AttribPool = require('./AttributePool'); - var Changeset = require('./Changeset'); - var ChangesetUtils = require('./ChangesetUtils'); - var linestylefilter = require('./linestylefilter').linestylefilter; - var SkipList = require('./skiplist'); - var undoModule = require('./undomodule').undoModule; - var AttributeManager = require('./AttributeManager'); - var Scroll = require('./scroll'); - - var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;" - // changed to false - var isSetUp = false; - - var THE_TAB = ' '; //4 - var MAX_LIST_LEVEL = 16; - - var LINE_NUMBER_PADDING_RIGHT = 4; - var LINE_NUMBER_PADDING_LEFT = 4; - var MIN_LINEDIV_WIDTH = 20; - var EDIT_BODY_PADDING_TOP = 8; - var EDIT_BODY_PADDING_LEFT = 8; - - var FORMATTING_STYLES = ['bold', 'italic', 'underline', 'strikethrough']; - var SELECT_BUTTON_CLASS = 'selected'; - - var caughtErrors = []; - - var thisAuthor = ''; - - var disposed = false; - var editorInfo = parent.editorInfo; - - - var iframe = window.frameElement; - var outerWin = iframe.ace_outerWin; - iframe.ace_outerWin = null; // prevent IE 6 memory leak - var sideDiv = iframe.nextSibling; - var lineMetricsDiv = sideDiv.nextSibling; - initLineNumbers(); - - var scroll = Scroll.init(outerWin); - - var outsideKeyDown = noop; - - var outsideKeyPress = function(){return true;}; - - var outsideNotifyDirty = noop; - - // selFocusAtStart -- determines whether the selection extends "backwards", so that the focus - // point (controlled with the arrow keys) is at the beginning; not supported in IE, though - // native IE selections have that behavior (which we try not to interfere with). - // Must be false if selection is collapsed! - var rep = { - lines: new SkipList(), - selStart: null, - selEnd: null, - selFocusAtStart: false, - alltext: "", - alines: [], - apool: new AttribPool() - }; - - // lines, alltext, alines, and DOM are set up in init() - if (undoModule.enabled) - { - undoModule.apool = rep.apool; - } - - var root, doc; // set in init() - var isEditable = true; - var doesWrap = true; - var hasLineNumbers = true; - var isStyled = true; - - // space around the innermost iframe element - var iframePadLeft = MIN_LINEDIV_WIDTH + LINE_NUMBER_PADDING_RIGHT + EDIT_BODY_PADDING_LEFT; - var iframePadTop = EDIT_BODY_PADDING_TOP; - var iframePadBottom = 0, - iframePadRight = 0; - - var console = (DEBUG && window.console); - var documentAttributeManager; - - if (!window.console) - { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; - console = {}; - for (var i = 0; i < names.length; ++i) - console[names[i]] = noop; - //console.error = function(str) { alert(str); }; - } - - var PROFILER = window.PROFILER; - if (!PROFILER) - { - PROFILER = function() - { - return { - start: noop, - mark: noop, - literal: noop, - end: noop, - cancel: noop - }; - }; - } - - // "dmesg" is for displaying messages in the in-page output pane - // visible when "?djs=1" is appended to the pad URL. It generally - // remains a no-op unless djs is enabled, but we make a habit of - // only calling it in error cases or while debugging. - var dmesg = noop; - window.dmesg = noop; - - var scheduler = parent; // hack for opera required - - var textFace = 'monospace'; - var textSize = 12; - - - function textLineHeight() - { - return Math.round(textSize * 4 / 3); - } - - var dynamicCSS = null; - var outerDynamicCSS = null; - var parentDynamicCSS = null; - - function initDynamicCSS() - { - dynamicCSS = makeCSSManager("dynamicsyntax"); - outerDynamicCSS = makeCSSManager("dynamicsyntax", "outer"); - parentDynamicCSS = makeCSSManager("dynamicsyntax", "parent"); - } - - var changesetTracker = makeChangesetTracker(scheduler, rep.apool, { - withCallbacks: function(operationName, f) - { - inCallStackIfNecessary(operationName, function() - { - fastIncorp(1); - f( - { - setDocumentAttributedText: function(atext) - { - setDocAText(atext); - }, - applyChangesetToDocument: function(changeset, preferInsertionAfterCaret) - { - var oldEventType = currentCallStack.editEvent.eventType; - currentCallStack.startNewEvent("nonundoable"); - - performDocumentApplyChangeset(changeset, preferInsertionAfterCaret); - - currentCallStack.startNewEvent(oldEventType); - } - }); - }); - } - }); - - var authorInfos = {}; // presence of key determines if author is present in doc - - function getAuthorInfos(){ - return authorInfos; - }; - editorInfo.ace_getAuthorInfos= getAuthorInfos; - - function setAuthorStyle(author, info) - { - if (!dynamicCSS) { - return; - } - var authorSelector = getAuthorColorClassSelector(getAuthorClassName(author)); - - var authorStyleSet = hooks.callAll('aceSetAuthorStyle', { - dynamicCSS: dynamicCSS, - parentDynamicCSS: parentDynamicCSS, - outerDynamicCSS: outerDynamicCSS, - info: info, - author: author, - authorSelector: authorSelector, - }); - - // Prevent default behaviour if any hook says so - if (_.any(authorStyleSet, function(it) { return it })) - { - return - } - - if (!info) - { - dynamicCSS.removeSelectorStyle(authorSelector); - parentDynamicCSS.removeSelectorStyle(authorSelector); - } - else - { - if (info.bgcolor) - { - var bgcolor = info.bgcolor; - if ((typeof info.fade) == "number") - { - bgcolor = fadeColor(bgcolor, info.fade); - } - - var authorStyle = dynamicCSS.selectorStyle(authorSelector); - var parentAuthorStyle = parentDynamicCSS.selectorStyle(authorSelector); - var anchorStyle = dynamicCSS.selectorStyle(authorSelector + ' > a') - - // author color - authorStyle.backgroundColor = bgcolor; - parentAuthorStyle.backgroundColor = bgcolor; - - // text contrast - if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5) - { - authorStyle.color = '#ffffff'; - parentAuthorStyle.color = '#ffffff'; - }else{ - authorStyle.color = null; - parentAuthorStyle.color = null; - } - - // anchor text contrast - if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.55) - { - anchorStyle.color = colorutils.triple2css(colorutils.complementary(colorutils.css2triple(bgcolor))); - }else{ - anchorStyle.color = null; - } - } - } - } - - function setAuthorInfo(author, info) - { - if ((typeof author) != "string") - { - throw new Error("setAuthorInfo: author (" + author + ") is not a string"); - } - if (!info) - { - delete authorInfos[author]; - } - else - { - authorInfos[author] = info; - } - setAuthorStyle(author, info); - } - - function getAuthorClassName(author) - { - return "author-" + author.replace(/[^a-y0-9]/g, function(c) - { - if (c == ".") return "-"; - return 'z' + c.charCodeAt(0) + 'z'; - }); - } - - function className2Author(className) - { - if (className.substring(0, 7) == "author-") - { - return className.substring(7).replace(/[a-y0-9]+|-|z.+?z/g, function(cc) - { - if (cc == '-') return '.'; - else if (cc.charAt(0) == 'z') - { - return String.fromCharCode(Number(cc.slice(1, -1))); - } - else - { - return cc; - } - }); - } - return null; - } - - function getAuthorColorClassSelector(oneClassName) - { - return ".authorColors ." + oneClassName; - } - - function setUpTrackingCSS() - { - if (dynamicCSS) - { - var backgroundHeight = lineMetricsDiv.offsetHeight; - var lineHeight = textLineHeight(); - var extraBodding = 0; - var extraTodding = 0; - if (backgroundHeight < lineHeight) - { - extraBodding = Math.ceil((lineHeight - backgroundHeight) / 2); - extraTodding = lineHeight - backgroundHeight - extraBodding; - } - var spanStyle = dynamicCSS.selectorStyle("#innerdocbody span"); - spanStyle.paddingTop = extraTodding + "px"; - spanStyle.paddingBottom = extraBodding + "px"; - } - } - - function fadeColor(colorCSS, fadeFrac) - { - var color = colorutils.css2triple(colorCSS); - color = colorutils.blend(color, [1, 1, 1], fadeFrac); - return colorutils.triple2css(color); - } - - editorInfo.ace_getRep = function() - { - return rep; - }; - - editorInfo.ace_getAuthor = function() - { - return thisAuthor; - } - - var _nonScrollableEditEvents = { - "applyChangesToBase": 1 - }; - - _.each(hooks.callAll('aceRegisterNonScrollableEditEvents'), function(eventType) { - _nonScrollableEditEvents[eventType] = 1; - }); - - function isScrollableEditEvent(eventType) - { - return !_nonScrollableEditEvents[eventType]; - } - - var currentCallStack = null; - - function inCallStack(type, action) - { - if (disposed) return; - - if (currentCallStack) - { - console.error("Can't enter callstack " + type + ", already in " + currentCallStack.type); - } - - var profiling = false; - - function profileRest() - { - profiling = true; - console.profile(); - } - - function newEditEvent(eventType) - { - return { - eventType: eventType, - backset: null - }; - } - - function submitOldEvent(evt) - { - if (rep.selStart && rep.selEnd) - { - var selStartChar = rep.lines.offsetOfIndex(rep.selStart[0]) + rep.selStart[1]; - var selEndChar = rep.lines.offsetOfIndex(rep.selEnd[0]) + rep.selEnd[1]; - evt.selStart = selStartChar; - evt.selEnd = selEndChar; - evt.selFocusAtStart = rep.selFocusAtStart; - } - if (undoModule.enabled) - { - var undoWorked = false; - try - { - if (isPadLoading(evt.eventType)) - { - undoModule.clearHistory(); - } - else if (evt.eventType == "nonundoable") - { - if (evt.changeset) - { - undoModule.reportExternalChange(evt.changeset); - } - } - else - { - undoModule.reportEvent(evt); - } - undoWorked = true; - } - finally - { - if (!undoWorked) - { - undoModule.enabled = false; // for safety - } - } - } - } - - function startNewEvent(eventType, dontSubmitOld) - { - var oldEvent = currentCallStack.editEvent; - if (!dontSubmitOld) - { - submitOldEvent(oldEvent); - } - currentCallStack.editEvent = newEditEvent(eventType); - return oldEvent; - } - - currentCallStack = { - type: type, - docTextChanged: false, - selectionAffected: false, - userChangedSelection: false, - domClean: false, - profileRest: profileRest, - isUserChange: false, - // is this a "user change" type of call-stack - repChanged: false, - editEvent: newEditEvent(type), - startNewEvent: startNewEvent - }; - var cleanExit = false; - var result; - try - { - result = action(); - - hooks.callAll('aceEditEvent', { - callstack: currentCallStack, - editorInfo: editorInfo, - rep: rep, - documentAttributeManager: documentAttributeManager - }); - - //console.log("Just did action for: "+type); - cleanExit = true; - } - catch (e) - { - caughtErrors.push( - { - error: e, - time: +new Date() - }); - dmesg(e.toString()); - throw e; - } - finally - { - var cs = currentCallStack; - //console.log("Finished action for: "+type); - if (cleanExit) - { - submitOldEvent(cs.editEvent); - if (cs.domClean && cs.type != "setup") - { - // if (cs.isUserChange) - // { - // if (cs.repChanged) parenModule.notifyChange(); - // else parenModule.notifyTick(); - // } - if (cs.selectionAffected) - { - updateBrowserSelectionFromRep(); - } - if ((cs.docTextChanged || cs.userChangedSelection) && isScrollableEditEvent(cs.type)) - { - scrollSelectionIntoView(); - } - if (cs.docTextChanged && cs.type.indexOf("importText") < 0) - { - outsideNotifyDirty(); - } - } - } - else - { - // non-clean exit - if (currentCallStack.type == "idleWorkTimer") - { - idleWorkTimer.atLeast(1000); - } - } - currentCallStack = null; - if (profiling) console.profileEnd(); - } - return result; - } - editorInfo.ace_inCallStack = inCallStack; - - function inCallStackIfNecessary(type, action) - { - if (!currentCallStack) - { - inCallStack(type, action); - } - else - { - action(); - } - } - editorInfo.ace_inCallStackIfNecessary = inCallStackIfNecessary; - - function dispose() - { - disposed = true; - if (idleWorkTimer) idleWorkTimer.never(); - teardown(); - } - - function checkALines() - { - return; // disable for speed - - - function error() - { - throw new Error("checkALines"); - } - if (rep.alines.length != rep.lines.length()) - { - error(); - } - for (var i = 0; i < rep.alines.length; i++) - { - var aline = rep.alines[i]; - var lineText = rep.lines.atIndex(i).text + "\n"; - var lineTextLength = lineText.length; - var opIter = Changeset.opIterator(aline); - var alineLength = 0; - while (opIter.hasNext()) - { - var o = opIter.next(); - alineLength += o.chars; - if (opIter.hasNext()) - { - if (o.lines !== 0) error(); - } - else - { - if (o.lines != 1) error(); - } - } - if (alineLength != lineTextLength) - { - error(); - } - } - } - - function setWraps(newVal) - { - doesWrap = newVal; - var dwClass = "doesWrap"; - setClassPresence(root, "doesWrap", doesWrap); - scheduler.setTimeout(function() - { - inCallStackIfNecessary("setWraps", function() - { - fastIncorp(7); - recreateDOM(); - fixView(); - }); - }, 0); - - // Chrome can't handle the truth.. If CSS rule white-space:pre-wrap - // is true then any paste event will insert two lines.. - // Sadly this will mean you get a walking Caret in Chrome when clicking on a URL - // So this has to be set to pre-wrap ;( - // We need to file a bug w/ the Chromium team. - if(browser.chrome){ - $("#innerdocbody").addClass("noprewrap"); - } - - } - - function setStyled(newVal) - { - var oldVal = isStyled; - isStyled = !! newVal; - - if (newVal != oldVal) - { - if (!newVal) - { - // clear styles - inCallStackIfNecessary("setStyled", function() - { - fastIncorp(12); - var clearStyles = []; - for (var k in STYLE_ATTRIBS) - { - clearStyles.push([k, '']); - } - performDocumentApplyAttributesToCharRange(0, rep.alltext.length, clearStyles); - }); - } - } - } - - function setTextFace(face) - { - textFace = face; - root.style.fontFamily = textFace; - lineMetricsDiv.style.fontFamily = textFace; - scheduler.setTimeout(function() - { - setUpTrackingCSS(); - }, 0); - } - - function setTextSize(size) - { - textSize = size; - root.style.fontSize = textSize + "px"; - root.style.lineHeight = textLineHeight() + "px"; - sideDiv.style.lineHeight = textLineHeight() + "px"; - lineMetricsDiv.style.fontSize = textSize + "px"; - scheduler.setTimeout(function() - { - setUpTrackingCSS(); - }, 0); - } - - function recreateDOM() - { - // precond: normalized - recolorLinesInRange(0, rep.alltext.length); - } - - function setEditable(newVal) - { - isEditable = newVal; - - // the following may fail, e.g. if iframe is hidden - if (!isEditable) - { - setDesignMode(false); - } - else - { - setDesignMode(true); - } - setClassPresence(root, "static", !isEditable); - } - - function enforceEditability() - { - setEditable(isEditable); - } - - function importText(text, undoable, dontProcess) - { - var lines; - if (dontProcess) - { - if (text.charAt(text.length - 1) != "\n") - { - throw new Error("new raw text must end with newline"); - } - if (/[\r\t\xa0]/.exec(text)) - { - throw new Error("new raw text must not contain CR, tab, or nbsp"); - } - lines = text.substring(0, text.length - 1).split('\n'); - } - else - { - lines = _.map(text.split('\n'), textify); - } - var newText = "\n"; - if (lines.length > 0) - { - newText = lines.join('\n') + '\n'; - } - - inCallStackIfNecessary("importText" + (undoable ? "Undoable" : ""), function() - { - setDocText(newText); - }); - - if (dontProcess && rep.alltext != text) - { - throw new Error("mismatch error setting raw text in importText"); - } - } - - function importAText(atext, apoolJsonObj, undoable) - { - atext = Changeset.cloneAText(atext); - if (apoolJsonObj) - { - var wireApool = (new AttribPool()).fromJsonable(apoolJsonObj); - atext.attribs = Changeset.moveOpsToNewPool(atext.attribs, wireApool, rep.apool); - } - inCallStackIfNecessary("importText" + (undoable ? "Undoable" : ""), function() - { - setDocAText(atext); - }); - } - - function setDocAText(atext) - { - fastIncorp(8); - - var oldLen = rep.lines.totalWidth(); - var numLines = rep.lines.length(); - var upToLastLine = rep.lines.offsetOfIndex(numLines - 1); - var lastLineLength = rep.lines.atIndex(numLines - 1).text.length; - var assem = Changeset.smartOpAssembler(); - var o = Changeset.newOp('-'); - o.chars = upToLastLine; - o.lines = numLines - 1; - assem.append(o); - o.chars = lastLineLength; - o.lines = 0; - assem.append(o); - Changeset.appendATextToAssembler(atext, assem); - var newLen = oldLen + assem.getLengthChange(); - var changeset = Changeset.checkRep( - Changeset.pack(oldLen, newLen, assem.toString(), atext.text.slice(0, -1))); - performDocumentApplyChangeset(changeset); - - performSelectionChange([0, rep.lines.atIndex(0).lineMarker], [0, rep.lines.atIndex(0).lineMarker]); - - idleWorkTimer.atMost(100); - - if (rep.alltext != atext.text) - { - dmesg(htmlPrettyEscape(rep.alltext)); - dmesg(htmlPrettyEscape(atext.text)); - throw new Error("mismatch error setting raw text in setDocAText"); - } - } - - function setDocText(text) - { - setDocAText(Changeset.makeAText(text)); - } - - function getDocText() - { - var alltext = rep.alltext; - var len = alltext.length; - if (len > 0) len--; // final extra newline - return alltext.substring(0, len); - } - - function exportText() - { - if (currentCallStack && !currentCallStack.domClean) - { - inCallStackIfNecessary("exportText", function() - { - fastIncorp(2); - }); - } - return getDocText(); - } - - function editorChangedSize() - { - fixView(); - } - - function setOnKeyPress(handler) - { - outsideKeyPress = handler; - } - - function setOnKeyDown(handler) - { - outsideKeyDown = handler; - } - - function setNotifyDirty(handler) - { - outsideNotifyDirty = handler; - } - - function getFormattedCode() - { - if (currentCallStack && !currentCallStack.domClean) - { - inCallStackIfNecessary("getFormattedCode", incorporateUserChanges); - } - var buf = []; - if (rep.lines.length() > 0) - { - // should be the case, even for empty file - var entry = rep.lines.atIndex(0); - while (entry) - { - var domInfo = entry.domInfo; - buf.push((domInfo && domInfo.getInnerHTML()) || domline.processSpaces(domline.escapeHTML(entry.text), doesWrap) || ' ' /*empty line*/ ); - entry = rep.lines.next(entry); - } - } - return '
    ' + buf.join('
    \n
    ') + '
    '; - } - - var CMDS = { - clearauthorship: function(prompt) - { - if ((!(rep.selStart && rep.selEnd)) || isCaret()) - { - if (prompt) - { - prompt(); - } - else - { - performDocumentApplyAttributesToCharRange(0, rep.alltext.length, [ - ['author', ''] - ]); - } - } - else - { - setAttributeOnSelection('author', ''); - } - } - }; - - function execCommand(cmd) - { - cmd = cmd.toLowerCase(); - var cmdArgs = Array.prototype.slice.call(arguments, 1); - if (CMDS[cmd]) - { - inCallStackIfNecessary(cmd, function() - { - fastIncorp(9); - CMDS[cmd].apply(CMDS, cmdArgs); - }); - } - } - - function replaceRange(start, end, text) - { - inCallStackIfNecessary('replaceRange', function() - { - fastIncorp(9); - performDocumentReplaceRange(start, end, text); - }); - } - - editorInfo.ace_focus = focus; - editorInfo.ace_importText = importText; - editorInfo.ace_importAText = importAText; - editorInfo.ace_exportText = exportText; - editorInfo.ace_editorChangedSize = editorChangedSize; - editorInfo.ace_setOnKeyPress = setOnKeyPress; - editorInfo.ace_setOnKeyDown = setOnKeyDown; - editorInfo.ace_setNotifyDirty = setNotifyDirty; - editorInfo.ace_dispose = dispose; - editorInfo.ace_getFormattedCode = getFormattedCode; - editorInfo.ace_setEditable = setEditable; - editorInfo.ace_execCommand = execCommand; - editorInfo.ace_replaceRange = replaceRange; - editorInfo.ace_getAuthorInfos= getAuthorInfos; - editorInfo.ace_performDocumentReplaceRange = performDocumentReplaceRange; - editorInfo.ace_performDocumentReplaceCharRange = performDocumentReplaceCharRange; - editorInfo.ace_renumberList = renumberList; - editorInfo.ace_doReturnKey = doReturnKey; - editorInfo.ace_isBlockElement = isBlockElement; - editorInfo.ace_getLineListType = getLineListType; - - editorInfo.ace_callWithAce = function(fn, callStack, normalize) - { - var wrapper = function() - { - return fn(editorInfo); - }; - - if (normalize !== undefined) - { - var wrapper1 = wrapper; - wrapper = function() - { - editorInfo.ace_fastIncorp(9); - wrapper1(); - }; - } - - if (callStack !== undefined) - { - return editorInfo.ace_inCallStack(callStack, wrapper); - } - else - { - return wrapper(); - } - }; - - // This methed exposes a setter for some ace properties - // @param key the name of the parameter - // @param value the value to set to - editorInfo.ace_setProperty = function(key, value) - { - - // Convinience function returning a setter for a class on an element - var setClassPresenceNamed = function(element, cls){ - return function(value){ - setClassPresence(element, cls, !! value) - } - }; - - // These properties are exposed - var setters = { - wraps: setWraps, - showsauthorcolors: setClassPresenceNamed(root, "authorColors"), - showsuserselections: setClassPresenceNamed(root, "userSelections"), - showslinenumbers : function(value){ - hasLineNumbers = !! value; - // disable line numbers on mobile devices - if (browser.mobile) hasLineNumbers = false; - setClassPresence(sideDiv, "sidedivhidden", !hasLineNumbers); - fixView(); - }, - grayedout: setClassPresenceNamed(outerWin.document.body, "grayedout"), - dmesg: function(){ dmesg = window.dmesg = value; }, - userauthor: function(value){ - thisAuthor = String(value); - documentAttributeManager.author = thisAuthor; - }, - styled: setStyled, - textface: setTextFace, - textsize: setTextSize, - rtlistrue: function(value) { - setClassPresence(root, "rtl", value) - setClassPresence(root, "ltr", !value) - document.documentElement.dir = value? 'rtl' : 'ltr' - } - }; - - var setter = setters[key.toLowerCase()]; - - // check if setter is present - if(setter !== undefined){ - setter(value) - } - }; - - editorInfo.ace_setBaseText = function(txt) - { - changesetTracker.setBaseText(txt); - }; - editorInfo.ace_setBaseAttributedText = function(atxt, apoolJsonObj) - { - setUpTrackingCSS(); - changesetTracker.setBaseAttributedText(atxt, apoolJsonObj); - }; - editorInfo.ace_applyChangesToBase = function(c, optAuthor, apoolJsonObj) - { - changesetTracker.applyChangesToBase(c, optAuthor, apoolJsonObj); - }; - editorInfo.ace_prepareUserChangeset = function() - { - return changesetTracker.prepareUserChangeset(); - }; - editorInfo.ace_applyPreparedChangesetToBase = function() - { - changesetTracker.applyPreparedChangesetToBase(); - }; - editorInfo.ace_setUserChangeNotificationCallback = function(f) - { - changesetTracker.setUserChangeNotificationCallback(f); - }; - editorInfo.ace_setAuthorInfo = function(author, info) - { - setAuthorInfo(author, info); - }; - editorInfo.ace_setAuthorSelectionRange = function(author, start, end) - { - changesetTracker.setAuthorSelectionRange(author, start, end); - }; - - editorInfo.ace_getUnhandledErrors = function() - { - return caughtErrors.slice(); - }; - - editorInfo.ace_getDocument = function() - { - return doc; - }; - - editorInfo.ace_getDebugProperty = function(prop) - { - if (prop == "debugger") - { - // obfuscate "eval" so as not to scare yuicompressor - window['ev' + 'al']("debugger"); - } - else if (prop == "rep") - { - return rep; - } - else if (prop == "window") - { - return window; - } - else if (prop == "document") - { - return document; - } - return undefined; - }; - - function now() - { - return (new Date()).getTime(); - } - - function newTimeLimit(ms) - { - //console.debug("new time limit"); - var startTime = now(); - var lastElapsed = 0; - var exceededAlready = false; - var printedTrace = false; - var isTimeUp = function() - { - if (exceededAlready) - { - if ((!printedTrace)) - { // && now() - startTime - ms > 300) { - //console.trace(); - printedTrace = true; - } - return true; - } - var elapsed = now() - startTime; - if (elapsed > ms) - { - exceededAlready = true; - //console.debug("time limit hit, before was %d/%d", lastElapsed, ms); - //console.trace(); - return true; - } - else - { - lastElapsed = elapsed; - return false; - } - }; - - isTimeUp.elapsed = function() - { - return now() - startTime; - }; - return isTimeUp; - } - - - function makeIdleAction(func) - { - var scheduledTimeout = null; - var scheduledTime = 0; - - function unschedule() - { - if (scheduledTimeout) - { - scheduler.clearTimeout(scheduledTimeout); - scheduledTimeout = null; - } - } - - function reschedule(time) - { - unschedule(); - scheduledTime = time; - var delay = time - now(); - if (delay < 0) delay = 0; - scheduledTimeout = scheduler.setTimeout(callback, delay); - } - - function callback() - { - scheduledTimeout = null; - // func may reschedule the action - func(); - } - return { - atMost: function(ms) - { - var latestTime = now() + ms; - if ((!scheduledTimeout) || scheduledTime > latestTime) - { - reschedule(latestTime); - } - }, - // atLeast(ms) will schedule the action if not scheduled yet. - // In other words, "infinity" is replaced by ms, even though - // it is technically larger. - atLeast: function(ms) - { - var earliestTime = now() + ms; - if ((!scheduledTimeout) || scheduledTime < earliestTime) - { - reschedule(earliestTime); - } - }, - never: function() - { - unschedule(); - } - }; - } - - function fastIncorp(n) - { - // normalize but don't do any lexing or anything - incorporateUserChanges(newTimeLimit(0)); - } - editorInfo.ace_fastIncorp = fastIncorp; - - var idleWorkTimer = makeIdleAction(function() - { - - //if (! top.BEFORE) top.BEFORE = []; - //top.BEFORE.push(magicdom.root.dom.innerHTML); - //if (! isEditable) return; // and don't reschedule - if (inInternationalComposition) - { - // don't do idle input incorporation during international input composition - idleWorkTimer.atLeast(500); - return; - } - - inCallStackIfNecessary("idleWorkTimer", function() - { - - var isTimeUp = newTimeLimit(250); - - //console.time("idlework"); - var finishedImportantWork = false; - var finishedWork = false; - - try - { - - // isTimeUp() is a soft constraint for incorporateUserChanges, - // which always renormalizes the DOM, no matter how long it takes, - // but doesn't necessarily lex and highlight it - incorporateUserChanges(isTimeUp); - - if (isTimeUp()) return; - - updateLineNumbers(); // update line numbers if any time left - if (isTimeUp()) return; - - var visibleRange = scroll.getVisibleCharRange(rep); - var docRange = [0, rep.lines.totalWidth()]; - //console.log("%o %o", docRange, visibleRange); - finishedImportantWork = true; - finishedWork = true; - } - finally - { - //console.timeEnd("idlework"); - if (finishedWork) - { - idleWorkTimer.atMost(1000); - } - else if (finishedImportantWork) - { - // if we've finished highlighting the view area, - // more highlighting could be counter-productive, - // e.g. if the user just opened a triple-quote and will soon close it. - idleWorkTimer.atMost(500); - } - else - { - var timeToWait = Math.round(isTimeUp.elapsed() / 2); - if (timeToWait < 100) timeToWait = 100; - idleWorkTimer.atMost(timeToWait); - } - } - }); - - //if (! top.AFTER) top.AFTER = []; - //top.AFTER.push(magicdom.root.dom.innerHTML); - }); - - var _nextId = 1; - - function uniqueId(n) - { - // not actually guaranteed to be unique, e.g. if user copy-pastes - // nodes with ids - var nid = n.id; - if (nid) return nid; - return (n.id = "magicdomid" + (_nextId++)); - } - - - function recolorLinesInRange(startChar, endChar, isTimeUp, optModFunc) - { - if (endChar <= startChar) return; - if (startChar < 0 || startChar >= rep.lines.totalWidth()) return; - var lineEntry = rep.lines.atOffset(startChar); // rounds down to line boundary - var lineStart = rep.lines.offsetOfEntry(lineEntry); - var lineIndex = rep.lines.indexOfEntry(lineEntry); - var selectionNeedsResetting = false; - var firstLine = null; - var lastLine = null; - isTimeUp = (isTimeUp || noop); - - // tokenFunc function; accesses current value of lineEntry and curDocChar, - // also mutates curDocChar - var curDocChar; - var tokenFunc = function(tokenText, tokenClass) - { - lineEntry.domInfo.appendSpan(tokenText, tokenClass); - }; - if (optModFunc) - { - var f = tokenFunc; - tokenFunc = function(tokenText, tokenClass) - { - optModFunc(tokenText, tokenClass, f, curDocChar); - curDocChar += tokenText.length; - }; - } - - while (lineEntry && lineStart < endChar && !isTimeUp()) - { - //var timer = newTimeLimit(200); - var lineEnd = lineStart + lineEntry.width; - - curDocChar = lineStart; - lineEntry.domInfo.clearSpans(); - getSpansForLine(lineEntry, tokenFunc, lineStart); - lineEntry.domInfo.finishUpdate(); - - markNodeClean(lineEntry.lineNode); - - if (rep.selStart && rep.selStart[0] == lineIndex || rep.selEnd && rep.selEnd[0] == lineIndex) - { - selectionNeedsResetting = true; - } - - //if (timer()) console.dirxml(lineEntry.lineNode.dom); - if (firstLine === null) firstLine = lineIndex; - lastLine = lineIndex; - lineStart = lineEnd; - lineEntry = rep.lines.next(lineEntry); - lineIndex++; - } - if (selectionNeedsResetting) - { - currentCallStack.selectionAffected = true; - } - //console.debug("Recolored line range %d-%d", firstLine, lastLine); - } - - // like getSpansForRange, but for a line, and the func takes (text,class) - // instead of (width,class); excludes the trailing '\n' from - // consideration by func - - - function getSpansForLine(lineEntry, textAndClassFunc, lineEntryOffsetHint) - { - var lineEntryOffset = lineEntryOffsetHint; - if ((typeof lineEntryOffset) != "number") - { - lineEntryOffset = rep.lines.offsetOfEntry(lineEntry); - } - var text = lineEntry.text; - var width = lineEntry.width; // text.length+1 - if (text.length === 0) - { - // allow getLineStyleFilter to set line-div styles - var func = linestylefilter.getLineStyleFilter( - 0, '', textAndClassFunc, rep.apool); - func('', ''); - } - else - { - var offsetIntoLine = 0; - var filteredFunc = linestylefilter.getFilterStack(text, textAndClassFunc, browser); - var lineNum = rep.lines.indexOfEntry(lineEntry); - var aline = rep.alines[lineNum]; - filteredFunc = linestylefilter.getLineStyleFilter( - text.length, aline, filteredFunc, rep.apool); - filteredFunc(text, ''); - } - } - - var observedChanges; - - function clearObservedChanges() - { - observedChanges = { - cleanNodesNearChanges: {} - }; - } - clearObservedChanges(); - - function getCleanNodeByKey(key) - { - var p = PROFILER("getCleanNodeByKey", false); - p.extra = 0; - var n = doc.getElementById(key); - // copying and pasting can lead to duplicate ids - while (n && isNodeDirty(n)) - { - p.extra++; - n.id = ""; - n = doc.getElementById(key); - } - p.literal(p.extra, "extra"); - p.end(); - return n; - } - - function observeChangesAroundNode(node) - { - // Around this top-level DOM node, look for changes to the document - // (from how it looks in our representation) and record them in a way - // that can be used to "normalize" the document (apply the changes to our - // representation, and put the DOM in a canonical form). - // top.console.log("observeChangesAroundNode(%o)", node); - var cleanNode; - var hasAdjacentDirtyness; - if (!isNodeDirty(node)) - { - cleanNode = node; - var prevSib = cleanNode.previousSibling; - var nextSib = cleanNode.nextSibling; - hasAdjacentDirtyness = ((prevSib && isNodeDirty(prevSib)) || (nextSib && isNodeDirty(nextSib))); - } - else - { - // node is dirty, look for clean node above - var upNode = node.previousSibling; - while (upNode && isNodeDirty(upNode)) - { - upNode = upNode.previousSibling; - } - if (upNode) - { - cleanNode = upNode; - } - else - { - var downNode = node.nextSibling; - while (downNode && isNodeDirty(downNode)) - { - downNode = downNode.nextSibling; - } - if (downNode) - { - cleanNode = downNode; - } - } - if (!cleanNode) - { - // Couldn't find any adjacent clean nodes! - // Since top and bottom of doc is dirty, the dirty area will be detected. - return; - } - hasAdjacentDirtyness = true; - } - - if (hasAdjacentDirtyness) - { - // previous or next line is dirty - observedChanges.cleanNodesNearChanges['$' + uniqueId(cleanNode)] = true; - } - else - { - // next and prev lines are clean (if they exist) - var lineKey = uniqueId(cleanNode); - var prevSib = cleanNode.previousSibling; - var nextSib = cleanNode.nextSibling; - var actualPrevKey = ((prevSib && uniqueId(prevSib)) || null); - var actualNextKey = ((nextSib && uniqueId(nextSib)) || null); - var repPrevEntry = rep.lines.prev(rep.lines.atKey(lineKey)); - var repNextEntry = rep.lines.next(rep.lines.atKey(lineKey)); - var repPrevKey = ((repPrevEntry && repPrevEntry.key) || null); - var repNextKey = ((repNextEntry && repNextEntry.key) || null); - if (actualPrevKey != repPrevKey || actualNextKey != repNextKey) - { - observedChanges.cleanNodesNearChanges['$' + uniqueId(cleanNode)] = true; - } - } - } - - function observeChangesAroundSelection() - { - if (currentCallStack.observedSelection) return; - currentCallStack.observedSelection = true; - - var p = PROFILER("getSelection", false); - var selection = getSelection(); - p.end(); - - if (selection) - { - var node1 = topLevel(selection.startPoint.node); - var node2 = topLevel(selection.endPoint.node); - if (node1) observeChangesAroundNode(node1); - if (node2 && node1 != node2) - { - observeChangesAroundNode(node2); - } - } - } - - function observeSuspiciousNodes() - { - // inspired by Firefox bug #473255, where pasting formatted text - // causes the cursor to jump away, making the new HTML never found. - if (root.getElementsByTagName) - { - var nds = root.getElementsByTagName("style"); - for (var i = 0; i < nds.length; i++) - { - var n = topLevel(nds[i]); - if (n && n.parentNode == root) - { - observeChangesAroundNode(n); - } - } - } - } - - function incorporateUserChanges(isTimeUp) - { - - if (currentCallStack.domClean) return false; - - currentCallStack.isUserChange = true; - - isTimeUp = (isTimeUp || - function() - { - return false; - }); - - if (DEBUG && window.DONT_INCORP || window.DEBUG_DONT_INCORP) return false; - - var p = PROFILER("incorp", false); - - //if (doc.body.innerHTML.indexOf("AppJet") >= 0) - //dmesg(htmlPrettyEscape(doc.body.innerHTML)); - //if (top.RECORD) top.RECORD.push(doc.body.innerHTML); - // returns true if dom changes were made - if (!root.firstChild) - { - root.innerHTML = "
    "; - } - - p.mark("obs"); - observeChangesAroundSelection(); - observeSuspiciousNodes(); - p.mark("dirty"); - var dirtyRanges = getDirtyRanges(); - //console.log("dirtyRanges: "+toSource(dirtyRanges)); - var dirtyRangesCheckOut = true; - var j = 0; - var a, b; - while (j < dirtyRanges.length) - { - a = dirtyRanges[j][0]; - b = dirtyRanges[j][1]; - if (!((a === 0 || getCleanNodeByKey(rep.lines.atIndex(a - 1).key)) && (b == rep.lines.length() || getCleanNodeByKey(rep.lines.atIndex(b).key)))) - { - dirtyRangesCheckOut = false; - break; - } - j++; - } - if (!dirtyRangesCheckOut) - { - var numBodyNodes = root.childNodes.length; - for (var k = 0; k < numBodyNodes; k++) - { - var bodyNode = root.childNodes.item(k); - if ((bodyNode.tagName) && ((!bodyNode.id) || (!rep.lines.containsKey(bodyNode.id)))) - { - observeChangesAroundNode(bodyNode); - } - } - dirtyRanges = getDirtyRanges(); - } - - clearObservedChanges(); - - p.mark("getsel"); - var selection = getSelection(); - - //console.log(magicdom.root.dom.innerHTML); - //console.log("got selection: %o", selection); - var selStart, selEnd; // each one, if truthy, has [line,char] needed to set selection - var i = 0; - var splicesToDo = []; - var netNumLinesChangeSoFar = 0; - var toDeleteAtEnd = []; - p.mark("ranges"); - p.literal(dirtyRanges.length, "numdirt"); - var domInsertsNeeded = []; // each entry is [nodeToInsertAfter, [info1, info2, ...]] - while (i < dirtyRanges.length) - { - var range = dirtyRanges[i]; - a = range[0]; - b = range[1]; - var firstDirtyNode = (((a === 0) && root.firstChild) || getCleanNodeByKey(rep.lines.atIndex(a - 1).key).nextSibling); - firstDirtyNode = (firstDirtyNode && isNodeDirty(firstDirtyNode) && firstDirtyNode); - var lastDirtyNode = (((b == rep.lines.length()) && root.lastChild) || getCleanNodeByKey(rep.lines.atIndex(b).key).previousSibling); - lastDirtyNode = (lastDirtyNode && isNodeDirty(lastDirtyNode) && lastDirtyNode); - if (firstDirtyNode && lastDirtyNode) - { - var cc = makeContentCollector(isStyled, browser, rep.apool, null, className2Author); - cc.notifySelection(selection); - var dirtyNodes = []; - for (var n = firstDirtyNode; n && !(n.previousSibling && n.previousSibling == lastDirtyNode); - n = n.nextSibling) - { - if (browser.msie) - { - // try to undo IE's pesky and overzealous linkification - try - { - n.createTextRange().execCommand("unlink", false, null); - } - catch (e) - {} - } - cc.collectContent(n); - dirtyNodes.push(n); - } - cc.notifyNextNode(lastDirtyNode.nextSibling); - var lines = cc.getLines(); - if ((lines.length <= 1 || lines[lines.length - 1] !== "") && lastDirtyNode.nextSibling) - { - // dirty region doesn't currently end a line, even taking the following node - // (or lack of node) into account, so include the following clean node. - // It could be SPAN or a DIV; basically this is any case where the contentCollector - // decides it isn't done. - // Note that this clean node might need to be there for the next dirty range. - //console.log("inclusive of "+lastDirtyNode.next().dom.tagName); - b++; - var cleanLine = lastDirtyNode.nextSibling; - cc.collectContent(cleanLine); - toDeleteAtEnd.push(cleanLine); - cc.notifyNextNode(cleanLine.nextSibling); - } - - var ccData = cc.finish(); - var ss = ccData.selStart; - var se = ccData.selEnd; - lines = ccData.lines; - var lineAttribs = ccData.lineAttribs; - var linesWrapped = ccData.linesWrapped; - var scrollToTheLeftNeeded = false; - - if (linesWrapped > 0) - { - if(!browser.msie){ - // chrome decides in it's infinite wisdom that its okay to put the browsers visisble window in the middle of the span - // an outcome of this is that the first chars of the string are no longer visible to the user.. Yay chrome.. - // Move the browsers visible area to the left hand side of the span - // Firefox isn't quite so bad, but it's still pretty quirky. - var scrollToTheLeftNeeded = true; - } - // console.log("Editor warning: " + linesWrapped + " long line" + (linesWrapped == 1 ? " was" : "s were") + " hard-wrapped into " + ccData.numLinesAfter + " lines."); - } - - if (ss[0] >= 0) selStart = [ss[0] + a + netNumLinesChangeSoFar, ss[1]]; - if (se[0] >= 0) selEnd = [se[0] + a + netNumLinesChangeSoFar, se[1]]; - - var entries = []; - var nodeToAddAfter = lastDirtyNode; - var lineNodeInfos = new Array(lines.length); - for (var k = 0; k < lines.length; k++) - { - var lineString = lines[k]; - var newEntry = createDomLineEntry(lineString); - entries.push(newEntry); - lineNodeInfos[k] = newEntry.domInfo; - } - //var fragment = magicdom.wrapDom(document.createDocumentFragment()); - domInsertsNeeded.push([nodeToAddAfter, lineNodeInfos]); - _.each(dirtyNodes,function(n){ - toDeleteAtEnd.push(n); - }); - var spliceHints = {}; - if (selStart) spliceHints.selStart = selStart; - if (selEnd) spliceHints.selEnd = selEnd; - splicesToDo.push([a + netNumLinesChangeSoFar, b - a, entries, lineAttribs, spliceHints]); - netNumLinesChangeSoFar += (lines.length - (b - a)); - } - else if (b > a) - { - splicesToDo.push([a + netNumLinesChangeSoFar, b - a, [], - [] - ]); - } - i++; - } - - var domChanges = (splicesToDo.length > 0); - - // update the representation - p.mark("splice"); - _.each(splicesToDo, function(splice) - { - doIncorpLineSplice(splice[0], splice[1], splice[2], splice[3], splice[4]); - }); - - //p.mark("relex"); - //rep.lexer.lexCharRange(scroll.getVisibleCharRange(rep), function() { return false; }); - //var isTimeUp = newTimeLimit(100); - // do DOM inserts - p.mark("insert"); - _.each(domInsertsNeeded,function(ins) - { - insertDomLines(ins[0], ins[1], isTimeUp); - }); - - p.mark("del"); - // delete old dom nodes - _.each(toDeleteAtEnd,function(n) - { - //var id = n.uniqueId(); - // parent of n may not be "root" in IE due to non-tree-shaped DOM (wtf) - if(n.parentNode) n.parentNode.removeChild(n); - - //dmesg(htmlPrettyEscape(htmlForRemovedChild(n))); - //console.log("removed: "+id); - }); - - if(scrollToTheLeftNeeded){ // needed to stop chrome from breaking the ui when long strings without spaces are pasted - $("#innerdocbody").scrollLeft(0); - } - - p.mark("findsel"); - // if the nodes that define the selection weren't encountered during - // content collection, figure out where those nodes are now. - if (selection && !selStart) - { - //if (domChanges) dmesg("selection not collected"); - var selStartFromHook = hooks.callAll('aceStartLineAndCharForPoint', { - callstack: currentCallStack, - editorInfo: editorInfo, - rep: rep, - root:root, - point:selection.startPoint, - documentAttributeManager: documentAttributeManager - }); - selStart = (selStartFromHook==null||selStartFromHook.length==0)?getLineAndCharForPoint(selection.startPoint):selStartFromHook; - } - if (selection && !selEnd) - { - var selEndFromHook = hooks.callAll('aceEndLineAndCharForPoint', { - callstack: currentCallStack, - editorInfo: editorInfo, - rep: rep, - root:root, - point:selection.endPoint, - documentAttributeManager: documentAttributeManager - }); - selEnd = (selEndFromHook==null||selEndFromHook.length==0)?getLineAndCharForPoint(selection.endPoint):selEndFromHook; - } - - // selection from content collection can, in various ways, extend past final - // BR in firefox DOM, so cap the line - var numLines = rep.lines.length(); - if (selStart && selStart[0] >= numLines) - { - selStart[0] = numLines - 1; - selStart[1] = rep.lines.atIndex(selStart[0]).text.length; - } - if (selEnd && selEnd[0] >= numLines) - { - selEnd[0] = numLines - 1; - selEnd[1] = rep.lines.atIndex(selEnd[0]).text.length; - } - - p.mark("repsel"); - // update rep if we have a new selection - // NOTE: IE loses the selection when you click stuff in e.g. the - // editbar, so removing the selection when it's lost is not a good - // idea. - if (selection) repSelectionChange(selStart, selEnd, selection && selection.focusAtStart); - // update browser selection - p.mark("browsel"); - if (selection && (domChanges || isCaret())) - { - // if no DOM changes (not this case), want to treat range selection delicately, - // e.g. in IE not lose which end of the selection is the focus/anchor; - // on the other hand, we may have just noticed a press of PageUp/PageDown - currentCallStack.selectionAffected = true; - } - - currentCallStack.domClean = true; - - p.mark("fixview"); - - fixView(); - - p.end("END"); - - return domChanges; - } - - var STYLE_ATTRIBS = { - bold: true, - italic: true, - underline: true, - strikethrough: true, - list: true - }; - var OTHER_INCORPED_ATTRIBS = { - insertorder: true, - author: true - }; - - function isStyleAttribute(aname) - { - return !!STYLE_ATTRIBS[aname]; - } - - function isOtherIncorpedAttribute(aname) - { - return !!OTHER_INCORPED_ATTRIBS[aname]; - } - - function insertDomLines(nodeToAddAfter, infoStructs, isTimeUp) - { - isTimeUp = (isTimeUp || - function() - { - return false; - }); - - var lastEntry; - var lineStartOffset; - if (infoStructs.length < 1) return; - var startEntry = rep.lines.atKey(uniqueId(infoStructs[0].node)); - var endEntry = rep.lines.atKey(uniqueId(infoStructs[infoStructs.length - 1].node)); - var charStart = rep.lines.offsetOfEntry(startEntry); - var charEnd = rep.lines.offsetOfEntry(endEntry) + endEntry.width; - - //rep.lexer.lexCharRange([charStart, charEnd], isTimeUp); - _.each(infoStructs, function(info) - { - var p2 = PROFILER("insertLine", false); - var node = info.node; - var key = uniqueId(node); - var entry; - p2.mark("findEntry"); - if (lastEntry) - { - // optimization to avoid recalculation - var next = rep.lines.next(lastEntry); - if (next && next.key == key) - { - entry = next; - lineStartOffset += lastEntry.width; - } - } - if (!entry) - { - p2.literal(1, "nonopt"); - entry = rep.lines.atKey(key); - lineStartOffset = rep.lines.offsetOfKey(key); - } - else p2.literal(0, "nonopt"); - lastEntry = entry; - p2.mark("spans"); - getSpansForLine(entry, function(tokenText, tokenClass) - { - info.appendSpan(tokenText, tokenClass); - }, lineStartOffset, isTimeUp()); - //else if (entry.text.length > 0) { - //info.appendSpan(entry.text, 'dirty'); - //} - p2.mark("addLine"); - info.prepareForAdd(); - entry.lineMarker = info.lineMarker; - if (!nodeToAddAfter) - { - root.insertBefore(node, root.firstChild); - } - else - { - root.insertBefore(node, nodeToAddAfter.nextSibling); - } - nodeToAddAfter = node; - info.notifyAdded(); - p2.mark("markClean"); - markNodeClean(node); - p2.end(); - }); - } - - function isCaret() - { - return (rep.selStart && rep.selEnd && rep.selStart[0] == rep.selEnd[0] && rep.selStart[1] == rep.selEnd[1]); - } - editorInfo.ace_isCaret = isCaret; - - // prereq: isCaret() - - - function caretLine() - { - return rep.selStart[0]; - } - editorInfo.ace_caretLine = caretLine; - - function caretColumn() - { - return rep.selStart[1]; - } - editorInfo.ace_caretColumn = caretColumn; - - function caretDocChar() - { - return rep.lines.offsetOfIndex(caretLine()) + caretColumn(); - } - editorInfo.ace_caretDocChar = caretDocChar; - - function handleReturnIndentation() - { - // on return, indent to level of previous line - if (isCaret() && caretColumn() === 0 && caretLine() > 0) - { - var lineNum = caretLine(); - var thisLine = rep.lines.atIndex(lineNum); - var prevLine = rep.lines.prev(thisLine); - var prevLineText = prevLine.text; - var theIndent = /^ *(?:)/.exec(prevLineText)[0]; - var shouldIndent = parent.parent.clientVars.indentationOnNewLine; - if (shouldIndent && /[\[\(\:\{]\s*$/.exec(prevLineText)) - { - theIndent += THE_TAB; - } - var cs = Changeset.builder(rep.lines.totalWidth()).keep( - rep.lines.offsetOfIndex(lineNum), lineNum).insert( - theIndent, [ - ['author', thisAuthor] - ], rep.apool).toString(); - performDocumentApplyChangeset(cs); - performSelectionChange([lineNum, theIndent.length], [lineNum, theIndent.length]); - } - } - - function getPointForLineAndChar(lineAndChar) - { - var line = lineAndChar[0]; - var charsLeft = lineAndChar[1]; - //console.log("line: %d, key: %s, node: %o", line, rep.lines.atIndex(line).key, - //getCleanNodeByKey(rep.lines.atIndex(line).key)); - var lineEntry = rep.lines.atIndex(line); - charsLeft -= lineEntry.lineMarker; - if (charsLeft < 0) - { - charsLeft = 0; - } - var lineNode = lineEntry.lineNode; - var n = lineNode; - var after = false; - if (charsLeft === 0) - { - var index = 0; - - if (browser.msie && parseInt(browser.version) >= 11) { - browser.msie = false; // Temp fix to resolve enter and backspace issues.. - // Note that this makes MSIE behave like modern browsers.. - } - if (browser.msie && line == (rep.lines.length() - 1) && lineNode.childNodes.length === 0) - { - // best to stay at end of last empty div in IE - index = 1; - } - return { - node: lineNode, - index: index, - maxIndex: 1 - }; - } - while (!(n == lineNode && after)) - { - if (after) - { - if (n.nextSibling) - { - n = n.nextSibling; - after = false; - } - else n = n.parentNode; - } - else - { - if (isNodeText(n)) - { - var len = n.nodeValue.length; - if (charsLeft <= len) - { - return { - node: n, - index: charsLeft, - maxIndex: len - }; - } - charsLeft -= len; - after = true; - } - else - { - if (n.firstChild) n = n.firstChild; - else after = true; - } - } - } - return { - node: lineNode, - index: 1, - maxIndex: 1 - }; - } - - function nodeText(n) - { - if (browser.msie) { - return n.innerText; - } else { - return n.textContent || n.nodeValue || ''; - } - } - - function getLineAndCharForPoint(point) - { - // Turn DOM node selection into [line,char] selection. - // This method has to work when the DOM is not pristine, - // assuming the point is not in a dirty node. - if (point.node == root) - { - if (point.index === 0) - { - return [0, 0]; - } - else - { - var N = rep.lines.length(); - var ln = rep.lines.atIndex(N - 1); - return [N - 1, ln.text.length]; - } - } - else - { - var n = point.node; - var col = 0; - // if this part fails, it probably means the selection node - // was dirty, and we didn't see it when collecting dirty nodes. - if (isNodeText(n)) - { - col = point.index; - } - else if (point.index > 0) - { - col = nodeText(n).length; - } - var parNode, prevSib; - while ((parNode = n.parentNode) != root) - { - if ((prevSib = n.previousSibling)) - { - n = prevSib; - col += nodeText(n).length; - } - else - { - n = parNode; - } - } - if (n.id === "") console.debug("BAD"); - if (n.firstChild && isBlockElement(n.firstChild)) - { - col += 1; // lineMarker - } - var lineEntry = rep.lines.atKey(n.id); - var lineNum = rep.lines.indexOfEntry(lineEntry); - return [lineNum, col]; - } - } - editorInfo.ace_getLineAndCharForPoint = getLineAndCharForPoint; - - function createDomLineEntry(lineString) - { - var info = doCreateDomLine(lineString.length > 0); - var newNode = info.node; - return { - key: uniqueId(newNode), - text: lineString, - lineNode: newNode, - domInfo: info, - lineMarker: 0 - }; - } - - function canApplyChangesetToDocument(changes) - { - return Changeset.oldLen(changes) == rep.alltext.length; - } - - function performDocumentApplyChangeset(changes, insertsAfterSelection) - { - doRepApplyChangeset(changes, insertsAfterSelection); - - var requiredSelectionSetting = null; - if (rep.selStart && rep.selEnd) - { - var selStartChar = rep.lines.offsetOfIndex(rep.selStart[0]) + rep.selStart[1]; - var selEndChar = rep.lines.offsetOfIndex(rep.selEnd[0]) + rep.selEnd[1]; - var result = Changeset.characterRangeFollow(changes, selStartChar, selEndChar, insertsAfterSelection); - requiredSelectionSetting = [result[0], result[1], rep.selFocusAtStart]; - } - - var linesMutatee = { - splice: function(start, numRemoved, newLinesVA) - { - var args = Array.prototype.slice.call(arguments, 2); - domAndRepSplice(start, numRemoved, _.map(args, function(s){ return s.slice(0, -1); }), null); - }, - get: function(i) - { - return rep.lines.atIndex(i).text + '\n'; - }, - length: function() - { - return rep.lines.length(); - }, - slice_notused: function(start, end) - { - return _.map(rep.lines.slice(start, end), function(e) - { - return e.text + '\n'; - }); - } - }; - - Changeset.mutateTextLines(changes, linesMutatee); - - checkALines(); - - if (requiredSelectionSetting) - { - performSelectionChange(lineAndColumnFromChar(requiredSelectionSetting[0]), lineAndColumnFromChar(requiredSelectionSetting[1]), requiredSelectionSetting[2]); - } - - function domAndRepSplice(startLine, deleteCount, newLineStrings, isTimeUp) - { - // dgreensp 3/2009: the spliced lines may be in the middle of a dirty region, - // so if no explicit time limit, don't spend a lot of time highlighting - isTimeUp = (isTimeUp || newTimeLimit(50)); - - var keysToDelete = []; - if (deleteCount > 0) - { - var entryToDelete = rep.lines.atIndex(startLine); - for (var i = 0; i < deleteCount; i++) - { - keysToDelete.push(entryToDelete.key); - entryToDelete = rep.lines.next(entryToDelete); - } - } - - var lineEntries = _.map(newLineStrings, createDomLineEntry); - - doRepLineSplice(startLine, deleteCount, lineEntries); - - var nodeToAddAfter; - if (startLine > 0) - { - nodeToAddAfter = getCleanNodeByKey(rep.lines.atIndex(startLine - 1).key); - } - else nodeToAddAfter = null; - - insertDomLines(nodeToAddAfter, _.map(lineEntries, function(entry) - { - return entry.domInfo; - }), isTimeUp); - - _.each(keysToDelete, function(k) - { - var n = doc.getElementById(k); - n.parentNode.removeChild(n); - }); - - if ((rep.selStart && rep.selStart[0] >= startLine && rep.selStart[0] <= startLine + deleteCount) || (rep.selEnd && rep.selEnd[0] >= startLine && rep.selEnd[0] <= startLine + deleteCount)) - { - currentCallStack.selectionAffected = true; - } - } - } - - function checkChangesetLineInformationAgainstRep(changes) - { - return true; // disable for speed - var opIter = Changeset.opIterator(Changeset.unpack(changes).ops); - var curOffset = 0; - var curLine = 0; - var curCol = 0; - while (opIter.hasNext()) - { - var o = opIter.next(); - if (o.opcode == '-' || o.opcode == '=') - { - curOffset += o.chars; - if (o.lines) - { - curLine += o.lines; - curCol = 0; - } - else - { - curCol += o.chars; - } - } - var calcLine = rep.lines.indexOfOffset(curOffset); - var calcLineStart = rep.lines.offsetOfIndex(calcLine); - var calcCol = curOffset - calcLineStart; - if (calcCol != curCol || calcLine != curLine) - { - return false; - } - } - return true; - } - - function doRepApplyChangeset(changes, insertsAfterSelection) - { - Changeset.checkRep(changes); - - if (Changeset.oldLen(changes) != rep.alltext.length) throw new Error("doRepApplyChangeset length mismatch: " + Changeset.oldLen(changes) + "/" + rep.alltext.length); - - if (!checkChangesetLineInformationAgainstRep(changes)) - { - throw new Error("doRepApplyChangeset line break mismatch"); - } - - (function doRecordUndoInformation(changes) - { - var editEvent = currentCallStack.editEvent; - if (editEvent.eventType == "nonundoable") - { - if (!editEvent.changeset) - { - editEvent.changeset = changes; - } - else - { - editEvent.changeset = Changeset.compose(editEvent.changeset, changes, rep.apool); - } - } - else - { - var inverseChangeset = Changeset.inverse(changes, { - get: function(i) - { - return rep.lines.atIndex(i).text + '\n'; - }, - length: function() - { - return rep.lines.length(); - } - }, rep.alines, rep.apool); - - if (!editEvent.backset) - { - editEvent.backset = inverseChangeset; - } - else - { - editEvent.backset = Changeset.compose(inverseChangeset, editEvent.backset, rep.apool); - } - } - })(changes); - - //rep.alltext = Changeset.applyToText(changes, rep.alltext); - Changeset.mutateAttributionLines(changes, rep.alines, rep.apool); - - if (changesetTracker.isTracking()) - { - changesetTracker.composeUserChangeset(changes); - } - - } - - /* - Converts the position of a char (index in String) into a [row, col] tuple - */ - function lineAndColumnFromChar(x) - { - var lineEntry = rep.lines.atOffset(x); - var lineStart = rep.lines.offsetOfEntry(lineEntry); - var lineNum = rep.lines.indexOfEntry(lineEntry); - return [lineNum, x - lineStart]; - } - - function performDocumentReplaceCharRange(startChar, endChar, newText) - { - if (startChar == endChar && newText.length === 0) - { - return; - } - // Requires that the replacement preserve the property that the - // internal document text ends in a newline. Given this, we - // rewrite the splice so that it doesn't touch the very last - // char of the document. - if (endChar == rep.alltext.length) - { - if (startChar == endChar) - { - // an insert at end - startChar--; - endChar--; - newText = '\n' + newText.substring(0, newText.length - 1); - } - else if (newText.length === 0) - { - // a delete at end - startChar--; - endChar--; - } - else - { - // a replace at end - endChar--; - newText = newText.substring(0, newText.length - 1); - } - } - performDocumentReplaceRange(lineAndColumnFromChar(startChar), lineAndColumnFromChar(endChar), newText); - } - - function performDocumentReplaceRange(start, end, newText) - { - if (start === undefined) start = rep.selStart; - if (end === undefined) end = rep.selEnd; - - //dmesg(String([start.toSource(),end.toSource(),newText.toSource()])); - // start[0]: <--- start[1] --->CCCCCCCCCCC\n - // CCCCCCCCCCCCCCCCCCCC\n - // CCCC\n - // end[0]: -------\n - var builder = Changeset.builder(rep.lines.totalWidth()); - ChangesetUtils.buildKeepToStartOfRange(rep, builder, start); - ChangesetUtils.buildRemoveRange(rep, builder, start, end); - builder.insert(newText, [ - ['author', thisAuthor] - ], rep.apool); - var cs = builder.toString(); - - performDocumentApplyChangeset(cs); - } - - function performDocumentApplyAttributesToCharRange(start, end, attribs) - { - end = Math.min(end, rep.alltext.length - 1); - documentAttributeManager.setAttributesOnRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs); - } - editorInfo.ace_performDocumentApplyAttributesToCharRange = performDocumentApplyAttributesToCharRange; - - - function setAttributeOnSelection(attributeName, attributeValue) - { - if (!(rep.selStart && rep.selEnd)) return; - - documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [ - [attributeName, attributeValue] - ]); - } - editorInfo.ace_setAttributeOnSelection = setAttributeOnSelection; - - - function getAttributeOnSelection(attributeName, prevChar){ - if (!(rep.selStart && rep.selEnd)) return - var isNotSelection = (rep.selStart[0] == rep.selEnd[0] && rep.selEnd[1] === rep.selStart[1]); - if(isNotSelection){ - if(prevChar){ - // If it's not the start of the line - if(rep.selStart[1] !== 0){ - rep.selStart[1]--; - } - } - } - - var withIt = Changeset.makeAttribsString('+', [ - [attributeName, 'true'] - ], rep.apool); - var withItRegex = new RegExp(withIt.replace(/\*/g, '\\*') + "(\\*|$)"); - function hasIt(attribs) - { - return withItRegex.test(attribs); - } - - return rangeHasAttrib(rep.selStart, rep.selEnd) - - function rangeHasAttrib(selStart, selEnd) { - // if range is collapsed -> no attribs in range - if(selStart[1] == selEnd[1] && selStart[0] == selEnd[0]) return false - - if(selStart[0] != selEnd[0]) { // -> More than one line selected - var hasAttrib = true - - // from selStart to the end of the first line - hasAttrib = hasAttrib && rangeHasAttrib(selStart, [selStart[0], rep.lines.atIndex(selStart[0]).text.length]) - - // for all lines in between - for(var n=selStart[0]+1; n < selEnd[0]; n++) { - hasAttrib = hasAttrib && rangeHasAttrib([n, 0], [n, rep.lines.atIndex(n).text.length]) - } - - // for the last, potentially partial, line - hasAttrib = hasAttrib && rangeHasAttrib([selEnd[0], 0], [selEnd[0], selEnd[1]]) - - return hasAttrib - } - - // Logic tells us we now have a range on a single line - - var lineNum = selStart[0] - , start = selStart[1] - , end = selEnd[1] - , hasAttrib = true - - // Iterate over attribs on this line - - var opIter = Changeset.opIterator(rep.alines[lineNum]) - , indexIntoLine = 0 - - while (opIter.hasNext()) { - var op = opIter.next(); - var opStartInLine = indexIntoLine; - var opEndInLine = opStartInLine + op.chars; - if (!hasIt(op.attribs)) { - // does op overlap selection? - if (!(opEndInLine <= start || opStartInLine >= end)) { - hasAttrib = false; // since it's overlapping but hasn't got the attrib -> range hasn't got it - break; - } - } - indexIntoLine = opEndInLine; - } - - return hasAttrib - } - } - - editorInfo.ace_getAttributeOnSelection = getAttributeOnSelection; - - function toggleAttributeOnSelection(attributeName) - { - if (!(rep.selStart && rep.selEnd)) return; - - var selectionAllHasIt = true; - var withIt = Changeset.makeAttribsString('+', [ - [attributeName, 'true'] - ], rep.apool); - var withItRegex = new RegExp(withIt.replace(/\*/g, '\\*') + "(\\*|$)"); - - function hasIt(attribs) - { - return withItRegex.test(attribs); - } - - var selStartLine = rep.selStart[0]; - var selEndLine = rep.selEnd[0]; - for (var n = selStartLine; n <= selEndLine; n++) - { - var opIter = Changeset.opIterator(rep.alines[n]); - var indexIntoLine = 0; - var selectionStartInLine = 0; - if (documentAttributeManager.lineHasMarker(n)) { - selectionStartInLine = 1; // ignore "*" used as line marker - } - var selectionEndInLine = rep.lines.atIndex(n).text.length; // exclude newline - if (n == selStartLine) - { - selectionStartInLine = rep.selStart[1]; - } - if (n == selEndLine) - { - selectionEndInLine = rep.selEnd[1]; - } - while (opIter.hasNext()) - { - var op = opIter.next(); - var opStartInLine = indexIntoLine; - var opEndInLine = opStartInLine + op.chars; - if (!hasIt(op.attribs)) - { - // does op overlap selection? - if (!(opEndInLine <= selectionStartInLine || opStartInLine >= selectionEndInLine)) - { - selectionAllHasIt = false; - break; - } - } - indexIntoLine = opEndInLine; - } - if (!selectionAllHasIt) - { - break; - } - } - - - var attributeValue = selectionAllHasIt ? '' : 'true'; - documentAttributeManager.setAttributesOnRange(rep.selStart, rep.selEnd, [[attributeName, attributeValue]]); - if (attribIsFormattingStyle(attributeName)) { - updateStyleButtonState(attributeName, !selectionAllHasIt); // italic, bold, ... - } - } - editorInfo.ace_toggleAttributeOnSelection = toggleAttributeOnSelection; - - function performDocumentReplaceSelection(newText) - { - if (!(rep.selStart && rep.selEnd)) return; - performDocumentReplaceRange(rep.selStart, rep.selEnd, newText); - } - - // Change the abstract representation of the document to have a different set of lines. - // Must be called after rep.alltext is set. - - - function doRepLineSplice(startLine, deleteCount, newLineEntries) - { - - _.each(newLineEntries, function(entry) - { - entry.width = entry.text.length + 1; - }); - - var startOldChar = rep.lines.offsetOfIndex(startLine); - var endOldChar = rep.lines.offsetOfIndex(startLine + deleteCount); - - var oldRegionStart = rep.lines.offsetOfIndex(startLine); - var oldRegionEnd = rep.lines.offsetOfIndex(startLine + deleteCount); - rep.lines.splice(startLine, deleteCount, newLineEntries); - currentCallStack.docTextChanged = true; - currentCallStack.repChanged = true; - var newRegionEnd = rep.lines.offsetOfIndex(startLine + newLineEntries.length); - - var newText = _.map(newLineEntries, function(e) - { - return e.text + '\n'; - }).join(''); - - rep.alltext = rep.alltext.substring(0, startOldChar) + newText + rep.alltext.substring(endOldChar, rep.alltext.length); - - //var newTotalLength = rep.alltext.length; - //rep.lexer.updateBuffer(rep.alltext, oldRegionStart, oldRegionEnd - oldRegionStart, - //newRegionEnd - oldRegionStart); - } - - function doIncorpLineSplice(startLine, deleteCount, newLineEntries, lineAttribs, hints) - { - var startOldChar = rep.lines.offsetOfIndex(startLine); - var endOldChar = rep.lines.offsetOfIndex(startLine + deleteCount); - - var oldRegionStart = rep.lines.offsetOfIndex(startLine); - - var selStartHintChar, selEndHintChar; - if (hints && hints.selStart) - { - selStartHintChar = rep.lines.offsetOfIndex(hints.selStart[0]) + hints.selStart[1] - oldRegionStart; - } - if (hints && hints.selEnd) - { - selEndHintChar = rep.lines.offsetOfIndex(hints.selEnd[0]) + hints.selEnd[1] - oldRegionStart; - } - - var newText = _.map(newLineEntries, function(e) - { - return e.text + '\n'; - }).join(''); - var oldText = rep.alltext.substring(startOldChar, endOldChar); - var oldAttribs = rep.alines.slice(startLine, startLine + deleteCount).join(''); - var newAttribs = lineAttribs.join('|1+1') + '|1+1'; // not valid in a changeset - var analysis = analyzeChange(oldText, newText, oldAttribs, newAttribs, selStartHintChar, selEndHintChar); - var commonStart = analysis[0]; - var commonEnd = analysis[1]; - var shortOldText = oldText.substring(commonStart, oldText.length - commonEnd); - var shortNewText = newText.substring(commonStart, newText.length - commonEnd); - var spliceStart = startOldChar + commonStart; - var spliceEnd = endOldChar - commonEnd; - var shiftFinalNewlineToBeforeNewText = false; - - // adjust the splice to not involve the final newline of the document; - // be very defensive - if (shortOldText.charAt(shortOldText.length - 1) == '\n' && shortNewText.charAt(shortNewText.length - 1) == '\n') - { - // replacing text that ends in newline with text that also ends in newline - // (still, after analysis, somehow) - shortOldText = shortOldText.slice(0, -1); - shortNewText = shortNewText.slice(0, -1); - spliceEnd--; - commonEnd++; - } - if (shortOldText.length === 0 && spliceStart == rep.alltext.length && shortNewText.length > 0) - { - // inserting after final newline, bad - spliceStart--; - spliceEnd--; - shortNewText = '\n' + shortNewText.slice(0, -1); - shiftFinalNewlineToBeforeNewText = true; - } - if (spliceEnd == rep.alltext.length && shortOldText.length > 0 && shortNewText.length === 0) - { - // deletion at end of rep.alltext - if (rep.alltext.charAt(spliceStart - 1) == '\n') - { - // (if not then what the heck? it will definitely lead - // to a rep.alltext without a final newline) - spliceStart--; - spliceEnd--; - } - } - - if (!(shortOldText.length === 0 && shortNewText.length === 0)) - { - var oldDocText = rep.alltext; - var oldLen = oldDocText.length; - - var spliceStartLine = rep.lines.indexOfOffset(spliceStart); - var spliceStartLineStart = rep.lines.offsetOfIndex(spliceStartLine); - - var startBuilder = function() - { - var builder = Changeset.builder(oldLen); - builder.keep(spliceStartLineStart, spliceStartLine); - builder.keep(spliceStart - spliceStartLineStart); - return builder; - }; - - var eachAttribRun = function(attribs, func /*(startInNewText, endInNewText, attribs)*/ ) - { - var attribsIter = Changeset.opIterator(attribs); - var textIndex = 0; - var newTextStart = commonStart; - var newTextEnd = newText.length - commonEnd - (shiftFinalNewlineToBeforeNewText ? 1 : 0); - while (attribsIter.hasNext()) - { - var op = attribsIter.next(); - var nextIndex = textIndex + op.chars; - if (!(nextIndex <= newTextStart || textIndex >= newTextEnd)) - { - func(Math.max(newTextStart, textIndex), Math.min(newTextEnd, nextIndex), op.attribs); - } - textIndex = nextIndex; - } - }; - - var justApplyStyles = (shortNewText == shortOldText); - var theChangeset; - - if (justApplyStyles) - { - // create changeset that clears the incorporated styles on - // the existing text. we compose this with the - // changeset the applies the styles found in the DOM. - // This allows us to incorporate, e.g., Safari's native "unbold". - var incorpedAttribClearer = cachedStrFunc(function(oldAtts) - { - return Changeset.mapAttribNumbers(oldAtts, function(n) - { - var k = rep.apool.getAttribKey(n); - if (isStyleAttribute(k)) - { - return rep.apool.putAttrib([k, '']); - } - return false; - }); - }); - - var builder1 = startBuilder(); - if (shiftFinalNewlineToBeforeNewText) - { - builder1.keep(1, 1); - } - eachAttribRun(oldAttribs, function(start, end, attribs) - { - builder1.keepText(newText.substring(start, end), incorpedAttribClearer(attribs)); - }); - var clearer = builder1.toString(); - - var builder2 = startBuilder(); - if (shiftFinalNewlineToBeforeNewText) - { - builder2.keep(1, 1); - } - eachAttribRun(newAttribs, function(start, end, attribs) - { - builder2.keepText(newText.substring(start, end), attribs); - }); - var styler = builder2.toString(); - - theChangeset = Changeset.compose(clearer, styler, rep.apool); - } - else - { - var builder = startBuilder(); - - var spliceEndLine = rep.lines.indexOfOffset(spliceEnd); - var spliceEndLineStart = rep.lines.offsetOfIndex(spliceEndLine); - if (spliceEndLineStart > spliceStart) - { - builder.remove(spliceEndLineStart - spliceStart, spliceEndLine - spliceStartLine); - builder.remove(spliceEnd - spliceEndLineStart); - } - else - { - builder.remove(spliceEnd - spliceStart); - } - - var isNewTextMultiauthor = false; - var authorAtt = Changeset.makeAttribsString('+', (thisAuthor ? [ - ['author', thisAuthor] - ] : []), rep.apool); - var authorizer = cachedStrFunc(function(oldAtts) - { - if (isNewTextMultiauthor) - { - // prefer colors from DOM - return Changeset.composeAttributes(authorAtt, oldAtts, true, rep.apool); - } - else - { - // use this author's color - return Changeset.composeAttributes(oldAtts, authorAtt, true, rep.apool); - } - }); - - var foundDomAuthor = ''; - eachAttribRun(newAttribs, function(start, end, attribs) - { - var a = Changeset.attribsAttributeValue(attribs, 'author', rep.apool); - if (a && a != foundDomAuthor) - { - if (!foundDomAuthor) - { - foundDomAuthor = a; - } - else - { - isNewTextMultiauthor = true; // multiple authors in DOM! - } - } - }); - - if (shiftFinalNewlineToBeforeNewText) - { - builder.insert('\n', authorizer('')); - } - - eachAttribRun(newAttribs, function(start, end, attribs) - { - builder.insert(newText.substring(start, end), authorizer(attribs)); - }); - theChangeset = builder.toString(); - } - - //dmesg(htmlPrettyEscape(theChangeset)); - doRepApplyChangeset(theChangeset); - } - - // do this no matter what, because we need to get the right - // line keys into the rep. - doRepLineSplice(startLine, deleteCount, newLineEntries); - - checkALines(); - } - - function cachedStrFunc(func) - { - var cache = {}; - return function(s) - { - if (!cache[s]) - { - cache[s] = func(s); - } - return cache[s]; - }; - } - - function analyzeChange(oldText, newText, oldAttribs, newAttribs, optSelStartHint, optSelEndHint) - { - function incorpedAttribFilter(anum) - { - return !isOtherIncorpedAttribute(rep.apool.getAttribKey(anum)); - } - - function attribRuns(attribs) - { - var lengs = []; - var atts = []; - var iter = Changeset.opIterator(attribs); - while (iter.hasNext()) - { - var op = iter.next(); - lengs.push(op.chars); - atts.push(op.attribs); - } - return [lengs, atts]; - } - - function attribIterator(runs, backward) - { - var lengs = runs[0]; - var atts = runs[1]; - var i = (backward ? lengs.length - 1 : 0); - var j = 0; - return function next() - { - while (j >= lengs[i]) - { - if (backward) i--; - else i++; - j = 0; - } - var a = atts[i]; - j++; - return a; - }; - } - - var oldLen = oldText.length; - var newLen = newText.length; - var minLen = Math.min(oldLen, newLen); - - var oldARuns = attribRuns(Changeset.filterAttribNumbers(oldAttribs, incorpedAttribFilter)); - var newARuns = attribRuns(Changeset.filterAttribNumbers(newAttribs, incorpedAttribFilter)); - - var commonStart = 0; - var oldStartIter = attribIterator(oldARuns, false); - var newStartIter = attribIterator(newARuns, false); - while (commonStart < minLen) - { - if (oldText.charAt(commonStart) == newText.charAt(commonStart) && oldStartIter() == newStartIter()) - { - commonStart++; - } - else break; - } - - var commonEnd = 0; - var oldEndIter = attribIterator(oldARuns, true); - var newEndIter = attribIterator(newARuns, true); - while (commonEnd < minLen) - { - if (commonEnd === 0) - { - // assume newline in common - oldEndIter(); - newEndIter(); - commonEnd++; - } - else if (oldText.charAt(oldLen - 1 - commonEnd) == newText.charAt(newLen - 1 - commonEnd) && oldEndIter() == newEndIter()) - { - commonEnd++; - } - else break; - } - - var hintedCommonEnd = -1; - if ((typeof optSelEndHint) == "number") - { - hintedCommonEnd = newLen - optSelEndHint; - } - - - if (commonStart + commonEnd > oldLen) - { - // ambiguous insertion - var minCommonEnd = oldLen - commonStart; - var maxCommonEnd = commonEnd; - if (hintedCommonEnd >= minCommonEnd && hintedCommonEnd <= maxCommonEnd) - { - commonEnd = hintedCommonEnd; - } - else - { - commonEnd = minCommonEnd; - } - commonStart = oldLen - commonEnd; - } - if (commonStart + commonEnd > newLen) - { - // ambiguous deletion - var minCommonEnd = newLen - commonStart; - var maxCommonEnd = commonEnd; - if (hintedCommonEnd >= minCommonEnd && hintedCommonEnd <= maxCommonEnd) - { - commonEnd = hintedCommonEnd; - } - else - { - commonEnd = minCommonEnd; - } - commonStart = newLen - commonEnd; - } - - return [commonStart, commonEnd]; - } - - function equalLineAndChars(a, b) - { - if (!a) return !b; - if (!b) return !a; - return (a[0] == b[0] && a[1] == b[1]); - } - - function performSelectionChange(selectStart, selectEnd, focusAtStart) - { - if (repSelectionChange(selectStart, selectEnd, focusAtStart)) - { - currentCallStack.selectionAffected = true; - } - } - editorInfo.ace_performSelectionChange = performSelectionChange; - - // Change the abstract representation of the document to have a different selection. - // Should not rely on the line representation. Should not affect the DOM. - - - function repSelectionChange(selectStart, selectEnd, focusAtStart) - { - focusAtStart = !! focusAtStart; - - var newSelFocusAtStart = (focusAtStart && ((!selectStart) || (!selectEnd) || (selectStart[0] != selectEnd[0]) || (selectStart[1] != selectEnd[1]))); - - if ((!equalLineAndChars(rep.selStart, selectStart)) || (!equalLineAndChars(rep.selEnd, selectEnd)) || (rep.selFocusAtStart != newSelFocusAtStart)) - { - rep.selStart = selectStart; - rep.selEnd = selectEnd; - rep.selFocusAtStart = newSelFocusAtStart; - currentCallStack.repChanged = true; - - // select the formatting buttons when there is the style applied on selection - selectFormattingButtonIfLineHasStyleApplied(rep); - - hooks.callAll('aceSelectionChanged', { - rep: rep, - callstack: currentCallStack, - documentAttributeManager: documentAttributeManager, - }); - - // we scroll when user places the caret at the last line of the pad - // when this settings is enabled - var docTextChanged = currentCallStack.docTextChanged; - if(!docTextChanged){ - var isScrollableEvent = !isPadLoading(currentCallStack.type) && isScrollableEditEvent(currentCallStack.type); - var innerHeight = getInnerHeight(); - scroll.scrollWhenCaretIsInTheLastLineOfViewportWhenNecessary(rep, isScrollableEvent, innerHeight); - } - - return true; - //console.log("selStart: %o, selEnd: %o, focusAtStart: %s", rep.selStart, rep.selEnd, - //String(!!rep.selFocusAtStart)); - } - return false; - //console.log("%o %o %s", rep.selStart, rep.selEnd, rep.selFocusAtStart); - } - - function isPadLoading(eventType) - { - return (eventType === 'setup') || (eventType === 'setBaseText') || (eventType === 'importText'); - } - - function updateStyleButtonState(attribName, hasStyleOnRepSelection) { - var $formattingButton = parent.parent.$('[data-key="' + attribName + '"]').find('a'); - $formattingButton.toggleClass(SELECT_BUTTON_CLASS, hasStyleOnRepSelection); - } - - function attribIsFormattingStyle(attributeName) { - return _.contains(FORMATTING_STYLES, attributeName); - } - - function selectFormattingButtonIfLineHasStyleApplied (rep) { - _.each(FORMATTING_STYLES, function (style) { - var hasStyleOnRepSelection = documentAttributeManager.hasAttributeOnSelectionOrCaretPosition(style); - updateStyleButtonState(style, hasStyleOnRepSelection); - }) - } - - function doCreateDomLine(nonEmpty) - { - if (browser.msie && (!nonEmpty)) - { - var result = { - node: null, - appendSpan: noop, - prepareForAdd: noop, - notifyAdded: noop, - clearSpans: noop, - finishUpdate: noop, - lineMarker: 0 - }; - - var lineElem = doc.createElement("div"); - result.node = lineElem; - - result.notifyAdded = function() - { - // magic -- settng an empty div's innerHTML to the empty string - // keeps it from collapsing. Apparently innerHTML must be set *after* - // adding the node to the DOM. - // Such a div is what IE 6 creates naturally when you make a blank line - // in a document of divs. However, when copy-and-pasted the div will - // contain a space, so we note its emptiness with a property. - lineElem.innerHTML = " "; // Frist we set a value that isnt blank - // a primitive-valued property survives copy-and-paste - setAssoc(lineElem, "shouldBeEmpty", true); - // an object property doesn't - setAssoc(lineElem, "unpasted", {}); - lineElem.innerHTML = ""; // Then we make it blank.. New line and no space = Awesome :) - }; - var lineClass = 'ace-line'; - result.appendSpan = function(txt, cls) - { - if ((!txt) && cls) - { - // gain a whole-line style (currently to show insertion point in CSS) - lineClass = domline.addToLineClass(lineClass, cls); - } - // otherwise, ignore appendSpan, this is an empty line - }; - result.clearSpans = function() - { - lineClass = ''; // non-null to cause update - }; - - var writeClass = function() - { - if (lineClass !== null) lineElem.className = lineClass; - }; - - result.prepareForAdd = writeClass; - result.finishUpdate = writeClass; - result.getInnerHTML = function() - { - return ""; - }; - return result; - } - else - { - return domline.createDomLine(nonEmpty, doesWrap, browser, doc); - } - } - - function textify(str) - { - return str.replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' '); - } - - var _blockElems = { - "div": 1, - "p": 1, - "pre": 1, - "li": 1, - "ol": 1, - "ul": 1 - }; - - _.each(hooks.callAll('aceRegisterBlockElements'), function(element){ - _blockElems[element] = 1; - }); - - function isBlockElement(n) - { - return !!_blockElems[(n.tagName || "").toLowerCase()]; - } - - function getDirtyRanges() - { - // based on observedChanges, return a list of ranges of original lines - // that need to be removed or replaced with new user content to incorporate - // the user's changes into the line representation. ranges may be zero-length, - // indicating inserted content. for example, [0,0] means content was inserted - // at the top of the document, while [3,4] means line 3 was deleted, modified, - // or replaced with one or more new lines of content. ranges do not touch. - var p = PROFILER("getDirtyRanges", false); - p.forIndices = 0; - p.consecutives = 0; - p.corrections = 0; - - var cleanNodeForIndexCache = {}; - var N = rep.lines.length(); // old number of lines - - - function cleanNodeForIndex(i) - { - // if line (i) in the un-updated line representation maps to a clean node - // in the document, return that node. - // if (i) is out of bounds, return true. else return false. - if (cleanNodeForIndexCache[i] === undefined) - { - p.forIndices++; - var result; - if (i < 0 || i >= N) - { - result = true; // truthy, but no actual node - } - else - { - var key = rep.lines.atIndex(i).key; - result = (getCleanNodeByKey(key) || false); - } - cleanNodeForIndexCache[i] = result; - } - return cleanNodeForIndexCache[i]; - } - var isConsecutiveCache = {}; - - function isConsecutive(i) - { - if (isConsecutiveCache[i] === undefined) - { - p.consecutives++; - isConsecutiveCache[i] = (function() - { - // returns whether line (i) and line (i-1), assumed to be map to clean DOM nodes, - // or document boundaries, are consecutive in the changed DOM - var a = cleanNodeForIndex(i - 1); - var b = cleanNodeForIndex(i); - if ((!a) || (!b)) return false; // violates precondition - if ((a === true) && (b === true)) return !root.firstChild; - if ((a === true) && b.previousSibling) return false; - if ((b === true) && a.nextSibling) return false; - if ((a === true) || (b === true)) return true; - return a.nextSibling == b; - })(); - } - return isConsecutiveCache[i]; - } - - function isClean(i) - { - // returns whether line (i) in the un-updated representation maps to a clean node, - // or is outside the bounds of the document - return !!cleanNodeForIndex(i); - } - // list of pairs, each representing a range of lines that is clean and consecutive - // in the changed DOM. lines (-1) and (N) are always clean, but may or may not - // be consecutive with lines in the document. pairs are in sorted order. - var cleanRanges = [ - [-1, N + 1] - ]; - - function rangeForLine(i) - { - // returns index of cleanRange containing i, or -1 if none - var answer = -1; - _.each(cleanRanges ,function(r, idx) - { - if (i >= r[1]) return false; // keep looking - if (i < r[0]) return true; // not found, stop looking - answer = idx; - return true; // found, stop looking - }); - return answer; - } - - function removeLineFromRange(rng, line) - { - // rng is index into cleanRanges, line is line number - // precond: line is in rng - var a = cleanRanges[rng][0]; - var b = cleanRanges[rng][1]; - if ((a + 1) == b) cleanRanges.splice(rng, 1); - else if (line == a) cleanRanges[rng][0]++; - else if (line == (b - 1)) cleanRanges[rng][1]--; - else cleanRanges.splice(rng, 1, [a, line], [line + 1, b]); - } - - function splitRange(rng, pt) - { - // precond: pt splits cleanRanges[rng] into two non-empty ranges - var a = cleanRanges[rng][0]; - var b = cleanRanges[rng][1]; - cleanRanges.splice(rng, 1, [a, pt], [pt, b]); - } - var correctedLines = {}; - - function correctlyAssignLine(line) - { - if (correctedLines[line]) return true; - p.corrections++; - correctedLines[line] = true; - // "line" is an index of a line in the un-updated rep. - // returns whether line was already correctly assigned (i.e. correctly - // clean or dirty, according to cleanRanges, and if clean, correctly - // attached or not attached (i.e. in the same range as) the prev and next lines). - //console.log("correctly assigning: %d", line); - var rng = rangeForLine(line); - var lineClean = isClean(line); - if (rng < 0) - { - if (lineClean) - { - console.debug("somehow lost clean line"); - } - return true; - } - if (!lineClean) - { - // a clean-range includes this dirty line, fix it - removeLineFromRange(rng, line); - return false; - } - else - { - // line is clean, but could be wrongly connected to a clean line - // above or below - var a = cleanRanges[rng][0]; - var b = cleanRanges[rng][1]; - var didSomething = false; - // we'll leave non-clean adjacent nodes in the clean range for the caller to - // detect and deal with. we deal with whether the range should be split - // just above or just below this line. - if (a < line && isClean(line - 1) && !isConsecutive(line)) - { - splitRange(rng, line); - didSomething = true; - } - if (b > (line + 1) && isClean(line + 1) && !isConsecutive(line + 1)) - { - splitRange(rng, line + 1); - didSomething = true; - } - return !didSomething; - } - } - - function detectChangesAroundLine(line, reqInARow) - { - // make sure cleanRanges is correct about line number "line" and the surrounding - // lines; only stops checking at end of document or after no changes need - // making for several consecutive lines. note that iteration is over old lines, - // so this operation takes time proportional to the number of old lines - // that are changed or missing, not the number of new lines inserted. - var correctInARow = 0; - var currentIndex = line; - while (correctInARow < reqInARow && currentIndex >= 0) - { - if (correctlyAssignLine(currentIndex)) - { - correctInARow++; - } - else correctInARow = 0; - currentIndex--; - } - correctInARow = 0; - currentIndex = line; - while (correctInARow < reqInARow && currentIndex < N) - { - if (correctlyAssignLine(currentIndex)) - { - correctInARow++; - } - else correctInARow = 0; - currentIndex++; - } - } - - if (N === 0) - { - p.cancel(); - if (!isConsecutive(0)) - { - splitRange(0, 0); - } - } - else - { - p.mark("topbot"); - detectChangesAroundLine(0, 1); - detectChangesAroundLine(N - 1, 1); - - p.mark("obs"); - //console.log("observedChanges: "+toSource(observedChanges)); - for (var k in observedChanges.cleanNodesNearChanges) - { - var key = k.substring(1); - if (rep.lines.containsKey(key)) - { - var line = rep.lines.indexOfKey(key); - detectChangesAroundLine(line, 2); - } - } - p.mark("stats&calc"); - p.literal(p.forIndices, "byidx"); - p.literal(p.consecutives, "cons"); - p.literal(p.corrections, "corr"); - } - - var dirtyRanges = []; - for (var r = 0; r < cleanRanges.length - 1; r++) - { - dirtyRanges.push([cleanRanges[r][1], cleanRanges[r + 1][0]]); - } - - p.end(); - - return dirtyRanges; - } - - function markNodeClean(n) - { - // clean nodes have knownHTML that matches their innerHTML - var dirtiness = {}; - dirtiness.nodeId = uniqueId(n); - dirtiness.knownHTML = n.innerHTML; - if (browser.msie) - { - // adding a space to an "empty" div in IE designMode doesn't - // change the innerHTML of the div's parent; also, other - // browsers don't support innerText - dirtiness.knownText = n.innerText; - } - setAssoc(n, "dirtiness", dirtiness); - } - - function isNodeDirty(n) - { - var p = PROFILER("cleanCheck", false); - if (n.parentNode != root) return true; - var data = getAssoc(n, "dirtiness"); - if (!data) return true; - if (n.id !== data.nodeId) return true; - if (browser.msie) - { - if (n.innerText !== data.knownText) return true; - } - if (n.innerHTML !== data.knownHTML) return true; - p.end(); - return false; - } - - function getViewPortTopBottom() - { - var theTop = scroll.getScrollY(); - var doc = outerWin.document; - var height = doc.documentElement.clientHeight; // includes padding - - // we have to get the exactly height of the viewport. So it has to subtract all the values which changes - // the viewport height (E.g. padding, position top) - var viewportExtraSpacesAndPosition = getEditorPositionTop() + getPaddingTopAddedWhenPageViewIsEnable(); - return { - top: theTop, - bottom: (theTop + height - viewportExtraSpacesAndPosition) - }; - } - - - function getEditorPositionTop() - { - var editor = parent.document.getElementsByTagName('iframe'); - var editorPositionTop = editor[0].offsetTop; - return editorPositionTop; - } - - // ep_page_view adds padding-top, which makes the viewport smaller - function getPaddingTopAddedWhenPageViewIsEnable() - { - var rootDocument = parent.parent.document; - var aceOuter = rootDocument.getElementsByName("ace_outer"); - var aceOuterPaddingTop = parseInt($(aceOuter).css("padding-top")); - return aceOuterPaddingTop; - } - - function handleCut(evt) - { - inCallStackIfNecessary("handleCut", function() - { - doDeleteKey(evt); - }); - return true; - } - - function handleClick(evt) - { - inCallStackIfNecessary("handleClick", function() - { - idleWorkTimer.atMost(200); - }); - - function isLink(n) - { - return (n.tagName || '').toLowerCase() == "a" && n.href; - } - - // only want to catch left-click - if ((!evt.ctrlKey) && (evt.button != 2) && (evt.button != 3)) - { - // find A tag with HREF - var n = evt.target; - while (n && n.parentNode && !isLink(n)) - { - n = n.parentNode; - } - if (n && isLink(n)) - { - try - { - var newWindow = window.open(n.href, '_blank'); - newWindow.focus(); - } - catch (e) - { - // absorb "user canceled" error in IE for certain prompts - } - evt.preventDefault(); - } - } - - hideEditBarDropdowns(); - } - - function hideEditBarDropdowns() - { - if(window.parent.parent.padeditbar){ // required in case its in an iframe should probably use parent.. See Issue 327 https://github.com/ether/etherpad-lite/issues/327 - window.parent.parent.padeditbar.toggleDropDown("none"); - } - } - - function doReturnKey() - { - if (!(rep.selStart && rep.selEnd)) - { - return; - } - - var lineNum = rep.selStart[0]; - var listType = getLineListType(lineNum); - - if (listType) - { - var text = rep.lines.atIndex(lineNum).text; - listType = /([a-z]+)([0-9]+)/.exec(listType); - var type = listType[1]; - var level = Number(listType[2]); - - //detect empty list item; exclude indentation - if(text === '*' && type !== "indent") - { - //if not already on the highest level - if(level > 1) - { - setLineListType(lineNum, type+(level-1));//automatically decrease the level - } - else - { - setLineListType(lineNum, '');//remove the list - renumberList(lineNum + 1);//trigger renumbering of list that may be right after - } - } - else if (lineNum + 1 <= rep.lines.length()) - { - performDocumentReplaceSelection('\n'); - setLineListType(lineNum + 1, type+level); - } - } - else - { - performDocumentReplaceSelection('\n'); - handleReturnIndentation(); - } - } - - function doIndentOutdent(isOut) - { - if (!((rep.selStart && rep.selEnd) || - ((rep.selStart[0] == rep.selEnd[0]) && (rep.selStart[1] == rep.selEnd[1]) && rep.selEnd[1] > 1)) && - (isOut != true) - ) - { - return false; - } - - var firstLine, lastLine; - firstLine = rep.selStart[0]; - lastLine = Math.max(firstLine, rep.selEnd[0] - ((rep.selEnd[1] === 0) ? 1 : 0)); - var mods = []; - for (var n = firstLine; n <= lastLine; n++) - { - var listType = getLineListType(n); - var t = 'indent'; - var level = 0; - if (listType) - { - listType = /([a-z]+)([0-9]+)/.exec(listType); - if (listType) - { - t = listType[1]; - level = Number(listType[2]); - } - } - var newLevel = Math.max(0, Math.min(MAX_LIST_LEVEL, level + (isOut ? -1 : 1))); - if (level != newLevel) - { - mods.push([n, (newLevel > 0) ? t + newLevel : '']); - } - } - - _.each(mods, function(mod){ - setLineListType(mod[0], mod[1]); - }); - return true; - } - editorInfo.ace_doIndentOutdent = doIndentOutdent; - - function doTabKey(shiftDown) - { - if (!doIndentOutdent(shiftDown)) - { - performDocumentReplaceSelection(THE_TAB); - } - } - - function doDeleteKey(optEvt) - { - var evt = optEvt || {}; - var handled = false; - if (rep.selStart) - { - if (isCaret()) - { - var lineNum = caretLine(); - var col = caretColumn(); - var lineEntry = rep.lines.atIndex(lineNum); - var lineText = lineEntry.text; - var lineMarker = lineEntry.lineMarker; - if (/^ +$/.exec(lineText.substring(lineMarker, col))) - { - var col2 = col - lineMarker; - var tabSize = THE_TAB.length; - var toDelete = ((col2 - 1) % tabSize) + 1; - performDocumentReplaceRange([lineNum, col - toDelete], [lineNum, col], ''); - //scrollSelectionIntoView(); - handled = true; - } - } - if (!handled) - { - if (isCaret()) - { - var theLine = caretLine(); - var lineEntry = rep.lines.atIndex(theLine); - if (caretColumn() <= lineEntry.lineMarker) - { - // delete at beginning of line - var action = 'delete_newline'; - var prevLineListType = (theLine > 0 ? getLineListType(theLine - 1) : ''); - var thisLineListType = getLineListType(theLine); - var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1)); - var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker); - - var thisLineHasMarker = documentAttributeManager.lineHasMarker(theLine); - - if (thisLineListType) - { - // this line is a list - if (prevLineBlank && !prevLineListType) - { - // previous line is blank, remove it - performDocumentReplaceRange([theLine - 1, prevLineEntry.text.length], [theLine, 0], ''); - } - else - { - // delistify - performDocumentReplaceRange([theLine, 0], [theLine, lineEntry.lineMarker], ''); - } - }else if (thisLineHasMarker && prevLineEntry){ - // If the line has any attributes assigned, remove them by removing the marker '*' - performDocumentReplaceRange([theLine -1 , prevLineEntry.text.length], [theLine, lineEntry.lineMarker], ''); - } - else if (theLine > 0) - { - // remove newline - performDocumentReplaceRange([theLine - 1, prevLineEntry.text.length], [theLine, 0], ''); - } - } - else - { - var docChar = caretDocChar(); - if (docChar > 0) - { - if (evt.metaKey || evt.ctrlKey || evt.altKey) - { - // delete as many unicode "letters or digits" in a row as possible; - // always delete one char, delete further even if that first char - // isn't actually a word char. - var deleteBackTo = docChar - 1; - while (deleteBackTo > lineEntry.lineMarker && isWordChar(rep.alltext.charAt(deleteBackTo - 1))) - { - deleteBackTo--; - } - performDocumentReplaceCharRange(deleteBackTo, docChar, ''); - } - else - { - // normal delete - performDocumentReplaceCharRange(docChar - 1, docChar, ''); - } - } - } - } - else - { - performDocumentReplaceSelection(''); - } - } - } - //if the list has been removed, it is necessary to renumber - //starting from the *next* line because the list may have been - //separated. If it returns null, it means that the list was not cut, try - //from the current one. - var line = caretLine(); - if(line != -1 && renumberList(line+1) === null) - { - renumberList(line); - } - } - - // set of "letter or digit" chars is based on section 20.5.16 of the original Java Language Spec - var REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/; - var REGEX_SPACE = /\s/; - - function isWordChar(c) - { - return !!REGEX_WORDCHAR.exec(c); - } - editorInfo.ace_isWordChar = isWordChar; - - function isSpaceChar(c) - { - return !!REGEX_SPACE.exec(c); - } - - function moveByWordInLine(lineText, initialIndex, forwardNotBack) - { - var i = initialIndex; - - function nextChar() - { - if (forwardNotBack) return lineText.charAt(i); - else return lineText.charAt(i - 1); - } - - function advance() - { - if (forwardNotBack) i++; - else i--; - } - - function isDone() - { - if (forwardNotBack) return i >= lineText.length; - else return i <= 0; - } - - // On Mac and Linux, move right moves to end of word and move left moves to start; - // on Windows, always move to start of word. - // On Windows, Firefox and IE disagree on whether to stop for punctuation (FF says no). - if (browser.msie && forwardNotBack) - { - while ((!isDone()) && isWordChar(nextChar())) - { - advance(); - } - while ((!isDone()) && !isWordChar(nextChar())) - { - advance(); - } - } - else - { - while ((!isDone()) && !isWordChar(nextChar())) - { - advance(); - } - while ((!isDone()) && isWordChar(nextChar())) - { - advance(); - } - } - - return i; - } - - function handleKeyEvent(evt) - { - // if (DEBUG && window.DONT_INCORP) return; - if (!isEditable) return; - var type = evt.type; - var charCode = evt.charCode; - var keyCode = evt.keyCode; - var which = evt.which; - var altKey = evt.altKey; - var shiftKey = evt.shiftKey; - - // Is caret potentially hidden by the chat button? - var myselection = document.getSelection(); // get the current caret selection - var caretOffsetTop = myselection.focusNode.parentNode.offsetTop | myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214 - - if(myselection.focusNode.wholeText){ // Is there any content? If not lineHeight will report wrong.. - var lineHeight = myselection.focusNode.parentNode.offsetHeight; // line height of populated links - }else{ - var lineHeight = myselection.focusNode.offsetHeight; // line height of blank lines - } - - var heightOfChatIcon = parent.parent.$('#chaticon').height(); // height of the chat icon button - lineHeight = (lineHeight *2) + heightOfChatIcon; - var viewport = getViewPortTopBottom(); - var viewportHeight = viewport.bottom - viewport.top - lineHeight; - var relCaretOffsetTop = caretOffsetTop - viewport.top; // relative Caret Offset Top to viewport - if (viewportHeight < relCaretOffsetTop){ - parent.parent.$("#chaticon").css("opacity",".3"); // make chaticon opacity low when user types near it - }else{ - parent.parent.$("#chaticon").css("opacity","1"); // make chaticon opacity back to full (so fully visible) - } - - //dmesg("keyevent type: "+type+", which: "+which); - // Don't take action based on modifier keys going up and down. - // Modifier keys do not generate "keypress" events. - // 224 is the command-key under Mac Firefox. - // 91 is the Windows key in IE; it is ASCII for open-bracket but isn't the keycode for that key - // 20 is capslock in IE. - var isModKey = ((!charCode) && ((type == "keyup") || (type == "keydown")) && (keyCode == 16 || keyCode == 17 || keyCode == 18 || keyCode == 20 || keyCode == 224 || keyCode == 91)); - if (isModKey) return; - - // If the key is a keypress and the browser is opera and the key is enter, do nothign at all as this fires twice. - if (keyCode == 13 && browser.opera && (type == "keypress")){ - return; // This stops double enters in Opera but double Tabs still show on single tab keypress, adding keyCode == 9 to this doesn't help as the event is fired twice - } - var specialHandled = false; - var isTypeForSpecialKey = ((browser.msie || browser.safari || browser.chrome) ? (type == "keydown") : (type == "keypress")); - var isTypeForCmdKey = ((browser.msie || browser.safari || browser.chrome) ? (type == "keydown") : (type == "keypress")); - var stopped = false; - - inCallStackIfNecessary("handleKeyEvent", function() - { - if (type == "keypress" || (isTypeForSpecialKey && keyCode == 13 /*return*/ )) - { - // in IE, special keys don't send keypress, the keydown does the action - if (!outsideKeyPress(evt)) - { - evt.preventDefault(); - stopped = true; - } - } - else if (evt.key === "Dead"){ - // If it's a dead key we don't want to do any Etherpad behavior. - stopped = true; - return true; - } - else if (type == "keydown") - { - outsideKeyDown(evt); - } - if (!stopped) - { - var specialHandledInHook = hooks.callAll('aceKeyEvent', { - callstack: currentCallStack, - editorInfo: editorInfo, - rep: rep, - documentAttributeManager: documentAttributeManager, - evt:evt - }); - - // if any hook returned true, set specialHandled with true - if (specialHandledInHook) { - specialHandled = _.contains(specialHandledInHook, true); - } - - var padShortcutEnabled = parent.parent.clientVars.padShortcutEnabled; - if ((!specialHandled) && altKey && isTypeForSpecialKey && keyCode == 120 && padShortcutEnabled.altF9){ - // Alt F9 focuses on the File Menu and/or editbar. - // Note that while most editors use Alt F10 this is not desirable - // As ubuntu cannot use Alt F10.... - // Focus on the editbar. -- TODO: Move Focus back to previous state (we know it so we can use it) - var firstEditbarElement = parent.parent.$('#editbar').children("ul").first().children().first().children().first().children().first(); - $(this).blur(); - firstEditbarElement.focus(); - evt.preventDefault(); - } - if ((!specialHandled) && altKey && keyCode == 67 && type === "keydown" && padShortcutEnabled.altC){ - // Alt c focuses on the Chat window - $(this).blur(); - parent.parent.chat.show(); - parent.parent.$("#chatinput").focus(); - evt.preventDefault(); - } - if ((!specialHandled) && evt.ctrlKey && shiftKey && keyCode == 50 && type === "keydown" && padShortcutEnabled.cmdShift2){ - // Control-Shift-2 shows a gritter popup showing a line author - var lineNumber = rep.selEnd[0]; - var alineAttrs = rep.alines[lineNumber]; - var apool = rep.apool; - - // TODO: support selection ranges - // TODO: Still work when authorship colors have been cleared - // TODO: i18n - // TODO: There appears to be a race condition or so. - - var author = null; - if (alineAttrs) { - var authors = []; - var authorNames = []; - var opIter = Changeset.opIterator(alineAttrs); - - while (opIter.hasNext()){ - var op = opIter.next(); - authorId = Changeset.opAttributeValue(op, 'author', apool); - - // Only push unique authors and ones with values - if(authors.indexOf(authorId) === -1 && authorId !== ""){ - authors.push(authorId); - } - - } - - } - - // No author information is available IE on a new pad. - if(authors.length === 0){ - var authorString = "No author information is available"; - } - else{ - // Known authors info, both current and historical - var padAuthors = parent.parent.pad.userList(); - var authorObj = {}; - authors.forEach(function(authorId){ - padAuthors.forEach(function(padAuthor){ - // If the person doing the lookup is the author.. - if(padAuthor.userId === authorId){ - if(parent.parent.clientVars.userId === authorId){ - authorObj = { - name: "Me" - } - }else{ - authorObj = padAuthor; - } - } - }); - if(!authorObj){ - author = "Unknown"; - return; - } - author = authorObj.name; - if(!author) author = "Unknown"; - authorNames.push(author); - }) - } - if(authors.length === 1){ - var authorString = "The author of this line is " + authorNames; - } - if(authors.length > 1){ - var authorString = "The authors of this line are " + authorNames.join(" & "); - } - - parent.parent.$.gritter.add({ - // (string | mandatory) the heading of the notification - title: 'Line Authors', - // (string | mandatory) the text inside the notification - text: authorString, - // (bool | optional) if you want it to fade out on its own or just sit there - sticky: false, - // (int | optional) the time you want it to be alive for before fading out - time: '4000' - }); - } - if ((!specialHandled) && isTypeForSpecialKey && keyCode == 8 && padShortcutEnabled.delete) - { - // "delete" key; in mozilla, if we're at the beginning of a line, normalize now, - // or else deleting a blank line can take two delete presses. - // -- - // we do deletes completely customly now: - // - allows consistent (and better) meta-delete behavior - // - normalizing and then allowing default behavior confused IE - // - probably eliminates a few minor quirks - fastIncorp(3); - evt.preventDefault(); - doDeleteKey(evt); - specialHandled = true; - } - if ((!specialHandled) && isTypeForSpecialKey && keyCode == 13 && padShortcutEnabled.return) - { - // return key, handle specially; - // note that in mozilla we need to do an incorporation for proper return behavior anyway. - fastIncorp(4); - evt.preventDefault(); - doReturnKey(); - //scrollSelectionIntoView(); - scheduler.setTimeout(function() - { - outerWin.scrollBy(-100, 0); - }, 0); - specialHandled = true; - } - if ((!specialHandled) && isTypeForSpecialKey && keyCode == 27 && padShortcutEnabled.esc) - { - // prevent esc key; - // in mozilla versions 14-19 avoid reconnecting pad. - - fastIncorp(4); - evt.preventDefault(); - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "s" && (evt.metaKey || evt.ctrlKey) && !evt.altKey && padShortcutEnabled.cmdS) /* Do a saved revision on ctrl S */ - { - evt.preventDefault(); - var originalBackground = parent.parent.$('#revisionlink').css("background") - parent.parent.$('#revisionlink').css({"background":"lightyellow"}); - scheduler.setTimeout(function(){ - parent.parent.$('#revisionlink').css({"background":originalBackground}); - }, 1000); - parent.parent.pad.collabClient.sendMessage({"type":"SAVE_REVISION"}); /* The parent.parent part of this is BAD and I feel bad.. It may break something */ - specialHandled = true; - } - if ((!specialHandled) && isTypeForSpecialKey && keyCode == 9 && !(evt.metaKey || evt.ctrlKey) && padShortcutEnabled.tab) - { - // tab - fastIncorp(5); - evt.preventDefault(); - doTabKey(evt.shiftKey); - //scrollSelectionIntoView(); - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "z" && (evt.metaKey || evt.ctrlKey) && !evt.altKey && padShortcutEnabled.cmdZ) - { - // cmd-Z (undo) - fastIncorp(6); - evt.preventDefault(); - if (evt.shiftKey) - { - doUndoRedo("redo"); - } - else - { - doUndoRedo("undo"); - } - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "y" && (evt.metaKey || evt.ctrlKey) && padShortcutEnabled.cmdY) - { - // cmd-Y (redo) - fastIncorp(10); - evt.preventDefault(); - doUndoRedo("redo"); - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "b" && (evt.metaKey || evt.ctrlKey) && padShortcutEnabled.cmdB) - { - // cmd-B (bold) - fastIncorp(13); - evt.preventDefault(); - toggleAttributeOnSelection('bold'); - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "i" && (evt.metaKey || evt.ctrlKey) && padShortcutEnabled.cmdI) - { - // cmd-I (italic) - fastIncorp(14); - evt.preventDefault(); - toggleAttributeOnSelection('italic'); - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "u" && (evt.metaKey || evt.ctrlKey) && padShortcutEnabled.cmdU) - { - // cmd-U (underline) - fastIncorp(15); - evt.preventDefault(); - toggleAttributeOnSelection('underline'); - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "5" && (evt.metaKey || evt.ctrlKey) && evt.altKey !== true && padShortcutEnabled.cmd5) - { - // cmd-5 (strikethrough) - fastIncorp(13); - evt.preventDefault(); - toggleAttributeOnSelection('strikethrough'); - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "l" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey && padShortcutEnabled.cmdShiftL) - { - // cmd-shift-L (unorderedlist) - fastIncorp(9); - evt.preventDefault(); - doInsertUnorderedList() - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && ((String.fromCharCode(which).toLowerCase() == "n" && padShortcutEnabled.cmdShiftN) || (String.fromCharCode(which) == 1 && padShortcutEnabled.cmdShift1)) && (evt.metaKey || evt.ctrlKey) && evt.shiftKey) - { - // cmd-shift-N and cmd-shift-1 (orderedlist) - fastIncorp(9); - evt.preventDefault(); - doInsertOrderedList() - specialHandled = true; - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "c" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey && padShortcutEnabled.cmdShiftC) { - // cmd-shift-C (clearauthorship) - fastIncorp(9); - evt.preventDefault(); - CMDS.clearauthorship(); - } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "h" && (evt.ctrlKey) && padShortcutEnabled.cmdH) - { - // cmd-H (backspace) - fastIncorp(20); - evt.preventDefault(); - doDeleteKey(); - specialHandled = true; - } - if((evt.which == 36 && evt.ctrlKey == true) && padShortcutEnabled.ctrlHome){ scroll.setScrollY(0); } // Control Home send to Y = 0 - if((evt.which == 33 || evt.which == 34) && type == 'keydown' && !evt.ctrlKey){ - - evt.preventDefault(); // This is required, browsers will try to do normal default behavior on page up / down and the default behavior SUCKS - - var oldVisibleLineRange = scroll.getVisibleLineRange(rep); - var topOffset = rep.selStart[0] - oldVisibleLineRange[0]; - if(topOffset < 0 ){ - topOffset = 0; - } - - var isPageDown = evt.which === 34; - var isPageUp = evt.which === 33; - - scheduler.setTimeout(function(){ - var newVisibleLineRange = scroll.getVisibleLineRange(rep); // the visible lines IE 1,10 - var linesCount = rep.lines.length(); // total count of lines in pad IE 10 - var numberOfLinesInViewport = newVisibleLineRange[1] - newVisibleLineRange[0]; // How many lines are in the viewport right now? - - if(isPageUp && padShortcutEnabled.pageUp){ - rep.selEnd[0] = rep.selEnd[0] - numberOfLinesInViewport; // move to the bottom line +1 in the viewport (essentially skipping over a page) - rep.selStart[0] = rep.selStart[0] - numberOfLinesInViewport; // move to the bottom line +1 in the viewport (essentially skipping over a page) - } - - if(isPageDown && padShortcutEnabled.pageDown){ // if we hit page down - if(rep.selEnd[0] >= oldVisibleLineRange[0]){ // If the new viewpoint position is actually further than where we are right now - rep.selStart[0] = oldVisibleLineRange[1] -1; // dont go further in the page down than what's visible IE go from 0 to 50 if 50 is visible on screen but dont go below that else we miss content - rep.selEnd[0] = oldVisibleLineRange[1] -1; // dont go further in the page down than what's visible IE go from 0 to 50 if 50 is visible on screen but dont go below that else we miss content - } - } - - //ensure min and max - if(rep.selEnd[0] < 0){ - rep.selEnd[0] = 0; - } - if(rep.selStart[0] < 0){ - rep.selStart[0] = 0; - } - if(rep.selEnd[0] >= linesCount){ - rep.selEnd[0] = linesCount-1; - } - updateBrowserSelectionFromRep(); - var myselection = document.getSelection(); // get the current caret selection, can't use rep. here because that only gives us the start position not the current - var caretOffsetTop = myselection.focusNode.parentNode.offsetTop || myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214 - - // sometimes the first selection is -1 which causes problems (Especially with ep_page_view) - // so use focusNode.offsetTop value. - if(caretOffsetTop === -1) caretOffsetTop = myselection.focusNode.offsetTop; - scroll.setScrollY(caretOffsetTop); // set the scrollY offset of the viewport on the document - - }, 200); - } - - // scroll to viewport when user presses arrow keys and caret is out of the viewport - if((evt.which == 37 || evt.which == 38 || evt.which == 39 || evt.which == 40)){ - // we use arrowKeyWasReleased to avoid triggering the animation when a key is continuously pressed - // this makes the scroll smooth - if(!continuouslyPressingArrowKey(type)){ - // We use getSelection() instead of rep to get the caret position. This avoids errors like when - // the caret position is not synchronized with the rep. For example, when an user presses arrow - // down to scroll the pad without releasing the key. When the key is released the rep is not - // synchronized, so we don't get the right node where caret is. - var selection = getSelection(); - - if(selection){ - var arrowUp = evt.which === 38; - var innerHeight = getInnerHeight(); - scroll.scrollWhenPressArrowKeys(arrowUp, rep, innerHeight); - } - } - } - } - - if (type == "keydown") - { - idleWorkTimer.atLeast(500); - } - else if (type == "keypress") - { - if ((!specialHandled) && false /*parenModule.shouldNormalizeOnChar(charCode)*/) - { - idleWorkTimer.atMost(0); - } - else - { - idleWorkTimer.atLeast(500); - } - } - else if (type == "keyup") - { - var wait = 0; - idleWorkTimer.atLeast(wait); - idleWorkTimer.atMost(wait); - } - - // Is part of multi-keystroke international character on Firefox Mac - var isFirefoxHalfCharacter = (browser.firefox && evt.altKey && charCode === 0 && keyCode === 0); - - // Is part of multi-keystroke international character on Safari Mac - var isSafariHalfCharacter = (browser.safari && evt.altKey && keyCode == 229); - - if (thisKeyDoesntTriggerNormalize || isFirefoxHalfCharacter || isSafariHalfCharacter) - { - idleWorkTimer.atLeast(3000); // give user time to type - // if this is a keydown, e.g., the keyup shouldn't trigger a normalize - thisKeyDoesntTriggerNormalize = true; - } - - if ((!specialHandled) && (!thisKeyDoesntTriggerNormalize) && (!inInternationalComposition)) - { - if (type != "keyup") - { - observeChangesAroundSelection(); - } - } - - if (type == "keyup") - { - thisKeyDoesntTriggerNormalize = false; - } - }); - } - - var thisKeyDoesntTriggerNormalize = false; - - var arrowKeyWasReleased = true; - function continuouslyPressingArrowKey(type) { - var firstTimeKeyIsContinuouslyPressed = false; - - if (type == 'keyup') arrowKeyWasReleased = true; - else if (type == 'keydown' && arrowKeyWasReleased) { - firstTimeKeyIsContinuouslyPressed = true; - arrowKeyWasReleased = false; - } - - return !firstTimeKeyIsContinuouslyPressed; - } - - function doUndoRedo(which) - { - // precond: normalized DOM - if (undoModule.enabled) - { - var whichMethod; - if (which == "undo") whichMethod = 'performUndo'; - if (which == "redo") whichMethod = 'performRedo'; - if (whichMethod) - { - var oldEventType = currentCallStack.editEvent.eventType; - currentCallStack.startNewEvent(which); - undoModule[whichMethod](function(backset, selectionInfo) - { - if (backset) - { - performDocumentApplyChangeset(backset); - } - if (selectionInfo) - { - performSelectionChange(lineAndColumnFromChar(selectionInfo.selStart), lineAndColumnFromChar(selectionInfo.selEnd), selectionInfo.selFocusAtStart); - } - var oldEvent = currentCallStack.startNewEvent(oldEventType, true); - return oldEvent; - }); - } - } - } - editorInfo.ace_doUndoRedo = doUndoRedo; - - function updateBrowserSelectionFromRep() - { - // requires normalized DOM! - var selStart = rep.selStart, - selEnd = rep.selEnd; - - if (!(selStart && selEnd)) - { - setSelection(null); - return; - } - - var selection = {}; - - var ss = [selStart[0], selStart[1]]; - selection.startPoint = getPointForLineAndChar(ss); - - var se = [selEnd[0], selEnd[1]]; - selection.endPoint = getPointForLineAndChar(se); - - selection.focusAtStart = !! rep.selFocusAtStart; - setSelection(selection); - } - editorInfo.ace_updateBrowserSelectionFromRep = updateBrowserSelectionFromRep; - - function nodeMaxIndex(nd) - { - if (isNodeText(nd)) return nd.nodeValue.length; - else return 1; - } - - function hasIESelection() - { - var browserSelection; - try - { - browserSelection = doc.selection; - } - catch (e) - {} - if (!browserSelection) return false; - var origSelectionRange; - try - { - origSelectionRange = browserSelection.createRange(); - } - catch (e) - {} - if (!origSelectionRange) return false; - return true; - } - - function getSelection() - { - // returns null, or a structure containing startPoint and endPoint, - // each of which has node (a magicdom node), index, and maxIndex. If the node - // is a text node, maxIndex is the length of the text; else maxIndex is 1. - // index is between 0 and maxIndex, inclusive. - if (browser.msie) - { - var browserSelection; - try - { - browserSelection = doc.selection; - } - catch (e) - {} - if (!browserSelection) return null; - var origSelectionRange; - try - { - origSelectionRange = browserSelection.createRange(); - } - catch (e) - {} - if (!origSelectionRange) return null; - var selectionParent = origSelectionRange.parentElement(); - if (selectionParent.ownerDocument != doc) return null; - - var newRange = function() - { - return doc.body.createTextRange(); - }; - - var rangeForElementNode = function(nd) - { - var rng = newRange(); - // doesn't work on text nodes - rng.moveToElementText(nd); - return rng; - }; - - var pointFromCollapsedRange = function(rng) - { - var parNode = rng.parentElement(); - var elemBelow = -1; - var elemAbove = parNode.childNodes.length; - var rangeWithin = rangeForElementNode(parNode); - - if (rng.compareEndPoints("StartToStart", rangeWithin) === 0) - { - return { - node: parNode, - index: 0, - maxIndex: 1 - }; - } - else if (rng.compareEndPoints("EndToEnd", rangeWithin) === 0) - { - if (isBlockElement(parNode) && parNode.nextSibling) - { - // caret after block is not consistent across browsers - // (same line vs next) so put caret before next node - return { - node: parNode.nextSibling, - index: 0, - maxIndex: 1 - }; - } - return { - node: parNode, - index: 1, - maxIndex: 1 - }; - } - else if (parNode.childNodes.length === 0) - { - return { - node: parNode, - index: 0, - maxIndex: 1 - }; - } - - for (var i = 0; i < parNode.childNodes.length; i++) - { - var n = parNode.childNodes.item(i); - if (!isNodeText(n)) - { - var nodeRange = rangeForElementNode(n); - var startComp = rng.compareEndPoints("StartToStart", nodeRange); - var endComp = rng.compareEndPoints("EndToEnd", nodeRange); - if (startComp >= 0 && endComp <= 0) - { - var index = 0; - if (startComp > 0) - { - index = 1; - } - return { - node: n, - index: index, - maxIndex: 1 - }; - } - else if (endComp > 0) - { - if (i > elemBelow) - { - elemBelow = i; - rangeWithin.setEndPoint("StartToEnd", nodeRange); - } - } - else if (startComp < 0) - { - if (i < elemAbove) - { - elemAbove = i; - rangeWithin.setEndPoint("EndToStart", nodeRange); - } - } - } - } - if ((elemAbove - elemBelow) == 1) - { - if (elemBelow >= 0) - { - return { - node: parNode.childNodes.item(elemBelow), - index: 1, - maxIndex: 1 - }; - } - else - { - return { - node: parNode.childNodes.item(elemAbove), - index: 0, - maxIndex: 1 - }; - } - } - var idx = 0; - var r = rng.duplicate(); - // infinite stateful binary search! call function for values 0 to inf, - // expecting the answer to be about 40. return index of smallest - // true value. - var indexIntoRange = binarySearchInfinite(40, function(i) - { - // the search algorithm whips the caret back and forth, - // though it has to be moved relatively and may hit - // the end of the buffer - var delta = i - idx; - var moved = Math.abs(r.move("character", -delta)); - // next line is work-around for fact that when moving left, the beginning - // of a text node is considered to be after the start of the parent element: - if (r.move("character", -1)) r.move("character", 1); - if (delta < 0) idx -= moved; - else idx += moved; - return (r.compareEndPoints("StartToStart", rangeWithin) <= 0); - }); - // iterate over consecutive text nodes, point is in one of them - var textNode = elemBelow + 1; - var indexLeft = indexIntoRange; - while (textNode < elemAbove) - { - var tn = parNode.childNodes.item(textNode); - if (indexLeft <= tn.nodeValue.length) - { - return { - node: tn, - index: indexLeft, - maxIndex: tn.nodeValue.length - }; - } - indexLeft -= tn.nodeValue.length; - textNode++; - } - var tn = parNode.childNodes.item(textNode - 1); - return { - node: tn, - index: tn.nodeValue.length, - maxIndex: tn.nodeValue.length - }; - }; - - var selection = {}; - if (origSelectionRange.compareEndPoints("StartToEnd", origSelectionRange) === 0) - { - // collapsed - var pnt = pointFromCollapsedRange(origSelectionRange); - selection.startPoint = pnt; - selection.endPoint = { - node: pnt.node, - index: pnt.index, - maxIndex: pnt.maxIndex - }; - } - else - { - var start = origSelectionRange.duplicate(); - start.collapse(true); - var end = origSelectionRange.duplicate(); - end.collapse(false); - selection.startPoint = pointFromCollapsedRange(start); - selection.endPoint = pointFromCollapsedRange(end); - } - return selection; - } - else - { - // non-IE browser - var browserSelection = window.getSelection(); - if (browserSelection && browserSelection.type != "None" && browserSelection.rangeCount !== 0) - { - var range = browserSelection.getRangeAt(0); - - function isInBody(n) - { - while (n && !(n.tagName && n.tagName.toLowerCase() == "body")) - { - n = n.parentNode; - } - return !!n; - } - - function pointFromRangeBound(container, offset) - { - if (!isInBody(container)) - { - // command-click in Firefox selects whole document, HEAD and BODY! - return { - node: root, - index: 0, - maxIndex: 1 - }; - } - var n = container; - var childCount = n.childNodes.length; - if (isNodeText(n)) - { - return { - node: n, - index: offset, - maxIndex: n.nodeValue.length - }; - } - else if (childCount === 0) - { - return { - node: n, - index: 0, - maxIndex: 1 - }; - } - // treat point between two nodes as BEFORE the second (rather than after the first) - // if possible; this way point at end of a line block-element is treated as - // at beginning of next line - else if (offset == childCount) - { - var nd = n.childNodes.item(childCount - 1); - var max = nodeMaxIndex(nd); - return { - node: nd, - index: max, - maxIndex: max - }; - } - else - { - var nd = n.childNodes.item(offset); - var max = nodeMaxIndex(nd); - return { - node: nd, - index: 0, - maxIndex: max - }; - } - } - var selection = {}; - selection.startPoint = pointFromRangeBound(range.startContainer, range.startOffset); - selection.endPoint = pointFromRangeBound(range.endContainer, range.endOffset); - selection.focusAtStart = (((range.startContainer != range.endContainer) || (range.startOffset != range.endOffset)) && browserSelection.anchorNode && (browserSelection.anchorNode == range.endContainer) && (browserSelection.anchorOffset == range.endOffset)); - - if(selection.startPoint.node.ownerDocument !== window.document){ - return null; - } - - return selection; - } - else return null; - } - } - - function setSelection(selection) - { - function copyPoint(pt) - { - return { - node: pt.node, - index: pt.index, - maxIndex: pt.maxIndex - }; - } - if (browser.msie) - { - // Oddly enough, accessing scrollHeight fixes return key handling on IE 8, - // presumably by forcing some kind of internal DOM update. - doc.body.scrollHeight; - - function moveToElementText(s, n) - { - while (n.firstChild && !isNodeText(n.firstChild)) - { - n = n.firstChild; - } - s.moveToElementText(n); - } - - function newRange() - { - return doc.body.createTextRange(); - } - - function setCollapsedBefore(s, n) - { - // s is an IE TextRange, n is a dom node - if (isNodeText(n)) - { - // previous node should not also be text, but prevent inf recurs - if (n.previousSibling && !isNodeText(n.previousSibling)) - { - setCollapsedAfter(s, n.previousSibling); - } - else - { - setCollapsedBefore(s, n.parentNode); - } - } - else - { - moveToElementText(s, n); - // work around for issue that caret at beginning of line - // somehow ends up at end of previous line - if (s.move('character', 1)) - { - s.move('character', -1); - } - s.collapse(true); // to start - } - } - - function setCollapsedAfter(s, n) - { - // s is an IE TextRange, n is a magicdom node - if (isNodeText(n)) - { - // can't use end of container when no nextSibling (could be on next line), - // so use previousSibling or start of container and move forward. - setCollapsedBefore(s, n); - s.move("character", n.nodeValue.length); - } - else - { - moveToElementText(s, n); - s.collapse(false); // to end - } - } - - function getPointRange(point) - { - var s = newRange(); - var n = point.node; - if (isNodeText(n)) - { - setCollapsedBefore(s, n); - s.move("character", point.index); - } - else if (point.index === 0) - { - setCollapsedBefore(s, n); - } - else - { - setCollapsedAfter(s, n); - } - return s; - } - - if (selection) - { - if (!hasIESelection()) - { - return; // don't steal focus - } - - var startPoint = copyPoint(selection.startPoint); - var endPoint = copyPoint(selection.endPoint); - - // fix issue where selection can't be extended past end of line - // with shift-rightarrow or shift-downarrow - if (endPoint.index == endPoint.maxIndex && endPoint.node.nextSibling) - { - endPoint.node = endPoint.node.nextSibling; - endPoint.index = 0; - endPoint.maxIndex = nodeMaxIndex(endPoint.node); - } - var range = getPointRange(startPoint); - range.setEndPoint("EndToEnd", getPointRange(endPoint)); - - // setting the selection in IE causes everything to scroll - // so that the selection is visible. if setting the selection - // definitely accomplishes nothing, don't do it. - - - function isEqualToDocumentSelection(rng) - { - var browserSelection; - try - { - browserSelection = doc.selection; - } - catch (e) - {} - if (!browserSelection) return false; - var rng2 = browserSelection.createRange(); - if (rng2.parentElement().ownerDocument != doc) return false; - if (rng.compareEndPoints("StartToStart", rng2) !== 0) return false; - if (rng.compareEndPoints("EndToEnd", rng2) !== 0) return false; - return true; - } - if (!isEqualToDocumentSelection(range)) - { - //dmesg(toSource(selection)); - //dmesg(escapeHTML(doc.body.innerHTML)); - range.select(); - } - } - else - { - try - { - doc.selection.empty(); - } - catch (e) - {} - } - } - else - { - // non-IE browser - var isCollapsed; - - function pointToRangeBound(pt) - { - var p = copyPoint(pt); - // Make sure Firefox cursor is deep enough; fixes cursor jumping when at top level, - // and also problem where cut/copy of a whole line selected with fake arrow-keys - // copies the next line too. - if (isCollapsed) - { - function diveDeep() - { - while (p.node.childNodes.length > 0) - { - //&& (p.node == root || p.node.parentNode == root)) { - if (p.index === 0) - { - p.node = p.node.firstChild; - p.maxIndex = nodeMaxIndex(p.node); - } - else if (p.index == p.maxIndex) - { - p.node = p.node.lastChild; - p.maxIndex = nodeMaxIndex(p.node); - p.index = p.maxIndex; - } - else break; - } - } - // now fix problem where cursor at end of text node at end of span-like element - // with background doesn't seem to show up... - if (isNodeText(p.node) && p.index == p.maxIndex) - { - var n = p.node; - while ((!n.nextSibling) && (n != root) && (n.parentNode != root)) - { - n = n.parentNode; - } - if (n.nextSibling && (!((typeof n.nextSibling.tagName) == "string" && n.nextSibling.tagName.toLowerCase() == "br")) && (n != p.node) && (n != root) && (n.parentNode != root)) - { - // found a parent, go to next node and dive in - p.node = n.nextSibling; - p.maxIndex = nodeMaxIndex(p.node); - p.index = 0; - diveDeep(); - } - } - // try to make sure insertion point is styled; - // also fixes other FF problems - if (!isNodeText(p.node)) - { - diveDeep(); - } - } - if (isNodeText(p.node)) - { - return { - container: p.node, - offset: p.index - }; - } - else - { - // p.index in {0,1} - return { - container: p.node.parentNode, - offset: childIndex(p.node) + p.index - }; - } - } - var browserSelection = window.getSelection(); - if (browserSelection) - { - browserSelection.removeAllRanges(); - if (selection) - { - isCollapsed = (selection.startPoint.node === selection.endPoint.node && selection.startPoint.index === selection.endPoint.index); - var start = pointToRangeBound(selection.startPoint); - var end = pointToRangeBound(selection.endPoint); - - if ((!isCollapsed) && selection.focusAtStart && browserSelection.collapse && browserSelection.extend) - { - // can handle "backwards"-oriented selection, shift-arrow-keys move start - // of selection - browserSelection.collapse(end.container, end.offset); - //console.trace(); - //console.log(htmlPrettyEscape(rep.alltext)); - //console.log("%o %o", rep.selStart, rep.selEnd); - //console.log("%o %d", start.container, start.offset); - browserSelection.extend(start.container, start.offset); - } - else - { - var range = doc.createRange(); - range.setStart(start.container, start.offset); - range.setEnd(end.container, end.offset); - browserSelection.removeAllRanges(); - browserSelection.addRange(range); - } - } - } - } - } - - function childIndex(n) - { - var idx = 0; - while (n.previousSibling) - { - idx++; - n = n.previousSibling; - } - return idx; - } - - function fixView() - { - // calling this method repeatedly should be fast - if (getInnerWidth() === 0 || getInnerHeight() === 0) - { - return; - } - - function setIfNecessary(obj, prop, value) - { - if (obj[prop] != value) - { - obj[prop] = value; - } - } - - var lineNumberWidth = sideDiv.firstChild.offsetWidth; - var newSideDivWidth = lineNumberWidth + LINE_NUMBER_PADDING_LEFT; - if (newSideDivWidth < MIN_LINEDIV_WIDTH) newSideDivWidth = MIN_LINEDIV_WIDTH; - iframePadLeft = EDIT_BODY_PADDING_LEFT; - if (hasLineNumbers) iframePadLeft += newSideDivWidth + LINE_NUMBER_PADDING_RIGHT; - setIfNecessary(iframe.style, "left", iframePadLeft + "px"); - setIfNecessary(sideDiv.style, "width", newSideDivWidth + "px"); - - for (var i = 0; i < 2; i++) - { - var newHeight = root.clientHeight; - var newWidth = (browser.msie ? root.createTextRange().boundingWidth : root.clientWidth); - var viewHeight = getInnerHeight() - iframePadBottom - iframePadTop; - var viewWidth = getInnerWidth() - iframePadLeft - iframePadRight; - if (newHeight < viewHeight) - { - newHeight = viewHeight; - if (browser.msie) setIfNecessary(outerWin.document.documentElement.style, 'overflowY', 'auto'); - } - else - { - if (browser.msie) setIfNecessary(outerWin.document.documentElement.style, 'overflowY', 'scroll'); - } - if (doesWrap) - { - newWidth = viewWidth; - } - else - { - if (newWidth < viewWidth) newWidth = viewWidth; - } - setIfNecessary(iframe.style, "height", newHeight + "px"); - setIfNecessary(iframe.style, "width", newWidth + "px"); - setIfNecessary(sideDiv.style, "height", newHeight + "px"); - } - if (browser.firefox) - { - if (!doesWrap) - { - // the body:display:table-cell hack makes mozilla do scrolling - // correctly by shrinking the to fit around its content, - // but mozilla won't act on clicks below the body. We keep the - // style.height property set to the viewport height (editor height - // not including scrollbar), so it will never shrink so that part of - // the editor isn't clickable. - var body = root; - var styleHeight = viewHeight + "px"; - setIfNecessary(body.style, "height", styleHeight); - } - else - { - setIfNecessary(root.style, "height", ""); - } - } - var win = outerWin; - var r = 20; - - enforceEditability(); - - $(sideDiv).addClass('sidedivdelayed'); - } - - var _teardownActions = []; - - function teardown() - { - _.each(_teardownActions, function(a) - { - a(); - }); - } - - function setDesignMode(newVal) - { - try - { - function setIfNecessary(target, prop, val) - { - if (String(target[prop]).toLowerCase() != val) - { - target[prop] = val; - return true; - } - return false; - } - if (browser.msie || browser.safari) - { - setIfNecessary(root, 'contentEditable', (newVal ? 'true' : 'false')); - } - else - { - var wasSet = setIfNecessary(doc, 'designMode', (newVal ? 'on' : 'off')); - if (wasSet && newVal && browser.opera) - { - // turning on designMode clears event handlers - bindTheEventHandlers(); - } - } - return true; - } - catch (e) - { - return false; - } - } - - var iePastedLines = null; - - function handleIEPaste(evt) - { - // Pasting in IE loses blank lines in a way that loses information; - // "one\n\ntwo\nthree" becomes "

    one

    two

    three

    ", - // which becomes "one\ntwo\nthree". We can get the correct text - // from the clipboard directly, but we still have to let the paste - // happen to get the style information. - var clipText = window.clipboardData && window.clipboardData.getData("Text"); - if (clipText && doc.selection) - { - // this "paste" event seems to mess with the selection whether we try to - // stop it or not, so can't really do document-level manipulation now - // or in an idle call-stack. instead, use IE native manipulation - //function escapeLine(txt) { - //return processSpaces(escapeHTML(textify(txt))); - //} - //var newHTML = map(clipText.replace(/\r/g,'').split('\n'), escapeLine).join('
    '); - //doc.selection.createRange().pasteHTML(newHTML); - //evt.preventDefault(); - //iePastedLines = map(clipText.replace(/\r/g,'').split('\n'), textify); - } - } - - - var inInternationalComposition = false; - function handleCompositionEvent(evt) - { - // international input events, fired in FF3, at least; allow e.g. Japanese input - if (evt.type == "compositionstart") - { - inInternationalComposition = true; - } - else if (evt.type == "compositionend") - { - inInternationalComposition = false; - } - } - - editorInfo.ace_getInInternationalComposition = function () - { - return inInternationalComposition; - } - - function bindTheEventHandlers() - { - $(document).on("keydown", handleKeyEvent); - $(document).on("keypress", handleKeyEvent); - $(document).on("keyup", handleKeyEvent); - $(document).on("click", handleClick); - // dropdowns on edit bar need to be closed on clicks on both pad inner and pad outer - $(outerWin.document).on("click", hideEditBarDropdowns); - // Disabled: https://github.com/ether/etherpad-lite/issues/2546 - // Will break OL re-numbering: https://github.com/ether/etherpad-lite/pull/2533 - // $(document).on("cut", handleCut); - - $(root).on("blur", handleBlur); - if (browser.msie) - { - $(document).on("click", handleIEOuterClick); - } - if (browser.msie) $(root).on("paste", handleIEPaste); - - // Don't paste on middle click of links - $(root).on("paste", function(e){ - // TODO: this breaks pasting strings into URLS when using - // Control C and Control V -- the Event is never available - // here.. :( - if(e.target.a || e.target.localName === "a"){ - e.preventDefault(); - } - - // Call paste hook - hooks.callAll('acePaste', { - editorInfo: editorInfo, - rep: rep, - documentAttributeManager: documentAttributeManager, - e: e - }); - }) - - // We reference document here, this is because if we don't this will expose a bug - // in Google Chrome. This bug will cause the last character on the last line to - // not fire an event when dropped into.. - $(document).on("drop", function(e){ - if(e.target.a || e.target.localName === "a"){ - e.preventDefault(); - } - - // Bug fix: when user drags some content and drop it far from its origin, we - // need to merge the changes into a single changeset. So mark origin with - - - -
    APIKEY:
    -
    -

    createGroup()

    - - - - -
    -
    - -
    -
    createGroup()
    -
    deleteGroup(groupID)
    -
    createGroupIfNotExistsFor(groupMapper)
    -
    listPads(groupID)
    -
    createPad(padID,text)
    -
    createGroupPad(groupID,padName,text)
    -
    createAuthor(name)
    -
    createAuthorIfNotExistsFor(authorMapper,name)
    -
    createSession(groupID,authorID,validUntil)
    -
    deleteSession(sessionID)
    -
    getSessionInfo(sessionID)
    -
    listSessionsOfGroup(groupID)
    -
    listSessionsOfAuthor(authorID)
    -
    getText(padID,rev)
    -
    setText(padID,text)
    -
    getRevisionsCount(padID)
    -
    getLastEdited(padID)
    -
    deletePad(padID)
    -
    getReadOnlyID(padID)
    -
    setPublicStatus(padID,publicStatus)
    -
    getPublicStatus(padID)
    -
    setPassword(padID,password)
    -
    isPasswordProtected(padID)
    - - diff --git a/sources/src/templates/admin/index.html b/sources/src/templates/admin/index.html deleted file mode 100644 index 45755a4..0000000 --- a/sources/src/templates/admin/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - Admin Dashboard - Etherpad - - - - - - -
    - -
    - - - diff --git a/sources/src/templates/admin/plugins-info.html b/sources/src/templates/admin/plugins-info.html deleted file mode 100644 index 8dd0bf8..0000000 --- a/sources/src/templates/admin/plugins-info.html +++ /dev/null @@ -1,46 +0,0 @@ -<% - var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins"); -%> - - - - Plugin information - Etherpad - - - - -
    - - -
    -

    Etherpad version

    -

    Version number: <%= epVersion %>

    -

    Git sha: <%= gitCommit %>

    - -

    Installed plugins

    -
    <%- plugins.formatPlugins().replace(", ","\n") %>
    - -

    Installed parts

    -
    <%= plugins.formatParts() %>
    - -

    Installed hooks

    -

    Server side hooks

    -
    <%- plugins.formatHooks() %>
    - -

    Client side hooks

    -
    <%- plugins.formatHooks("client_hooks") %>
    - -
    -
    - - - diff --git a/sources/src/templates/admin/plugins.html b/sources/src/templates/admin/plugins.html deleted file mode 100644 index 0fff784..0000000 --- a/sources/src/templates/admin/plugins.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - Plugin manager - Etherpad - - - - - - - -
    - - <% if (errors.length) { %> -
    - <% errors.forEach(function (item) { %> -
    <%= item.toString() %>
    - <% }) %> -
    - <% } %> - - - -
    -

    Installed plugins

    - - - - - - - - - - - - - - - - - - - - - - -
    NameDescriptionVersion
    -
    - -

    -
    -
    -

    You haven't installed any plugins yet.

    -


    Fetching installed plugins...

    -
    - -
    -
    - -

    Available plugins

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    NameDescriptionVersionLast update
    -
    - -

    -
    -
    -
    -

     

    -

    No plugins found.

    -


    Fetching...

    -
    -
    -
    - -
    -
    - - - diff --git a/sources/src/templates/admin/settings.html b/sources/src/templates/admin/settings.html deleted file mode 100644 index 74f3552..0000000 --- a/sources/src/templates/admin/settings.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - Settings - Etherpad - - - - - - - - - - -
    - - <% if (errors.length) { %> -
    - <% errors.forEach(function (item) { %> -
    <%= item.toString() %>
    - <% }) %> -
    - <% } %> - - - - - - -
    -

    -
    - -
    - - - diff --git a/sources/src/templates/export_html.html b/sources/src/templates/export_html.html deleted file mode 100644 index b8893b7..0000000 --- a/sources/src/templates/export_html.html +++ /dev/null @@ -1,143 +0,0 @@ - - - -<%- padId %> - - - - - - - -<%- body %> - - diff --git a/sources/src/templates/index.html b/sources/src/templates/index.html deleted file mode 100644 index 92bea58..0000000 --- a/sources/src/templates/index.html +++ /dev/null @@ -1,206 +0,0 @@ -<% - var settings = require("ep_etherpad-lite/node/utils/Settings"); -%> - - - - <%=settings.title%> - - - - - - - - - - - - - - -
    - <% e.begin_block("indexWrapper"); %> -
    - - -
    - - -
    -
    - <% e.end_block(); %> -
    - - - - - diff --git a/sources/src/templates/javascript.html b/sources/src/templates/javascript.html deleted file mode 100644 index 29031c4..0000000 --- a/sources/src/templates/javascript.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - JavaScript license information - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    jquery-2.1.1.min.jsExpatjquery.js
    html10n.jsExpathtml10n.js
    l10n.jsApache-2.0-onlyl10n.js
    socket.io.jsExpatsocket.io.js
    require-kernel.jsExpatrequire-kernel.js
    index.jsApache-2.0-onlyindex.js
    timeslider.jsApache-2.0-onlytimeslider.js
    pad.jsApache-2.0-onlypad.js
    plugins.jsApache-2.0-onlyplugins.js
    minify.json.jsExpatminify.json.js
    settings.jsApache-2.0-onlysettings.js
    jquery.autosize.jsExpatjquery.autosize.js
    - - diff --git a/sources/src/templates/pad.html b/sources/src/templates/pad.html deleted file mode 100644 index 9a9c6f0..0000000 --- a/sources/src/templates/pad.html +++ /dev/null @@ -1,428 +0,0 @@ -<% - var settings = require("ep_etherpad-lite/node/utils/Settings") - , hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks') - , langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs - ; -%> - -<% e.begin_block("htmlHead"); %> - -<% e.end_block(); %> - - <%=settings.title%> - - - - - - - - - <% e.begin_block("styles"); %> - - - <% e.begin_block("customStyles"); %> - - <% e.end_block(); %> - - - <% e.end_block(); %> - - - - - - - - <% e.begin_block("body"); %> -
    -
    -
    -
    - - - -
    - <% e.begin_block("afterEditbar"); %><% e.end_block(); %> - -
    - <% e.begin_block("userlist"); %> -
    -
    -
    -
    - - - -
    -
    -
    -
    -
    -
    -
    - - -
    -
    -
    -
    - <% e.end_block(); %> -
    - -
    -
    -
    -
    -

    You need a password to access this pad

    -
    - -
    -
    -
    -

    You do not have permission to access this pad

    -
    -
    -

    Your password was wrong

    -
    -
    -

    Cookie could not be found. Please allow cookies in your browser!

    -
    - <% e.begin_block("loading"); %> -

    Loading...

    - <% e.end_block(); %> - -
    -
    - - - - - - - - - -
    - - - 0 -
    - -
    -
    - - █   -
    -
    -
    - -
    -
    -
    - -
    -
    -
    - -
     
    - - <% e.end_block(); %> - - <% e.begin_block("scripts"); %> - - - - - - - - - - <% e.begin_block("customScripts"); %> - - <% e.end_block(); %> - - - - - <% e.end_block(); %> - diff --git a/sources/src/templates/timeslider.html b/sources/src/templates/timeslider.html deleted file mode 100644 index 395d0c4..0000000 --- a/sources/src/templates/timeslider.html +++ /dev/null @@ -1,276 +0,0 @@ -<% - var settings = require("ep_etherpad-lite/node/utils/Settings") - , langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs -%> - - -<%=settings.title%> Timeslider - - - - - - - <% e.begin_block("timesliderStyles"); %> - - - - - <% e.end_block(); %> - - - <% e.begin_block("timesliderScripts"); %> - - - <% e.end_block(); %> - - -<% e.begin_block("timesliderBody"); %> - -
    -
    - <% e.begin_block("timesliderTop"); %> -
    - - -
    -
    - -
    -
    -
    - -
    -
    - <% e.begin_block("timesliderEditbarRight"); %> -
      - <%- toolbar.menu(settings.toolbar.timeslider) %> -
    - <% e.end_block(); %> -
    - -
    -

    - - -

    -

    - - -

    -
    -
    - <% e.end_block(); %> -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    - - - - - - -
    - -
    - - - - - - - - - - - - -<% e.end_block(); %> - - - diff --git a/sources/src/web.config b/sources/src/web.config deleted file mode 100644 index e057b91..0000000 --- a/sources/src/web.config +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sources/start.bat b/sources/start.bat deleted file mode 100644 index 0f6fc55..0000000 --- a/sources/start.bat +++ /dev/null @@ -1 +0,0 @@ -node node_modules\ep_etherpad-lite\node\server.js \ No newline at end of file diff --git a/sources/tests/README.md b/sources/tests/README.md deleted file mode 100644 index 201ee4c..0000000 --- a/sources/tests/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# About this folder: Tests - -## Frontend - -To run the tests, point your browser to `/tests/frontend` - -## Backend - -To run the tests, run ``bin/backendTests.sh`` diff --git a/sources/tests/backend/loadSettings.js b/sources/tests/backend/loadSettings.js deleted file mode 100644 index f208fe3..0000000 --- a/sources/tests/backend/loadSettings.js +++ /dev/null @@ -1,17 +0,0 @@ -var jsonminify = require(__dirname+"/../../src/node_modules/jsonminify"); - -function loadSettings(){ - var settingsStr = fs.readFileSync(__dirname+"/../../settings.json").toString(); - // try to parse the settings - var settings; - try { - if(settingsStr) { - settingsStr = jsonminify(settingsStr).replace(",]","]").replace(",}","}"); - return JSON.parse(settingsStr); - } - }catch(e){ - console.error("whoops something is bad with settings"); - } -} - -exports.loadSettings = loadSettings; diff --git a/sources/tests/backend/specs/api/chat.js b/sources/tests/backend/specs/api/chat.js deleted file mode 100644 index 2bcd978..0000000 --- a/sources/tests/backend/specs/api/chat.js +++ /dev/null @@ -1,114 +0,0 @@ -var assert = require('assert') - supertest = require(__dirname+'/../../../../src/node_modules/supertest'), - fs = require('fs'), - settings = require(__dirname+'/../../loadSettings').loadSettings(), - api = supertest('http://'+settings.ip+":"+settings.port), - path = require('path'); - -var filePath = path.join(__dirname, '../../../../APIKEY.txt'); - -var apiKey = fs.readFileSync(filePath, {encoding: 'utf-8'}); -apiKey = apiKey.replace(/\n$/, ""); -var apiVersion = 1; -var authorID = ""; -var padID = makeid(); -var timestamp = Date.now(); - -describe('API Versioning', function(){ - it('errors if can not connect', function(done) { - api.get('/api/') - .expect(function(res){ - apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); - return; - }) - .expect(200, done) - }); -}) - -// BEGIN GROUP AND AUTHOR TESTS -///////////////////////////////////// -///////////////////////////////////// - -/* Tests performed --> createPad(padID) - -> createAuthor([name]) -- should return an authorID - -> appendChatMessage(padID, text, authorID, time) - -> getChatHead(padID) - -> getChatHistory(padID) -*/ - -describe('createPad', function(){ - it('creates a new Pad', function(done) { - api.get(endPoint('createPad')+"&padID="+padID) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create new Pad"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createAuthor', function(){ - it('Creates an author with a name set', function(done) { - api.get(endPoint('createAuthor')) - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.authorID) throw new Error("Unable to create author"); - authorID = res.body.data.authorID; // we will be this author for the rest of the tests - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('appendChatMessage', function(){ - it('Adds a chat message to the pad', function(done) { - api.get(endPoint('appendChatMessage')+"&padID="+padID+"&text=blalblalbha&authorID="+authorID+"&time="+timestamp) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create chat message"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - - -describe('getChatHead', function(){ - it('Gets the head of chat', function(done) { - api.get(endPoint('getChatHead')+"&padID="+padID) - .expect(function(res){ - if(res.body.data.chatHead !== 0) throw new Error("Chat Head Length is wrong"); - - if(res.body.code !== 0) throw new Error("Unable to get chat head"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getChatHistory', function(){ - it('Gets Chat History of a Pad', function(done) { - api.get(endPoint('getChatHistory')+"&padID="+padID) - .expect(function(res){ - if(res.body.data.messages.length !== 1) throw new Error("Chat History Length is wrong"); - if(res.body.code !== 0) throw new Error("Unable to get chat history"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -var endPoint = function(point){ - return '/api/'+apiVersion+'/'+point+'?apikey='+apiKey; -} - -function makeid() -{ - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - for( var i=0; i < 5; i++ ){ - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - return text; -} diff --git a/sources/tests/backend/specs/api/pad.js b/sources/tests/backend/specs/api/pad.js deleted file mode 100644 index 1db9058..0000000 --- a/sources/tests/backend/specs/api/pad.js +++ /dev/null @@ -1,617 +0,0 @@ -var assert = require('assert') - supertest = require(__dirname+'/../../../../src/node_modules/supertest'), - fs = require('fs'), - settings = require(__dirname+'/../../loadSettings').loadSettings(), - api = supertest('http://'+settings.ip+":"+settings.port), - path = require('path'), - async = require(__dirname+'/../../../../src/node_modules/async'); - -var filePath = path.join(__dirname, '../../../../APIKEY.txt'); - -var apiKey = fs.readFileSync(filePath, {encoding: 'utf-8'}); -apiKey = apiKey.replace(/\n$/, ""); -var apiVersion = 1; -var testPadId = makeid(); -var lastEdited = ""; -var text = generateLongText(); -var ULhtml = '
    • one
    • 2

      • UL2
    '; - -describe('Connectivity', function(){ - it('errors if can not connect', function(done) { - api.get('/api/') - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('API Versioning', function(){ - it('errors if can not connect', function(done) { - api.get('/api/') - .expect(function(res){ - apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); - return; - }) - .expect(200, done) - }); -}) - -describe('Permission', function(){ - it('errors if can connect without correct APIKey', function(done) { - // This is broken because Etherpad doesn't handle HTTP codes properly see #2343 - // If your APIKey is password you deserve to fail all tests anyway - var permErrorURL = '/api/'+apiVersion+'/createPad?apikey=password&padID=test'; - api.get(permErrorURL) - .expect(401, done) - }); -}) - -/* Pad Tests Order of execution --> deletePad -- This gives us a guaranteed clear environment - -> createPad - -> getRevisions -- Should be 0 - -> getSavedRevisionsCount(padID) -- Should be 0 - -> listSavedRevisions(padID) -- Should be an empty array - -> getHTML -- Should be the default pad text in HTML format - -> deletePad -- Should just delete a pad - -> getHTML -- Should return an error - -> createPad(withText) - -> getText -- Should have the text specified above as the pad text - -> setText - -> getText -- Should be the text set before - -> getRevisions -- Should be 0 still? - -> saveRevision - -> getSavedRevisionsCount(padID) -- Should be 0 still? - -> listSavedRevisions(padID) -- Should be an empty array still ? - -> padUsersCount -- Should be 0 - -> getReadOnlyId -- Should be a value - -> listAuthorsOfPad(padID) -- should be empty array? - -> getLastEdited(padID) -- Should be when pad was made - -> setText(padId) - -> getLastEdited(padID) -- Should be when setText was performed - -> padUsers(padID) -- Should be when setText was performed - - -> setText(padId, "hello world") - -> getLastEdited(padID) -- Should be when pad was made - -> getText(padId) -- Should be "hello world" - -> movePad(padID, newPadId) -- Should provide consistant pad data - -> getText(newPadId) -- Should be "hello world" - -> movePad(newPadID, originalPadId) -- Should provide consistant pad data - -> getText(originalPadId) -- Should be "hello world" - -> getLastEdited(padID) -- Should not be 0 - -> appendText(padID, "hello") - -> getText(padID) -- Should be "hello worldhello" - -> setHTML(padID) -- Should fail on invalid HTML - -> setHTML(padID) *3 -- Should fail on invalid HTML - -> getHTML(padID) -- Should return HTML close to posted HTML - -> createPad -- Tries to create pads with bad url characters - -*/ - -describe('deletePad', function(){ - it('deletes a Pad', function(done) { - api.get(endPoint('deletePad')+"&padID="+testPadId) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createPad', function(){ - it('creates a new Pad', function(done) { - api.get(endPoint('createPad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create new Pad"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getRevisionsCount', function(){ - it('gets revision count of Pad', function(done) { - api.get(endPoint('getRevisionsCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Revision Count"); - if(res.body.data.revisions !== 0) throw new Error("Incorrect Revision Count"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getSavedRevisionsCount', function(){ - it('gets saved revisions count of Pad', function(done) { - api.get(endPoint('getSavedRevisionsCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions Count"); - if(res.body.data.savedRevisions !== 0) throw new Error("Incorrect Saved Revisions Count"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('listSavedRevisions', function(){ - it('gets saved revision list of Pad', function(done) { - api.get(endPoint('listSavedRevisions')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions List"); - if(!res.body.data.savedRevisions.equals([])) throw new Error("Incorrect Saved Revisions List"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getHTML', function(){ - it('get the HTML of Pad', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.html.length <= 1) throw new Error("Unable to get the HTML"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('deletePad', function(){ - it('deletes a Pad', function(done) { - api.get(endPoint('deletePad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Deletion failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getHTML', function(){ - it('get the HTML of a Pad -- Should return a failure', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 1) throw new Error("Pad deletion failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createPad', function(){ - it('creates a new Pad with text', function(done) { - api.get(endPoint('createPad')+"&padID="+testPadId+"&text=testText") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Creation failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getText', function(){ - it('gets the Pad text and expect it to be testText with \n which is a line break', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.text !== "testText\n") throw new Error("Pad Creation with text") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('setText', function(){ - it('creates a new Pad with text', function(done) { - api.get(endPoint('setText')+"&padID="+testPadId+"&text=testTextTwo") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad setting text failed"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getText', function(){ - it('gets the Pad text', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.text !== "testTextTwo\n") throw new Error("Setting Text") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getRevisionsCount', function(){ - it('gets Revision Count of a Pad', function(done) { - api.get(endPoint('getRevisionsCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.revisions !== 1) throw new Error("Unable to get text revision count") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('saveRevision', function(){ - it('saves Revision', function(done) { - api.get(endPoint('saveRevision')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to save Revision"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getSavedRevisionsCount', function(){ - it('gets saved revisions count of Pad', function(done) { - api.get(endPoint('getSavedRevisionsCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions Count"); - if(res.body.data.savedRevisions !== 1) throw new Error("Incorrect Saved Revisions Count"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('listSavedRevisions', function(){ - it('gets saved revision list of Pad', function(done) { - api.get(endPoint('listSavedRevisions')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions List"); - if(!res.body.data.savedRevisions.equals([1])) throw new Error("Incorrect Saved Revisions List"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) -describe('padUsersCount', function(){ - it('gets User Count of a Pad', function(done) { - api.get(endPoint('padUsersCount')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.padUsersCount !== 0) throw new Error("Incorrect Pad User count") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getReadOnlyID', function(){ - it('Gets the Read Only ID of a Pad', function(done) { - api.get(endPoint('getReadOnlyID')+"&padID="+testPadId) - .expect(function(res){ - if(!res.body.data.readOnlyID) throw new Error("No Read Only ID for Pad") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('listAuthorsOfPad', function(){ - it('Get Authors of the Pad', function(done) { - api.get(endPoint('listAuthorsOfPad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.authorIDs.length !== 0) throw new Error("# of Authors of pad is not 0") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getLastEdited', function(){ - it('Get When Pad was left Edited', function(done) { - api.get(endPoint('getLastEdited')+"&padID="+testPadId) - .expect(function(res){ - if(!res.body.data.lastEdited){ - throw new Error("# of Authors of pad is not 0") - }else{ - lastEdited = res.body.data.lastEdited; - } - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('setText', function(){ - it('creates a new Pad with text', function(done) { - api.get(endPoint('setText')+"&padID="+testPadId+"&text=testTextTwo") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad setting text failed"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getLastEdited', function(){ - it('Get When Pad was left Edited', function(done) { - api.get(endPoint('getLastEdited')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.lastEdited <= lastEdited){ - throw new Error("Editing A Pad is not updating when it was last edited") - } - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('padUsers', function(){ - it('gets User Count of a Pad', function(done) { - api.get(endPoint('padUsers')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.padUsers.length !== 0) throw new Error("Incorrect Pad Users") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('deletePad', function(){ - it('deletes a Pad', function(done) { - api.get(endPoint('deletePad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Deletion failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -var originalPadId = testPadId; -var newPadId = makeid(); - -describe('createPad', function(){ - it('creates a new Pad with text', function(done) { - api.get(endPoint('createPad')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Creation failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('setText', function(){ - it('Sets text on a pad Id', function(done) { - api.get(endPoint('setText')+"&padID="+testPadId+"&text="+text) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Set Text failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getText', function(){ - it('Gets text on a pad Id', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Get Text failed") - if(res.body.data.text !== text+"\n") throw new Error("Pad Text not set properly"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('setText', function(){ - it('Sets text on a pad Id including an explicit newline', function(done) { - api.get(endPoint('setText')+"&padID="+testPadId+"&text="+text+'%0A') - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Set Text failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getText', function(){ - it("Gets text on a pad Id and doesn't have an excess newline", function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Get Text failed") - if(res.body.data.text !== text+"\n") throw new Error("Pad Text not set properly"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getLastEdited', function(){ - it('Gets when pad was last edited', function(done) { - api.get(endPoint('getLastEdited')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.lastEdited === 0) throw new Error("Get Last Edited Failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('movePad', function(){ - it('Move a Pad to a different Pad ID', function(done) { - api.get(endPoint('movePad')+"&sourceID="+testPadId+"&destinationID="+newPadId+"&force=true") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Moving Pad Failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getText', function(){ - it('Gets text on a pad Id', function(done) { - api.get(endPoint('getText')+"&padID="+newPadId) - .expect(function(res){ - if(res.body.data.text !== text+"\n") throw new Error("Pad Get Text failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('movePad', function(){ - it('Move a Pad to a different Pad ID', function(done) { - api.get(endPoint('movePad')+"&sourceID="+newPadId+"&destinationID="+testPadId+"&force=false") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Moving Pad Failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getText', function(){ - it('Gets text on a pad Id', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.data.text !== text+"\n") throw new Error("Pad Get Text failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getLastEdited', function(){ - it('Gets when pad was last edited', function(done) { - api.get(endPoint('getLastEdited')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.lastEdited === 0) throw new Error("Get Last Edited Failed") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('appendText', function(){ - it('Append text to a pad Id', function(done) { - api.get(endPoint('appendText', '1.2.13')+"&padID="+testPadId+"&text=hello") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Append Text failed"); - }) - .expect('Content-Type', /json/) - .expect(200, done); - }); -}); - -describe('getText', function(){ - it('Gets text on a pad Id', function(done) { - api.get(endPoint('getText')+"&padID="+testPadId) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Pad Get Text failed"); - if(res.body.data.text !== text+"hello\n") throw new Error("Pad Text not set properly"); - }) - .expect('Content-Type', /json/) - .expect(200, done); - }); -}); - - -describe('setHTML', function(){ - it('Sets the HTML of a Pad attempting to pass ugly HTML', function(done) { - var html = "
    Hello HTML
    "; - api.get(endPoint('setHTML')+"&padID="+testPadId+"&html="+html) - .expect(function(res){ - if(res.body.code !== 1) throw new Error("Allowing crappy HTML to be imported") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('setHTML', function(){ - it('Sets the HTML of a Pad with a bunch of weird unordered lists inserted', function(done) { - api.get(endPoint('setHTML')+"&padID="+testPadId+"&html="+ULhtml) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("List HTML cant be imported") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getHTML', function(){ - it('Gets the HTML of a Pad with a bunch of weird unordered lists inserted', function(done) { - api.get(endPoint('getHTML')+"&padID="+testPadId) - .expect(function(res){ - var ehtml = res.body.data.html.replace("
    ", "").toLowerCase(); - var uhtml = ULhtml.toLowerCase(); - if(ehtml !== uhtml) throw new Error("Imported HTML does not match served HTML") - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createPad', function(){ - it('errors if pad can be created', function(done) { - var badUrlChars = ["/", "%23", "%3F", "%26"]; - async.map( - badUrlChars, - function (badUrlChar, cb) { - api.get(endPoint('createPad')+"&padID="+badUrlChar) - .expect(function(res){ - if(res.body.code !== 1) throw new Error("Pad with bad characters was created"); - }) - .expect('Content-Type', /json/) - .end(cb); - }, - done); - }); -}) - - -/* - -> movePadForce Test - -*/ - -var endPoint = function(point, version){ - version = version || apiVersion; - return '/api/'+version+'/'+point+'?apikey='+apiKey; -} - -function makeid() -{ - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - for( var i=0; i < 5; i++ ){ - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - return text; -} - -function generateLongText(){ - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - for( var i=0; i < 80000; i++ ){ - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - return text; -} - -// Need this to compare arrays (listSavedRevisions test) -Array.prototype.equals = function (array) { - // if the other array is a falsy value, return - if (!array) - return false; - // compare lengths - can save a lot of time - if (this.length != array.length) - return false; - for (var i = 0, l=this.length; i < l; i++) { - // Check if we have nested arrays - if (this[i] instanceof Array && array[i] instanceof Array) { - // recurse into the nested arrays - if (!this[i].equals(array[i])) - return false; - } else if (this[i] != array[i]) { - // Warning - two different object instances will never be equal: {x:20} != {x:20} - return false; - } - } - return true; -} diff --git a/sources/tests/backend/specs/api/sessionsAndGroups.js b/sources/tests/backend/specs/api/sessionsAndGroups.js deleted file mode 100644 index 961cb2d..0000000 --- a/sources/tests/backend/specs/api/sessionsAndGroups.js +++ /dev/null @@ -1,365 +0,0 @@ -var assert = require('assert') - supertest = require(__dirname+'/../../../../src/node_modules/supertest'), - fs = require('fs'), - settings = require(__dirname+'/../../loadSettings').loadSettings(), - api = supertest('http://'+settings.ip+":"+settings.port), - path = require('path'); - -var filePath = path.join(__dirname, '../../../../APIKEY.txt'); - -var apiKey = fs.readFileSync(filePath, {encoding: 'utf-8'}); -apiKey = apiKey.replace(/\n$/, ""); -var apiVersion = 1; -var testPadId = makeid(); -var groupID = ""; -var authorID = ""; -var sessionID = ""; -var padID = makeid(); - -describe('API Versioning', function(){ - it('errors if can not connect', function(done) { - api.get('/api/') - .expect(function(res){ - apiVersion = res.body.currentVersion; - if (!res.body.currentVersion) throw new Error("No version set in API"); - return; - }) - .expect(200, done) - }); -}) - -// BEGIN GROUP AND AUTHOR TESTS -///////////////////////////////////// -///////////////////////////////////// - -/* Tests performed --> createGroup() -- should return a groupID - -> listSessionsOfGroup(groupID) -- should be 0 - -> deleteGroup(groupID) - -> createGroupIfNotExistsFor(groupMapper) -- should return a groupID - - -> createAuthor([name]) -- should return an authorID - -> createAuthorIfNotExistsFor(authorMapper [, name]) -- should return an authorID - -> getAuthorName(authorID) -- should return a name IE "john" - --> createSession(groupID, authorID, validUntil) - -> getSessionInfo(sessionID) - -> listSessionsOfGroup(groupID) -- should be 1 - -> deleteSession(sessionID) - -> getSessionInfo(sessionID) -- should have author id etc in - --> listPads(groupID) -- should be empty array - -> createGroupPad(groupID, padName [, text]) - -> listPads(groupID) -- should be empty array - -> getPublicStatus(padId) - -> setPublicStatus(padId, status) - -> getPublicStatus(padId) - -> isPasswordProtected(padID) -- should be false - -> setPassword(padID, password) - -> isPasswordProtected(padID) -- should be true - --> listPadsOfAuthor(authorID) -*/ - -describe('createGroup', function(){ - it('creates a new group', function(done) { - api.get(endPoint('createGroup')) - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.groupID) throw new Error("Unable to create new Pad"); - groupID = res.body.data.groupID; - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('listSessionsOfGroup', function(){ - it('Lists the session of a group', function(done) { - api.get(endPoint('listSessionsOfGroup')+"&groupID="+groupID) - .expect(function(res){ - if(res.body.code !== 0 || res.body.data !== null) throw new Error("Sessions show as existing for this group"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('deleteGroup', function(){ - it('Deletes a group', function(done) { - api.get(endPoint('deleteGroup')+"&groupID="+groupID) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Group failed to be deleted"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createGroupIfNotExistsFor', function(){ - it('Creates a group if one doesnt exist for mapper 0', function(done) { - api.get(endPoint('createGroupIfNotExistsFor')+"&groupMapper=management") - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.groupID) throw new Error("Sessions show as existing for this group"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createGroup', function(){ - it('creates a new group', function(done) { - api.get(endPoint('createGroup')) - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.groupID) throw new Error("Unable to create new Pad"); - groupID = res.body.data.groupID; - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createAuthor', function(){ - it('Creates an author with a name set', function(done) { - api.get(endPoint('createAuthor')) - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.authorID) throw new Error("Unable to create author"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createAuthor', function(){ - it('Creates an author with a name set', function(done) { - api.get(endPoint('createAuthor')+"&name=john") - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.authorID) throw new Error("Unable to create user with name set"); - authorID = res.body.data.authorID; // we will be this author for the rest of the tests - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createAuthorIfNotExistsFor', function(){ - it('Creates an author if it doesnt exist already and provides mapping', function(done) { - api.get(endPoint('createAuthorIfNotExistsFor')+"&authorMapper=chris") - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.authorID) throw new Error("Unable to create author with mapper"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getAuthorName', function(){ - it('Gets the author name', function(done) { - api.get(endPoint('getAuthorName')+"&authorID="+authorID) - .expect(function(res){ - if(res.body.code !== 0 || res.body.data !== "john") throw new Error("Unable to get Author Name from Author ID"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -// BEGIN SESSION TESTS -/////////////////////////////////////// -/////////////////////////////////////// - -describe('createSession', function(){ - it('Creates a session for an Author', function(done) { - api.get(endPoint('createSession')+"&authorID="+authorID+"&groupID="+groupID+"&validUntil=999999999999") - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.sessionID) throw new Error("Unable to create Session"); - sessionID = res.body.data.sessionID; - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getSessionInfo', function(){ - it('Gets session inf', function(done) { - api.get(endPoint('getSessionInfo')+"&sessionID="+sessionID) - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.groupID || !res.body.data.authorID || !res.body.data.validUntil) throw new Error("Unable to get Session info"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('listSessionsOfGroup', function(){ - it('Gets sessions of a group', function(done) { - api.get(endPoint('listSessionsOfGroup')+"&groupID="+groupID) - .expect(function(res){ - if(res.body.code !== 0 || typeof res.body.data !== "object") throw new Error("Unable to get sessions of a group"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('deleteSession', function(){ - it('Deletes a session', function(done) { - api.get(endPoint('deleteSession')+"&sessionID="+sessionID) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to delete a session"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getSessionInfo', function(){ - it('Gets session info', function(done) { - api.get(endPoint('getSessionInfo')+"&sessionID="+sessionID) - .expect(function(res){ - if(res.body.code !== 1) throw new Error("Session was not properly deleted"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -// GROUP PAD MANAGEMENT -/////////////////////////////////////// -/////////////////////////////////////// - -describe('listPads', function(){ - it('Lists Pads of a Group', function(done) { - api.get(endPoint('listPads')+"&groupID="+groupID) - .expect(function(res){ - if(res.body.code !== 0 || res.body.data.padIDs.length !== 0) throw new Error("Group already had pads for some reason"+res.body.data.padIDs); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('createGroupPad', function(){ - it('Creates a Group Pad', function(done) { - api.get(endPoint('createGroupPad')+"&groupID="+groupID+"&padName="+padID) - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unable to create group pad"); - padID = res.body.data.padID; - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('listPads', function(){ - it('Lists Pads of a Group', function(done) { - api.get(endPoint('listPads')+"&groupID="+groupID) - .expect(function(res){ - if(res.body.code !== 0 || res.body.data.padIDs.length !== 1) throw new Error("Group isnt listing this pad"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -// PAD SECURITY /-_-\ -/////////////////////////////////////// -/////////////////////////////////////// - -describe('getPublicStatus', function(){ - it('Gets the public status of a pad', function(done) { - api.get(endPoint('getPublicStatus')+"&padID="+padID) - .expect(function(res){ - if(res.body.code !== 0 || res.body.data.publicstatus) throw new Error("Unable to get public status of this pad"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('setPublicStatus', function(){ - it('Sets the public status of a pad', function(done) { - api.get(endPoint('setPublicStatus')+"&padID="+padID+"&publicStatus=true") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Setting status did not work"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('getPublicStatus', function(){ - it('Gets the public status of a pad', function(done) { - api.get(endPoint('getPublicStatus')+"&padID="+padID) - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.publicStatus) throw new Error("Setting public status of this pad did not work"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('isPasswordProtected', function(){ - it('Gets the public status of a pad', function(done) { - api.get(endPoint('isPasswordProtected')+"&padID="+padID) - .expect(function(res){ - if(res.body.code !== 0 || res.body.data.isPasswordProtected) throw new Error("Pad is password protected by default"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('setPassword', function(){ - it('Gets the public status of a pad', function(done) { - api.get(endPoint('setPassword')+"&padID="+padID+"&password=test") - .expect(function(res){ - if(res.body.code !== 0) throw new Error("Unabe to set password"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - -describe('isPasswordProtected', function(){ - it('Gets the public status of a pad', function(done) { - api.get(endPoint('isPasswordProtected')+"&padID="+padID) - .expect(function(res){ - if(res.body.code !== 0 || !res.body.data.isPasswordProtected) throw new Error("Pad password protection has not applied"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - - -// NOT SURE HOW TO POPULAT THIS /-_-\ -/////////////////////////////////////// -/////////////////////////////////////// - -describe('listPadsOfAuthor', function(){ - it('Gets the Pads of an Author', function(done) { - api.get(endPoint('listPadsOfAuthor')+"&authorID="+authorID) - .expect(function(res){ - if(res.body.code !== 0 || res.body.data.padIDs.length !== 0) throw new Error("Pad password protection has not applied"); - }) - .expect('Content-Type', /json/) - .expect(200, done) - }); -}) - - - -var endPoint = function(point){ - return '/api/'+apiVersion+'/'+point+'?apikey='+apiKey; -} - -function makeid() -{ - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - for( var i=0; i < 5; i++ ){ - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - return text; -} diff --git a/sources/tests/backend/specs/api/tidy.js b/sources/tests/backend/specs/api/tidy.js deleted file mode 100644 index 47cb49f..0000000 --- a/sources/tests/backend/specs/api/tidy.js +++ /dev/null @@ -1,63 +0,0 @@ -var assert = require('assert') - fs = require('fs'), - path = require('path'), - TidyHtml = null, - Settings = null; - -var npm = require("../../../../src/node_modules/npm/lib/npm.js"); - -describe('tidyHtml', function() { - before(function(done) { - npm.load({}, function(err) { - assert.ok(!err); - TidyHtml = require('../../../../src/node/utils/TidyHtml'); - Settings = require('../../../../src/node/utils/Settings'); - return done() - }); - }); - - it('Tidies HTML', function(done) { - // If the user hasn't configured Tidy, we skip this tests as it's required for this test - if (!Settings.tidyHtml) { - this.skip(); - } - - // Try to tidy up a bad HTML file - var tmpDir = process.env.TEMP || "/tmp"; - var tmpFile = path.join(tmpDir, 'tmp_' + (Math.floor(Math.random() * 1000000)) + '.html') - fs.writeFileSync(tmpFile, '

    a paragraph

  2. List without outer UL
  3. trailing closing p

    '); - TidyHtml.tidy(tmpFile, function(err){ - assert.ok(!err); - - // Read the file again - var cleanedHtml = fs.readFileSync(tmpFile).toString(); - - var expectedHtml = [ - '', - '', - '', - '

    a paragraph

    ', - '
      ', - '
    • List without outer UL
    • ', - '
    • trailing closing p
    • ', - '
    ', - '', - '', - ].join('\n'); - assert.notStrictEqual(cleanedHtml.indexOf(expectedHtml), -1); - return done(); - }); - }); - - it('can deal with errors', function(done) { - // If the user hasn't configured Tidy, we skip this tests as it's required for this test - if (!Settings.tidyHtml) { - this.skip(); - } - - TidyHtml.tidy('/some/none/existing/file.html', function(err) { - assert.ok(err); - return done(); - }); - }); -}); diff --git a/sources/tests/frontend/helper.js b/sources/tests/frontend/helper.js deleted file mode 100644 index 7a8d19b..0000000 --- a/sources/tests/frontend/helper.js +++ /dev/null @@ -1,219 +0,0 @@ -var helper = {}; - -(function(){ - var $iframeContainer, $iframe, jsLibraries = {}; - - helper.init = function(cb){ - $iframeContainer = $("#iframe-container"); - - $.get('/static/js/jquery.js').done(function(code){ - // make sure we don't override existing jquery - jsLibraries["jquery"] = "if(typeof $ === 'undefined') {\n" + code + "\n}"; - - $.get('/tests/frontend/lib/sendkeys.js').done(function(code){ - jsLibraries["sendkeys"] = code; - - cb(); - }); - }); - } - - helper.randomString = function randomString(len) - { - var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - var randomstring = ''; - for (var i = 0; i < len; i++) - { - var rnum = Math.floor(Math.random() * chars.length); - randomstring += chars.substring(rnum, rnum + 1); - } - return randomstring; - } - - var getFrameJQuery = function($iframe){ - /* - I tried over 9000 ways to inject javascript into iframes. - This is the only way I found that worked in IE 7+8+9, FF and Chrome - */ - - var win = $iframe[0].contentWindow; - var doc = win.document; - - //IE 8+9 Hack to make eval appear - //http://stackoverflow.com/questions/2720444/why-does-this-window-object-not-have-the-eval-function - win.execScript && win.execScript("null"); - - win.eval(jsLibraries["jquery"]); - win.eval(jsLibraries["sendkeys"]); - - win.$.window = win; - win.$.document = doc; - - return win.$; - } - - helper.clearCookies = function(){ - window.document.cookie = ""; - } - - helper.newPad = function(cb, padName){ - //build opts object - var opts = {clearCookies: true} - if(typeof cb === 'function'){ - opts.cb = cb - } else { - opts = _.defaults(cb, opts); - } - - //clear cookies - if(opts.clearCookies){ - helper.clearCookies(); - } - - if(!padName) - padName = "FRONTEND_TEST_" + helper.randomString(20); - $iframe = $(""); - - //clean up inner iframe references - helper.padChrome$ = helper.padOuter$ = helper.padInner$ = null; - - //clean up iframes properly to prevent IE from memoryleaking - $iframeContainer.find("iframe").purgeFrame().done(function(){ - $iframeContainer.append($iframe); - $iframe.one('load', function(){ - helper.waitFor(function(){ - return !$iframe.contents().find("#editorloadingbox").is(":visible"); - }, 50000).done(function(){ - helper.padChrome$ = getFrameJQuery( $('#iframe-container iframe')); - helper.padOuter$ = getFrameJQuery(helper.padChrome$('iframe[name="ace_outer"]')); - helper.padInner$ = getFrameJQuery( helper.padOuter$('iframe[name="ace_inner"]')); - - //disable all animations, this makes tests faster and easier - helper.padChrome$.fx.off = true; - helper.padOuter$.fx.off = true; - helper.padInner$.fx.off = true; - - opts.cb(); - }).fail(function(){ - throw new Error("Pad never loaded"); - }); - }); - }); - - return padName; - } - - helper.waitFor = function(conditionFunc, _timeoutTime, _intervalTime){ - var timeoutTime = _timeoutTime || 1000; - var intervalTime = _intervalTime || 10; - - var deferred = $.Deferred(); - - var _fail = deferred.fail; - var listenForFail = false; - deferred.fail = function(){ - listenForFail = true; - _fail.apply(this, arguments); - } - - var intervalCheck = setInterval(function(){ - var passed = false; - - passed = conditionFunc(); - - if(passed){ - clearInterval(intervalCheck); - clearTimeout(timeout); - - deferred.resolve(); - } - }, intervalTime); - - var timeout = setTimeout(function(){ - clearInterval(intervalCheck); - var error = new Error("wait for condition never became true " + conditionFunc.toString()); - deferred.reject(error); - - if(!listenForFail){ - throw error; - } - }, timeoutTime); - - return deferred; - } - - helper.selectLines = function($startLine, $endLine, startOffset, endOffset){ - // if no offset is provided, use beginning of start line and end of end line - startOffset = startOffset || 0; - endOffset = endOffset === undefined ? $endLine.text().length : endOffset; - - var inner$ = helper.padInner$; - var selection = inner$.document.getSelection(); - var range = selection.getRangeAt(0); - - var start = getTextNodeAndOffsetOf($startLine, startOffset); - var end = getTextNodeAndOffsetOf($endLine, endOffset); - - range.setStart(start.node, start.offset); - range.setEnd(end.node, end.offset); - - selection.removeAllRanges(); - selection.addRange(range); - } - - var getTextNodeAndOffsetOf = function($targetLine, targetOffsetAtLine){ - var $textNodes = $targetLine.find('*').contents().filter(function(){ - return this.nodeType === Node.TEXT_NODE; - }); - - // search node where targetOffsetAtLine is reached, and its 'inner offset' - var textNodeWhereOffsetIs = null; - var offsetBeforeTextNode = 0; - var offsetInsideTextNode = 0; - $textNodes.each(function(index, element){ - var elementTotalOffset = element.textContent.length; - textNodeWhereOffsetIs = element; - offsetInsideTextNode = targetOffsetAtLine - offsetBeforeTextNode; - - var foundTextNode = offsetBeforeTextNode + elementTotalOffset >= targetOffsetAtLine; - if (foundTextNode){ - return false; //stop .each by returning false - } - - offsetBeforeTextNode += elementTotalOffset; - }); - - // edge cases - if (textNodeWhereOffsetIs === null){ - // there was no text node inside $targetLine, so it is an empty line (
    ). - // Use beginning of line - textNodeWhereOffsetIs = $targetLine.get(0); - offsetInsideTextNode = 0; - } - // avoid errors if provided targetOffsetAtLine is higher than line offset (maxOffset). - // Use max allowed instead - var maxOffset = textNodeWhereOffsetIs.textContent.length; - offsetInsideTextNode = Math.min(offsetInsideTextNode, maxOffset); - - return { - node: textNodeWhereOffsetIs, - offset: offsetInsideTextNode, - }; - } - - /* Ensure console.log doesn't blow up in IE, ugly but ok for a test framework imho*/ - window.console = window.console || {}; - window.console.log = window.console.log || function(){} - - //force usage of callbacks in it - var _it = it; - it = function(name, func){ - if(func && func.length !== 1){ - func = function(){ - throw new Error("Please use always a callback with it() - " + func.toString()); - } - } - - _it(name, func); - } -})() \ No newline at end of file diff --git a/sources/tests/frontend/index.html b/sources/tests/frontend/index.html deleted file mode 100644 index 1bf1049..0000000 --- a/sources/tests/frontend/index.html +++ /dev/null @@ -1,26 +0,0 @@ - - - Frontend tests - - - - -
    -
    -
    - - - - - - - - - - - - - - - - diff --git a/sources/tests/frontend/lib/expect.js b/sources/tests/frontend/lib/expect.js deleted file mode 100644 index ab5a1ee..0000000 --- a/sources/tests/frontend/lib/expect.js +++ /dev/null @@ -1,1247 +0,0 @@ - -(function (global, module) { - - if ('undefined' == typeof module) { - var module = { exports: {} } - , exports = module.exports - } - - /** - * Exports. - */ - - module.exports = expect; - expect.Assertion = Assertion; - - /** - * Exports version. - */ - - expect.version = '0.1.2'; - - /** - * Possible assertion flags. - */ - - var flags = { - not: ['to', 'be', 'have', 'include', 'only'] - , to: ['be', 'have', 'include', 'only', 'not'] - , only: ['have'] - , have: ['own'] - , be: ['an'] - }; - - function expect (obj) { - return new Assertion(obj); - } - - /** - * Constructor - * - * @api private - */ - - function Assertion (obj, flag, parent) { - this.obj = obj; - this.flags = {}; - - if (undefined != parent) { - this.flags[flag] = true; - - for (var i in parent.flags) { - if (parent.flags.hasOwnProperty(i)) { - this.flags[i] = true; - } - } - } - - var $flags = flag ? flags[flag] : keys(flags) - , self = this - - if ($flags) { - for (var i = 0, l = $flags.length; i < l; i++) { - // avoid recursion - if (this.flags[$flags[i]]) continue; - - var name = $flags[i] - , assertion = new Assertion(this.obj, name, this) - - if ('function' == typeof Assertion.prototype[name]) { - // clone the function, make sure we dont touch the prot reference - var old = this[name]; - this[name] = function () { - return old.apply(self, arguments); - } - - for (var fn in Assertion.prototype) { - if (Assertion.prototype.hasOwnProperty(fn) && fn != name) { - this[name][fn] = bind(assertion[fn], assertion); - } - } - } else { - this[name] = assertion; - } - } - } - }; - - /** - * Performs an assertion - * - * @api private - */ - - Assertion.prototype.assert = function (truth, msg, error) { - var msg = this.flags.not ? error : msg - , ok = this.flags.not ? !truth : truth; - - if (!ok) { - throw new Error(msg.call(this)); - } - - this.and = new Assertion(this.obj); - }; - - /** - * Check if the value is truthy - * - * @api public - */ - - Assertion.prototype.ok = function () { - this.assert( - !!this.obj - , function(){ return 'expected ' + i(this.obj) + ' to be truthy' } - , function(){ return 'expected ' + i(this.obj) + ' to be falsy' }); - }; - - /** - * Assert that the function throws. - * - * @param {Function|RegExp} callback, or regexp to match error string against - * @api public - */ - - Assertion.prototype.throwError = - Assertion.prototype.throwException = function (fn) { - expect(this.obj).to.be.a('function'); - - var thrown = false - , not = this.flags.not - - try { - this.obj(); - } catch (e) { - if ('function' == typeof fn) { - fn(e); - } else if ('object' == typeof fn) { - var subject = 'string' == typeof e ? e : e.message; - if (not) { - expect(subject).to.not.match(fn); - } else { - expect(subject).to.match(fn); - } - } - thrown = true; - } - - if ('object' == typeof fn && not) { - // in the presence of a matcher, ensure the `not` only applies to - // the matching. - this.flags.not = false; - } - - var name = this.obj.name || 'fn'; - this.assert( - thrown - , function(){ return 'expected ' + name + ' to throw an exception' } - , function(){ return 'expected ' + name + ' not to throw an exception' }); - }; - - /** - * Checks if the array is empty. - * - * @api public - */ - - Assertion.prototype.empty = function () { - var expectation; - - if ('object' == typeof this.obj && null !== this.obj && !isArray(this.obj)) { - if ('number' == typeof this.obj.length) { - expectation = !this.obj.length; - } else { - expectation = !keys(this.obj).length; - } - } else { - if ('string' != typeof this.obj) { - expect(this.obj).to.be.an('object'); - } - - expect(this.obj).to.have.property('length'); - expectation = !this.obj.length; - } - - this.assert( - expectation - , function(){ return 'expected ' + i(this.obj) + ' to be empty' } - , function(){ return 'expected ' + i(this.obj) + ' to not be empty' }); - return this; - }; - - /** - * Checks if the obj exactly equals another. - * - * @api public - */ - - Assertion.prototype.be = - Assertion.prototype.equal = function (obj) { - this.assert( - obj === this.obj - , function(){ return 'expected ' + i(this.obj) + ' to equal ' + i(obj) } - , function(){ return 'expected ' + i(this.obj) + ' to not equal ' + i(obj) }); - return this; - }; - - /** - * Checks if the obj sortof equals another. - * - * @api public - */ - - Assertion.prototype.eql = function (obj) { - this.assert( - expect.eql(obj, this.obj) - , function(){ return 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj) } - , function(){ return 'expected ' + i(this.obj) + ' to sort of not equal ' + i(obj) }); - return this; - }; - - /** - * Assert within start to finish (inclusive). - * - * @param {Number} start - * @param {Number} finish - * @api public - */ - - Assertion.prototype.within = function (start, finish) { - var range = start + '..' + finish; - this.assert( - this.obj >= start && this.obj <= finish - , function(){ return 'expected ' + i(this.obj) + ' to be within ' + range } - , function(){ return 'expected ' + i(this.obj) + ' to not be within ' + range }); - return this; - }; - - /** - * Assert typeof / instance of - * - * @api public - */ - - Assertion.prototype.a = - Assertion.prototype.an = function (type) { - if ('string' == typeof type) { - // proper english in error msg - var n = /^[aeiou]/.test(type) ? 'n' : ''; - - // typeof with support for 'array' - this.assert( - 'array' == type ? isArray(this.obj) : - 'object' == type - ? 'object' == typeof this.obj && null !== this.obj - : type == typeof this.obj - , function(){ return 'expected ' + i(this.obj) + ' to be a' + n + ' ' + type } - , function(){ return 'expected ' + i(this.obj) + ' not to be a' + n + ' ' + type }); - } else { - // instanceof - var name = type.name || 'supplied constructor'; - this.assert( - this.obj instanceof type - , function(){ return 'expected ' + i(this.obj) + ' to be an instance of ' + name } - , function(){ return 'expected ' + i(this.obj) + ' not to be an instance of ' + name }); - } - - return this; - }; - - /** - * Assert numeric value above _n_. - * - * @param {Number} n - * @api public - */ - - Assertion.prototype.greaterThan = - Assertion.prototype.above = function (n) { - this.assert( - this.obj > n - , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n } - , function(){ return 'expected ' + i(this.obj) + ' to be below ' + n }); - return this; - }; - - /** - * Assert numeric value below _n_. - * - * @param {Number} n - * @api public - */ - - Assertion.prototype.lessThan = - Assertion.prototype.below = function (n) { - this.assert( - this.obj < n - , function(){ return 'expected ' + i(this.obj) + ' to be below ' + n } - , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n }); - return this; - }; - - /** - * Assert string value matches _regexp_. - * - * @param {RegExp} regexp - * @api public - */ - - Assertion.prototype.match = function (regexp) { - this.assert( - regexp.exec(this.obj) - , function(){ return 'expected ' + i(this.obj) + ' to match ' + regexp } - , function(){ return 'expected ' + i(this.obj) + ' not to match ' + regexp }); - return this; - }; - - /** - * Assert property "length" exists and has value of _n_. - * - * @param {Number} n - * @api public - */ - - Assertion.prototype.length = function (n) { - expect(this.obj).to.have.property('length'); - var len = this.obj.length; - this.assert( - n == len - , function(){ return 'expected ' + i(this.obj) + ' to have a length of ' + n + ' but got ' + len } - , function(){ return 'expected ' + i(this.obj) + ' to not have a length of ' + len }); - return this; - }; - - /** - * Assert property _name_ exists, with optional _val_. - * - * @param {String} name - * @param {Mixed} val - * @api public - */ - - Assertion.prototype.property = function (name, val) { - if (this.flags.own) { - this.assert( - Object.prototype.hasOwnProperty.call(this.obj, name) - , function(){ return 'expected ' + i(this.obj) + ' to have own property ' + i(name) } - , function(){ return 'expected ' + i(this.obj) + ' to not have own property ' + i(name) }); - return this; - } - - if (this.flags.not && undefined !== val) { - if (undefined === this.obj[name]) { - throw new Error(i(this.obj) + ' has no property ' + i(name)); - } - } else { - var hasProp; - try { - hasProp = name in this.obj - } catch (e) { - hasProp = undefined !== this.obj[name] - } - - this.assert( - hasProp - , function(){ return 'expected ' + i(this.obj) + ' to have a property ' + i(name) } - , function(){ return 'expected ' + i(this.obj) + ' to not have a property ' + i(name) }); - } - - if (undefined !== val) { - this.assert( - val === this.obj[name] - , function(){ return 'expected ' + i(this.obj) + ' to have a property ' + i(name) - + ' of ' + i(val) + ', but got ' + i(this.obj[name]) } - , function(){ return 'expected ' + i(this.obj) + ' to not have a property ' + i(name) - + ' of ' + i(val) }); - } - - this.obj = this.obj[name]; - return this; - }; - - /** - * Assert that the array contains _obj_ or string contains _obj_. - * - * @param {Mixed} obj|string - * @api public - */ - - Assertion.prototype.string = - Assertion.prototype.contain = function (obj) { - if ('string' == typeof this.obj) { - this.assert( - ~this.obj.indexOf(obj) - , function(){ return 'expected ' + i(this.obj) + ' to contain ' + i(obj) } - , function(){ return 'expected ' + i(this.obj) + ' to not contain ' + i(obj) }); - } else { - this.assert( - ~indexOf(this.obj, obj) - , function(){ return 'expected ' + i(this.obj) + ' to contain ' + i(obj) } - , function(){ return 'expected ' + i(this.obj) + ' to not contain ' + i(obj) }); - } - return this; - }; - - /** - * Assert exact keys or inclusion of keys by using - * the `.own` modifier. - * - * @param {Array|String ...} keys - * @api public - */ - - Assertion.prototype.key = - Assertion.prototype.keys = function ($keys) { - var str - , ok = true; - - $keys = isArray($keys) - ? $keys - : Array.prototype.slice.call(arguments); - - if (!$keys.length) throw new Error('keys required'); - - var actual = keys(this.obj) - , len = $keys.length; - - // Inclusion - ok = every($keys, function (key) { - return ~indexOf(actual, key); - }); - - // Strict - if (!this.flags.not && this.flags.only) { - ok = ok && $keys.length == actual.length; - } - - // Key string - if (len > 1) { - $keys = map($keys, function (key) { - return i(key); - }); - var last = $keys.pop(); - str = $keys.join(', ') + ', and ' + last; - } else { - str = i($keys[0]); - } - - // Form - str = (len > 1 ? 'keys ' : 'key ') + str; - - // Have / include - str = (!this.flags.only ? 'include ' : 'only have ') + str; - - // Assertion - this.assert( - ok - , function(){ return 'expected ' + i(this.obj) + ' to ' + str } - , function(){ return 'expected ' + i(this.obj) + ' to not ' + str }); - - return this; - }; - /** - * Assert a failure. - * - * @param {String ...} custom message - * @api public - */ - Assertion.prototype.fail = function (msg) { - msg = msg || "explicit failure"; - this.assert(false, msg, msg); - return this; - }; - - /** - * Function bind implementation. - */ - - function bind (fn, scope) { - return function () { - return fn.apply(scope, arguments); - } - } - - /** - * Array every compatibility - * - * @see bit.ly/5Fq1N2 - * @api public - */ - - function every (arr, fn, thisObj) { - var scope = thisObj || global; - for (var i = 0, j = arr.length; i < j; ++i) { - if (!fn.call(scope, arr[i], i, arr)) { - return false; - } - } - return true; - }; - - /** - * Array indexOf compatibility. - * - * @see bit.ly/a5Dxa2 - * @api public - */ - - function indexOf (arr, o, i) { - if (Array.prototype.indexOf) { - return Array.prototype.indexOf.call(arr, o, i); - } - - if (arr.length === undefined) { - return -1; - } - - for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0 - ; i < j && arr[i] !== o; i++); - - return j <= i ? -1 : i; - }; - - // https://gist.github.com/1044128/ - var getOuterHTML = function(element) { - if ('outerHTML' in element) return element.outerHTML; - var ns = "http://www.w3.org/1999/xhtml"; - var container = document.createElementNS(ns, '_'); - var elemProto = (window.HTMLElement || window.Element).prototype; - var xmlSerializer = new XMLSerializer(); - var html; - if (document.xmlVersion) { - return xmlSerializer.serializeToString(element); - } else { - container.appendChild(element.cloneNode(false)); - html = container.innerHTML.replace('><', '>' + element.innerHTML + '<'); - container.innerHTML = ''; - return html; - } - }; - - // Returns true if object is a DOM element. - var isDOMElement = function (object) { - if (typeof HTMLElement === 'object') { - return object instanceof HTMLElement; - } else { - return object && - typeof object === 'object' && - object.nodeType === 1 && - typeof object.nodeName === 'string'; - } - }; - - /** - * Inspects an object. - * - * @see taken from node.js `util` module (copyright Joyent, MIT license) - * @api private - */ - - function i (obj, showHidden, depth) { - var seen = []; - - function stylize (str) { - return str; - }; - - function format (value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (value && typeof value.inspect === 'function' && - // Filter out the util module, it's inspect function is special - value !== exports && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - return value.inspect(recurseTimes); - } - - // Primitive types cannot have properties - switch (typeof value) { - case 'undefined': - return stylize('undefined', 'undefined'); - - case 'string': - var simple = '\'' + json.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return stylize(simple, 'string'); - - case 'number': - return stylize('' + value, 'number'); - - case 'boolean': - return stylize('' + value, 'boolean'); - } - // For some reason typeof null is "object", so special case here. - if (value === null) { - return stylize('null', 'null'); - } - - if (isDOMElement(value)) { - return getOuterHTML(value); - } - - // Look up the keys of the object. - var visible_keys = keys(value); - var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys; - - // Functions without properties can be shortcutted. - if (typeof value === 'function' && $keys.length === 0) { - if (isRegExp(value)) { - return stylize('' + value, 'regexp'); - } else { - var name = value.name ? ': ' + value.name : ''; - return stylize('[Function' + name + ']', 'special'); - } - } - - // Dates without properties can be shortcutted - if (isDate(value) && $keys.length === 0) { - return stylize(value.toUTCString(), 'date'); - } - - var base, type, braces; - // Determine the object type - if (isArray(value)) { - type = 'Array'; - braces = ['[', ']']; - } else { - type = 'Object'; - braces = ['{', '}']; - } - - // Make functions say that they are functions - if (typeof value === 'function') { - var n = value.name ? ': ' + value.name : ''; - base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; - } else { - base = ''; - } - - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + value.toUTCString(); - } - - if ($keys.length === 0) { - return braces[0] + base + braces[1]; - } - - if (recurseTimes < 0) { - if (isRegExp(value)) { - return stylize('' + value, 'regexp'); - } else { - return stylize('[Object]', 'special'); - } - } - - seen.push(value); - - var output = map($keys, function (key) { - var name, str; - if (value.__lookupGetter__) { - if (value.__lookupGetter__(key)) { - if (value.__lookupSetter__(key)) { - str = stylize('[Getter/Setter]', 'special'); - } else { - str = stylize('[Getter]', 'special'); - } - } else { - if (value.__lookupSetter__(key)) { - str = stylize('[Setter]', 'special'); - } - } - } - if (indexOf(visible_keys, key) < 0) { - name = '[' + key + ']'; - } - if (!str) { - if (indexOf(seen, value[key]) < 0) { - if (recurseTimes === null) { - str = format(value[key]); - } else { - str = format(value[key], recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (isArray(value)) { - str = map(str.split('\n'), function (line) { - return ' ' + line; - }).join('\n').substr(2); - } else { - str = '\n' + map(str.split('\n'), function (line) { - return ' ' + line; - }).join('\n'); - } - } - } else { - str = stylize('[Circular]', 'special'); - } - } - if (typeof name === 'undefined') { - if (type === 'Array' && key.match(/^\d+$/)) { - return str; - } - name = json.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = stylize(name, 'name'); - } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = stylize(name, 'string'); - } - } - - return name + ': ' + str; - }); - - seen.pop(); - - var numLinesEst = 0; - var length = reduce(output, function (prev, cur) { - numLinesEst++; - if (indexOf(cur, '\n') >= 0) numLinesEst++; - return prev + cur.length + 1; - }, 0); - - if (length > 50) { - output = braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; - - } else { - output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; - } - - return output; - } - return format(obj, (typeof depth === 'undefined' ? 2 : depth)); - }; - - function isArray (ar) { - return Object.prototype.toString.call(ar) == '[object Array]'; - }; - - function isRegExp(re) { - var s = '' + re; - return re instanceof RegExp || // easy case - // duck-type for context-switching evalcx case - typeof(re) === 'function' && - re.constructor.name === 'RegExp' && - re.compile && - re.test && - re.exec && - s.match(/^\/.*\/[gim]{0,3}$/); - }; - - function isDate(d) { - if (d instanceof Date) return true; - return false; - }; - - function keys (obj) { - if (Object.keys) { - return Object.keys(obj); - } - - var keys = []; - - for (var i in obj) { - if (Object.prototype.hasOwnProperty.call(obj, i)) { - keys.push(i); - } - } - - return keys; - } - - function map (arr, mapper, that) { - if (Array.prototype.map) { - return Array.prototype.map.call(arr, mapper, that); - } - - var other= new Array(arr.length); - - for (var i= 0, n = arr.length; i= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - - // if array contains no values, no initial value to return - if (++i >= len) - throw new TypeError(); - } while (true); - } - - for (; i < len; i++) { - if (i in this) - rv = fun.call(null, rv, this[i], i, this); - } - - return rv; - }; - - /** - * Asserts deep equality - * - * @see taken from node.js `assert` module (copyright Joyent, MIT license) - * @api private - */ - - expect.eql = function eql (actual, expected) { - // 7.1. All identical values are equivalent, as determined by ===. - if (actual === expected) { - return true; - } else if ('undefined' != typeof Buffer - && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { - if (actual.length != expected.length) return false; - - for (var i = 0; i < actual.length; i++) { - if (actual[i] !== expected[i]) return false; - } - - return true; - - // 7.2. If the expected value is a Date object, the actual value is - // equivalent if it is also a Date object that refers to the same time. - } else if (actual instanceof Date && expected instanceof Date) { - return actual.getTime() === expected.getTime(); - - // 7.3. Other pairs that do not both pass typeof value == "object", - // equivalence is determined by ==. - } else if (typeof actual != 'object' && typeof expected != 'object') { - return actual == expected; - - // 7.4. For all other Object pairs, including Array objects, equivalence is - // determined by having the same number of owned properties (as verified - // with Object.prototype.hasOwnProperty.call), the same set of keys - // (although not necessarily the same order), equivalent values for every - // corresponding key, and an identical "prototype" property. Note: this - // accounts for both named and indexed properties on Arrays. - } else { - return objEquiv(actual, expected); - } - } - - function isUndefinedOrNull (value) { - return value === null || value === undefined; - } - - function isArguments (object) { - return Object.prototype.toString.call(object) == '[object Arguments]'; - } - - function objEquiv (a, b) { - if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) - return false; - // an identical "prototype" property. - if (a.prototype !== b.prototype) return false; - //~~~I've managed to break Object.keys through screwy arguments passing. - // Converting to array solves the problem. - if (isArguments(a)) { - if (!isArguments(b)) { - return false; - } - a = pSlice.call(a); - b = pSlice.call(b); - return expect.eql(a, b); - } - try{ - var ka = keys(a), - kb = keys(b), - key, i; - } catch (e) {//happens when one is a string literal and the other isn't - return false; - } - // having the same number of owned properties (keys incorporates hasOwnProperty) - if (ka.length != kb.length) - return false; - //the same set of keys (although not necessarily the same order), - ka.sort(); - kb.sort(); - //~~~cheap key test - for (i = ka.length - 1; i >= 0; i--) { - if (ka[i] != kb[i]) - return false; - } - //equivalent values for every corresponding key, and - //~~~possibly expensive deep test - for (i = ka.length - 1; i >= 0; i--) { - key = ka[i]; - if (!expect.eql(a[key], b[key])) - return false; - } - return true; - } - - var json = (function () { - "use strict"; - - if ('object' == typeof JSON && JSON.parse && JSON.stringify) { - return { - parse: nativeJSON.parse - , stringify: nativeJSON.stringify - } - } - - var JSON = {}; - - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - function date(d, key) { - return isFinite(d.valueOf()) ? - d.getUTCFullYear() + '-' + - f(d.getUTCMonth() + 1) + '-' + - f(d.getUTCDate()) + 'T' + - f(d.getUTCHours()) + ':' + - f(d.getUTCMinutes()) + ':' + - f(d.getUTCSeconds()) + 'Z' : null; - }; - - var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - gap, - indent, - meta = { // table of character substitutions - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '\\': '\\\\' - }, - rep; - - - function quote(string) { - - // If the string contains no control characters, no quote characters, and no - // backslash characters, then we can safely slap some quotes around it. - // Otherwise we must also replace the offending characters with safe escape - // sequences. - - escapable.lastIndex = 0; - return escapable.test(string) ? '"' + string.replace(escapable, function (a) { - var c = meta[a]; - return typeof c === 'string' ? c : - '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }) + '"' : '"' + string + '"'; - } - - - function str(key, holder) { - - // Produce a string from holder[key]. - - var i, // The loop counter. - k, // The member key. - v, // The member value. - length, - mind = gap, - partial, - value = holder[key]; - - // If the value has a toJSON method, call it to obtain a replacement value. - - if (value instanceof Date) { - value = date(key); - } - - // If we were called with a replacer function, then call the replacer to - // obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - - // What happens next depends on the value's type. - - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - - // JSON numbers must be finite. Encode non-finite numbers as null. - - return isFinite(value) ? String(value) : 'null'; - - case 'boolean': - case 'null': - - // If the value is a boolean or null, convert it to a string. Note: - // typeof null does not produce 'null'. The case is included here in - // the remote chance that this gets fixed someday. - - return String(value); - - // If the type is 'object', we might be dealing with an object or an array or - // null. - - case 'object': - - // Due to a specification blunder in ECMAScript, typeof null is 'object', - // so watch out for that case. - - if (!value) { - return 'null'; - } - - // Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - - // Is the value an array? - - if (Object.prototype.toString.apply(value) === '[object Array]') { - - // The value is an array. Stringify every element. Use null as a placeholder - // for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - - // Join all of the elements together, separated with commas, and wrap them in - // brackets. - - v = partial.length === 0 ? '[]' : gap ? - '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : - '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - - // If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - if (typeof rep[i] === 'string') { - k = rep[i]; - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } else { - - // Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } - - // Join all of the member texts together, separated with commas, - // and wrap them in braces. - - v = partial.length === 0 ? '{}' : gap ? - '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : - '{' + partial.join(',') + '}'; - gap = mind; - return v; - } - } - - // If the JSON object does not yet have a stringify method, give it one. - - JSON.stringify = function (value, replacer, space) { - - // The stringify method takes a value and an optional replacer, and an optional - // space parameter, and returns a JSON text. The replacer can be a function - // that can replace values, or an array of strings that will select the keys. - // A default replacer method can be provided. Use of the space parameter can - // produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - - // If the space parameter is a number, make an indent string containing that - // many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - - // If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - - // If there is a replacer, it must be a function or an array. - // Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - - // Make a fake root object containing our value under the key of ''. - // Return the result of stringifying the value. - - return str('', {'': value}); - }; - - // If the JSON object does not yet have a parse method, give it one. - - JSON.parse = function (text, reviver) { - // The parse method takes a text and an optional reviver function, and returns - // a JavaScript value if the text is a valid JSON text. - - var j; - - function walk(holder, key) { - - // The walk method is used to recursively walk the resulting structure so - // that modifications can be made. - - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.prototype.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } - - - // Parsing happens in four stages. In the first stage, we replace certain - // Unicode characters with escape sequences. JavaScript handles many characters - // incorrectly, either silently deleting them, or treating them as line endings. - - text = String(text); - cx.lastIndex = 0; - if (cx.test(text)) { - text = text.replace(cx, function (a) { - return '\\u' + - ('0000' + a.charCodeAt(0).toString(16)).slice(-4); - }); - } - - // In the second stage, we run the text against regular expressions that look - // for non-JSON patterns. We are especially concerned with '()' and 'new' - // because they can cause invocation, and '=' because it can cause mutation. - // But just to be safe, we want to reject all unexpected forms. - - // We split the second stage into 4 regexp operations in order to work around - // crippling inefficiencies in IE's and Safari's regexp engines. First we - // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we - // replace all simple value tokens with ']' characters. Third, we delete all - // open brackets that follow a colon or comma or that begin the text. Finally, - // we look to see that the remaining characters are only whitespace or ']' or - // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. - - if (/^[\],:{}\s]*$/ - .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') - .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') - .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { - - // In the third stage we use the eval function to compile the text into a - // JavaScript structure. The '{' operator is subject to a syntactic ambiguity - // in JavaScript: it can begin a block or an object literal. We wrap the text - // in parens to eliminate the ambiguity. - - j = eval('(' + text + ')'); - - // In the optional fourth stage, we recursively walk the new structure, passing - // each name/value pair to a reviver function for possible transformation. - - return typeof reviver === 'function' ? - walk({'': j}, '') : j; - } - - // If the text is not JSON parseable, then a SyntaxError is thrown. - - throw new SyntaxError('JSON.parse'); - }; - - return JSON; - })(); - - if ('undefined' != typeof window) { - window.expect = module.exports; - } - -})( - this - , 'undefined' != typeof module ? module : {} - , 'undefined' != typeof exports ? exports : {} -); diff --git a/sources/tests/frontend/lib/jquery.iframe.js b/sources/tests/frontend/lib/jquery.iframe.js deleted file mode 100644 index 604ae1b..0000000 --- a/sources/tests/frontend/lib/jquery.iframe.js +++ /dev/null @@ -1,40 +0,0 @@ -//copied from http://stackoverflow.com/questions/8407946/is-it-possible-to-use-iframes-in-ie-without-memory-leaks -(function($) { - $.fn.purgeFrame = function() { - var deferred; - var browser = bowser; - - if (browser.msie && parseFloat(browser.version, 10) < 9) { - deferred = purge(this); - } else { - this.remove(); - deferred = $.Deferred(); - deferred.resolve(); - } - - return deferred; - }; - - function purge($frame) { - var sem = $frame.length - , deferred = $.Deferred(); - - $frame.load(function() { - var frame = this; - frame.contentWindow.document.innerHTML = ''; - - sem -= 1; - if (sem <= 0) { - $frame.remove(); - deferred.resolve(); - } - }); - $frame.attr('src', 'about:blank'); - - if ($frame.length === 0) { - deferred.resolve(); - } - - return deferred.promise(); - } -})(jQuery); diff --git a/sources/tests/frontend/lib/mocha.js b/sources/tests/frontend/lib/mocha.js deleted file mode 100644 index 5f2da01..0000000 --- a/sources/tests/frontend/lib/mocha.js +++ /dev/null @@ -1,4868 +0,0 @@ -;(function(){ - - -// CommonJS require() - -function require(p){ - var path = require.resolve(p) - , mod = require.modules[path]; - if (!mod) throw new Error('failed to require "' + p + '"'); - if (!mod.exports) { - mod.exports = {}; - mod.call(mod.exports, mod, mod.exports, require.relative(path)); - } - return mod.exports; - } - -require.modules = {}; - -require.resolve = function (path){ - var orig = path - , reg = path + '.js' - , index = path + '/index.js'; - return require.modules[reg] && reg - || require.modules[index] && index - || orig; - }; - -require.register = function (path, fn){ - require.modules[path] = fn; - }; - -require.relative = function (parent) { - return function(p){ - if ('.' != p.charAt(0)) return require(p); - - var path = parent.split('/') - , segs = p.split('/'); - path.pop(); - - for (var i = 0; i < segs.length; i++) { - var seg = segs[i]; - if ('..' == seg) path.pop(); - else if ('.' != seg) path.push(seg); - } - - return require(path.join('/')); - }; - }; - - -require.register("browser/debug.js", function(module, exports, require){ - -module.exports = function(type){ - return function(){ - - } -}; -}); // module: browser/debug.js - -require.register("browser/diff.js", function(module, exports, require){ - -}); // module: browser/diff.js - -require.register("browser/events.js", function(module, exports, require){ - -/** - * Module exports. - */ - -exports.EventEmitter = EventEmitter; - -/** - * Check if `obj` is an array. - */ - -function isArray(obj) { - return '[object Array]' == {}.toString.call(obj); -} - -/** - * Event emitter constructor. - * - * @api public - */ - -function EventEmitter(){}; - -/** - * Adds a listener. - * - * @api public - */ - -EventEmitter.prototype.on = function (name, fn) { - if (!this.$events) { - this.$events = {}; - } - - if (!this.$events[name]) { - this.$events[name] = fn; - } else if (isArray(this.$events[name])) { - this.$events[name].push(fn); - } else { - this.$events[name] = [this.$events[name], fn]; - } - - return this; -}; - -EventEmitter.prototype.addListener = EventEmitter.prototype.on; - -/** - * Adds a volatile listener. - * - * @api public - */ - -EventEmitter.prototype.once = function (name, fn) { - var self = this; - - function on () { - self.removeListener(name, on); - fn.apply(this, arguments); - }; - - on.listener = fn; - this.on(name, on); - - return this; -}; - -/** - * Removes a listener. - * - * @api public - */ - -EventEmitter.prototype.removeListener = function (name, fn) { - if (this.$events && this.$events[name]) { - var list = this.$events[name]; - - if (isArray(list)) { - var pos = -1; - - for (var i = 0, l = list.length; i < l; i++) { - if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { - pos = i; - break; - } - } - - if (pos < 0) { - return this; - } - - list.splice(pos, 1); - - if (!list.length) { - delete this.$events[name]; - } - } else if (list === fn || (list.listener && list.listener === fn)) { - delete this.$events[name]; - } - } - - return this; -}; - -/** - * Removes all listeners for an event. - * - * @api public - */ - -EventEmitter.prototype.removeAllListeners = function (name) { - if (name === undefined) { - this.$events = {}; - return this; - } - - if (this.$events && this.$events[name]) { - this.$events[name] = null; - } - - return this; -}; - -/** - * Gets all listeners for a certain event. - * - * @api public - */ - -EventEmitter.prototype.listeners = function (name) { - if (!this.$events) { - this.$events = {}; - } - - if (!this.$events[name]) { - this.$events[name] = []; - } - - if (!isArray(this.$events[name])) { - this.$events[name] = [this.$events[name]]; - } - - return this.$events[name]; -}; - -/** - * Emits an event. - * - * @api public - */ - -EventEmitter.prototype.emit = function (name) { - if (!this.$events) { - return false; - } - - var handler = this.$events[name]; - - if (!handler) { - return false; - } - - var args = [].slice.call(arguments, 1); - - if ('function' == typeof handler) { - handler.apply(this, args); - } else if (isArray(handler)) { - var listeners = handler.slice(); - - for (var i = 0, l = listeners.length; i < l; i++) { - listeners[i].apply(this, args); - } - } else { - return false; - } - - return true; -}; -}); // module: browser/events.js - -require.register("browser/fs.js", function(module, exports, require){ - -}); // module: browser/fs.js - -require.register("browser/path.js", function(module, exports, require){ - -}); // module: browser/path.js - -require.register("browser/progress.js", function(module, exports, require){ - -/** - * Expose `Progress`. - */ - -module.exports = Progress; - -/** - * Initialize a new `Progress` indicator. - */ - -function Progress() { - this.percent = 0; - this.size(0); - this.fontSize(11); - this.font('helvetica, arial, sans-serif'); -} - -/** - * Set progress size to `n`. - * - * @param {Number} n - * @return {Progress} for chaining - * @api public - */ - -Progress.prototype.size = function(n){ - this._size = n; - return this; -}; - -/** - * Set text to `str`. - * - * @param {String} str - * @return {Progress} for chaining - * @api public - */ - -Progress.prototype.text = function(str){ - this._text = str; - return this; -}; - -/** - * Set font size to `n`. - * - * @param {Number} n - * @return {Progress} for chaining - * @api public - */ - -Progress.prototype.fontSize = function(n){ - this._fontSize = n; - return this; -}; - -/** - * Set font `family`. - * - * @param {String} family - * @return {Progress} for chaining - */ - -Progress.prototype.font = function(family){ - this._font = family; - return this; -}; - -/** - * Update percentage to `n`. - * - * @param {Number} n - * @return {Progress} for chaining - */ - -Progress.prototype.update = function(n){ - this.percent = n; - return this; -}; - -/** - * Draw on `ctx`. - * - * @param {CanvasRenderingContext2d} ctx - * @return {Progress} for chaining - */ - -Progress.prototype.draw = function(ctx){ - var percent = Math.min(this.percent, 100) - , size = this._size - , half = size / 2 - , x = half - , y = half - , rad = half - 1 - , fontSize = this._fontSize; - - ctx.font = fontSize + 'px ' + this._font; - - var angle = Math.PI * 2 * (percent / 100); - ctx.clearRect(0, 0, size, size); - - // outer circle - ctx.strokeStyle = '#9f9f9f'; - ctx.beginPath(); - ctx.arc(x, y, rad, 0, angle, false); - ctx.stroke(); - - // inner circle - ctx.strokeStyle = '#eee'; - ctx.beginPath(); - ctx.arc(x, y, rad - 1, 0, angle, true); - ctx.stroke(); - - // text - var text = this._text || (percent | 0) + '%' - , w = ctx.measureText(text).width; - - ctx.fillText( - text - , x - w / 2 + 1 - , y + fontSize / 2 - 1); - - return this; -}; - -}); // module: browser/progress.js - -require.register("browser/tty.js", function(module, exports, require){ - -exports.isatty = function(){ - return true; -}; - -exports.getWindowSize = function(){ - return [window.innerHeight, window.innerWidth]; -}; -}); // module: browser/tty.js - -require.register("context.js", function(module, exports, require){ - -/** - * Expose `Context`. - */ - -module.exports = Context; - -/** - * Initialize a new `Context`. - * - * @api private - */ - -function Context(){} - -/** - * Set or get the context `Runnable` to `runnable`. - * - * @param {Runnable} runnable - * @return {Context} - * @api private - */ - -Context.prototype.runnable = function(runnable){ - if (0 == arguments.length) return this._runnable; - this.test = this._runnable = runnable; - return this; -}; - -/** - * Set test timeout `ms`. - * - * @param {Number} ms - * @return {Context} self - * @api private - */ - -Context.prototype.timeout = function(ms){ - this.runnable().timeout(ms); - return this; -}; - -/** - * Set test slowness threshold `ms`. - * - * @param {Number} ms - * @return {Context} self - * @api private - */ - -Context.prototype.slow = function(ms){ - this.runnable().slow(ms); - return this; -}; - -/** - * Inspect the context void of `._runnable`. - * - * @return {String} - * @api private - */ - -Context.prototype.inspect = function(){ - return JSON.stringify(this, function(key, val){ - if ('_runnable' == key) return; - if ('test' == key) return; - return val; - }, 2); -}; - -}); // module: context.js - -require.register("hook.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Runnable = require('./runnable'); - -/** - * Expose `Hook`. - */ - -module.exports = Hook; - -/** - * Initialize a new `Hook` with the given `title` and callback `fn`. - * - * @param {String} title - * @param {Function} fn - * @api private - */ - -function Hook(title, fn) { - Runnable.call(this, title, fn); - this.type = 'hook'; -} - -/** - * Inherit from `Runnable.prototype`. - */ - -Hook.prototype = new Runnable; -Hook.prototype.constructor = Hook; - - -/** - * Get or set the test `err`. - * - * @param {Error} err - * @return {Error} - * @api public - */ - -Hook.prototype.error = function(err){ - if (0 == arguments.length) { - var err = this._error; - this._error = null; - return err; - } - - this._error = err; -}; - - -}); // module: hook.js - -require.register("interfaces/bdd.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Suite = require('../suite') - , Test = require('../test'); - -/** - * BDD-style interface: - * - * describe('Array', function(){ - * describe('#indexOf()', function(){ - * it('should return -1 when not present', function(){ - * - * }); - * - * it('should return the index when present', function(){ - * - * }); - * }); - * }); - * - */ - -module.exports = function(suite){ - var suites = [suite]; - - suite.on('pre-require', function(context, file, mocha){ - - /** - * Execute before running tests. - */ - - context.before = function(fn){ - suites[0].beforeAll(fn); - }; - - /** - * Execute after running tests. - */ - - context.after = function(fn){ - suites[0].afterAll(fn); - }; - - /** - * Execute before each test case. - */ - - context.beforeEach = function(fn){ - suites[0].beforeEach(fn); - }; - - /** - * Execute after each test case. - */ - - context.afterEach = function(fn){ - suites[0].afterEach(fn); - }; - - /** - * Describe a "suite" with the given `title` - * and callback `fn` containing nested suites - * and/or tests. - */ - - context.describe = context.context = function(title, fn){ - var suite = Suite.create(suites[0], title); - suites.unshift(suite); - fn(); - suites.shift(); - return suite; - }; - - /** - * Pending describe. - */ - - context.xdescribe = - context.xcontext = - context.describe.skip = function(title, fn){ - var suite = Suite.create(suites[0], title); - suite.pending = true; - suites.unshift(suite); - fn(); - suites.shift(); - }; - - /** - * Exclusive suite. - */ - - context.describe.only = function(title, fn){ - var suite = context.describe(title, fn); - mocha.grep(suite.fullTitle()); - }; - - /** - * Describe a specification or test-case - * with the given `title` and callback `fn` - * acting as a thunk. - */ - - context.it = context.specify = function(title, fn){ - var suite = suites[0]; - if (suite.pending) var fn = null; - var test = new Test(title, fn); - suite.addTest(test); - return test; - }; - - /** - * Exclusive test-case. - */ - - context.it.only = function(title, fn){ - var test = context.it(title, fn); - mocha.grep(test.fullTitle()); - }; - - /** - * Pending test case. - */ - - context.xit = - context.xspecify = - context.it.skip = function(title){ - context.it(title); - }; - }); -}; - -}); // module: interfaces/bdd.js - -require.register("interfaces/exports.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Suite = require('../suite') - , Test = require('../test'); - -/** - * TDD-style interface: - * - * exports.Array = { - * '#indexOf()': { - * 'should return -1 when the value is not present': function(){ - * - * }, - * - * 'should return the correct index when the value is present': function(){ - * - * } - * } - * }; - * - */ - -module.exports = function(suite){ - var suites = [suite]; - - suite.on('require', visit); - - function visit(obj) { - var suite; - for (var key in obj) { - if ('function' == typeof obj[key]) { - var fn = obj[key]; - switch (key) { - case 'before': - suites[0].beforeAll(fn); - break; - case 'after': - suites[0].afterAll(fn); - break; - case 'beforeEach': - suites[0].beforeEach(fn); - break; - case 'afterEach': - suites[0].afterEach(fn); - break; - default: - suites[0].addTest(new Test(key, fn)); - } - } else { - var suite = Suite.create(suites[0], key); - suites.unshift(suite); - visit(obj[key]); - suites.shift(); - } - } - } -}; -}); // module: interfaces/exports.js - -require.register("interfaces/index.js", function(module, exports, require){ - -exports.bdd = require('./bdd'); -exports.tdd = require('./tdd'); -exports.qunit = require('./qunit'); -exports.exports = require('./exports'); - -}); // module: interfaces/index.js - -require.register("interfaces/qunit.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Suite = require('../suite') - , Test = require('../test'); - -/** - * QUnit-style interface: - * - * suite('Array'); - * - * test('#length', function(){ - * var arr = [1,2,3]; - * ok(arr.length == 3); - * }); - * - * test('#indexOf()', function(){ - * var arr = [1,2,3]; - * ok(arr.indexOf(1) == 0); - * ok(arr.indexOf(2) == 1); - * ok(arr.indexOf(3) == 2); - * }); - * - * suite('String'); - * - * test('#length', function(){ - * ok('foo'.length == 3); - * }); - * - */ - -module.exports = function(suite){ - var suites = [suite]; - - suite.on('pre-require', function(context){ - - /** - * Execute before running tests. - */ - - context.before = function(fn){ - suites[0].beforeAll(fn); - }; - - /** - * Execute after running tests. - */ - - context.after = function(fn){ - suites[0].afterAll(fn); - }; - - /** - * Execute before each test case. - */ - - context.beforeEach = function(fn){ - suites[0].beforeEach(fn); - }; - - /** - * Execute after each test case. - */ - - context.afterEach = function(fn){ - suites[0].afterEach(fn); - }; - - /** - * Describe a "suite" with the given `title`. - */ - - context.suite = function(title){ - if (suites.length > 1) suites.shift(); - var suite = Suite.create(suites[0], title); - suites.unshift(suite); - }; - - /** - * Describe a specification or test-case - * with the given `title` and callback `fn` - * acting as a thunk. - */ - - context.test = function(title, fn){ - suites[0].addTest(new Test(title, fn)); - }; - }); -}; - -}); // module: interfaces/qunit.js - -require.register("interfaces/tdd.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Suite = require('../suite') - , Test = require('../test'); - -/** - * TDD-style interface: - * - * suite('Array', function(){ - * suite('#indexOf()', function(){ - * suiteSetup(function(){ - * - * }); - * - * test('should return -1 when not present', function(){ - * - * }); - * - * test('should return the index when present', function(){ - * - * }); - * - * suiteTeardown(function(){ - * - * }); - * }); - * }); - * - */ - -module.exports = function(suite){ - var suites = [suite]; - - suite.on('pre-require', function(context, file, mocha){ - - /** - * Execute before each test case. - */ - - context.setup = function(fn){ - suites[0].beforeEach(fn); - }; - - /** - * Execute after each test case. - */ - - context.teardown = function(fn){ - suites[0].afterEach(fn); - }; - - /** - * Execute before the suite. - */ - - context.suiteSetup = function(fn){ - suites[0].beforeAll(fn); - }; - - /** - * Execute after the suite. - */ - - context.suiteTeardown = function(fn){ - suites[0].afterAll(fn); - }; - - /** - * Describe a "suite" with the given `title` - * and callback `fn` containing nested suites - * and/or tests. - */ - - context.suite = function(title, fn){ - var suite = Suite.create(suites[0], title); - suites.unshift(suite); - fn(); - suites.shift(); - return suite; - }; - - /** - * Exclusive test-case. - */ - - context.suite.only = function(title, fn){ - var suite = context.suite(title, fn); - mocha.grep(suite.fullTitle()); - }; - - /** - * Describe a specification or test-case - * with the given `title` and callback `fn` - * acting as a thunk. - */ - - context.test = function(title, fn){ - var test = new Test(title, fn); - suites[0].addTest(test); - return test; - }; - - /** - * Exclusive test-case. - */ - - context.test.only = function(title, fn){ - var test = context.test(title, fn); - mocha.grep(test.fullTitle()); - }; - }); -}; - -}); // module: interfaces/tdd.js - -require.register("mocha.js", function(module, exports, require){ -/*! - * mocha - * Copyright(c) 2011 TJ Holowaychuk - * MIT Licensed - */ - -/** - * Module dependencies. - */ - -var path = require('browser/path') - , utils = require('./utils'); - -/** - * Expose `Mocha`. - */ - -exports = module.exports = Mocha; - -/** - * Expose internals. - */ - -exports.utils = utils; -exports.interfaces = require('./interfaces'); -exports.reporters = require('./reporters'); -exports.Runnable = require('./runnable'); -exports.Context = require('./context'); -exports.Runner = require('./runner'); -exports.Suite = require('./suite'); -exports.Hook = require('./hook'); -exports.Test = require('./test'); - -/** - * Return image `name` path. - * - * @param {String} name - * @return {String} - * @api private - */ - -function image(name) { - return __dirname + '/../images/' + name + '.png'; -} - -/** - * Setup mocha with `options`. - * - * Options: - * - * - `ui` name "bdd", "tdd", "exports" etc - * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` - * - `globals` array of accepted globals - * - `timeout` timeout in milliseconds - * - `slow` milliseconds to wait before considering a test slow - * - `ignoreLeaks` ignore global leaks - * - `grep` string or regexp to filter tests with - * - * @param {Object} options - * @api public - */ - -function Mocha(options) { - options = options || {}; - this.files = []; - this.options = options; - this.grep(options.grep); - this.suite = new exports.Suite('', new exports.Context); - this.ui(options.ui); - this.reporter(options.reporter); - if (options.timeout) this.timeout(options.timeout); - if (options.slow) this.slow(options.slow); -} - -/** - * Add test `file`. - * - * @param {String} file - * @api public - */ - -Mocha.prototype.addFile = function(file){ - this.files.push(file); - return this; -}; - -/** - * Set reporter to `reporter`, defaults to "dot". - * - * @param {String|Function} reporter name of a reporter or a reporter constructor - * @api public - */ - -Mocha.prototype.reporter = function(reporter){ - if ('function' == typeof reporter) { - this._reporter = reporter; - } else { - reporter = reporter || 'dot'; - try { - this._reporter = require('./reporters/' + reporter); - } catch (err) { - this._reporter = require(reporter); - } - if (!this._reporter) throw new Error('invalid reporter "' + reporter + '"'); - } - return this; -}; - -/** - * Set test UI `name`, defaults to "bdd". - * - * @param {String} bdd - * @api public - */ - -Mocha.prototype.ui = function(name){ - name = name || 'bdd'; - this._ui = exports.interfaces[name]; - if (!this._ui) throw new Error('invalid interface "' + name + '"'); - this._ui = this._ui(this.suite); - return this; -}; - -/** - * Load registered files. - * - * @api private - */ - -Mocha.prototype.loadFiles = function(fn){ - var self = this; - var suite = this.suite; - var pending = this.files.length; - this.files.forEach(function(file){ - file = path.resolve(file); - suite.emit('pre-require', global, file, self); - suite.emit('require', require(file), file, self); - suite.emit('post-require', global, file, self); - --pending || (fn && fn()); - }); -}; - -/** - * Enable growl support. - * - * @api private - */ - -Mocha.prototype._growl = function(runner, reporter) { - var notify = require('growl'); - - runner.on('end', function(){ - var stats = reporter.stats; - if (stats.failures) { - var msg = stats.failures + ' of ' + runner.total + ' tests failed'; - notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); - } else { - notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { - name: 'mocha' - , title: 'Passed' - , image: image('ok') - }); - } - }); -}; - -/** - * Add regexp to grep, if `re` is a string it is escaped. - * - * @param {RegExp|String} re - * @return {Mocha} - * @api public - */ - -Mocha.prototype.grep = function(re){ - this.options.grep = 'string' == typeof re - ? new RegExp(utils.escapeRegexp(re)) - : re; - return this; -}; - -/** - * Invert `.grep()` matches. - * - * @return {Mocha} - * @api public - */ - -Mocha.prototype.invert = function(){ - this.options.invert = true; - return this; -}; - -/** - * Ignore global leaks. - * - * @return {Mocha} - * @api public - */ - -Mocha.prototype.ignoreLeaks = function(){ - this.options.ignoreLeaks = true; - return this; -}; - -/** - * Enable global leak checking. - * - * @return {Mocha} - * @api public - */ - -Mocha.prototype.checkLeaks = function(){ - this.options.ignoreLeaks = false; - return this; -}; - -/** - * Enable growl support. - * - * @return {Mocha} - * @api public - */ - -Mocha.prototype.growl = function(){ - this.options.growl = true; - return this; -}; - -/** - * Ignore `globals` array or string. - * - * @param {Array|String} globals - * @return {Mocha} - * @api public - */ - -Mocha.prototype.globals = function(globals){ - this.options.globals = (this.options.globals || []).concat(globals); - return this; -}; - -/** - * Set the timeout in milliseconds. - * - * @param {Number} timeout - * @return {Mocha} - * @api public - */ - -Mocha.prototype.timeout = function(timeout){ - this.suite.timeout(timeout); - return this; -}; - -/** - * Set slowness threshold in milliseconds. - * - * @param {Number} slow - * @return {Mocha} - * @api public - */ - -Mocha.prototype.slow = function(slow){ - this.suite.slow(slow); - return this; -}; - -/** - * Run tests and invoke `fn()` when complete. - * - * @param {Function} fn - * @return {Runner} - * @api public - */ - -Mocha.prototype.run = function(fn){ - if (this.files.length) this.loadFiles(); - var suite = this.suite; - var options = this.options; - var runner = new exports.Runner(suite); - var reporter = new this._reporter(runner); - runner.ignoreLeaks = options.ignoreLeaks; - if (options.grep) runner.grep(options.grep, options.invert); - if (options.globals) runner.globals(options.globals); - if (options.growl) this._growl(runner, reporter); - return runner.run(fn); -}; - -}); // module: mocha.js - -require.register("ms.js", function(module, exports, require){ - -/** - * Helpers. - */ - -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; - -/** - * Parse or format the given `val`. - * - * @param {String|Number} val - * @return {String|Number} - * @api public - */ - -module.exports = function(val){ - if ('string' == typeof val) return parse(val); - return format(val); -} - -/** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - -function parse(str) { - var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); - if (!m) return; - var n = parseFloat(m[1]); - var type = (m[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'y': - return n * 31557600000; - case 'days': - case 'day': - case 'd': - return n * 86400000; - case 'hours': - case 'hour': - case 'h': - return n * 3600000; - case 'minutes': - case 'minute': - case 'm': - return n * 60000; - case 'seconds': - case 'second': - case 's': - return n * 1000; - case 'ms': - return n; - } -} - -/** - * Format the given `ms`. - * - * @param {Number} ms - * @return {String} - * @api public - */ - -function format(ms) { - if (ms == d) return (ms / d) + ' day'; - if (ms > d) return (ms / d) + ' days'; - if (ms == h) return (ms / h) + ' hour'; - if (ms > h) return (ms / h) + ' hours'; - if (ms == m) return (ms / m) + ' minute'; - if (ms > m) return (ms / m) + ' minutes'; - if (ms == s) return (ms / s) + ' second'; - if (ms > s) return (ms / s) + ' seconds'; - return ms + ' ms'; -} -}); // module: ms.js - -require.register("reporters/base.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var tty = require('browser/tty') - , diff = require('browser/diff') - , ms = require('../ms'); - -/** - * Save timer references to avoid Sinon interfering (see GH-237). - */ - -var Date = global.Date - , setTimeout = global.setTimeout - , setInterval = global.setInterval - , clearTimeout = global.clearTimeout - , clearInterval = global.clearInterval; - -/** - * Check if both stdio streams are associated with a tty. - */ - -var isatty = tty.isatty(1) && tty.isatty(2); - -/** - * Expose `Base`. - */ - -exports = module.exports = Base; - -/** - * Enable coloring by default. - */ - -exports.useColors = isatty; - -/** - * Default color map. - */ - -exports.colors = { - 'pass': 90 - , 'fail': 31 - , 'bright pass': 92 - , 'bright fail': 91 - , 'bright yellow': 93 - , 'pending': 36 - , 'suite': 0 - , 'error title': 0 - , 'error message': 31 - , 'error stack': 90 - , 'checkmark': 32 - , 'fast': 90 - , 'medium': 33 - , 'slow': 31 - , 'green': 32 - , 'light': 90 - , 'diff gutter': 90 - , 'diff added': 42 - , 'diff removed': 41 -}; - -/** - * Color `str` with the given `type`, - * allowing colors to be disabled, - * as well as user-defined color - * schemes. - * - * @param {String} type - * @param {String} str - * @return {String} - * @api private - */ - -var color = exports.color = function(type, str) { - if (!exports.useColors) return str; - return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; -}; - -/** - * Expose term window size, with some - * defaults for when stderr is not a tty. - */ - -exports.window = { - width: isatty - ? process.stdout.getWindowSize - ? process.stdout.getWindowSize(1)[0] - : tty.getWindowSize()[1] - : 75 -}; - -/** - * Expose some basic cursor interactions - * that are common among reporters. - */ - -exports.cursor = { - hide: function(){ - process.stdout.write('\u001b[?25l'); - }, - - show: function(){ - process.stdout.write('\u001b[?25h'); - }, - - deleteLine: function(){ - process.stdout.write('\u001b[2K'); - }, - - beginningOfLine: function(){ - process.stdout.write('\u001b[0G'); - }, - - CR: function(){ - exports.cursor.deleteLine(); - exports.cursor.beginningOfLine(); - } -}; - -/** - * Outut the given `failures` as a list. - * - * @param {Array} failures - * @api public - */ - -exports.list = function(failures){ - console.error(); - failures.forEach(function(test, i){ - // format - var fmt = color('error title', ' %s) %s:\n') - + color('error message', ' %s') - + color('error stack', '\n%s\n'); - - // msg - var err = test.err - , message = err.message || '' - , stack = err.stack || message - , index = stack.indexOf(message) + message.length - , msg = stack.slice(0, index) - , actual = err.actual - , expected = err.expected; - - // actual / expected diff - if ('string' == typeof actual && 'string' == typeof expected) { - var len = Math.max(actual.length, expected.length); - - if (len < 20) msg = errorDiff(err, 'Chars'); - else msg = errorDiff(err, 'Words'); - - // linenos - var lines = msg.split('\n'); - if (lines.length > 4) { - var width = String(lines.length).length; - msg = lines.map(function(str, i){ - return pad(++i, width) + ' |' + ' ' + str; - }).join('\n'); - } - - // legend - msg = '\n' - + color('diff removed', 'actual') - + ' ' - + color('diff added', 'expected') - + '\n\n' - + msg - + '\n'; - - // indent - msg = msg.replace(/^/gm, ' '); - - fmt = color('error title', ' %s) %s:\n%s') - + color('error stack', '\n%s\n'); - } - - // indent stack trace without msg - stack = stack.slice(index ? index + 1 : index) - .replace(/^/gm, ' '); - - console.error(fmt, (i + 1), test.fullTitle(), msg, stack); - }); -}; - -/** - * Initialize a new `Base` reporter. - * - * All other reporters generally - * inherit from this reporter, providing - * stats such as test duration, number - * of tests passed / failed etc. - * - * @param {Runner} runner - * @api public - */ - -function Base(runner) { - var self = this - , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } - , failures = this.failures = []; - - if (!runner) return; - this.runner = runner; - - runner.on('start', function(){ - stats.start = new Date; - }); - - runner.on('suite', function(suite){ - stats.suites = stats.suites || 0; - suite.root || stats.suites++; - }); - - runner.on('test end', function(test){ - stats.tests = stats.tests || 0; - stats.tests++; - }); - - runner.on('pass', function(test){ - stats.passes = stats.passes || 0; - - var medium = test.slow() / 2; - test.speed = test.duration > test.slow() - ? 'slow' - : test.duration > medium - ? 'medium' - : 'fast'; - - stats.passes++; - }); - - runner.on('fail', function(test, err){ - stats.failures = stats.failures || 0; - stats.failures++; - test.err = err; - failures.push(test); - }); - - runner.on('end', function(){ - stats.end = new Date; - stats.duration = new Date - stats.start; - }); - - runner.on('pending', function(){ - stats.pending++; - }); -} - -/** - * Output common epilogue used by many of - * the bundled reporters. - * - * @api public - */ - -Base.prototype.epilogue = function(){ - var stats = this.stats - , fmt - , tests; - - console.log(); - - function pluralize(n) { - return 1 == n ? 'test' : 'tests'; - } - - // failure - if (stats.failures) { - fmt = color('bright fail', ' ✖') - + color('fail', ' %d of %d %s failed') - + color('light', ':') - - console.error(fmt, - stats.failures, - this.runner.total, - pluralize(this.runner.total)); - - Base.list(this.failures); - console.error(); - return; - } - - // pass - fmt = color('bright pass', ' ✔') - + color('green', ' %d %s complete') - + color('light', ' (%s)'); - - console.log(fmt, - stats.tests || 0, - pluralize(stats.tests), - ms(stats.duration)); - - // pending - if (stats.pending) { - fmt = color('pending', ' •') - + color('pending', ' %d %s pending'); - - console.log(fmt, stats.pending, pluralize(stats.pending)); - } - - console.log(); -}; - -/** - * Pad the given `str` to `len`. - * - * @param {String} str - * @param {String} len - * @return {String} - * @api private - */ - -function pad(str, len) { - str = String(str); - return Array(len - str.length + 1).join(' ') + str; -} - -/** - * Return a character diff for `err`. - * - * @param {Error} err - * @return {String} - * @api private - */ - -function errorDiff(err, type) { - return diff['diff' + type](err.actual, err.expected).map(function(str){ - str.value = str.value - .replace(/\t/g, '') - .replace(/\r/g, '') - .replace(/\n/g, '\n'); - if (str.added) return colorLines('diff added', str.value); - if (str.removed) return colorLines('diff removed', str.value); - return str.value; - }).join(''); -} - -/** - * Color lines for `str`, using the color `name`. - * - * @param {String} name - * @param {String} str - * @return {String} - * @api private - */ - -function colorLines(name, str) { - return str.split('\n').map(function(str){ - return color(name, str); - }).join('\n'); -} - -}); // module: reporters/base.js - -require.register("reporters/doc.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , utils = require('../utils'); - -/** - * Expose `Doc`. - */ - -exports = module.exports = Doc; - -/** - * Initialize a new `Doc` reporter. - * - * @param {Runner} runner - * @api public - */ - -function Doc(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , total = runner.total - , indents = 2; - - function indent() { - return Array(indents).join(' '); - } - - runner.on('suite', function(suite){ - if (suite.root) return; - ++indents; - console.log('%s
    ', indent()); - ++indents; - console.log('%s

    %s

    ', indent(), suite.title); - console.log('%s
    ', indent()); - }); - - runner.on('suite end', function(suite){ - if (suite.root) return; - console.log('%s
    ', indent()); - --indents; - console.log('%s
    ', indent()); - --indents; - }); - - runner.on('pass', function(test){ - console.log('%s
    %s
    ', indent(), test.title); - var code = utils.escape(utils.clean(test.fn.toString())); - console.log('%s
    %s
    ', indent(), code); - }); -} - -}); // module: reporters/doc.js - -require.register("reporters/dot.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , color = Base.color; - -/** - * Expose `Dot`. - */ - -exports = module.exports = Dot; - -/** - * Initialize a new `Dot` matrix test reporter. - * - * @param {Runner} runner - * @api public - */ - -function Dot(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , width = Base.window.width * .75 | 0 - , c = '․' - , n = 0; - - runner.on('start', function(){ - process.stdout.write('\n '); - }); - - runner.on('pending', function(test){ - process.stdout.write(color('pending', c)); - }); - - runner.on('pass', function(test){ - if (++n % width == 0) process.stdout.write('\n '); - if ('slow' == test.speed) { - process.stdout.write(color('bright yellow', c)); - } else { - process.stdout.write(color(test.speed, c)); - } - }); - - runner.on('fail', function(test, err){ - if (++n % width == 0) process.stdout.write('\n '); - process.stdout.write(color('fail', c)); - }); - - runner.on('end', function(){ - console.log(); - self.epilogue(); - }); -} - -/** - * Inherit from `Base.prototype`. - */ - -Dot.prototype = new Base; -Dot.prototype.constructor = Dot; - -}); // module: reporters/dot.js - -require.register("reporters/html-cov.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var JSONCov = require('./json-cov') - , fs = require('browser/fs'); - -/** - * Expose `HTMLCov`. - */ - -exports = module.exports = HTMLCov; - -/** - * Initialize a new `JsCoverage` reporter. - * - * @param {Runner} runner - * @api public - */ - -function HTMLCov(runner) { - var jade = require('jade') - , file = __dirname + '/templates/coverage.jade' - , str = fs.readFileSync(file, 'utf8') - , fn = jade.compile(str, { filename: file }) - , self = this; - - JSONCov.call(this, runner, false); - - runner.on('end', function(){ - process.stdout.write(fn({ - cov: self.cov - , coverageClass: coverageClass - })); - }); -} - -/** - * Return coverage class for `n`. - * - * @return {String} - * @api private - */ - -function coverageClass(n) { - if (n >= 75) return 'high'; - if (n >= 50) return 'medium'; - if (n >= 25) return 'low'; - return 'terrible'; -} -}); // module: reporters/html-cov.js - -require.register("reporters/html.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , utils = require('../utils') - , Progress = require('../browser/progress') - , escape = utils.escape; - -/** - * Save timer references to avoid Sinon interfering (see GH-237). - */ - -var Date = global.Date - , setTimeout = global.setTimeout - , setInterval = global.setInterval - , clearTimeout = global.clearTimeout - , clearInterval = global.clearInterval; - -/** - * Expose `Doc`. - */ - -exports = module.exports = HTML; - -/** - * Stats template. - */ - -var statsTemplate = ''; - -/** - * Initialize a new `Doc` reporter. - * - * @param {Runner} runner - * @api public - */ - -function HTML(runner, root) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , total = runner.total - , stat = fragment(statsTemplate) - , items = stat.getElementsByTagName('li') - , passes = items[1].getElementsByTagName('em')[0] - , passesLink = items[1].getElementsByTagName('a')[0] - , failures = items[2].getElementsByTagName('em')[0] - , failuresLink = items[2].getElementsByTagName('a')[0] - , duration = items[3].getElementsByTagName('em')[0] - , canvas = stat.getElementsByTagName('canvas')[0] - , report = fragment('
      ') - , stack = [report] - , progress - , ctx - - root = root || document.getElementById('mocha'); - - if (canvas.getContext) { - var ratio = window.devicePixelRatio || 1; - canvas.style.width = canvas.width; - canvas.style.height = canvas.height; - canvas.width *= ratio; - canvas.height *= ratio; - ctx = canvas.getContext('2d'); - ctx.scale(ratio, ratio); - progress = new Progress; - } - - if (!root) return error('#mocha div missing, add it to your document'); - - // pass toggle - on(passesLink, 'click', function () { - var className = /pass/.test(report.className) ? '' : ' pass'; - report.className = report.className.replace(/fail|pass/g, '') + className; - }); - - // failure toggle - on(failuresLink, 'click', function () { - var className = /fail/.test(report.className) ? '' : ' fail'; - report.className = report.className.replace(/fail|pass/g, '') + className; - }); - - root.appendChild(stat); - root.appendChild(report); - - if (progress) progress.size(40); - - runner.on('suite', function(suite){ - if (suite.root) return; - - // suite - var url = '?grep=' + encodeURIComponent(suite.fullTitle()); - var el = fragment('
    • %s

    • ', url, escape(suite.title)); - - // container - stack[0].appendChild(el); - stack.unshift(document.createElement('ul')); - el.appendChild(stack[0]); - }); - - runner.on('suite end', function(suite){ - if (suite.root) return; - stack.shift(); - }); - - runner.on('fail', function(test, err){ - if ('hook' == test.type || err.uncaught) runner.emit('test end', test); - }); - - runner.on('test end', function(test){ - window.scrollTo(0, document.body.scrollHeight); - - // TODO: add to stats - var percent = stats.tests / total * 100 | 0; - if (progress) progress.update(percent).draw(ctx); - - // update stats - var ms = new Date - stats.start; - text(passes, stats.passes); - text(failures, stats.failures); - text(duration, (ms / 1000).toFixed(2)); - - // test - if ('passed' == test.state) { - var el = fragment('
    • %e%ems

    • ', test.speed, test.title, test.duration); - } else if (test.pending) { - var el = fragment('
    • %e

    • ', test.title); - } else { - var el = fragment('
    • %e

    • ', test.title); - var str = test.err.stack || test.err.toString(); - - // FF / Opera do not add the message - if (!~str.indexOf(test.err.message)) { - str = test.err.message + '\n' + str; - } - - // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we - // check for the result of the stringifying. - if ('[object Error]' == str) str = test.err.message; - - // Safari doesn't give you a stack. Let's at least provide a source line. - if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { - str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; - } - - el.appendChild(fragment('
      %e
      ', str)); - } - - // toggle code - // TODO: defer - if (!test.pending) { - var h2 = el.getElementsByTagName('h2')[0]; - - on(h2, 'click', function(){ - pre.style.display = 'none' == pre.style.display - ? 'inline-block' - : 'none'; - }); - - var pre = fragment('
      %e
      ', utils.clean(test.fn.toString())); - el.appendChild(pre); - pre.style.display = 'none'; - } - - stack[0].appendChild(el); - }); -} - -/** - * Display error `msg`. - */ - -function error(msg) { - document.body.appendChild(fragment('
      %s
      ', msg)); -} - -/** - * Return a DOM fragment from `html`. - */ - -function fragment(html) { - var args = arguments - , div = document.createElement('div') - , i = 1; - - div.innerHTML = html.replace(/%([se])/g, function(_, type){ - switch (type) { - case 's': return String(args[i++]); - case 'e': return escape(args[i++]); - } - }); - - return div.firstChild; -} - -/** - * Set `el` text to `str`. - */ - -function text(el, str) { - if (el.textContent) { - el.textContent = str; - } else { - el.innerText = str; - } -} - -/** - * Listen on `event` with callback `fn`. - */ - -function on(el, event, fn) { - if (el.addEventListener) { - el.addEventListener(event, fn, false); - } else { - el.attachEvent('on' + event, fn); - } -} - -}); // module: reporters/html.js - -require.register("reporters/index.js", function(module, exports, require){ - -exports.Base = require('./base'); -exports.Dot = require('./dot'); -exports.Doc = require('./doc'); -exports.TAP = require('./tap'); -exports.JSON = require('./json'); -exports.HTML = require('./html'); -exports.List = require('./list'); -exports.Min = require('./min'); -exports.Spec = require('./spec'); -exports.Nyan = require('./nyan'); -exports.XUnit = require('./xunit'); -exports.Markdown = require('./markdown'); -exports.Progress = require('./progress'); -exports.Landing = require('./landing'); -exports.JSONCov = require('./json-cov'); -exports.HTMLCov = require('./html-cov'); -exports.JSONStream = require('./json-stream'); -exports.Teamcity = require('./teamcity'); - -}); // module: reporters/index.js - -require.register("reporters/json-cov.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base'); - -/** - * Expose `JSONCov`. - */ - -exports = module.exports = JSONCov; - -/** - * Initialize a new `JsCoverage` reporter. - * - * @param {Runner} runner - * @param {Boolean} output - * @api public - */ - -function JSONCov(runner, output) { - var self = this - , output = 1 == arguments.length ? true : output; - - Base.call(this, runner); - - var tests = [] - , failures = [] - , passes = []; - - runner.on('test end', function(test){ - tests.push(test); - }); - - runner.on('pass', function(test){ - passes.push(test); - }); - - runner.on('fail', function(test){ - failures.push(test); - }); - - runner.on('end', function(){ - var cov = global._$jscoverage || {}; - var result = self.cov = map(cov); - result.stats = self.stats; - result.tests = tests.map(clean); - result.failures = failures.map(clean); - result.passes = passes.map(clean); - if (!output) return; - process.stdout.write(JSON.stringify(result, null, 2 )); - }); -} - -/** - * Map jscoverage data to a JSON structure - * suitable for reporting. - * - * @param {Object} cov - * @return {Object} - * @api private - */ - -function map(cov) { - var ret = { - instrumentation: 'node-jscoverage' - , sloc: 0 - , hits: 0 - , misses: 0 - , coverage: 0 - , files: [] - }; - - for (var filename in cov) { - var data = coverage(filename, cov[filename]); - ret.files.push(data); - ret.hits += data.hits; - ret.misses += data.misses; - ret.sloc += data.sloc; - } - - if (ret.sloc > 0) { - ret.coverage = (ret.hits / ret.sloc) * 100; - } - - return ret; -}; - -/** - * Map jscoverage data for a single source file - * to a JSON structure suitable for reporting. - * - * @param {String} filename name of the source file - * @param {Object} data jscoverage coverage data - * @return {Object} - * @api private - */ - -function coverage(filename, data) { - var ret = { - filename: filename, - coverage: 0, - hits: 0, - misses: 0, - sloc: 0, - source: {} - }; - - data.source.forEach(function(line, num){ - num++; - - if (data[num] === 0) { - ret.misses++; - ret.sloc++; - } else if (data[num] !== undefined) { - ret.hits++; - ret.sloc++; - } - - ret.source[num] = { - source: line - , coverage: data[num] === undefined - ? '' - : data[num] - }; - }); - - ret.coverage = ret.hits / ret.sloc * 100; - - return ret; -} - -/** - * Return a plain-object representation of `test` - * free of cyclic properties etc. - * - * @param {Object} test - * @return {Object} - * @api private - */ - -function clean(test) { - return { - title: test.title - , fullTitle: test.fullTitle() - , duration: test.duration - } -} - -}); // module: reporters/json-cov.js - -require.register("reporters/json-stream.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , color = Base.color; - -/** - * Expose `List`. - */ - -exports = module.exports = List; - -/** - * Initialize a new `List` test reporter. - * - * @param {Runner} runner - * @api public - */ - -function List(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , total = runner.total; - - runner.on('start', function(){ - console.log(JSON.stringify(['start', { total: total }])); - }); - - runner.on('pass', function(test){ - console.log(JSON.stringify(['pass', clean(test)])); - }); - - runner.on('fail', function(test, err){ - console.log(JSON.stringify(['fail', clean(test)])); - }); - - runner.on('end', function(){ - process.stdout.write(JSON.stringify(['end', self.stats])); - }); -} - -/** - * Return a plain-object representation of `test` - * free of cyclic properties etc. - * - * @param {Object} test - * @return {Object} - * @api private - */ - -function clean(test) { - return { - title: test.title - , fullTitle: test.fullTitle() - , duration: test.duration - } -} -}); // module: reporters/json-stream.js - -require.register("reporters/json.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `JSON`. - */ - -exports = module.exports = JSONReporter; - -/** - * Initialize a new `JSON` reporter. - * - * @param {Runner} runner - * @api public - */ - -function JSONReporter(runner) { - var self = this; - Base.call(this, runner); - - var tests = [] - , failures = [] - , passes = []; - - runner.on('test end', function(test){ - tests.push(test); - }); - - runner.on('pass', function(test){ - passes.push(test); - }); - - runner.on('fail', function(test){ - failures.push(test); - }); - - runner.on('end', function(){ - var obj = { - stats: self.stats - , tests: tests.map(clean) - , failures: failures.map(clean) - , passes: passes.map(clean) - }; - - process.stdout.write(JSON.stringify(obj, null, 2)); - }); -} - -/** - * Return a plain-object representation of `test` - * free of cyclic properties etc. - * - * @param {Object} test - * @return {Object} - * @api private - */ - -function clean(test) { - return { - title: test.title - , fullTitle: test.fullTitle() - , duration: test.duration - } -} -}); // module: reporters/json.js - -require.register("reporters/landing.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `Landing`. - */ - -exports = module.exports = Landing; - -/** - * Airplane color. - */ - -Base.colors.plane = 0; - -/** - * Airplane crash color. - */ - -Base.colors['plane crash'] = 31; - -/** - * Runway color. - */ - -Base.colors.runway = 90; - -/** - * Initialize a new `Landing` reporter. - * - * @param {Runner} runner - * @api public - */ - -function Landing(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , width = Base.window.width * .75 | 0 - , total = runner.total - , stream = process.stdout - , plane = color('plane', '✈') - , crashed = -1 - , n = 0; - - function runway() { - var buf = Array(width).join('-'); - return ' ' + color('runway', buf); - } - - runner.on('start', function(){ - stream.write('\n '); - cursor.hide(); - }); - - runner.on('test end', function(test){ - // check if the plane crashed - var col = -1 == crashed - ? width * ++n / total | 0 - : crashed; - - // show the crash - if ('failed' == test.state) { - plane = color('plane crash', '✈'); - crashed = col; - } - - // render landing strip - stream.write('\u001b[4F\n\n'); - stream.write(runway()); - stream.write('\n '); - stream.write(color('runway', Array(col).join('⋅'))); - stream.write(plane) - stream.write(color('runway', Array(width - col).join('⋅') + '\n')); - stream.write(runway()); - stream.write('\u001b[0m'); - }); - - runner.on('end', function(){ - cursor.show(); - console.log(); - self.epilogue(); - }); -} - -/** - * Inherit from `Base.prototype`. - */ - -Landing.prototype = new Base; -Landing.prototype.constructor = Landing; - -}); // module: reporters/landing.js - -require.register("reporters/list.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `List`. - */ - -exports = module.exports = List; - -/** - * Initialize a new `List` test reporter. - * - * @param {Runner} runner - * @api public - */ - -function List(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , n = 0; - - runner.on('start', function(){ - console.log(); - }); - - runner.on('test', function(test){ - process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); - }); - - runner.on('pending', function(test){ - var fmt = color('checkmark', ' -') - + color('pending', ' %s'); - console.log(fmt, test.fullTitle()); - }); - - runner.on('pass', function(test){ - var fmt = color('checkmark', ' ✓') - + color('pass', ' %s: ') - + color(test.speed, '%dms'); - cursor.CR(); - console.log(fmt, test.fullTitle(), test.duration); - }); - - runner.on('fail', function(test, err){ - cursor.CR(); - console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); - }); - - runner.on('end', self.epilogue.bind(self)); -} - -/** - * Inherit from `Base.prototype`. - */ - -List.prototype = new Base; -List.prototype.constructor = List; - - -}); // module: reporters/list.js - -require.register("reporters/markdown.js", function(module, exports, require){ -/** - * Module dependencies. - */ - -var Base = require('./base') - , utils = require('../utils'); - -/** - * Expose `Markdown`. - */ - -exports = module.exports = Markdown; - -/** - * Initialize a new `Markdown` reporter. - * - * @param {Runner} runner - * @api public - */ - -function Markdown(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , total = runner.total - , level = 0 - , buf = ''; - - function title(str) { - return Array(level).join('#') + ' ' + str; - } - - function indent() { - return Array(level).join(' '); - } - - function mapTOC(suite, obj) { - var ret = obj; - obj = obj[suite.title] = obj[suite.title] || { suite: suite }; - suite.suites.forEach(function(suite){ - mapTOC(suite, obj); - }); - return ret; - } - - function stringifyTOC(obj, level) { - ++level; - var buf = ''; - var link; - for (var key in obj) { - if ('suite' == key) continue; - if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; - if (key) buf += Array(level).join(' ') + link; - buf += stringifyTOC(obj[key], level); - } - --level; - return buf; - } - - function generateTOC(suite) { - var obj = mapTOC(suite, {}); - return stringifyTOC(obj, 0); - } - - generateTOC(runner.suite); - - runner.on('suite', function(suite){ - ++level; - var slug = utils.slug(suite.fullTitle()); - buf += '' + '\n'; - buf += title(suite.title) + '\n'; - }); - - runner.on('suite end', function(suite){ - --level; - }); - - runner.on('pass', function(test){ - var code = utils.clean(test.fn.toString()); - buf += test.title + '.\n'; - buf += '\n```js\n'; - buf += code + '\n'; - buf += '```\n\n'; - }); - - runner.on('end', function(){ - process.stdout.write('# TOC\n'); - process.stdout.write(generateTOC(runner.suite)); - process.stdout.write(buf); - }); -} -}); // module: reporters/markdown.js - -require.register("reporters/min.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base'); - -/** - * Expose `Min`. - */ - -exports = module.exports = Min; - -/** - * Initialize a new `Min` minimal test reporter (best used with --watch). - * - * @param {Runner} runner - * @api public - */ - -function Min(runner) { - Base.call(this, runner); - - runner.on('start', function(){ - // clear screen - process.stdout.write('\u001b[2J'); - // set cursor position - process.stdout.write('\u001b[1;3H'); - }); - - runner.on('end', this.epilogue.bind(this)); -} - -/** - * Inherit from `Base.prototype`. - */ - -Min.prototype = new Base; -Min.prototype.constructor = Min; - -}); // module: reporters/min.js - -require.register("reporters/nyan.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , color = Base.color; - -/** - * Expose `Dot`. - */ - -exports = module.exports = NyanCat; - -/** - * Initialize a new `Dot` matrix test reporter. - * - * @param {Runner} runner - * @api public - */ - -function NyanCat(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , width = Base.window.width * .75 | 0 - , rainbowColors = this.rainbowColors = self.generateColors() - , colorIndex = this.colorIndex = 0 - , numerOfLines = this.numberOfLines = 4 - , trajectories = this.trajectories = [[], [], [], []] - , nyanCatWidth = this.nyanCatWidth = 11 - , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) - , scoreboardWidth = this.scoreboardWidth = 5 - , tick = this.tick = 0 - , n = 0; - - runner.on('start', function(){ - Base.cursor.hide(); - self.draw('start'); - }); - - runner.on('pending', function(test){ - self.draw('pending'); - }); - - runner.on('pass', function(test){ - self.draw('pass'); - }); - - runner.on('fail', function(test, err){ - self.draw('fail'); - }); - - runner.on('end', function(){ - Base.cursor.show(); - for (var i = 0; i < self.numberOfLines; i++) write('\n'); - self.epilogue(); - }); -} - -/** - * Draw the nyan cat with runner `status`. - * - * @param {String} status - * @api private - */ - -NyanCat.prototype.draw = function(status){ - this.appendRainbow(); - this.drawScoreboard(); - this.drawRainbow(); - this.drawNyanCat(status); - this.tick = !this.tick; -}; - -/** - * Draw the "scoreboard" showing the number - * of passes, failures and pending tests. - * - * @api private - */ - -NyanCat.prototype.drawScoreboard = function(){ - var stats = this.stats; - var colors = Base.colors; - - function draw(color, n) { - write(' '); - write('\u001b[' + color + 'm' + n + '\u001b[0m'); - write('\n'); - } - - draw(colors.green, stats.passes); - draw(colors.fail, stats.failures); - draw(colors.pending, stats.pending); - write('\n'); - - this.cursorUp(this.numberOfLines); -}; - -/** - * Append the rainbow. - * - * @api private - */ - -NyanCat.prototype.appendRainbow = function(){ - var segment = this.tick ? '_' : '-'; - var rainbowified = this.rainbowify(segment); - - for (var index = 0; index < this.numberOfLines; index++) { - var trajectory = this.trajectories[index]; - if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); - trajectory.push(rainbowified); - } -}; - -/** - * Draw the rainbow. - * - * @api private - */ - -NyanCat.prototype.drawRainbow = function(){ - var self = this; - - this.trajectories.forEach(function(line, index) { - write('\u001b[' + self.scoreboardWidth + 'C'); - write(line.join('')); - write('\n'); - }); - - this.cursorUp(this.numberOfLines); -}; - -/** - * Draw the nyan cat with `status`. - * - * @param {String} status - * @api private - */ - -NyanCat.prototype.drawNyanCat = function(status) { - var self = this; - var startWidth = this.scoreboardWidth + this.trajectories[0].length; - - [0, 1, 2, 3].forEach(function(index) { - write('\u001b[' + startWidth + 'C'); - - switch (index) { - case 0: - write('_,------,'); - write('\n'); - break; - case 1: - var padding = self.tick ? ' ' : ' '; - write('_|' + padding + '/\\_/\\ '); - write('\n'); - break; - case 2: - var padding = self.tick ? '_' : '__'; - var tail = self.tick ? '~' : '^'; - var face; - switch (status) { - case 'pass': - face = '( ^ .^)'; - break; - case 'fail': - face = '( o .o)'; - break; - default: - face = '( - .-)'; - } - write(tail + '|' + padding + face + ' '); - write('\n'); - break; - case 3: - var padding = self.tick ? ' ' : ' '; - write(padding + '"" "" '); - write('\n'); - break; - } - }); - - this.cursorUp(this.numberOfLines); -}; - -/** - * Move cursor up `n`. - * - * @param {Number} n - * @api private - */ - -NyanCat.prototype.cursorUp = function(n) { - write('\u001b[' + n + 'A'); -}; - -/** - * Move cursor down `n`. - * - * @param {Number} n - * @api private - */ - -NyanCat.prototype.cursorDown = function(n) { - write('\u001b[' + n + 'B'); -}; - -/** - * Generate rainbow colors. - * - * @return {Array} - * @api private - */ - -NyanCat.prototype.generateColors = function(){ - var colors = []; - - for (var i = 0; i < (6 * 7); i++) { - var pi3 = Math.floor(Math.PI / 3); - var n = (i * (1.0 / 6)); - var r = Math.floor(3 * Math.sin(n) + 3); - var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); - var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); - colors.push(36 * r + 6 * g + b + 16); - } - - return colors; -}; - -/** - * Apply rainbow to the given `str`. - * - * @param {String} str - * @return {String} - * @api private - */ - -NyanCat.prototype.rainbowify = function(str){ - var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; - this.colorIndex += 1; - return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; -}; - -/** - * Stdout helper. - */ - -function write(string) { - process.stdout.write(string); -} - -/** - * Inherit from `Base.prototype`. - */ - -NyanCat.prototype = new Base; -NyanCat.prototype.constructor = NyanCat; - - -}); // module: reporters/nyan.js - -require.register("reporters/progress.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `Progress`. - */ - -exports = module.exports = Progress; - -/** - * General progress bar color. - */ - -Base.colors.progress = 90; - -/** - * Initialize a new `Progress` bar test reporter. - * - * @param {Runner} runner - * @param {Object} options - * @api public - */ - -function Progress(runner, options) { - Base.call(this, runner); - - var self = this - , options = options || {} - , stats = this.stats - , width = Base.window.width * .50 | 0 - , total = runner.total - , complete = 0 - , max = Math.max; - - // default chars - options.open = options.open || '['; - options.complete = options.complete || '▬'; - options.incomplete = options.incomplete || '⋅'; - options.close = options.close || ']'; - options.verbose = false; - - // tests started - runner.on('start', function(){ - console.log(); - cursor.hide(); - }); - - // tests complete - runner.on('test end', function(){ - complete++; - var incomplete = total - complete - , percent = complete / total - , n = width * percent | 0 - , i = width - n; - - cursor.CR(); - process.stdout.write('\u001b[J'); - process.stdout.write(color('progress', ' ' + options.open)); - process.stdout.write(Array(n).join(options.complete)); - process.stdout.write(Array(i).join(options.incomplete)); - process.stdout.write(color('progress', options.close)); - if (options.verbose) { - process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); - } - }); - - // tests are complete, output some stats - // and the failures if any - runner.on('end', function(){ - cursor.show(); - console.log(); - self.epilogue(); - }); -} - -/** - * Inherit from `Base.prototype`. - */ - -Progress.prototype = new Base; -Progress.prototype.constructor = Progress; - - -}); // module: reporters/progress.js - -require.register("reporters/spec.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `Spec`. - */ - -exports = module.exports = Spec; - -/** - * Initialize a new `Spec` test reporter. - * - * @param {Runner} runner - * @api public - */ - -function Spec(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , indents = 0 - , n = 0; - - function indent() { - return Array(indents).join(' ') - } - - runner.on('start', function(){ - console.log(); - }); - - runner.on('suite', function(suite){ - ++indents; - console.log(color('suite', '%s%s'), indent(), suite.title); - }); - - runner.on('suite end', function(suite){ - --indents; - if (1 == indents) console.log(); - }); - - runner.on('test', function(test){ - process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': ')); - }); - - runner.on('pending', function(test){ - var fmt = indent() + color('pending', ' - %s'); - console.log(fmt, test.title); - }); - - runner.on('pass', function(test){ - if ('fast' == test.speed) { - var fmt = indent() - + color('checkmark', ' ✓') - + color('pass', ' %s '); - cursor.CR(); - console.log(fmt, test.title); - } else { - var fmt = indent() - + color('checkmark', ' ✓') - + color('pass', ' %s ') - + color(test.speed, '(%dms)'); - cursor.CR(); - console.log(fmt, test.title, test.duration); - } - }); - - runner.on('fail', function(test, err){ - cursor.CR(); - console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); - }); - - runner.on('end', self.epilogue.bind(self)); -} - -/** - * Inherit from `Base.prototype`. - */ - -Spec.prototype = new Base; -Spec.prototype.constructor = Spec; - - -}); // module: reporters/spec.js - -require.register("reporters/tap.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `TAP`. - */ - -exports = module.exports = TAP; - -/** - * Initialize a new `TAP` reporter. - * - * @param {Runner} runner - * @api public - */ - -function TAP(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , n = 1; - - runner.on('start', function(){ - var total = runner.grepTotal(runner.suite); - console.log('%d..%d', 1, total); - }); - - runner.on('test end', function(){ - ++n; - }); - - runner.on('pending', function(test){ - console.log('ok %d %s # SKIP -', n, title(test)); - }); - - runner.on('pass', function(test){ - console.log('ok %d %s', n, title(test)); - }); - - runner.on('fail', function(test, err){ - console.log('not ok %d %s', n, title(test)); - console.log(err.stack.replace(/^/gm, ' ')); - }); -} - -/** - * Return a TAP-safe title of `test` - * - * @param {Object} test - * @return {String} - * @api private - */ - -function title(test) { - return test.fullTitle().replace(/#/g, ''); -} - -}); // module: reporters/tap.js - -require.register("reporters/teamcity.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base'); - -/** - * Expose `Teamcity`. - */ - -exports = module.exports = Teamcity; - -/** - * Initialize a new `Teamcity` reporter. - * - * @param {Runner} runner - * @api public - */ - -function Teamcity(runner) { - Base.call(this, runner); - var stats = this.stats; - - runner.on('start', function() { - console.log("##teamcity[testSuiteStarted name='mocha.suite']"); - }); - - runner.on('test', function(test) { - console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']"); - }); - - runner.on('fail', function(test, err) { - console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']"); - }); - - runner.on('pending', function(test) { - console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"); - }); - - runner.on('test end', function(test) { - console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']"); - }); - - runner.on('end', function() { - console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"); - }); -} - -/** - * Escape the given `str`. - */ - -function escape(str) { - return str - .replace(/\|/g, "||") - .replace(/\n/g, "|n") - .replace(/\r/g, "|r") - .replace(/\[/g, "|[") - .replace(/\]/g, "|]") - .replace(/\u0085/g, "|x") - .replace(/\u2028/g, "|l") - .replace(/\u2029/g, "|p") - .replace(/'/g, "|'"); -} - -}); // module: reporters/teamcity.js - -require.register("reporters/xunit.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , utils = require('../utils') - , escape = utils.escape; - -/** - * Save timer references to avoid Sinon interfering (see GH-237). - */ - -var Date = global.Date - , setTimeout = global.setTimeout - , setInterval = global.setInterval - , clearTimeout = global.clearTimeout - , clearInterval = global.clearInterval; - -/** - * Expose `XUnit`. - */ - -exports = module.exports = XUnit; - -/** - * Initialize a new `XUnit` reporter. - * - * @param {Runner} runner - * @api public - */ - -function XUnit(runner) { - Base.call(this, runner); - var stats = this.stats - , tests = [] - , self = this; - - runner.on('pass', function(test){ - tests.push(test); - }); - - runner.on('fail', function(test){ - tests.push(test); - }); - - runner.on('end', function(){ - console.log(tag('testsuite', { - name: 'Mocha Tests' - , tests: stats.tests - , failures: stats.failures - , errors: stats.failures - , skip: stats.tests - stats.failures - stats.passes - , timestamp: (new Date).toUTCString() - , time: stats.duration / 1000 - }, false)); - - tests.forEach(test); - console.log(''); - }); -} - -/** - * Inherit from `Base.prototype`. - */ - -XUnit.prototype = new Base; -XUnit.prototype.constructor = XUnit; - - -/** - * Output tag for the given `test.` - */ - -function test(test) { - var attrs = { - classname: test.parent.fullTitle() - , name: test.title - , time: test.duration / 1000 - }; - - if ('failed' == test.state) { - var err = test.err; - attrs.message = escape(err.message); - console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); - } else if (test.pending) { - console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); - } else { - console.log(tag('testcase', attrs, true) ); - } -} - -/** - * HTML tag helper. - */ - -function tag(name, attrs, close, content) { - var end = close ? '/>' : '>' - , pairs = [] - , tag; - - for (var key in attrs) { - pairs.push(key + '="' + escape(attrs[key]) + '"'); - } - - tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; - if (content) tag += content + ''; -} - -}); // module: reporters/xunit.js - -require.register("runnable.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var EventEmitter = require('browser/events').EventEmitter - , debug = require('browser/debug')('mocha:runnable'); - -/** - * Save timer references to avoid Sinon interfering (see GH-237). - */ - -var Date = global.Date - , setTimeout = global.setTimeout - , setInterval = global.setInterval - , clearTimeout = global.clearTimeout - , clearInterval = global.clearInterval; - -/** - * Expose `Runnable`. - */ - -module.exports = Runnable; - -/** - * Initialize a new `Runnable` with the given `title` and callback `fn`. - * - * @param {String} title - * @param {Function} fn - * @api private - */ - -function Runnable(title, fn) { - this.title = title; - this.fn = fn; - this.async = fn && fn.length; - this.sync = ! this.async; - this._timeout = 2000; - this._slow = 75; - this.timedOut = false; -} - -/** - * Inherit from `EventEmitter.prototype`. - */ - -Runnable.prototype = new EventEmitter; -Runnable.prototype.constructor = Runnable; - - -/** - * Set & get timeout `ms`. - * - * @param {Number} ms - * @return {Runnable|Number} ms or self - * @api private - */ - -Runnable.prototype.timeout = function(ms){ - if (0 == arguments.length) return this._timeout; - debug('timeout %d', ms); - this._timeout = ms; - if (this.timer) this.resetTimeout(); - return this; -}; - -/** - * Set & get slow `ms`. - * - * @param {Number} ms - * @return {Runnable|Number} ms or self - * @api private - */ - -Runnable.prototype.slow = function(ms){ - if (0 === arguments.length) return this._slow; - debug('timeout %d', ms); - this._slow = ms; - return this; -}; - -/** - * Return the full title generated by recursively - * concatenating the parent's full title. - * - * @return {String} - * @api public - */ - -Runnable.prototype.fullTitle = function(){ - return this.parent.fullTitle() + ' ' + this.title; -}; - -/** - * Clear the timeout. - * - * @api private - */ - -Runnable.prototype.clearTimeout = function(){ - clearTimeout(this.timer); -}; - -/** - * Inspect the runnable void of private properties. - * - * @return {String} - * @api private - */ - -Runnable.prototype.inspect = function(){ - return JSON.stringify(this, function(key, val){ - if ('_' == key[0]) return; - if ('parent' == key) return '#'; - if ('ctx' == key) return '#'; - return val; - }, 2); -}; - -/** - * Reset the timeout. - * - * @api private - */ - -Runnable.prototype.resetTimeout = function(){ - var self = this - , ms = this.timeout(); - - this.clearTimeout(); - if (ms) { - this.timer = setTimeout(function(){ - self.callback(new Error('timeout of ' + ms + 'ms exceeded')); - self.timedOut = true; - }, ms); - } -}; - -/** - * Run the test and invoke `fn(err)`. - * - * @param {Function} fn - * @api private - */ - -Runnable.prototype.run = function(fn){ - var self = this - , ms = this.timeout() - , start = new Date - , ctx = this.ctx - , finished - , emitted; - - if (ctx) ctx.runnable(this); - - // timeout - if (this.async) { - if (ms) { - this.timer = setTimeout(function(){ - done(new Error('timeout of ' + ms + 'ms exceeded')); - self.timedOut = true; - }, ms); - } - } - - // called multiple times - function multiple(err) { - if (emitted) return; - emitted = true; - self.emit('error', err || new Error('done() called multiple times')); - } - - // finished - function done(err) { - if (self.timedOut) return; - if (finished) return multiple(err); - self.clearTimeout(); - self.duration = new Date - start; - finished = true; - fn(err); - } - - // for .resetTimeout() - this.callback = done; - - // async - if (this.async) { - try { - this.fn.call(ctx, function(err){ - if (err instanceof Error) return done(err); - if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); - done(); - }); - } catch (err) { - done(err); - } - return; - } - - // sync - try { - if (!this.pending) this.fn.call(ctx); - this.duration = new Date - start; - fn(); - } catch (err) { - fn(err); - } -}; - -}); // module: runnable.js - -require.register("runner.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var EventEmitter = require('browser/events').EventEmitter - , debug = require('browser/debug')('mocha:runner') - , Test = require('./test') - , utils = require('./utils') - , filter = utils.filter - , keys = utils.keys - , noop = function(){}; - -/** - * Expose `Runner`. - */ - -module.exports = Runner; - -/** - * Initialize a `Runner` for the given `suite`. - * - * Events: - * - * - `start` execution started - * - `end` execution complete - * - `suite` (suite) test suite execution started - * - `suite end` (suite) all tests (and sub-suites) have finished - * - `test` (test) test execution started - * - `test end` (test) test completed - * - `hook` (hook) hook execution started - * - `hook end` (hook) hook complete - * - `pass` (test) test passed - * - `fail` (test, err) test failed - * - * @api public - */ - -function Runner(suite) { - var self = this; - this._globals = []; - this.suite = suite; - this.total = suite.total(); - this.failures = 0; - this.on('test end', function(test){ self.checkGlobals(test); }); - this.on('hook end', function(hook){ self.checkGlobals(hook); }); - this.grep(/.*/); - this.globals(utils.keys(global).concat(['errno'])); -} - -/** - * Inherit from `EventEmitter.prototype`. - */ - -Runner.prototype = new EventEmitter; -Runner.prototype.constructor = Runner; - - -/** - * Run tests with full titles matching `re`. Updates runner.total - * with number of tests matched. - * - * @param {RegExp} re - * @param {Boolean} invert - * @return {Runner} for chaining - * @api public - */ - -Runner.prototype.grep = function(re, invert){ - debug('grep %s', re); - this._grep = re; - this._invert = invert; - this.total = this.grepTotal(this.suite); - return this; -}; - -/** - * Returns the number of tests matching the grep search for the - * given suite. - * - * @param {Suite} suite - * @return {Number} - * @api public - */ - -Runner.prototype.grepTotal = function(suite) { - var self = this; - var total = 0; - - suite.eachTest(function(test){ - var match = self._grep.test(test.fullTitle()); - if (self._invert) match = !match; - if (match) total++; - }); - - return total; -}; - -/** - * Allow the given `arr` of globals. - * - * @param {Array} arr - * @return {Runner} for chaining - * @api public - */ - -Runner.prototype.globals = function(arr){ - if (0 == arguments.length) return this._globals; - debug('globals %j', arr); - utils.forEach(arr, function(arr){ - this._globals.push(arr); - }, this); - return this; -}; - -/** - * Check for global variable leaks. - * - * @api private - */ - -Runner.prototype.checkGlobals = function(test){ - if (this.ignoreLeaks) return; - var ok = this._globals; - var globals = keys(global); - var isNode = process.kill; - var leaks; - - // check length - 2 ('errno' and 'location' globals) - if (isNode && 1 == ok.length - globals.length) return - else if (2 == ok.length - globals.length) return; - - leaks = filterLeaks(ok, globals); - this._globals = this._globals.concat(leaks); - - if (leaks.length > 1) { - this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); - } else if (leaks.length) { - this.fail(test, new Error('global leak detected: ' + leaks[0])); - } -}; - -/** - * Fail the given `test`. - * - * @param {Test} test - * @param {Error} err - * @api private - */ - -Runner.prototype.fail = function(test, err){ - ++this.failures; - test.state = 'failed'; - if ('string' == typeof err) { - err = new Error('the string "' + err + '" was thrown, throw an Error :)'); - } - this.emit('fail', test, err); -}; - -/** - * Fail the given `hook` with `err`. - * - * Hook failures (currently) hard-end due - * to that fact that a failing hook will - * surely cause subsequent tests to fail, - * causing jumbled reporting. - * - * @param {Hook} hook - * @param {Error} err - * @api private - */ - -Runner.prototype.failHook = function(hook, err){ - this.fail(hook, err); - this.emit('end'); -}; - -/** - * Run hook `name` callbacks and then invoke `fn()`. - * - * @param {String} name - * @param {Function} function - * @api private - */ - -Runner.prototype.hook = function(name, fn){ - var suite = this.suite - , hooks = suite['_' + name] - , self = this - , timer; - - function next(i) { - var hook = hooks[i]; - if (!hook) return fn(); - self.currentRunnable = hook; - - self.emit('hook', hook); - - hook.on('error', function(err){ - self.failHook(hook, err); - }); - - hook.run(function(err){ - hook.removeAllListeners('error'); - var testError = hook.error(); - if (testError) self.fail(self.test, testError); - if (err) return self.failHook(hook, err); - self.emit('hook end', hook); - next(++i); - }); - } - - process.nextTick(function(){ - next(0); - }); -}; - -/** - * Run hook `name` for the given array of `suites` - * in order, and callback `fn(err)`. - * - * @param {String} name - * @param {Array} suites - * @param {Function} fn - * @api private - */ - -Runner.prototype.hooks = function(name, suites, fn){ - var self = this - , orig = this.suite; - - function next(suite) { - self.suite = suite; - - if (!suite) { - self.suite = orig; - return fn(); - } - - self.hook(name, function(err){ - if (err) { - self.suite = orig; - return fn(err); - } - - next(suites.pop()); - }); - } - - next(suites.pop()); -}; - -/** - * Run hooks from the top level down. - * - * @param {String} name - * @param {Function} fn - * @api private - */ - -Runner.prototype.hookUp = function(name, fn){ - var suites = [this.suite].concat(this.parents()).reverse(); - this.hooks(name, suites, fn); -}; - -/** - * Run hooks from the bottom up. - * - * @param {String} name - * @param {Function} fn - * @api private - */ - -Runner.prototype.hookDown = function(name, fn){ - var suites = [this.suite].concat(this.parents()); - this.hooks(name, suites, fn); -}; - -/** - * Return an array of parent Suites from - * closest to furthest. - * - * @return {Array} - * @api private - */ - -Runner.prototype.parents = function(){ - var suite = this.suite - , suites = []; - while (suite = suite.parent) suites.push(suite); - return suites; -}; - -/** - * Run the current test and callback `fn(err)`. - * - * @param {Function} fn - * @api private - */ - -Runner.prototype.runTest = function(fn){ - var test = this.test - , self = this; - - try { - test.on('error', function(err){ - self.fail(test, err); - }); - test.run(fn); - } catch (err) { - fn(err); - } -}; - -/** - * Run tests in the given `suite` and invoke - * the callback `fn()` when complete. - * - * @param {Suite} suite - * @param {Function} fn - * @api private - */ - -Runner.prototype.runTests = function(suite, fn){ - var self = this - , tests = suite.tests - , test; - - function next(err) { - // if we bail after first err - if (self.failures && suite._bail) return fn(); - - // next test - test = tests.shift(); - - // all done - if (!test) return fn(); - - // grep - var match = self._grep.test(test.fullTitle()); - if (self._invert) match = !match; - if (!match) return next(); - - // pending - if (test.pending) { - self.emit('pending', test); - self.emit('test end', test); - return next(); - } - - // execute test and hook(s) - self.emit('test', self.test = test); - self.hookDown('beforeEach', function(){ - self.currentRunnable = self.test; - self.runTest(function(err){ - test = self.test; - - if (err) { - self.fail(test, err); - self.emit('test end', test); - return self.hookUp('afterEach', next); - } - - test.state = 'passed'; - self.emit('pass', test); - self.emit('test end', test); - self.hookUp('afterEach', next); - }); - }); - } - - this.next = next; - next(); -}; - -/** - * Run the given `suite` and invoke the - * callback `fn()` when complete. - * - * @param {Suite} suite - * @param {Function} fn - * @api private - */ - -Runner.prototype.runSuite = function(suite, fn){ - var total = this.grepTotal(suite) - , self = this - , i = 0; - - debug('run suite %s', suite.fullTitle()); - - if (!total) return fn(); - - this.emit('suite', this.suite = suite); - - function next() { - var curr = suite.suites[i++]; - if (!curr) return done(); - self.runSuite(curr, next); - } - - function done() { - self.suite = suite; - self.hook('afterAll', function(){ - self.emit('suite end', suite); - fn(); - }); - } - - this.hook('beforeAll', function(){ - self.runTests(suite, next); - }); -}; - -/** - * Handle uncaught exceptions. - * - * @param {Error} err - * @api private - */ - -Runner.prototype.uncaught = function(err){ - debug('uncaught exception %s', err.message); - var runnable = this.currentRunnable; - if (!runnable || 'failed' == runnable.state) return; - runnable.clearTimeout(); - err.uncaught = true; - this.fail(runnable, err); - - // recover from test - if ('test' == runnable.type) { - this.emit('test end', runnable); - this.hookUp('afterEach', this.next); - return; - } - - // bail on hooks - this.emit('end'); -}; - -/** - * Run the root suite and invoke `fn(failures)` - * on completion. - * - * @param {Function} fn - * @return {Runner} for chaining - * @api public - */ - -Runner.prototype.run = function(fn){ - var self = this - , fn = fn || function(){}; - - debug('start'); - - // uncaught callback - function uncaught(err) { - self.uncaught(err); - } - - // callback - this.on('end', function(){ - debug('end'); - process.removeListener('uncaughtException', uncaught); - fn(self.failures); - }); - - // run suites - this.emit('start'); - this.runSuite(this.suite, function(){ - debug('finished running'); - self.emit('end'); - }); - - // uncaught exception - process.on('uncaughtException', uncaught); - - return this; -}; - -/** - * Filter leaks with the given globals flagged as `ok`. - * - * @param {Array} ok - * @param {Array} globals - * @return {Array} - * @api private - */ - -function filterLeaks(ok, globals) { - return filter(globals, function(key){ - var matched = filter(ok, function(ok){ - if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); - return key == ok; - }); - return matched.length == 0 && (!global.navigator || 'onerror' !== key); - }); -} - -}); // module: runner.js - -require.register("suite.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var EventEmitter = require('browser/events').EventEmitter - , debug = require('browser/debug')('mocha:suite') - , milliseconds = require('./ms') - , utils = require('./utils') - , Hook = require('./hook'); - -/** - * Expose `Suite`. - */ - -exports = module.exports = Suite; - -/** - * Create a new `Suite` with the given `title` - * and parent `Suite`. When a suite with the - * same title is already present, that suite - * is returned to provide nicer reporter - * and more flexible meta-testing. - * - * @param {Suite} parent - * @param {String} title - * @return {Suite} - * @api public - */ - -exports.create = function(parent, title){ - var suite = new Suite(title, parent.ctx); - suite.parent = parent; - if (parent.pending) suite.pending = true; - title = suite.fullTitle(); - parent.addSuite(suite); - return suite; -}; - -/** - * Initialize a new `Suite` with the given - * `title` and `ctx`. - * - * @param {String} title - * @param {Context} ctx - * @api private - */ - -function Suite(title, ctx) { - this.title = title; - this.ctx = ctx; - this.suites = []; - this.tests = []; - this.pending = false; - this._beforeEach = []; - this._beforeAll = []; - this._afterEach = []; - this._afterAll = []; - this.root = !title; - this._timeout = 2000; - this._slow = 75; - this._bail = false; -} - -/** - * Inherit from `EventEmitter.prototype`. - */ - -Suite.prototype = new EventEmitter; -Suite.prototype.constructor = Suite; - - -/** - * Return a clone of this `Suite`. - * - * @return {Suite} - * @api private - */ - -Suite.prototype.clone = function(){ - var suite = new Suite(this.title); - debug('clone'); - suite.ctx = this.ctx; - suite.timeout(this.timeout()); - suite.slow(this.slow()); - suite.bail(this.bail()); - return suite; -}; - -/** - * Set timeout `ms` or short-hand such as "2s". - * - * @param {Number|String} ms - * @return {Suite|Number} for chaining - * @api private - */ - -Suite.prototype.timeout = function(ms){ - if (0 == arguments.length) return this._timeout; - if ('string' == typeof ms) ms = milliseconds(ms); - debug('timeout %d', ms); - this._timeout = parseInt(ms, 10); - return this; -}; - -/** - * Set slow `ms` or short-hand such as "2s". - * - * @param {Number|String} ms - * @return {Suite|Number} for chaining - * @api private - */ - -Suite.prototype.slow = function(ms){ - if (0 === arguments.length) return this._slow; - if ('string' == typeof ms) ms = milliseconds(ms); - debug('slow %d', ms); - this._slow = ms; - return this; -}; - -/** - * Sets whether to bail after first error. - * - * @parma {Boolean} bail - * @return {Suite|Number} for chaining - * @api private - */ - -Suite.prototype.bail = function(bail){ - if (0 == arguments.length) return this._bail; - debug('bail %s', bail); - this._bail = bail; - return this; -}; - -/** - * Run `fn(test[, done])` before running tests. - * - * @param {Function} fn - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.beforeAll = function(fn){ - if (this.pending) return this; - var hook = new Hook('"before all" hook', fn); - hook.parent = this; - hook.timeout(this.timeout()); - hook.slow(this.slow()); - hook.ctx = this.ctx; - this._beforeAll.push(hook); - this.emit('beforeAll', hook); - return this; -}; - -/** - * Run `fn(test[, done])` after running tests. - * - * @param {Function} fn - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.afterAll = function(fn){ - if (this.pending) return this; - var hook = new Hook('"after all" hook', fn); - hook.parent = this; - hook.timeout(this.timeout()); - hook.slow(this.slow()); - hook.ctx = this.ctx; - this._afterAll.push(hook); - this.emit('afterAll', hook); - return this; -}; - -/** - * Run `fn(test[, done])` before each test case. - * - * @param {Function} fn - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.beforeEach = function(fn){ - if (this.pending) return this; - var hook = new Hook('"before each" hook', fn); - hook.parent = this; - hook.timeout(this.timeout()); - hook.slow(this.slow()); - hook.ctx = this.ctx; - this._beforeEach.push(hook); - this.emit('beforeEach', hook); - return this; -}; - -/** - * Run `fn(test[, done])` after each test case. - * - * @param {Function} fn - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.afterEach = function(fn){ - if (this.pending) return this; - var hook = new Hook('"after each" hook', fn); - hook.parent = this; - hook.timeout(this.timeout()); - hook.slow(this.slow()); - hook.ctx = this.ctx; - this._afterEach.push(hook); - this.emit('afterEach', hook); - return this; -}; - -/** - * Add a test `suite`. - * - * @param {Suite} suite - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.addSuite = function(suite){ - suite.parent = this; - suite.timeout(this.timeout()); - suite.slow(this.slow()); - suite.bail(this.bail()); - this.suites.push(suite); - this.emit('suite', suite); - return this; -}; - -/** - * Add a `test` to this suite. - * - * @param {Test} test - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.addTest = function(test){ - test.parent = this; - test.timeout(this.timeout()); - test.slow(this.slow()); - test.ctx = this.ctx; - this.tests.push(test); - this.emit('test', test); - return this; -}; - -/** - * Return the full title generated by recursively - * concatenating the parent's full title. - * - * @return {String} - * @api public - */ - -Suite.prototype.fullTitle = function(){ - if (this.parent) { - var full = this.parent.fullTitle(); - if (full) return full + ' ' + this.title; - } - return this.title; -}; - -/** - * Return the total number of tests. - * - * @return {Number} - * @api public - */ - -Suite.prototype.total = function(){ - return utils.reduce(this.suites, function(sum, suite){ - return sum + suite.total(); - }, 0) + this.tests.length; -}; - -/** - * Iterates through each suite recursively to find - * all tests. Applies a function in the format - * `fn(test)`. - * - * @param {Function} fn - * @return {Suite} - * @api private - */ - -Suite.prototype.eachTest = function(fn){ - utils.forEach(this.tests, fn); - utils.forEach(this.suites, function(suite){ - suite.eachTest(fn); - }); - return this; -}; - -}); // module: suite.js - -require.register("test.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Runnable = require('./runnable'); - -/** - * Expose `Test`. - */ - -module.exports = Test; - -/** - * Initialize a new `Test` with the given `title` and callback `fn`. - * - * @param {String} title - * @param {Function} fn - * @api private - */ - -function Test(title, fn) { - Runnable.call(this, title, fn); - this.pending = !fn; - this.type = 'test'; -} - -/** - * Inherit from `Runnable.prototype`. - */ - -Test.prototype = new Runnable; -Test.prototype.constructor = Test; - - -}); // module: test.js - -require.register("utils.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var fs = require('browser/fs') - , path = require('browser/path') - , join = path.join - , debug = require('browser/debug')('mocha:watch'); - -/** - * Ignored directories. - */ - -var ignore = ['node_modules', '.git']; - -/** - * Escape special characters in the given string of html. - * - * @param {String} html - * @return {String} - * @api private - */ - -exports.escape = function(html){ - return String(html) - .replace(/&/g, '&') - .replace(/"/g, '"') - .replace(//g, '>'); -}; - -/** - * Array#forEach (<=IE8) - * - * @param {Array} array - * @param {Function} fn - * @param {Object} scope - * @api private - */ - -exports.forEach = function(arr, fn, scope){ - for (var i = 0, l = arr.length; i < l; i++) - fn.call(scope, arr[i], i); -}; - -/** - * Array#indexOf (<=IE8) - * - * @parma {Array} arr - * @param {Object} obj to find index of - * @param {Number} start - * @api private - */ - -exports.indexOf = function(arr, obj, start){ - for (var i = start || 0, l = arr.length; i < l; i++) { - if (arr[i] === obj) - return i; - } - return -1; -}; - -/** - * Array#reduce (<=IE8) - * - * @param {Array} array - * @param {Function} fn - * @param {Object} initial value - * @api private - */ - -exports.reduce = function(arr, fn, val){ - var rval = val; - - for (var i = 0, l = arr.length; i < l; i++) { - rval = fn(rval, arr[i], i, arr); - } - - return rval; -}; - -/** - * Array#filter (<=IE8) - * - * @param {Array} array - * @param {Function} fn - * @api private - */ - -exports.filter = function(arr, fn){ - var ret = []; - - for (var i = 0, l = arr.length; i < l; i++) { - var val = arr[i]; - if (fn(val, i, arr)) ret.push(val); - } - - return ret; -}; - -/** - * Object.keys (<=IE8) - * - * @param {Object} obj - * @return {Array} keys - * @api private - */ - -exports.keys = Object.keys || function(obj) { - var keys = [] - , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 - - for (var key in obj) { - if (has.call(obj, key)) { - keys.push(key); - } - } - - return keys; -}; - -/** - * Watch the given `files` for changes - * and invoke `fn(file)` on modification. - * - * @param {Array} files - * @param {Function} fn - * @api private - */ - -exports.watch = function(files, fn){ - var options = { interval: 100 }; - files.forEach(function(file){ - debug('file %s', file); - fs.watchFile(file, options, function(curr, prev){ - if (prev.mtime < curr.mtime) fn(file); - }); - }); -}; - -/** - * Ignored files. - */ - -function ignored(path){ - return !~ignore.indexOf(path); -} - -/** - * Lookup files in the given `dir`. - * - * @return {Array} - * @api private - */ - -exports.files = function(dir, ret){ - ret = ret || []; - - fs.readdirSync(dir) - .filter(ignored) - .forEach(function(path){ - path = join(dir, path); - if (fs.statSync(path).isDirectory()) { - exports.files(path, ret); - } else if (path.match(/\.(js|coffee)$/)) { - ret.push(path); - } - }); - - return ret; -}; - -/** - * Compute a slug from the given `str`. - * - * @param {String} str - * @return {String} - * @api private - */ - -exports.slug = function(str){ - return str - .toLowerCase() - .replace(/ +/g, '-') - .replace(/[^-\w]/g, ''); -}; - -/** - * Strip the function definition from `str`, - * and re-indent for pre whitespace. - */ - -exports.clean = function(str) { - str = str - .replace(/^function *\(.*\) *{/, '') - .replace(/\s+\}$/, ''); - - var spaces = str.match(/^\n?( *)/)[1].length - , re = new RegExp('^ {' + spaces + '}', 'gm'); - - str = str.replace(re, ''); - - return exports.trim(str); -}; - -/** - * Escape regular expression characters in `str`. - * - * @param {String} str - * @return {String} - * @api private - */ - -exports.escapeRegexp = function(str){ - return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); -}; - -/** - * Trim the given `str`. - * - * @param {String} str - * @return {String} - * @api private - */ - -exports.trim = function(str){ - return str.replace(/^\s+|\s+$/g, ''); -}; - -/** - * Parse the given `qs`. - * - * @param {String} qs - * @return {Object} - * @api private - */ - -exports.parseQuery = function(qs){ - return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ - var i = pair.indexOf('=') - , key = pair.slice(0, i) - , val = pair.slice(++i); - - obj[key] = decodeURIComponent(val); - return obj; - }, {}); -}; - -/** - * Highlight the given string of `js`. - * - * @param {String} js - * @return {String} - * @api private - */ - -function highlight(js) { - return js - .replace(//g, '>') - .replace(/\/\/(.*)/gm, '//$1') - .replace(/('.*?')/gm, '$1') - .replace(/(\d+\.\d+)/gm, '$1') - .replace(/(\d+)/gm, '$1') - .replace(/\bnew *(\w+)/gm, 'new $1') - .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') -} - -/** - * Highlight the contents of tag `name`. - * - * @param {String} name - * @api private - */ - -exports.highlightTags = function(name) { - var code = document.getElementsByTagName(name); - for (var i = 0, len = code.length; i < len; ++i) { - code[i].innerHTML = highlight(code[i].innerHTML); - } -}; - -}); // module: utils.js -/** - * Node shims. - * - * These are meant only to allow - * mocha.js to run untouched, not - * to allow running node code in - * the browser. - */ - -process = {}; -process.exit = function(status){}; -process.stdout = {}; -global = window; - -/** - * next tick implementation. - */ - -process.nextTick = (function(){ - // postMessage behaves badly on IE8 - if (window.ActiveXObject || !window.postMessage) { - return function(fn){ fn() }; - } - - // based on setZeroTimeout by David Baron - // - http://dbaron.org/log/20100309-faster-timeouts - var timeouts = [] - , name = 'mocha-zero-timeout' - - window.addEventListener('message', function(e){ - if (e.source == window && e.data == name) { - if (e.stopPropagation) e.stopPropagation(); - if (timeouts.length) timeouts.shift()(); - } - }, true); - - return function(fn){ - timeouts.push(fn); - window.postMessage(name, '*'); - } -})(); - -/** - * Remove uncaughtException listener. - */ - -process.removeListener = function(e){ - if ('uncaughtException' == e) { - window.onerror = null; - } -}; - -/** - * Implements uncaughtException listener. - */ - -process.on = function(e, fn){ - if ('uncaughtException' == e) { - window.onerror = fn; - } -}; - -// boot -;(function(){ - - /** - * Expose mocha. - */ - - var Mocha = window.Mocha = require('mocha'), - mocha = window.mocha = new Mocha({ reporter: 'html' }); - - /** - * Override ui to ensure that the ui functions are initialized. - * Normally this would happen in Mocha.prototype.loadFiles. - */ - - mocha.ui = function(ui){ - Mocha.prototype.ui.call(this, ui); - this.suite.emit('pre-require', window, null, this); - return this; - }; - - /** - * Setup mocha with the given setting options. - */ - - mocha.setup = function(opts){ - if ('string' == typeof opts) opts = { ui: opts }; - for (var opt in opts) this[opt](opts[opt]); - return this; - }; - - /** - * Run mocha, returning the Runner. - */ - - mocha.run = function(fn){ - var options = mocha.options; - mocha.globals('location'); - - //var query = Mocha.utils.parseQuery(window.location.search || ''); - //if (query.grep) mocha.grep(query.grep); - - return Mocha.prototype.run.call(mocha, function(){ - Mocha.utils.highlightTags('code'); - if (fn) fn(); - }); - }; -})(); -})(); \ No newline at end of file diff --git a/sources/tests/frontend/lib/sendkeys.js b/sources/tests/frontend/lib/sendkeys.js deleted file mode 100644 index b576184..0000000 --- a/sources/tests/frontend/lib/sendkeys.js +++ /dev/null @@ -1,467 +0,0 @@ -// Cross-broswer implementation of text ranges and selections -// documentation: http://bililite.com/blog/2011/01/11/cross-browser-.and-selections/ -// Version: 1.1 -// Copyright (c) 2010 Daniel Wachsstock -// MIT license: -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: - -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -(function($){ - -bililiteRange = function(el, debug){ - var ret; - if (debug){ - ret = new NothingRange(); // Easier to force it to use the no-selection type than to try to find an old browser - }else if (document.selection && !document.addEventListener){ - // Internet Explorer 8 and lower - ret = new IERange(); - }else if (window.getSelection && el.setSelectionRange){ - // Standards. Element is an input or textarea - ret = new InputRange(); - }else if (window.getSelection){ - // Standards, with any other kind of element - ret = new W3CRange() - }else{ - // doesn't support selection - ret = new NothingRange(); - } - ret._el = el; - ret._doc = el.ownerDocument; - ret._win = 'defaultView' in ret._doc ? ret._doc.defaultView : ret._doc.parentWindow; - ret._textProp = textProp(el); - ret._bounds = [0, ret.length()]; - return ret; -} - -function textProp(el){ - // returns the property that contains the text of the element - if (typeof el.value != 'undefined') return 'value'; - if (typeof el.text != 'undefined') return 'text'; - if (typeof el.textContent != 'undefined') return 'textContent'; - return 'innerText'; -} - -// base class -function Range(){} -Range.prototype = { - length: function() { - return this._el[this._textProp].replace(/\r/g, '').length; // need to correct for IE's CrLf weirdness - }, - bounds: function(s){ - if (s === 'all'){ - this._bounds = [0, this.length()]; - }else if (s === 'start'){ - this._bounds = [0, 0]; - }else if (s === 'end'){ - this._bounds = [this.length(), this.length()]; - }else if (s === 'selection'){ - this.bounds ('all'); // first select the whole thing for constraining - this._bounds = this._nativeSelection(); - }else if (s){ - this._bounds = s; // don't error check now; the element may change at any moment, so constrain it when we need it. - }else{ - var b = [ - Math.max(0, Math.min (this.length(), this._bounds[0])), - Math.max(0, Math.min (this.length(), this._bounds[1])) - ]; - return b; // need to constrain it to fit - } - return this; // allow for chaining - }, - select: function(){ - this._nativeSelect(this._nativeRange(this.bounds())); - return this; // allow for chaining - }, - text: function(text, select){ - if (arguments.length){ - this._nativeSetText(text, this._nativeRange(this.bounds())); - if (select == 'start'){ - this.bounds ([this._bounds[0], this._bounds[0]]); - this.select(); - }else if (select == 'end'){ - this.bounds ([this._bounds[0]+text.length, this._bounds[0]+text.length]); - this.select(); - }else if (select == 'all'){ - this.bounds ([this._bounds[0], this._bounds[0]+text.length]); - this.select(); - } - return this; // allow for chaining - }else{ - return this._nativeGetText(this._nativeRange(this.bounds())); - } - }, - insertEOL: function (){ - this._nativeEOL(); - this._bounds = [this._bounds[0]+1, this._bounds[0]+1]; // move past the EOL marker - return this; - } -}; - - -function IERange(){} -IERange.prototype = new Range(); -IERange.prototype._nativeRange = function (bounds){ - var rng; - if (this._el.tagName == 'INPUT'){ - // IE 8 is very inconsistent; textareas have createTextRange but it doesn't work - rng = this._el.createTextRange(); - }else{ - rng = this._doc.body.createTextRange (); - rng.moveToElementText(this._el); - } - if (bounds){ - if (bounds[1] < 0) bounds[1] = 0; // IE tends to run elements out of bounds - if (bounds[0] > this.length()) bounds[0] = this.length(); - if (bounds[1] < rng.text.replace(/\r/g, '').length){ // correct for IE's CrLf wierdness - // block-display elements have an invisible, uncounted end of element marker, so we move an extra one and use the current length of the range - rng.moveEnd ('character', -1); - rng.moveEnd ('character', bounds[1]-rng.text.replace(/\r/g, '').length); - } - if (bounds[0] > 0) rng.moveStart('character', bounds[0]); - } - return rng; -}; -IERange.prototype._nativeSelect = function (rng){ - rng.select(); -}; -IERange.prototype._nativeSelection = function (){ - // returns [start, end] for the selection constrained to be in element - var rng = this._nativeRange(); // range of the element to constrain to - var len = this.length(); - if (this._doc.selection.type != 'Text') return [0,0]; // append to the end - var sel = this._doc.selection.createRange(); - try{ - return [ - iestart(sel, rng), - ieend (sel, rng) - ]; - }catch (e){ - // IE gets upset sometimes about comparing text to input elements, but the selections cannot overlap, so make a best guess - return (sel.parentElement().sourceIndex < this._el.sourceIndex) ? [0,0] : [len, len]; - } -}; -IERange.prototype._nativeGetText = function (rng){ - return rng.text.replace(/\r/g, ''); // correct for IE's CrLf weirdness -}; -IERange.prototype._nativeSetText = function (text, rng){ - rng.text = text; -}; -IERange.prototype._nativeEOL = function(){ - if (typeof this._el.value != 'undefined'){ - this.text('\n'); // for input and textarea, insert it straight - }else{ - this._nativeRange(this.bounds()).pasteHTML('
      '); - } -}; -// IE internals -function iestart(rng, constraint){ - // returns the position (in character) of the start of rng within constraint. If it's not in constraint, returns 0 if it's before, length if it's after - var len = constraint.text.replace(/\r/g, '').length; // correct for IE's CrLf wierdness - if (rng.compareEndPoints ('StartToStart', constraint) <= 0) return 0; // at or before the beginning - if (rng.compareEndPoints ('StartToEnd', constraint) >= 0) return len; - for (var i = 0; rng.compareEndPoints ('StartToStart', constraint) > 0; ++i, rng.moveStart('character', -1)); - return i; -} -function ieend (rng, constraint){ - // returns the position (in character) of the end of rng within constraint. If it's not in constraint, returns 0 if it's before, length if it's after - var len = constraint.text.replace(/\r/g, '').length; // correct for IE's CrLf wierdness - if (rng.compareEndPoints ('EndToEnd', constraint) >= 0) return len; // at or after the end - if (rng.compareEndPoints ('EndToStart', constraint) <= 0) return 0; - for (var i = 0; rng.compareEndPoints ('EndToStart', constraint) > 0; ++i, rng.moveEnd('character', -1)); - return i; -} - -// an input element in a standards document. "Native Range" is just the bounds array -function InputRange(){} -InputRange.prototype = new Range(); -InputRange.prototype._nativeRange = function(bounds) { - return bounds || [0, this.length()]; -}; -InputRange.prototype._nativeSelect = function (rng){ - this._el.setSelectionRange(rng[0], rng[1]); -}; -InputRange.prototype._nativeSelection = function(){ - return [this._el.selectionStart, this._el.selectionEnd]; -}; -InputRange.prototype._nativeGetText = function(rng){ - return this._el.value.substring(rng[0], rng[1]); -}; -InputRange.prototype._nativeSetText = function(text, rng){ - var val = this._el.value; - this._el.value = val.substring(0, rng[0]) + text + val.substring(rng[1]); -}; -InputRange.prototype._nativeEOL = function(){ - this.text('\n'); -}; - -function W3CRange(){} -W3CRange.prototype = new Range(); -W3CRange.prototype._nativeRange = function (bounds){ - var rng = this._doc.createRange(); - rng.selectNodeContents(this._el); - if (bounds){ - w3cmoveBoundary (rng, bounds[0], true, this._el); - rng.collapse (true); - w3cmoveBoundary (rng, bounds[1]-bounds[0], false, this._el); - } - return rng; -}; -W3CRange.prototype._nativeSelect = function (rng){ - this._win.getSelection().removeAllRanges(); - this._win.getSelection().addRange (rng); -}; -W3CRange.prototype._nativeSelection = function (){ - // returns [start, end] for the selection constrained to be in element - var rng = this._nativeRange(); // range of the element to constrain to - if (this._win.getSelection().rangeCount == 0) return [this.length(), this.length()]; // append to the end - var sel = this._win.getSelection().getRangeAt(0); - return [ - w3cstart(sel, rng), - w3cend (sel, rng) - ]; - } -W3CRange.prototype._nativeGetText = function (rng){ - return rng.toString(); -}; -W3CRange.prototype._nativeSetText = function (text, rng){ - rng.deleteContents(); - rng.insertNode (this._doc.createTextNode(text)); - this._el.normalize(); // merge the text with the surrounding text -}; -W3CRange.prototype._nativeEOL = function(){ - var rng = this._nativeRange(this.bounds()); - rng.deleteContents(); - var br = this._doc.createElement('br'); - br.setAttribute ('_moz_dirty', ''); // for Firefox - rng.insertNode (br); - rng.insertNode (this._doc.createTextNode('\n')); - rng.collapse (false); -}; -// W3C internals -function nextnode (node, root){ - // in-order traversal - // we've already visited node, so get kids then siblings - if (node.firstChild) return node.firstChild; - if (node.nextSibling) return node.nextSibling; - if (node===root) return null; - while (node.parentNode){ - // get uncles - node = node.parentNode; - if (node == root) return null; - if (node.nextSibling) return node.nextSibling; - } - return null; -} -function w3cmoveBoundary (rng, n, bStart, el){ - // move the boundary (bStart == true ? start : end) n characters forward, up to the end of element el. Forward only! - // if the start is moved after the end, then an exception is raised - if (n <= 0) return; - var node = rng[bStart ? 'startContainer' : 'endContainer']; - if (node.nodeType == 3){ - // we may be starting somewhere into the text - n += rng[bStart ? 'startOffset' : 'endOffset']; - } - while (node){ - if (node.nodeType == 3){ - if (n <= node.nodeValue.length){ - rng[bStart ? 'setStart' : 'setEnd'](node, n); - // special case: if we end next to a
      , include that node. - if (n == node.nodeValue.length){ - // skip past zero-length text nodes - for (var next = nextnode (node, el); next && next.nodeType==3 && next.nodeValue.length == 0; next = nextnode(next, el)){ - rng[bStart ? 'setStartAfter' : 'setEndAfter'](next); - } - if (next && next.nodeType == 1 && next.nodeName == "BR") rng[bStart ? 'setStartAfter' : 'setEndAfter'](next); - } - return; - }else{ - rng[bStart ? 'setStartAfter' : 'setEndAfter'](node); // skip past this one - n -= node.nodeValue.length; // and eat these characters - } - } - node = nextnode (node, el); - } -} -var START_TO_START = 0; // from the w3c definitions -var START_TO_END = 1; -var END_TO_END = 2; -var END_TO_START = 3; -// from the Mozilla documentation, for range.compareBoundaryPoints(how, sourceRange) -// -1, 0, or 1, indicating whether the corresponding boundary-point of range is respectively before, equal to, or after the corresponding boundary-point of sourceRange. - // * Range.END_TO_END compares the end boundary-point of sourceRange to the end boundary-point of range. - // * Range.END_TO_START compares the end boundary-point of sourceRange to the start boundary-point of range. - // * Range.START_TO_END compares the start boundary-point of sourceRange to the end boundary-point of range. - // * Range.START_TO_START compares the start boundary-point of sourceRange to the start boundary-point of range. -function w3cstart(rng, constraint){ - if (rng.compareBoundaryPoints (START_TO_START, constraint) <= 0) return 0; // at or before the beginning - if (rng.compareBoundaryPoints (END_TO_START, constraint) >= 0) return constraint.toString().length; - rng = rng.cloneRange(); // don't change the original - rng.setEnd (constraint.endContainer, constraint.endOffset); // they now end at the same place - return constraint.toString().length - rng.toString().length; -} -function w3cend (rng, constraint){ - if (rng.compareBoundaryPoints (END_TO_END, constraint) >= 0) return constraint.toString().length; // at or after the end - if (rng.compareBoundaryPoints (START_TO_END, constraint) <= 0) return 0; - rng = rng.cloneRange(); // don't change the original - rng.setStart (constraint.startContainer, constraint.startOffset); // they now start at the same place - return rng.toString().length; -} - -function NothingRange(){} -NothingRange.prototype = new Range(); -NothingRange.prototype._nativeRange = function(bounds) { - return bounds || [0,this.length()]; -}; -NothingRange.prototype._nativeSelect = function (rng){ // do nothing -}; -NothingRange.prototype._nativeSelection = function(){ - return [0,0]; -}; -NothingRange.prototype._nativeGetText = function (rng){ - return this._el[this._textProp].substring(rng[0], rng[1]); -}; -NothingRange.prototype._nativeSetText = function (text, rng){ - var val = this._el[this._textProp]; - this._el[this._textProp] = val.substring(0, rng[0]) + text + val.substring(rng[1]); -}; -NothingRange.prototype._nativeEOL = function(){ - this.text('\n'); -}; - -})(jQuery); - -// insert characters in a textarea or text input field -// special characters are enclosed in {}; use {{} for the { character itself -// documentation: http://bililite.com/blog/2008/08/20/the-fnsendkeys-plugin/ -// Version: 2.0 -// Copyright (c) 2010 Daniel Wachsstock -// MIT license: -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: - -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -(function($){ - -$.fn.sendkeys = function (x, opts){ - return this.each( function(){ - var localkeys = $.extend({}, opts, $(this).data('sendkeys')); // allow for element-specific key functions - // most elements to not keep track of their selection when they lose focus, so we have to do it for them - var rng = $.data (this, 'sendkeys.selection'); - if (!rng){ - rng = bililiteRange(this).bounds('selection'); - $.data(this, 'sendkeys.selection', rng); - $(this).bind('mouseup.sendkeys', function(){ - // we have to update the saved range. The routines here update the bounds with each press, but actual keypresses and mouseclicks do not - $.data(this, 'sendkeys.selection').bounds('selection'); - }).bind('keyup.sendkeys', function(evt){ - // restore the selection if we got here with a tab (a click should select what was clicked on) - if (evt.which == 9){ - // there's a flash of selection when we restore the focus, but I don't know how to avoid that - $.data(this, 'sendkeys.selection').select(); - }else{ - $.data(this, 'sendkeys.selection').bounds('selection'); - } - }); - } - this.focus(); - if (typeof x === 'undefined') return; // no string, so we just set up the event handlers - $.data(this, 'sendkeys.originalText', rng.text()); - x.replace(/\n/g, '{enter}'). // turn line feeds into explicit break insertions - replace(/{[^}]*}|[^{]+/g, function(s){ - (localkeys[s] || $.fn.sendkeys.defaults[s] || $.fn.sendkeys.defaults.simplechar)(rng, s); - }); - $(this).trigger({type: 'sendkeys', which: x}); - }); -}; // sendkeys - - -// add the functions publicly so they can be overridden -$.fn.sendkeys.defaults = { - simplechar: function (rng, s){ - rng.text(s, 'end'); - for (var i =0; i < s.length; ++i){ - var x = s.charCodeAt(i); - // a bit of cheating: rng._el is the element associated with rng. - $(rng._el).trigger({type: 'keypress', keyCode: x, which: x, charCode: x}); - } - }, - '{{}': function (rng){ - $.fn.sendkeys.defaults.simplechar (rng, '{') - }, - '{enter}': function (rng){ - rng.insertEOL(); - rng.select(); - var x = '\n'.charCodeAt(0); - $(rng._el).trigger({type: 'keypress', keyCode: x, which: x, charCode: x}); - }, - '{backspace}': function (rng){ - var b = rng.bounds(); - if (b[0] == b[1]) rng.bounds([b[0]-1, b[0]]); // no characters selected; it's just an insertion point. Remove the previous character - rng.text('', 'end'); // delete the characters and update the selection - }, - '{del}': function (rng){ - var b = rng.bounds(); - if (b[0] == b[1]) rng.bounds([b[0], b[0]+1]); // no characters selected; it's just an insertion point. Remove the next character - rng.text('', 'end'); // delete the characters and update the selection - }, - '{rightarrow}': function (rng){ - var b = rng.bounds(); - if (b[0] == b[1]) ++b[1]; // no characters selected; it's just an insertion point. Move to the right - rng.bounds([b[1], b[1]]).select(); - }, - '{leftarrow}': function (rng){ - var b = rng.bounds(); - if (b[0] == b[1]) --b[0]; // no characters selected; it's just an insertion point. Move to the left - rng.bounds([b[0], b[0]]).select(); - }, - '{selectall}' : function (rng){ - rng.bounds('all').select(); - }, - '{selection}': function (rng){ - $.fn.sendkeys.defaults.simplechar(rng, $.data(rng._el, 'sendkeys.originalText')); - }, - '{mark}' : function (rng){ - var bounds = rng.bounds(); - $(rng._el).one('sendkeys', function(){ - // set up the event listener to change the selection after the sendkeys is done - rng.bounds(bounds).select(); - }); - } -}; - -})(jQuery) diff --git a/sources/tests/frontend/lib/underscore.js b/sources/tests/frontend/lib/underscore.js deleted file mode 100644 index 1ebe267..0000000 --- a/sources/tests/frontend/lib/underscore.js +++ /dev/null @@ -1,1200 +0,0 @@ -// Underscore.js 1.4.2 -// http://underscorejs.org -// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore may be freely distributed under the MIT license. - -(function() { - - // Baseline setup - // -------------- - - // Establish the root object, `window` in the browser, or `global` on the server. - var root = this; - - // Save the previous value of the `_` variable. - var previousUnderscore = root._; - - // Establish the object that gets returned to break out of a loop iteration. - var breaker = {}; - - // Save bytes in the minified (but not gzipped) version: - var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; - - // Create quick reference variables for speed access to core prototypes. - var push = ArrayProto.push, - slice = ArrayProto.slice, - concat = ArrayProto.concat, - unshift = ArrayProto.unshift, - toString = ObjProto.toString, - hasOwnProperty = ObjProto.hasOwnProperty; - - // All **ECMAScript 5** native function implementations that we hope to use - // are declared here. - var - nativeForEach = ArrayProto.forEach, - nativeMap = ArrayProto.map, - nativeReduce = ArrayProto.reduce, - nativeReduceRight = ArrayProto.reduceRight, - nativeFilter = ArrayProto.filter, - nativeEvery = ArrayProto.every, - nativeSome = ArrayProto.some, - nativeIndexOf = ArrayProto.indexOf, - nativeLastIndexOf = ArrayProto.lastIndexOf, - nativeIsArray = Array.isArray, - nativeKeys = Object.keys, - nativeBind = FuncProto.bind; - - // Create a safe reference to the Underscore object for use below. - var _ = function(obj) { - if (obj instanceof _) return obj; - if (!(this instanceof _)) return new _(obj); - this._wrapped = obj; - }; - - // Export the Underscore object for **Node.js**, with - // backwards-compatibility for the old `require()` API. If we're in - // the browser, add `_` as a global object via a string identifier, - // for Closure Compiler "advanced" mode. - if (typeof exports !== 'undefined') { - if (typeof module !== 'undefined' && module.exports) { - exports = module.exports = _; - } - exports._ = _; - } else { - root['_'] = _; - } - - // Current version. - _.VERSION = '1.4.2'; - - // Collection Functions - // -------------------- - - // The cornerstone, an `each` implementation, aka `forEach`. - // Handles objects with the built-in `forEach`, arrays, and raw objects. - // Delegates to **ECMAScript 5**'s native `forEach` if available. - var each = _.each = _.forEach = function(obj, iterator, context) { - if (obj == null) return; - if (nativeForEach && obj.forEach === nativeForEach) { - obj.forEach(iterator, context); - } else if (obj.length === +obj.length) { - for (var i = 0, l = obj.length; i < l; i++) { - if (iterator.call(context, obj[i], i, obj) === breaker) return; - } - } else { - for (var key in obj) { - if (_.has(obj, key)) { - if (iterator.call(context, obj[key], key, obj) === breaker) return; - } - } - } - }; - - // Return the results of applying the iterator to each element. - // Delegates to **ECMAScript 5**'s native `map` if available. - _.map = _.collect = function(obj, iterator, context) { - var results = []; - if (obj == null) return results; - if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); - each(obj, function(value, index, list) { - results[results.length] = iterator.call(context, value, index, list); - }); - return results; - }; - - // **Reduce** builds up a single result from a list of values, aka `inject`, - // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. - _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { - var initial = arguments.length > 2; - if (obj == null) obj = []; - if (nativeReduce && obj.reduce === nativeReduce) { - if (context) iterator = _.bind(iterator, context); - return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); - } - each(obj, function(value, index, list) { - if (!initial) { - memo = value; - initial = true; - } else { - memo = iterator.call(context, memo, value, index, list); - } - }); - if (!initial) throw new TypeError('Reduce of empty array with no initial value'); - return memo; - }; - - // The right-associative version of reduce, also known as `foldr`. - // Delegates to **ECMAScript 5**'s native `reduceRight` if available. - _.reduceRight = _.foldr = function(obj, iterator, memo, context) { - var initial = arguments.length > 2; - if (obj == null) obj = []; - if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { - if (context) iterator = _.bind(iterator, context); - return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); - } - var length = obj.length; - if (length !== +length) { - var keys = _.keys(obj); - length = keys.length; - } - each(obj, function(value, index, list) { - index = keys ? keys[--length] : --length; - if (!initial) { - memo = obj[index]; - initial = true; - } else { - memo = iterator.call(context, memo, obj[index], index, list); - } - }); - if (!initial) throw new TypeError('Reduce of empty array with no initial value'); - return memo; - }; - - // Return the first value which passes a truth test. Aliased as `detect`. - _.find = _.detect = function(obj, iterator, context) { - var result; - any(obj, function(value, index, list) { - if (iterator.call(context, value, index, list)) { - result = value; - return true; - } - }); - return result; - }; - - // Return all the elements that pass a truth test. - // Delegates to **ECMAScript 5**'s native `filter` if available. - // Aliased as `select`. - _.filter = _.select = function(obj, iterator, context) { - var results = []; - if (obj == null) return results; - if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); - each(obj, function(value, index, list) { - if (iterator.call(context, value, index, list)) results[results.length] = value; - }); - return results; - }; - - // Return all the elements for which a truth test fails. - _.reject = function(obj, iterator, context) { - var results = []; - if (obj == null) return results; - each(obj, function(value, index, list) { - if (!iterator.call(context, value, index, list)) results[results.length] = value; - }); - return results; - }; - - // Determine whether all of the elements match a truth test. - // Delegates to **ECMAScript 5**'s native `every` if available. - // Aliased as `all`. - _.every = _.all = function(obj, iterator, context) { - iterator || (iterator = _.identity); - var result = true; - if (obj == null) return result; - if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); - each(obj, function(value, index, list) { - if (!(result = result && iterator.call(context, value, index, list))) return breaker; - }); - return !!result; - }; - - // Determine if at least one element in the object matches a truth test. - // Delegates to **ECMAScript 5**'s native `some` if available. - // Aliased as `any`. - var any = _.some = _.any = function(obj, iterator, context) { - iterator || (iterator = _.identity); - var result = false; - if (obj == null) return result; - if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); - each(obj, function(value, index, list) { - if (result || (result = iterator.call(context, value, index, list))) return breaker; - }); - return !!result; - }; - - // Determine if the array or object contains a given value (using `===`). - // Aliased as `include`. - _.contains = _.include = function(obj, target) { - var found = false; - if (obj == null) return found; - if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; - found = any(obj, function(value) { - return value === target; - }); - return found; - }; - - // Invoke a method (with arguments) on every item in a collection. - _.invoke = function(obj, method) { - var args = slice.call(arguments, 2); - return _.map(obj, function(value) { - return (_.isFunction(method) ? method : value[method]).apply(value, args); - }); - }; - - // Convenience version of a common use case of `map`: fetching a property. - _.pluck = function(obj, key) { - return _.map(obj, function(value){ return value[key]; }); - }; - - // Convenience version of a common use case of `filter`: selecting only objects - // with specific `key:value` pairs. - _.where = function(obj, attrs) { - if (_.isEmpty(attrs)) return []; - return _.filter(obj, function(value) { - for (var key in attrs) { - if (attrs[key] !== value[key]) return false; - } - return true; - }); - }; - - // Return the maximum element or (element-based computation). - // Can't optimize arrays of integers longer than 65,535 elements. - // See: https://bugs.webkit.org/show_bug.cgi?id=80797 - _.max = function(obj, iterator, context) { - if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { - return Math.max.apply(Math, obj); - } - if (!iterator && _.isEmpty(obj)) return -Infinity; - var result = {computed : -Infinity}; - each(obj, function(value, index, list) { - var computed = iterator ? iterator.call(context, value, index, list) : value; - computed >= result.computed && (result = {value : value, computed : computed}); - }); - return result.value; - }; - - // Return the minimum element (or element-based computation). - _.min = function(obj, iterator, context) { - if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { - return Math.min.apply(Math, obj); - } - if (!iterator && _.isEmpty(obj)) return Infinity; - var result = {computed : Infinity}; - each(obj, function(value, index, list) { - var computed = iterator ? iterator.call(context, value, index, list) : value; - computed < result.computed && (result = {value : value, computed : computed}); - }); - return result.value; - }; - - // Shuffle an array. - _.shuffle = function(obj) { - var rand; - var index = 0; - var shuffled = []; - each(obj, function(value) { - rand = _.random(index++); - shuffled[index - 1] = shuffled[rand]; - shuffled[rand] = value; - }); - return shuffled; - }; - - // An internal function to generate lookup iterators. - var lookupIterator = function(value) { - return _.isFunction(value) ? value : function(obj){ return obj[value]; }; - }; - - // Sort the object's values by a criterion produced by an iterator. - _.sortBy = function(obj, value, context) { - var iterator = lookupIterator(value); - return _.pluck(_.map(obj, function(value, index, list) { - return { - value : value, - index : index, - criteria : iterator.call(context, value, index, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; - } - return left.index < right.index ? -1 : 1; - }), 'value'); - }; - - // An internal function used for aggregate "group by" operations. - var group = function(obj, value, context, behavior) { - var result = {}; - var iterator = lookupIterator(value); - each(obj, function(value, index) { - var key = iterator.call(context, value, index, obj); - behavior(result, key, value); - }); - return result; - }; - - // Groups the object's values by a criterion. Pass either a string attribute - // to group by, or a function that returns the criterion. - _.groupBy = function(obj, value, context) { - return group(obj, value, context, function(result, key, value) { - (_.has(result, key) ? result[key] : (result[key] = [])).push(value); - }); - }; - - // Counts instances of an object that group by a certain criterion. Pass - // either a string attribute to count by, or a function that returns the - // criterion. - _.countBy = function(obj, value, context) { - return group(obj, value, context, function(result, key, value) { - if (!_.has(result, key)) result[key] = 0; - result[key]++; - }); - }; - - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iterator, context) { - iterator = iterator == null ? _.identity : lookupIterator(iterator); - var value = iterator.call(context, obj); - var low = 0, high = array.length; - while (low < high) { - var mid = (low + high) >>> 1; - iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; - } - return low; - }; - - // Safely convert anything iterable into a real, live array. - _.toArray = function(obj) { - if (!obj) return []; - if (obj.length === +obj.length) return slice.call(obj); - return _.values(obj); - }; - - // Return the number of elements in an object. - _.size = function(obj) { - return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; - }; - - // Array Functions - // --------------- - - // Get the first element of an array. Passing **n** will return the first N - // values in the array. Aliased as `head` and `take`. The **guard** check - // allows it to work with `_.map`. - _.first = _.head = _.take = function(array, n, guard) { - return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; - }; - - // Returns everything but the last entry of the array. Especially useful on - // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. The **guard** check allows it to work with - // `_.map`. - _.initial = function(array, n, guard) { - return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); - }; - - // Get the last element of an array. Passing **n** will return the last N - // values in the array. The **guard** check allows it to work with `_.map`. - _.last = function(array, n, guard) { - if ((n != null) && !guard) { - return slice.call(array, Math.max(array.length - n, 0)); - } else { - return array[array.length - 1]; - } - }; - - // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. - // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. The **guard** - // check allows it to work with `_.map`. - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, (n == null) || guard ? 1 : n); - }; - - // Trim out all falsy values from an array. - _.compact = function(array) { - return _.filter(array, function(value){ return !!value; }); - }; - - // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, output) { - each(input, function(value) { - if (_.isArray(value)) { - shallow ? push.apply(output, value) : flatten(value, shallow, output); - } else { - output.push(value); - } - }); - return output; - }; - - // Return a completely flattened version of an array. - _.flatten = function(array, shallow) { - return flatten(array, shallow, []); - }; - - // Return a version of the array that does not contain the specified value(s). - _.without = function(array) { - return _.difference(array, slice.call(arguments, 1)); - }; - - // Produce a duplicate-free version of the array. If the array has already - // been sorted, you have the option of using a faster algorithm. - // Aliased as `unique`. - _.uniq = _.unique = function(array, isSorted, iterator, context) { - var initial = iterator ? _.map(array, iterator, context) : array; - var results = []; - var seen = []; - each(initial, function(value, index) { - if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { - seen.push(value); - results.push(array[index]); - } - }); - return results; - }; - - // Produce an array that contains the union: each distinct element from all of - // the passed-in arrays. - _.union = function() { - return _.uniq(concat.apply(ArrayProto, arguments)); - }; - - // Produce an array that contains every item shared between all the - // passed-in arrays. - _.intersection = function(array) { - var rest = slice.call(arguments, 1); - return _.filter(_.uniq(array), function(item) { - return _.every(rest, function(other) { - return _.indexOf(other, item) >= 0; - }); - }); - }; - - // Take the difference between one array and a number of other arrays. - // Only the elements present in just the first array will remain. - _.difference = function(array) { - var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); - return _.filter(array, function(value){ return !_.contains(rest, value); }); - }; - - // Zip together multiple lists into a single array -- elements that share - // an index go together. - _.zip = function() { - var args = slice.call(arguments); - var length = _.max(_.pluck(args, 'length')); - var results = new Array(length); - for (var i = 0; i < length; i++) { - results[i] = _.pluck(args, "" + i); - } - return results; - }; - - // Converts lists into objects. Pass either a single array of `[key, value]` - // pairs, or two parallel arrays of the same length -- one of keys, and one of - // the corresponding values. - _.object = function(list, values) { - var result = {}; - for (var i = 0, l = list.length; i < l; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; - }; - - // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), - // we need this function. Return the position of the first occurrence of an - // item in an array, or -1 if the item is not included in the array. - // Delegates to **ECMAScript 5**'s native `indexOf` if available. - // If the array is large and already in sort order, pass `true` - // for **isSorted** to use binary search. - _.indexOf = function(array, item, isSorted) { - if (array == null) return -1; - var i = 0, l = array.length; - if (isSorted) { - if (typeof isSorted == 'number') { - i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); - } else { - i = _.sortedIndex(array, item); - return array[i] === item ? i : -1; - } - } - if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); - for (; i < l; i++) if (array[i] === item) return i; - return -1; - }; - - // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. - _.lastIndexOf = function(array, item, from) { - if (array == null) return -1; - var hasIndex = from != null; - if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { - return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); - } - var i = (hasIndex ? from : array.length); - while (i--) if (array[i] === item) return i; - return -1; - }; - - // Generate an integer Array containing an arithmetic progression. A port of - // the native Python `range()` function. See - // [the Python documentation](http://docs.python.org/library/functions.html#range). - _.range = function(start, stop, step) { - if (arguments.length <= 1) { - stop = start || 0; - start = 0; - } - step = arguments[2] || 1; - - var len = Math.max(Math.ceil((stop - start) / step), 0); - var idx = 0; - var range = new Array(len); - - while(idx < len) { - range[idx++] = start; - start += step; - } - - return range; - }; - - // Function (ahem) Functions - // ------------------ - - // Reusable constructor function for prototype setting. - var ctor = function(){}; - - // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Binding with arguments is also known as `curry`. - // Delegates to **ECMAScript 5**'s native `Function.bind` if available. - // We check for `func.bind` first, to fail fast when `func` is undefined. - _.bind = function bind(func, context) { - var bound, args; - if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - if (!_.isFunction(func)) throw new TypeError; - args = slice.call(arguments, 2); - return bound = function() { - if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); - ctor.prototype = func.prototype; - var self = new ctor; - var result = func.apply(self, args.concat(slice.call(arguments))); - if (Object(result) === result) return result; - return self; - }; - }; - - // Bind all of an object's methods to that object. Useful for ensuring that - // all callbacks defined on an object belong to it. - _.bindAll = function(obj) { - var funcs = slice.call(arguments, 1); - if (funcs.length == 0) funcs = _.functions(obj); - each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); - return obj; - }; - - // Memoize an expensive function by storing its results. - _.memoize = function(func, hasher) { - var memo = {}; - hasher || (hasher = _.identity); - return function() { - var key = hasher.apply(this, arguments); - return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); - }; - }; - - // Delays a function for the given number of milliseconds, and then calls - // it with the arguments supplied. - _.delay = function(func, wait) { - var args = slice.call(arguments, 2); - return setTimeout(function(){ return func.apply(null, args); }, wait); - }; - - // Defers a function, scheduling it to run after the current call stack has - // cleared. - _.defer = function(func) { - return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); - }; - - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. - _.throttle = function(func, wait) { - var context, args, timeout, throttling, more, result; - var whenDone = _.debounce(function(){ more = throttling = false; }, wait); - return function() { - context = this; args = arguments; - var later = function() { - timeout = null; - if (more) { - result = func.apply(context, args); - } - whenDone(); - }; - if (!timeout) timeout = setTimeout(later, wait); - if (throttling) { - more = true; - } else { - throttling = true; - result = func.apply(context, args); - } - whenDone(); - return result; - }; - }; - - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. If `immediate` is passed, trigger the function on the - // leading edge, instead of the trailing. - _.debounce = function(func, wait, immediate) { - var timeout, result; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - if (!immediate) result = func.apply(context, args); - }; - var callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) result = func.apply(context, args); - return result; - }; - }; - - // Returns a function that will be executed at most one time, no matter how - // often you call it. Useful for lazy initialization. - _.once = function(func) { - var ran = false, memo; - return function() { - if (ran) return memo; - ran = true; - memo = func.apply(this, arguments); - func = null; - return memo; - }; - }; - - // Returns the first function passed as an argument to the second, - // allowing you to adjust arguments, run code before and after, and - // conditionally execute the original function. - _.wrap = function(func, wrapper) { - return function() { - var args = [func]; - push.apply(args, arguments); - return wrapper.apply(this, args); - }; - }; - - // Returns a function that is the composition of a list of functions, each - // consuming the return value of the function that follows. - _.compose = function() { - var funcs = arguments; - return function() { - var args = arguments; - for (var i = funcs.length - 1; i >= 0; i--) { - args = [funcs[i].apply(this, args)]; - } - return args[0]; - }; - }; - - // Returns a function that will only be executed after being called N times. - _.after = function(times, func) { - if (times <= 0) return func(); - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; - }; - - // Object Functions - // ---------------- - - // Retrieve the names of an object's properties. - // Delegates to **ECMAScript 5**'s native `Object.keys` - _.keys = nativeKeys || function(obj) { - if (obj !== Object(obj)) throw new TypeError('Invalid object'); - var keys = []; - for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; - return keys; - }; - - // Retrieve the values of an object's properties. - _.values = function(obj) { - var values = []; - for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); - return values; - }; - - // Convert an object into a list of `[key, value]` pairs. - _.pairs = function(obj) { - var pairs = []; - for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); - return pairs; - }; - - // Invert the keys and values of an object. The values must be serializable. - _.invert = function(obj) { - var result = {}; - for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; - return result; - }; - - // Return a sorted list of the function names available on the object. - // Aliased as `methods` - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) names.push(key); - } - return names.sort(); - }; - - // Extend a given object with all the properties in passed-in object(s). - _.extend = function(obj) { - each(slice.call(arguments, 1), function(source) { - for (var prop in source) { - obj[prop] = source[prop]; - } - }); - return obj; - }; - - // Return a copy of the object only containing the whitelisted properties. - _.pick = function(obj) { - var copy = {}; - var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); - each(keys, function(key) { - if (key in obj) copy[key] = obj[key]; - }); - return copy; - }; - - // Return a copy of the object without the blacklisted properties. - _.omit = function(obj) { - var copy = {}; - var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); - for (var key in obj) { - if (!_.contains(keys, key)) copy[key] = obj[key]; - } - return copy; - }; - - // Fill in a given object with default properties. - _.defaults = function(obj) { - each(slice.call(arguments, 1), function(source) { - for (var prop in source) { - if (obj[prop] == null) obj[prop] = source[prop]; - } - }); - return obj; - }; - - // Create a (shallow-cloned) duplicate of an object. - _.clone = function(obj) { - if (!_.isObject(obj)) return obj; - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; - - // Invokes interceptor with the obj, and then returns obj. - // The primary purpose of this method is to "tap into" a method chain, in - // order to perform operations on intermediate results within the chain. - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; - - // Internal recursive comparison function for `isEqual`. - var eq = function(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. - if (a === b) return a !== 0 || 1 / a == 1 / b; - // A strict comparison is necessary because `null == undefined`. - if (a == null || b == null) return a === b; - // Unwrap any wrapped objects. - if (a instanceof _) a = a._wrapped; - if (b instanceof _) b = b._wrapped; - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className != toString.call(b)) return false; - switch (className) { - // Strings, numbers, dates, and booleans are compared by value. - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return a == String(b); - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for - // other numeric values. - return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a == +b; - // RegExps are compared by their source patterns and flags. - case '[object RegExp]': - return a.source == b.source && - a.global == b.global && - a.multiline == b.multiline && - a.ignoreCase == b.ignoreCase; - } - if (typeof a != 'object' || typeof b != 'object') return false; - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] == a) return bStack[length] == b; - } - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - var size = 0, result = true; - // Recursively compare objects and arrays. - if (className == '[object Array]') { - // Compare array lengths to determine if a deep comparison is necessary. - size = a.length; - result = size == b.length; - if (result) { - // Deep compare the contents, ignoring non-numeric properties. - while (size--) { - if (!(result = eq(a[size], b[size], aStack, bStack))) break; - } - } - } else { - // Objects with different constructors are not equivalent, but `Object`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && - _.isFunction(bCtor) && (bCtor instanceof bCtor))) { - return false; - } - // Deep compare objects. - for (var key in a) { - if (_.has(a, key)) { - // Count the expected number of properties. - size++; - // Deep compare each member. - if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; - } - } - // Ensure that both objects contain the same number of properties. - if (result) { - for (key in b) { - if (_.has(b, key) && !(size--)) break; - } - result = !size; - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return result; - }; - - // Perform a deep comparison to check if two objects are equal. - _.isEqual = function(a, b) { - return eq(a, b, [], []); - }; - - // Is a given array, string, or object empty? - // An "empty" object has no enumerable own-properties. - _.isEmpty = function(obj) { - if (obj == null) return true; - if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; - for (var key in obj) if (_.has(obj, key)) return false; - return true; - }; - - // Is a given value a DOM element? - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; - - // Is a given value an array? - // Delegates to ECMA5's native Array.isArray - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) == '[object Array]'; - }; - - // Is a given variable an object? - _.isObject = function(obj) { - return obj === Object(obj); - }; - - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. - each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { - _['is' + name] = function(obj) { - return toString.call(obj) == '[object ' + name + ']'; - }; - }); - - // Define a fallback version of the method in browsers (ahem, IE), where - // there isn't any inspectable "Arguments" type. - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return !!(obj && _.has(obj, 'callee')); - }; - } - - // Optimize `isFunction` if appropriate. - if (typeof (/./) !== 'function') { - _.isFunction = function(obj) { - return typeof obj === 'function'; - }; - } - - // Is a given object a finite number? - _.isFinite = function(obj) { - return _.isNumber(obj) && isFinite(obj); - }; - - // Is the given value `NaN`? (NaN is the only number which does not equal itself). - _.isNaN = function(obj) { - return _.isNumber(obj) && obj != +obj; - }; - - // Is a given value a boolean? - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; - }; - - // Is a given value equal to null? - _.isNull = function(obj) { - return obj === null; - }; - - // Is a given variable undefined? - _.isUndefined = function(obj) { - return obj === void 0; - }; - - // Shortcut function for checking if an object has a given property directly - // on itself (in other words, not on a prototype). - _.has = function(obj, key) { - return hasOwnProperty.call(obj, key); - }; - - // Utility Functions - // ----------------- - - // Run Underscore.js in *noConflict* mode, returning the `_` variable to its - // previous owner. Returns a reference to the Underscore object. - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; - - // Keep the identity function around for default iterators. - _.identity = function(value) { - return value; - }; - - // Run a function **n** times. - _.times = function(n, iterator, context) { - for (var i = 0; i < n; i++) iterator.call(context, i); - }; - - // Return a random integer between min and max (inclusive). - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + (0 | Math.random() * (max - min + 1)); - }; - - // List of HTML entities for escaping. - var entityMap = { - escape: { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '/': '/' - } - }; - entityMap.unescape = _.invert(entityMap.escape); - - // Regexes containing the keys and values listed immediately above. - var entityRegexes = { - escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), - unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') - }; - - // Functions for escaping and unescaping strings to/from HTML interpolation. - _.each(['escape', 'unescape'], function(method) { - _[method] = function(string) { - if (string == null) return ''; - return ('' + string).replace(entityRegexes[method], function(match) { - return entityMap[method][match]; - }); - }; - }); - - // If the value of the named property is a function then invoke it; - // otherwise, return it. - _.result = function(object, property) { - if (object == null) return null; - var value = object[property]; - return _.isFunction(value) ? value.call(object) : value; - }; - - // Add your own custom functions to the Underscore object. - _.mixin = function(obj) { - each(_.functions(obj), function(name){ - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return result.call(this, func.apply(_, args)); - }; - }); - }; - - // Generate a unique integer id (unique within the entire client session). - // Useful for temporary DOM ids. - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = idCounter++; - return prefix ? prefix + id : id; - }; - - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g, - escape : /<%-([\s\S]+?)%>/g - }; - - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; - - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\t': 't', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; - - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - _.template = function(text, data, settings) { - settings = _.defaults({}, settings, _.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = new RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset) - .replace(escaper, function(match) { return '\\' + escapes[match]; }); - source += - escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" : - interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" : - evaluate ? "';\n" + evaluate + "\n__p+='" : ''; - index = offset + match.length; - }); - source += "';\n"; - - // If a variable is not specified, place data values in local scope. - if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + "return __p;\n"; - - try { - var render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } - - if (data) return render(data, _); - var template = function(data) { - return render.call(this, data, _); - }; - - // Provide the compiled function source as a convenience for precompilation. - template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; - - return template; - }; - - // Add a "chain" function, which will delegate to the wrapper. - _.chain = function(obj) { - return _(obj).chain(); - }; - - // OOP - // --------------- - // If Underscore is called as a function, it returns a wrapped object that - // can be used OO-style. This wrapper holds altered versions of all the - // underscore functions. Wrapped objects may be chained. - - // Helper function to continue chaining intermediate results. - var result = function(obj) { - return this._chain ? _(obj).chain() : obj; - }; - - // Add all of the Underscore functions to the wrapper object. - _.mixin(_); - - // Add all mutator Array functions to the wrapper. - each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; - return result.call(this, obj); - }; - }); - - // Add all accessor Array functions to the wrapper. - each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return result.call(this, method.apply(this._wrapped, arguments)); - }; - }); - - _.extend(_.prototype, { - - // Start chaining a wrapped Underscore object. - chain: function() { - this._chain = true; - return this; - }, - - // Extracts the result from a wrapped and chained object. - value: function() { - return this._wrapped; - } - - }); - -}).call(this); diff --git a/sources/tests/frontend/runner.css b/sources/tests/frontend/runner.css deleted file mode 100644 index 7d5bb78..0000000 --- a/sources/tests/frontend/runner.css +++ /dev/null @@ -1,231 +0,0 @@ -html { - height: 100%; -} - -body { - padding: 0px; - margin: 0px; - height: 100%; -} - -#console { - display: none; -} - -#iframe-container { - width: 50%; - height: 100%; -} - -#iframe-container iframe { - height: 100%; - position:absolute; - min-width:500px; - max-width:800px; - left:50%; - width:100%; -} - -#mocha { - font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; - border-right: 2px solid #999; - width: 50%; - height: 100%; - position: absolute; - overflow: auto; - float:left; -} - -#mocha #report { - margin-top: 50px; -} - -#mocha ul, #mocha li { - margin: 0; - padding: 0; -} - -#mocha ul { - list-style: none; -} - -#mocha h1, #mocha h2 { - margin: 0; -} - -#mocha h1 { - margin-top: 15px; - font-size: 1em; - font-weight: 200; -} - -#mocha h1 a:visited -{ - color: #00E; -} - -#mocha .suite .suite h1 { - margin-top: 0; - font-size: .8em; -} - -#mocha h2 { - font-size: 12px; - font-weight: normal; - cursor: pointer; -} - -#mocha .suite { - margin-left: 15px; -} - -#mocha .test { - margin-left: 15px; -} - -#mocha .test:hover h2::after { - position: relative; - top: 0; - right: -10px; - content: '(view source)'; - font-size: 12px; - font-family: arial; - color: #888; -} - -#mocha .test.pending:hover h2::after { - content: '(pending)'; - font-family: arial; -} - -#mocha .test.pass.medium .duration { - background: #C09853; -} - -#mocha .test.pass.slow .duration { - background: #B94A48; -} - -#mocha .test.pass::before { - content: '✓'; - font-size: 12px; - display: block; - float: left; - margin-right: 5px; - color: #00d6b2; -} - -#mocha .test.pass .duration { - font-size: 9px; - margin-left: 5px; - padding: 2px 5px; - color: white; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - -ms-border-radius: 5px; - -o-border-radius: 5px; - border-radius: 5px; -} - -#mocha .test.pass.fast .duration { - display: none; -} - -#mocha .test.pending { - color: #0b97c4; -} - -#mocha .test.pending::before { - content: '◦'; - color: #0b97c4; -} - -#mocha .test.fail { - color: #c00; -} - -#mocha .test.fail pre { - color: black; -} - -#mocha .test.fail::before { - content: '✖'; - font-size: 12px; - display: block; - float: left; - margin-right: 5px; - color: #c00; -} - -#mocha .test pre.error { - color: #c00; -} - -#mocha .test pre { - display: inline-block; - font: 12px/1.5 monaco, monospace; - margin: 5px; - padding: 15px; - border: 1px solid #eee; - border-bottom-color: #ddd; - -webkit-border-radius: 3px; - -webkit-box-shadow: 0 1px 3px #eee; -} - -#report.pass .test.fail { - display: none; -} - -#report.fail .test.pass { - display: none; -} - -#error { - color: #c00; - font-size: 1.5 em; - font-weight: 100; - letter-spacing: 1px; -} - -#stats { - position: fixed; - top: 15px; - right: 52%; - font-size: 12px; - margin: 0; - color: #888; -} - -#stats .progress { - float: right; - padding-top: 0; -} - -#stats em { - color: black; -} - -#stats a { - text-decoration: none; - color: inherit; -} - -#stats a:hover { - border-bottom: 1px solid #eee; -} - -#stats li { - display: inline-block; - margin: 0 5px; - list-style: none; - padding-top: 11px; -} - -code .comment { color: #ddd } -code .init { color: #2F6FAD } -code .string { color: #5890AD } -code .keyword { color: #8A6343 } -code .number { color: #2F6FAD } diff --git a/sources/tests/frontend/runner.js b/sources/tests/frontend/runner.js deleted file mode 100644 index e77f670..0000000 --- a/sources/tests/frontend/runner.js +++ /dev/null @@ -1,198 +0,0 @@ -$(function(){ - function Base(runner) { - var self = this - , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } - , failures = this.failures = []; - - if (!runner) return; - this.runner = runner; - - runner.on('start', function(){ - stats.start = new Date; - }); - - runner.on('suite', function(suite){ - stats.suites = stats.suites || 0; - suite.root || stats.suites++; - }); - - runner.on('test end', function(test){ - stats.tests = stats.tests || 0; - stats.tests++; - }); - - runner.on('pass', function(test){ - stats.passes = stats.passes || 0; - - var medium = test.slow() / 2; - test.speed = test.duration > test.slow() - ? 'slow' - : test.duration > medium - ? 'medium' - : 'fast'; - - stats.passes++; - }); - - runner.on('fail', function(test, err){ - stats.failures = stats.failures || 0; - stats.failures++; - test.err = err; - failures.push(test); - }); - - runner.on('end', function(){ - stats.end = new Date; - stats.duration = new Date - stats.start; - }); - - runner.on('pending', function(){ - stats.pending++; - }); - } - - /* - This reporter wraps the original html reporter plus reports plain text into a hidden div. - This allows the webdriver client to pick up the test results - */ - var WebdriverAndHtmlReporter = function(html_reporter){ - return function(runner){ - Base.call(this, runner); - - // Scroll down test display after each test - mocha = $('#mocha')[0]; - runner.on('test', function(){ - mocha.scrollTop = mocha.scrollHeight; - }); - - //initalize the html reporter first - html_reporter(runner); - - var $console = $("#console"); - var level = 0; - var append = function(){ - var text = Array.prototype.join.apply(arguments, [" "]); - var oldText = $console.text(); - - var space = ""; - for(var i=0;i 0){ - var split = line.substr(0,100); - line = line.substr(100); - if(splitedText.length > 0) splitedText+="\n"; - splitedText += split; - } - }); - - //indent all lines with the given amount of space - var newText = _(splitedText.split("\n")).map(function(line){ - return space + line; - }).join("\\n"); - - $console.text(oldText + newText + "\\n"); - } - - runner.on('suite', function(suite){ - if (suite.root) return; - - append(suite.title); - level++; - }); - - runner.on('suite end', function(suite){ - if (suite.root) return; - level--; - - if(level == 0) { - append(""); - } - }); - - var stringifyException = function(exception){ - var err = exception.stack || exception.toString(); - - // FF / Opera do not add the message - if (!~err.indexOf(exception.message)) { - err = exception.message + '\n' + err; - } - - // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we - // check for the result of the stringifying. - if ('[object Error]' == err) err = exception.message; - - // Safari doesn't give you a stack. Let's at least provide a source line. - if (!exception.stack && exception.sourceURL && exception.line !== undefined) { - err += "\n(" + exception.sourceURL + ":" + exception.line + ")"; - } - - return err; - } - - var killTimeout; - runner.on('test end', function(test){ - if ('passed' == test.state) { - append("->","[green]PASSED[clear] :", test.title); - } else if (test.pending) { - append("->","[yellow]PENDING[clear]:", test.title); - } else { - append("->","[red]FAILED[clear] :", test.title, stringifyException(test.err)); - } - - if(killTimeout) clearTimeout(killTimeout); - killTimeout = setTimeout(function(){ - append("FINISHED - [red]no test started since 3 minutes, tests stopped[clear]"); - }, 60000 * 3); - }); - - var total = runner.total; - runner.on('end', function(){ - if(stats.tests >= total){ - var minutes = Math.floor(stats.duration / 1000 / 60); - var seconds = Math.round((stats.duration / 1000) % 60); - - append("FINISHED -", stats.passes, "tests passed,", stats.failures, "tests failed, duration: " + minutes + ":" + seconds); - } - }); - } - } - - //http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery - var getURLParameter = function (name) { - return decodeURI( - (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1] - ); - } - - //get the list of specs and filter it if requested - var specs = specs_list.slice(); - - //inject spec scripts into the dom - var $body = $('body'); - $.each(specs, function(i, spec){ - if(spec[0] != "/"){ // if the spec isn't a plugin spec which means the spec file might be in a different subfolder - $body.append('') - }else{ - $body.append('') - } - }); - - //initalize the test helper - helper.init(function(){ - //configure and start the test framework - var grep = getURLParameter("grep"); - if(grep != "null"){ - mocha.grep(grep); - } - - mocha.ignoreLeaks(); - - mocha.reporter(WebdriverAndHtmlReporter(mocha._reporter)); - - mocha.run(); - }); -}); diff --git a/sources/tests/frontend/specs/alphabet.js b/sources/tests/frontend/specs/alphabet.js deleted file mode 100644 index ae9570e..0000000 --- a/sources/tests/frontend/specs/alphabet.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("All the alphabet works n stuff", function(){ - var expectedString = "abcdefghijklmnopqrstuvwxyz"; - - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("when you enter any char it appears right", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var firstTextElement = inner$("div").first(); - - // simulate key presses to delete content - firstTextElement.sendkeys('{selectall}'); // select all - firstTextElement.sendkeys('{del}'); // clear the first line - firstTextElement.sendkeys(expectedString); // insert the string - - helper.waitFor(function(){ - return inner$("div").first().text() === expectedString; - }, 2000).done(done); - }); - -}); diff --git a/sources/tests/frontend/specs/automatic_reconnect.js b/sources/tests/frontend/specs/automatic_reconnect.js deleted file mode 100644 index e2d2df3..0000000 --- a/sources/tests/frontend/specs/automatic_reconnect.js +++ /dev/null @@ -1,71 +0,0 @@ -describe('Automatic pad reload on Force Reconnect message', function() { - var padId, $originalPadFrame; - - beforeEach(function(done) { - padId = helper.newPad(function() { - // enable userdup error to have timer to force reconnect - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); - $errorMessageModal.addClass('with_reconnect_timer'); - - // make sure there's a timeout set, otherwise automatic reconnect won't be enabled - helper.padChrome$.window.clientVars.automaticReconnectionTimeout = 2; - - // open same pad on another iframe, to force userdup error - var $otherIframeWithSamePad = $(''); - $originalPadFrame = $('#iframe-container iframe'); - $otherIframeWithSamePad.insertAfter($originalPadFrame); - - // wait for modal to be displayed - helper.waitFor(function() { - return $errorMessageModal.is(':visible'); - }, 50000).done(done); - }); - - this.timeout(60000); - }); - - it('displays a count down timer to automatically reconnect', function(done) { - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); - var $countDownTimer = $errorMessageModal.find('.reconnecttimer'); - - expect($countDownTimer.is(':visible')).to.be(true); - - done(); - }); - - context('and user clicks on Cancel', function() { - beforeEach(function() { - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); - $errorMessageModal.find('#cancelreconnect').click(); - }); - - it('does not show Cancel button nor timer anymore', function(done) { - var $errorMessageModal = helper.padChrome$('#connectivity .userdup'); - var $countDownTimer = $errorMessageModal.find('.reconnecttimer'); - var $cancelButton = $errorMessageModal.find('#cancelreconnect'); - - expect($countDownTimer.is(':visible')).to.be(false); - expect($cancelButton.is(':visible')).to.be(false); - - done(); - }); - }); - - context('and user does not click on Cancel until timer expires', function() { - var padWasReloaded = false; - - beforeEach(function() { - $originalPadFrame.one('load', function() { - padWasReloaded = true; - }); - }); - - it('reloads the pad', function(done) { - helper.waitFor(function() { - return padWasReloaded; - }, 5000).done(done); - - this.timeout(5000); - }); - }); -}); diff --git a/sources/tests/frontend/specs/bold.js b/sources/tests/frontend/specs/bold.js deleted file mode 100644 index b54466e..0000000 --- a/sources/tests/frontend/specs/bold.js +++ /dev/null @@ -1,72 +0,0 @@ -describe("bold button", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("makes text bold on click", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - //select this text element - $firstTextElement.sendkeys('{selectall}'); - - //get the bold button and click it - var $boldButton = chrome$(".buttonicon-bold"); - $boldButton.click(); - - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); - - // is there a element now? - var isBold = $newFirstTextElement.find("b").length === 1; - - //expect it to be bold - expect(isBold).to.be(true); - - //make sure the text hasn't changed - expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); - - done(); - }); - - it("makes text bold on keypress", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - //select this text element - $firstTextElement.sendkeys('{selectall}'); - - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); - e.ctrlKey = true; // Control key - e.which = 66; // b - inner$("#innerdocbody").trigger(e); - - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); - - // is there a element now? - var isBold = $newFirstTextElement.find("b").length === 1; - - //expect it to be bold - expect(isBold).to.be(true); - - //make sure the text hasn't changed - expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); - - done(); - }); -}); diff --git a/sources/tests/frontend/specs/caret.js b/sources/tests/frontend/specs/caret.js deleted file mode 100644 index 14ff8d6..0000000 --- a/sources/tests/frontend/specs/caret.js +++ /dev/null @@ -1,344 +0,0 @@ -describe("As the caret is moved is the UI properly updated?", function(){ - var padName; - var numberOfRows = 50; -/* - - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - xit("creates a pad", function(done) { - padName = helper.newPad(done); - this.timeout(60000); - }); -*/ - - /* Tests to do - * Keystroke up (38), down (40), left (37), right (39) with and without special keys IE control / shift - * Page up (33) / down (34) with and without special keys - * Page up on the first line shouldn't move the viewport - * Down down on the last line shouldn't move the viewport - * Down arrow on any other line except the last lines shouldn't move the viewport - * Do all of the above tests after a copy/paste event - */ - - /* Challenges - * How do we keep the authors focus on a line if the lines above the author are modified? We should only redraw the user to a location if they are typing and make sure shift and arrow keys aren't redrawing the UI else highlight - copy/paste would get broken - * How can we simulate an edit event in the test framework? - */ -/* - // THIS DOESNT WORK IN CHROME AS IT DOESNT MOVE THE CURSOR! - it("down arrow", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - var $newFirstTextElement = inner$("div").first(); - $newFirstTextElement.focus(); - keyEvent(inner$, 37, false, false); // arrow down - keyEvent(inner$, 37, false, false); // arrow down - - done(); - }); - - it("Creates N lines", function(done){ - var inner$ = helper.padInner$; -console.log(inner$); - var chrome$ = helper.padChrome$; - var $newFirstTextElement = inner$("div").first(); - - prepareDocument(numberOfRows, $newFirstTextElement); // N lines into the first div as a target - helper.waitFor(function(){ // Wait for the DOM to register the new items - return inner$("div").first().text().length == 6; - }).done(function(){ // Once the DOM has registered the items - done(); - }); - }); - - it("Moves caret up a line", function(done){ - var inner$ = helper.padInner$; - var $newFirstTextElement = inner$("div").first(); - var originalCaretPosition = caretPosition(inner$); - var originalPos = originalCaretPosition.y; - var newCaretPos; - keyEvent(inner$, 38, false, false); // arrow up - - helper.waitFor(function(){ // Wait for the DOM to register the new items - var newCaretPosition = caretPosition(inner$); - newCaretPos = newCaretPosition.y; - return (newCaretPos < originalPos); - }).done(function(){ - expect(newCaretPos).to.be.lessThan(originalPos); - done(); - }); - }); - - it("Moves caret down a line", function(done){ - var inner$ = helper.padInner$; - var $newFirstTextElement = inner$("div").first(); - var originalCaretPosition = caretPosition(inner$); - var originalPos = originalCaretPosition.y; - var newCaretPos; - keyEvent(inner$, 40, false, false); // arrow down - - helper.waitFor(function(){ // Wait for the DOM to register the new items - var newCaretPosition = caretPosition(inner$); - newCaretPos = newCaretPosition.y; - return (newCaretPos > originalPos); - }).done(function(){ - expect(newCaretPos).to.be.moreThan(originalPos); - done(); - }); - }); - - it("Moves caret to top of doc", function(done){ - var inner$ = helper.padInner$; - var $newFirstTextElement = inner$("div").first(); - var originalCaretPosition = caretPosition(inner$); - var originalPos = originalCaretPosition.y; - var newCaretPos; - - var i = 0; - while(i < numberOfRows){ // press pageup key N times - keyEvent(inner$, 33, false, false); - i++; - } - - helper.waitFor(function(){ // Wait for the DOM to register the new items - var newCaretPosition = caretPosition(inner$); - newCaretPos = newCaretPosition.y; - return (newCaretPos < originalPos); - }).done(function(){ - expect(newCaretPos).to.be.lessThan(originalPos); - done(); - }); - }); - - it("Moves caret right a position", function(done){ - var inner$ = helper.padInner$; - var $newFirstTextElement = inner$("div").first(); - var originalCaretPosition = caretPosition(inner$); - var originalPos = originalCaretPosition.x; - var newCaretPos; - keyEvent(inner$, 39, false, false); // arrow right - - helper.waitFor(function(){ // Wait for the DOM to register the new items - var newCaretPosition = caretPosition(inner$); - newCaretPos = newCaretPosition.x; - return (newCaretPos > originalPos); - }).done(function(){ - expect(newCaretPos).to.be.moreThan(originalPos); - done(); - }); - }); - - it("Moves caret left a position", function(done){ - var inner$ = helper.padInner$; - var $newFirstTextElement = inner$("div").first(); - var originalCaretPosition = caretPosition(inner$); - var originalPos = originalCaretPosition.x; - var newCaretPos; - keyEvent(inner$, 33, false, false); // arrow left - - helper.waitFor(function(){ // Wait for the DOM to register the new items - var newCaretPosition = caretPosition(inner$); - newCaretPos = newCaretPosition.x; - return (newCaretPos < originalPos); - }).done(function(){ - expect(newCaretPos).to.be.lessThan(originalPos); - done(); - }); - }); - - it("Moves caret to the next line using right arrow", function(done){ - var inner$ = helper.padInner$; - var $newFirstTextElement = inner$("div").first(); - var originalCaretPosition = caretPosition(inner$); - var originalPos = originalCaretPosition.y; - var newCaretPos; - keyEvent(inner$, 39, false, false); // arrow right - keyEvent(inner$, 39, false, false); // arrow right - keyEvent(inner$, 39, false, false); // arrow right - keyEvent(inner$, 39, false, false); // arrow right - keyEvent(inner$, 39, false, false); // arrow right - keyEvent(inner$, 39, false, false); // arrow right - keyEvent(inner$, 39, false, false); // arrow right - - helper.waitFor(function(){ // Wait for the DOM to register the new items - var newCaretPosition = caretPosition(inner$); - newCaretPos = newCaretPosition.y; - return (newCaretPos > originalPos); - }).done(function(){ - expect(newCaretPos).to.be.moreThan(originalPos); - done(); - }); - }); - - it("Moves caret to the previous line using left arrow", function(done){ - var inner$ = helper.padInner$; - var $newFirstTextElement = inner$("div").first(); - var originalCaretPosition = caretPosition(inner$); - var originalPos = originalCaretPosition.y; - var newCaretPos; - keyEvent(inner$, 33, false, false); // arrow left - - helper.waitFor(function(){ // Wait for the DOM to register the new items - var newCaretPosition = caretPosition(inner$); - newCaretPos = newCaretPosition.y; - return (newCaretPos < originalPos); - }).done(function(){ - expect(newCaretPos).to.be.lessThan(originalPos); - done(); - }); - }); - - - -/* - it("Creates N rows, changes height of rows, updates UI by caret key events", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - var numberOfRows = 50; - - //ace creates a new dom element when you press a keystroke, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); - var originalDivHeight = inner$("div").first().css("height"); - prepareDocument(numberOfRows, $newFirstTextElement); // N lines into the first div as a target - - helper.waitFor(function(){ // Wait for the DOM to register the new items - return inner$("div").first().text().length == 6; - }).done(function(){ // Once the DOM has registered the items - inner$("div").each(function(index){ // Randomize the item heights (replicates images / headings etc) - var random = Math.floor(Math.random() * (50)) + 20; - $(this).css("height", random+"px"); - }); - - console.log(caretPosition(inner$)); - var newDivHeight = inner$("div").first().css("height"); - var heightHasChanged = originalDivHeight != newDivHeight; // has the new div height changed from the original div height - expect(heightHasChanged).to.be(true); // expect the first line to be blank - }); - - // Is this Element now visible to the pad user? - helper.waitFor(function(){ // Wait for the DOM to register the new items - return isScrolledIntoView(inner$("div:nth-child("+numberOfRows+")"), inner$); // Wait for the DOM to scroll into place - }).done(function(){ // Once the DOM has registered the items - inner$("div").each(function(index){ // Randomize the item heights (replicates images / headings etc) - var random = Math.floor(Math.random() * (80 - 20 + 1)) + 20; - $(this).css("height", random+"px"); - }); - - var newDivHeight = inner$("div").first().css("height"); - var heightHasChanged = originalDivHeight != newDivHeight; // has the new div height changed from the original div height - expect(heightHasChanged).to.be(true); // expect the first line to be blank - }); - var i = 0; - while(i < numberOfRows){ // press down arrow - keyEvent(inner$, 40, false, false); - i++; - } - - // Does scrolling back up the pad with the up arrow show the correct contents? - helper.waitFor(function(){ // Wait for the new position to be in place - try{ - return isScrolledIntoView(inner$("div:nth-child("+numberOfRows+")"), inner$); // Wait for the DOM to scroll into place - }catch(e){ - return false; - } - }).done(function(){ // Once the DOM has registered the items - - var i = 0; - while(i < numberOfRows){ // press down arrow - keyEvent(inner$, 33, false, false); // doesn't work - i++; - } - - // Does scrolling back up the pad with the up arrow show the correct contents? - helper.waitFor(function(){ // Wait for the new position to be in place - try{ - return isScrolledIntoView(inner$("div:nth-child(0)"), inner$); // Wait for the DOM to scroll into place - }catch(e){ - return false; - } - }).done(function(){ // Once the DOM has registered the items - - - - }); - }); - - - var i = 0; - while(i < numberOfRows){ // press down arrow - keyEvent(inner$, 33, false, false); // doesn't work - i++; - } - - - // Does scrolling back up the pad with the up arrow show the correct contents? - helper.waitFor(function(){ // Wait for the new position to be in place - return isScrolledIntoView(inner$("div:nth-child(1)"), inner$); // Wait for the DOM to scroll into place - }).done(function(){ // Once the DOM has registered the items - expect(true).to.be(true); - done(); - }); -*/ - -}); - -function prepareDocument(n, target){ // generates a random document with random content on n lines - var i = 0; - while(i < n){ // for each line - target.sendkeys(makeStr()); // generate a random string and send that to the editor - target.sendkeys('{enter}'); // generator an enter keypress - i++; // rinse n times - } -} - -function keyEvent(target, charCode, ctrl, shift){ // sends a charCode to the window - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - var e = target.Event(evtType); - console.log(e); - if(ctrl){ - e.ctrlKey = true; // Control key - } - if(shift){ - e.shiftKey = true; // Shift Key - } - e.which = charCode; - e.keyCode = charCode; - target("#innerdocbody").trigger(e); -} - - -function makeStr(){ // from http://stackoverflow.com/questions/1349404/generate-a-string-of-5-random-characters-in-javascript - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - for( var i=0; i < 5; i++ ) - text += possible.charAt(Math.floor(Math.random() * possible.length)); - return text; -} - -function isScrolledIntoView(elem, $){ // from http://stackoverflow.com/questions/487073/check-if-element-is-visible-after-scrolling - var docViewTop = $(window).scrollTop(); - var docViewBottom = docViewTop + $(window).height(); - var elemTop = $(elem).offset().top; // how far the element is from the top of it's container - var elemBottom = elemTop + $(elem).height(); // how far plus the height of the elem.. IE is it all in? - elemBottom = elemBottom - 16; // don't ask, sorry but this is needed.. - return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); -} - -function caretPosition($){ - var doc = $.window.document; - var pos = doc.getSelection(); - pos.y = pos.anchorNode.parentElement.offsetTop; - pos.x = pos.anchorNode.parentElement.offsetLeft; - console.log(pos); - return pos; -} diff --git a/sources/tests/frontend/specs/change_user_name.js b/sources/tests/frontend/specs/change_user_name.js deleted file mode 100644 index ba089c9..0000000 --- a/sources/tests/frontend/specs/change_user_name.js +++ /dev/null @@ -1,72 +0,0 @@ -describe("change username value", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("Remembers the user name after a refresh", function(done) { - this.timeout(60000); - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); - $userButton.click(); - - var $usernameInput = chrome$("#myusernameedit"); - $usernameInput.click(); - - $usernameInput.val('John McLear'); - $usernameInput.blur(); - - setTimeout(function(){ //give it a second to save the username on the server side - helper.newPad({ // get a new pad, but don't clear the cookies - clearCookies: false - , cb: function(){ - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); - $userButton.click(); - - var $usernameInput = chrome$("#myusernameedit"); - expect($usernameInput.val()).to.be('John McLear') - done(); - } - }); - }, 1000); - }); - - - it("Own user name is shown when you enter a chat", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $userButton = chrome$(".buttonicon-showusers"); - $userButton.click(); - - var $usernameInput = chrome$("#myusernameedit"); - $usernameInput.click(); - - $usernameInput.val('John McLear'); - $usernameInput.blur(); - - //click on the chat button to make chat visible - var $chatButton = chrome$("#chaticon"); - $chatButton.click(); - var $chatInput = chrome$("#chatinput"); - $chatInput.sendkeys('O hi'); // simulate a keypress of typing JohnMcLear - $chatInput.sendkeys('{enter}'); // simulate a keypress of enter actually does evt.which = 10 not 13 - - //check if chat shows up - helper.waitFor(function(){ - return chrome$("#chattext").children("p").length !== 0; // wait until the chat message shows up - }).done(function(){ - var $firstChatMessage = chrome$("#chattext").children("p"); - var containsJohnMcLear = $firstChatMessage.text().indexOf("John McLear") !== -1; // does the string contain John McLear - expect(containsJohnMcLear).to.be(true); // expect the first chat message to contain JohnMcLear - done(); - }); - }); -}); diff --git a/sources/tests/frontend/specs/chat.js b/sources/tests/frontend/specs/chat.js deleted file mode 100644 index 7ebb76f..0000000 --- a/sources/tests/frontend/specs/chat.js +++ /dev/null @@ -1,130 +0,0 @@ -describe("Chat messages and UI", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("opens chat, sends a message and makes sure it exists on the page", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - var chatValue = "JohnMcLear"; - - //click on the chat button to make chat visible - var $chatButton = chrome$("#chaticon"); - $chatButton.click(); - var $chatInput = chrome$("#chatinput"); - $chatInput.sendkeys('JohnMcLear'); // simulate a keypress of typing JohnMcLear - $chatInput.sendkeys('{enter}'); // simulate a keypress of enter actually does evt.which = 10 not 13 - - //check if chat shows up - helper.waitFor(function(){ - return chrome$("#chattext").children("p").length !== 0; // wait until the chat message shows up - }).done(function(){ - var $firstChatMessage = chrome$("#chattext").children("p"); - var containsMessage = $firstChatMessage.text().indexOf("JohnMcLear") !== -1; // does the string contain JohnMcLear? - expect(containsMessage).to.be(true); // expect the first chat message to contain JohnMcLear - - // do a slightly more thorough check - var username = $firstChatMessage.children("b"); - var usernameValue = username.text(); - var time = $firstChatMessage.children(".time"); - var timeValue = time.text(); - var discoveredValue = $firstChatMessage.text(); - var chatMsgExists = (discoveredValue.indexOf("JohnMcLear") !== -1); - expect(chatMsgExists).to.be(true); - done(); - }); - - }); - - it("makes sure that an empty message can't be sent", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the chat button to make chat visible - var $chatButton = chrome$("#chaticon"); - $chatButton.click(); - var $chatInput = chrome$("#chatinput"); - $chatInput.sendkeys('{enter}'); // simulate a keypress of enter (to send an empty message) - $chatInput.sendkeys('mluto'); // simulate a keypress of typing mluto - $chatInput.sendkeys('{enter}'); // simulate a keypress of enter (to send 'mluto') - - //check if chat shows up - helper.waitFor(function(){ - return chrome$("#chattext").children("p").length !== 0; // wait until the chat message shows up - }).done(function(){ - // check that the empty message is not there - expect(chrome$("#chattext").children("p").length).to.be(1); - // check that the received message is not the empty one - var $firstChatMessage = chrome$("#chattext").children("p"); - var containsMessage = $firstChatMessage.text().indexOf("mluto") !== -1; - expect(containsMessage).to.be(true); - done(); - }); - }); - - it("makes chat stick to right side of the screen", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); - $settingsButton.click(); - - //get the chat selector - var $stickychatCheckbox = chrome$("#options-stickychat"); - - //select chat always on screen and fire change event - $stickychatCheckbox.attr('selected','selected'); - $stickychatCheckbox.change(); - $stickychatCheckbox.click(); - - //check if chat changed to get the stickychat Class - var $chatbox = chrome$("#chatbox"); - var hasStickyChatClass = $chatbox.hasClass("stickyChat"); - expect(hasStickyChatClass).to.be(true); - - //select chat always on screen and fire change event - $stickychatCheckbox.attr('selected','selected'); - $stickychatCheckbox.change(); - $stickychatCheckbox.click(); - - //check if chat changed to remove the stickychat Class - var hasStickyChatClass = $chatbox.hasClass("stickyChat"); - expect(hasStickyChatClass).to.be(false); - - done(); - }); - - it("makes chat stick to right side of the screen then makes it one step smaller", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); - $settingsButton.click(); - - //get the chat selector - var $stickychatCheckbox = chrome$("#options-stickychat"); - - //select chat always on screen and fire change event - $stickychatCheckbox.attr('selected','selected'); - $stickychatCheckbox.change(); - $stickychatCheckbox.click(); - - //check if chat changed to get the stickychat Class - var $chatbox = chrome$("#chatbox"); - var hasStickyChatClass = $chatbox.hasClass("stickyChat"); - expect(hasStickyChatClass).to.be(true); - - //select chat always on screen and fire change event - chrome$('#titlecross').click(); - - //check if chat changed to remove the stickychat Class - var hasStickyChatClass = $chatbox.hasClass("stickyChat"); - expect(hasStickyChatClass).to.be(false); - - done(); - }); -}); diff --git a/sources/tests/frontend/specs/chat_load_messages.js b/sources/tests/frontend/specs/chat_load_messages.js deleted file mode 100644 index 7b09b47..0000000 --- a/sources/tests/frontend/specs/chat_load_messages.js +++ /dev/null @@ -1,88 +0,0 @@ -describe("chat-load-messages", function(){ - var padName; - - it("creates a pad", function(done) { - padName = helper.newPad(done); - this.timeout(60000); - }); - - it("adds a lot of messages", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - var chatButton = chrome$("#chaticon"); - chatButton.click(); - var chatInput = chrome$("#chatinput"); - var chatText = chrome$("#chattext"); - - this.timeout(60000); - - var messages = 140; - for(var i=1; i <= messages; i++) { - var num = ''+i; - if(num.length == 1) - num = '00'+num; - if(num.length == 2) - num = '0'+num; - chatInput.sendkeys('msg' + num); - chatInput.sendkeys('{enter}'); - } - helper.waitFor(function(){ - return chatText.children("p").length == messages; - }, 60000).always(function(){ - expect(chatText.children("p").length).to.be(messages); - helper.newPad(done, padName); - }); - }); - - it("checks initial message count", function(done) { - var chatText; - var expectedCount = 101; - var chrome$ = helper.padChrome$; - helper.waitFor(function(){ - var chatButton = chrome$("#chaticon"); - chatButton.click(); - chatText = chrome$("#chattext"); - return chatText.children("p").length == expectedCount; - }).always(function(){ - expect(chatText.children("p").length).to.be(expectedCount); - done(); - }); - }); - - it("loads more messages", function(done) { - var expectedCount = 122; - var chrome$ = helper.padChrome$; - var chatButton = chrome$("#chaticon"); - chatButton.click(); - var chatText = chrome$("#chattext"); - var loadMsgBtn = chrome$("#chatloadmessagesbutton"); - - loadMsgBtn.click(); - helper.waitFor(function(){ - return chatText.children("p").length == expectedCount; - }).always(function(){ - expect(chatText.children("p").length).to.be(expectedCount); - done(); - }); - }); - - it("checks for button vanishing", function(done) { - var expectedDisplay = 'none'; - var chrome$ = helper.padChrome$; - var chatButton = chrome$("#chaticon"); - chatButton.click(); - var chatText = chrome$("#chattext"); - var loadMsgBtn = chrome$("#chatloadmessagesbutton"); - var loadMsgBall = chrome$("#chatloadmessagesball"); - - loadMsgBtn.click(); - helper.waitFor(function(){ - return loadMsgBtn.css('display') == expectedDisplay && - loadMsgBall.css('display') == expectedDisplay; - }).always(function(){ - expect(loadMsgBtn.css('display')).to.be(expectedDisplay); - expect(loadMsgBall.css('display')).to.be(expectedDisplay); - done(); - }); - }); -}); diff --git a/sources/tests/frontend/specs/clear_authorship_colors.js b/sources/tests/frontend/specs/clear_authorship_colors.js deleted file mode 100644 index 1417f63..0000000 --- a/sources/tests/frontend/specs/clear_authorship_colors.js +++ /dev/null @@ -1,59 +0,0 @@ -describe("clear authorship colors button", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("makes text clear authorship colors", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // override the confirm dialogue functioon - helper.padChrome$.window.confirm = function(){ - return true; - } - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - // Get the original text - var originalText = inner$("div").first().text(); - - // Set some new text - var sentText = "Hello"; - - //select this text element - $firstTextElement.sendkeys('{selectall}'); - $firstTextElement.sendkeys(sentText); - $firstTextElement.sendkeys('{rightarrow}'); - - helper.waitFor(function(){ - return inner$("div span").first().attr("class").indexOf("author") !== -1; // wait until we have the full value available - }).done(function(){ - //IE hates you if you don't give focus to the inner frame bevore you do a clearAuthorship - inner$("div").first().focus(); - - //get the clear authorship colors button and click it - var $clearauthorshipcolorsButton = chrome$(".buttonicon-clearauthorship"); - $clearauthorshipcolorsButton.click(); - - // does the first divs span include an author class? - console.log(inner$("div span").first().attr("class")); - var hasAuthorClass = inner$("div span").first().attr("class").indexOf("author") !== -1; - //expect(hasAuthorClass).to.be(false); - - // does the first div include an author class? - var hasAuthorClass = inner$("div").first().attr("class").indexOf("author") !== -1; - expect(hasAuthorClass).to.be(false); - - setTimeout(function(){ - var disconnectVisible = chrome$("div.disconnected").attr("class").indexOf("visible") === -1 - expect(disconnectVisible).to.be(true); - },1000); - - done(); - }); - - }); -}); diff --git a/sources/tests/frontend/specs/delete.js b/sources/tests/frontend/specs/delete.js deleted file mode 100644 index 86e76f5..0000000 --- a/sources/tests/frontend/specs/delete.js +++ /dev/null @@ -1,37 +0,0 @@ -describe("delete keystroke", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("makes text delete", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - // get the original length of this element - var elementLength = $firstTextElement.text().length; - - // get the original string value minus the last char - var originalTextValue = $firstTextElement.text(); - originalTextValueMinusFirstChar = originalTextValue.substring(1, originalTextValue.length ); - - // simulate key presses to delete content - $firstTextElement.sendkeys('{leftarrow}'); // simulate a keypress of the left arrow key - $firstTextElement.sendkeys('{del}'); // simulate a keypress of delete - - //ace creates a new dom element when you press a keystroke, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); - - // get the new length of this element - var newElementLength = $newFirstTextElement.text().length; - - //expect it to be one char less in length - expect(newElementLength).to.be((elementLength-1)); - - done(); - }); -}); diff --git a/sources/tests/frontend/specs/drag_and_drop.js b/sources/tests/frontend/specs/drag_and_drop.js deleted file mode 100644 index 821d3aa..0000000 --- a/sources/tests/frontend/specs/drag_and_drop.js +++ /dev/null @@ -1,168 +0,0 @@ -// WARNING: drag and drop is only simulated on these tests, so manual testing might also be necessary -describe('drag and drop', function() { - before(function(done) { - helper.newPad(function() { - createScriptWithSeveralLines(done); - }); - this.timeout(60000); - }); - - context('when user drags part of one line and drops it far form its original place', function() { - before(function(done) { - selectPartOfSourceLine(); - dragSelectedTextAndDropItIntoMiddleOfLine(TARGET_LINE); - - // make sure DnD was correctly simulated - helper.waitFor(function() { - var $targetLine = getLine(TARGET_LINE); - var sourceWasMovedToTarget = $targetLine.text() === 'Target line [line 1]'; - return sourceWasMovedToTarget; - }).done(done); - }); - - context('and user triggers UNDO', function() { - before(function() { - var $undoButton = helper.padChrome$(".buttonicon-undo"); - $undoButton.click(); - }); - - it('moves text back to its original place', function(done) { - // test text was removed from drop target - var $targetLine = getLine(TARGET_LINE); - expect($targetLine.text()).to.be('Target line []'); - - // test text was added back to original place - var $firstSourceLine = getLine(FIRST_SOURCE_LINE); - var $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); - expect($firstSourceLine.text()).to.be('Source line 1.'); - expect($lastSourceLine.text()).to.be('Source line 2.'); - - done(); - }); - }); - }); - - context('when user drags some lines far form its original place', function() { - before(function(done) { - selectMultipleSourceLines(); - dragSelectedTextAndDropItIntoMiddleOfLine(TARGET_LINE); - - // make sure DnD was correctly simulated - helper.waitFor(function() { - var $lineAfterTarget = getLine(TARGET_LINE + 1); - var sourceWasMovedToTarget = $lineAfterTarget.text() !== '...'; - return sourceWasMovedToTarget; - }).done(done); - }); - - context('and user triggers UNDO', function() { - before(function() { - var $undoButton = helper.padChrome$(".buttonicon-undo"); - $undoButton.click(); - }); - - it('moves text back to its original place', function(done) { - // test text was removed from drop target - var $targetLine = getLine(TARGET_LINE); - expect($targetLine.text()).to.be('Target line []'); - - // test text was added back to original place - var $firstSourceLine = getLine(FIRST_SOURCE_LINE); - var $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); - expect($firstSourceLine.text()).to.be('Source line 1.'); - expect($lastSourceLine.text()).to.be('Source line 2.'); - - done(); - }); - }); - }); - - /* ********************* Helper functions/constants ********************* */ - var TARGET_LINE = 2; - var FIRST_SOURCE_LINE = 5; - - var getLine = function(lineNumber) { - var $lines = helper.padInner$('div'); - return $lines.slice(lineNumber, lineNumber + 1); - } - - var createScriptWithSeveralLines = function(done) { - // create some lines to be used on the tests - var $firstLine = helper.padInner$('div').first(); - $firstLine.html('...
      ...
      Target line []
      ...
      ...
      Source line 1.
      Source line 2.
      '); - - // wait for lines to be split - helper.waitFor(function(){ - var $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); - return $lastSourceLine.text() === 'Source line 2.'; - }).done(done); - } - - var selectPartOfSourceLine = function() { - var $sourceLine = getLine(FIRST_SOURCE_LINE); - - // select 'line 1' from 'Source line 1.' - var start = 'Source '.length; - var end = start + 'line 1'.length; - helper.selectLines($sourceLine, $sourceLine, start, end); - } - var selectMultipleSourceLines = function() { - var $firstSourceLine = getLine(FIRST_SOURCE_LINE); - var $lastSourceLine = getLine(FIRST_SOURCE_LINE + 1); - - helper.selectLines($firstSourceLine, $lastSourceLine); - } - - var dragSelectedTextAndDropItIntoMiddleOfLine = function(targetLineNumber) { - // dragstart: start dragging content - triggerEvent('dragstart'); - - // drop: get HTML data from selected text - var draggedHtml = getHtmlFromSelectedText(); - triggerEvent('drop'); - - // dragend: remove original content + insert HTML data into target - moveSelectionIntoTarget(draggedHtml, targetLineNumber); - triggerEvent('dragend'); - } - - var getHtmlFromSelectedText = function() { - var innerDocument = helper.padInner$.document; - - var range = innerDocument.getSelection().getRangeAt(0); - var clonedSelection = range.cloneContents(); - var span = innerDocument.createElement('span'); - span.id = 'buffer'; - span.appendChild(clonedSelection); - var draggedHtml = span.outerHTML; - - return draggedHtml; - } - - var triggerEvent = function(eventName) { - var event = helper.padInner$.Event(eventName); - helper.padInner$('#innerdocbody').trigger(event); - } - - var moveSelectionIntoTarget = function(draggedHtml, targetLineNumber) { - var innerDocument = helper.padInner$.document; - - // delete original content - innerDocument.execCommand('delete'); - - // set position to insert content on target line - var $target = getLine(targetLineNumber); - $target.sendkeys('{selectall}{rightarrow}{leftarrow}'); - - // Insert content. - // Based on http://stackoverflow.com/a/6691294, to be IE-compatible - var range = innerDocument.getSelection().getRangeAt(0); - var frag = innerDocument.createDocumentFragment(); - var el = innerDocument.createElement('div'); - el.innerHTML = draggedHtml; - while (el.firstChild) { - frag.appendChild(el.firstChild); - } - range.insertNode(frag); - } -}); diff --git a/sources/tests/frontend/specs/embed_value.js b/sources/tests/frontend/specs/embed_value.js deleted file mode 100644 index 029f0dd..0000000 --- a/sources/tests/frontend/specs/embed_value.js +++ /dev/null @@ -1,136 +0,0 @@ -describe("embed links", function(){ - var objectify = function (str) - { - var hash = {}; - var parts = str.split('&'); - for(var i = 0; i < parts.length; i++) - { - var keyValue = parts[i].split('='); - hash[keyValue[0]] = keyValue[1]; - } - return hash; - } - - var checkiFrameCode = function(embedCode, readonly){ - //turn the code into an html element - var $embediFrame = $(embedCode); - - //read and check the frame attributes - var width = $embediFrame.attr("width"); - var height = $embediFrame.attr("height"); - var name = $embediFrame.attr("name"); - expect(width).to.be('600'); - expect(height).to.be('400'); - expect(name).to.be(readonly ? "embed_readonly" : "embed_readwrite"); - - //parse the url - var src = $embediFrame.attr("src"); - var questionMark = src.indexOf("?"); - var url = src.substr(0,questionMark); - var paramsStr = src.substr(questionMark+1); - var params = objectify(paramsStr); - - var expectedParams = { - showControls: 'true' - , showChat: 'true' - , showLineNumbers: 'true' - , useMonospaceFont: 'false' - } - - //check the url - if(readonly){ - expect(url.indexOf("r.") > 0).to.be(true); - } else { - expect(url).to.be(helper.padChrome$.window.location.href); - } - - //check if all parts of the url are like expected - expect(params).to.eql(expectedParams); - } - - describe("read and write", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - describe("the share link", function(){ - it("is the actual pad url", function(done){ - var chrome$ = helper.padChrome$; - - //open share dropdown - chrome$(".buttonicon-embed").click(); - - //get the link of the share field + the actual pad url and compare them - var shareLink = chrome$("#linkinput").val(); - var padURL = chrome$.window.location.href; - expect(shareLink).to.be(padURL); - - done(); - }); - }); - - describe("the embed as iframe code", function(){ - it("is an iframe with the the correct url parameters and correct size", function(done){ - var chrome$ = helper.padChrome$; - - //open share dropdown - chrome$(".buttonicon-embed").click(); - - //get the link of the share field + the actual pad url and compare them - var embedCode = chrome$("#embedinput").val(); - - checkiFrameCode(embedCode, false) - - done(); - }); - }); - }); - - describe("when read only option is set", function(){ - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - describe("the share link", function(){ - it("shows a read only url", function(done){ - var chrome$ = helper.padChrome$; - - //open share dropdown - chrome$(".buttonicon-embed").click(); - chrome$('#readonlyinput').click(); - chrome$('#readonlyinput:checkbox:not(:checked)').attr('checked', 'checked'); - - //get the link of the share field + the actual pad url and compare them - var shareLink = chrome$("#linkinput").val(); - var containsReadOnlyLink = shareLink.indexOf("r.") > 0 - expect(containsReadOnlyLink).to.be(true); - - done(); - }); - }); - - describe("the embed as iframe code", function(){ - it("is an iframe with the the correct url parameters and correct size", function(done){ - var chrome$ = helper.padChrome$; - - //open share dropdown - chrome$(".buttonicon-embed").click(); - //check read only checkbox, a bit hacky - chrome$('#readonlyinput').click(); - chrome$('#readonlyinput:checkbox:not(:checked)').attr('checked', 'checked'); - - - //get the link of the share field + the actual pad url and compare them - var embedCode = chrome$("#embedinput").val(); - - checkiFrameCode(embedCode, true); - - done(); - }); - }); - - }); -}); diff --git a/sources/tests/frontend/specs/enter.js b/sources/tests/frontend/specs/enter.js deleted file mode 100644 index baafede..0000000 --- a/sources/tests/frontend/specs/enter.js +++ /dev/null @@ -1,34 +0,0 @@ -describe("enter keystroke", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("creates a new line & puts cursor onto a new line", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - // get the original string value minus the last char - var originalTextValue = $firstTextElement.text(); - - // simulate key presses to enter content - $firstTextElement.sendkeys('{enter}'); - - //ace creates a new dom element when you press a keystroke, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); - - helper.waitFor(function(){ - return inner$("div").first().text() === ""; - }).done(function(){ - var $newSecondLine = inner$("div").first().next(); - var newFirstTextElementValue = inner$("div").first().text(); - expect(newFirstTextElementValue).to.be(""); // expect the first line to be blank - expect($newSecondLine.text()).to.be(originalTextValue); // expect the second line to be the same as the original first line. - done(); - }); - }); -}); diff --git a/sources/tests/frontend/specs/font_type.js b/sources/tests/frontend/specs/font_type.js deleted file mode 100644 index d2c7bc6..0000000 --- a/sources/tests/frontend/specs/font_type.js +++ /dev/null @@ -1,32 +0,0 @@ -describe("font select", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("makes text monospace", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); - $settingsButton.click(); - - //get the font menu and monospace option - var $viewfontmenu = chrome$("#viewfontmenu"); - var $monospaceoption = $viewfontmenu.find("[value=monospace]"); - - //select monospace and fire change event - $monospaceoption.attr('selected','selected'); - $viewfontmenu.val("monospace"); - $viewfontmenu.change(); - - //check if font changed to monospace - var fontFamily = inner$("body").css("font-family").toLowerCase(); - var containsStr = fontFamily.indexOf("monospace"); - expect(containsStr).to.not.be(-1); - - done(); - }); -}); diff --git a/sources/tests/frontend/specs/helper.js b/sources/tests/frontend/specs/helper.js deleted file mode 100644 index 8520769..0000000 --- a/sources/tests/frontend/specs/helper.js +++ /dev/null @@ -1,213 +0,0 @@ -describe("the test helper", function(){ - describe("the newPad method", function(){ - xit("doesn't leak memory if you creates iframes over and over again", function(done){ - this.timeout(100000); - - var times = 10; - - var loadPad = function(){ - helper.newPad(function(){ - times--; - if(times > 0){ - loadPad(); - } else { - done(); - } - }) - } - - loadPad(); - }); - - it("gives me 3 jquery instances of chrome, outer and inner", function(done){ - this.timeout(5000); - - helper.newPad(function(){ - //check if the jquery selectors have the desired elements - expect(helper.padChrome$("#editbar").length).to.be(1); - expect(helper.padOuter$("#outerdocbody").length).to.be(1); - expect(helper.padInner$("#innerdocbody").length).to.be(1); - - //check if the document object was set correctly - expect(helper.padChrome$.window.document).to.be(helper.padChrome$.document); - expect(helper.padOuter$.window.document).to.be(helper.padOuter$.document); - expect(helper.padInner$.window.document).to.be(helper.padInner$.document); - - done(); - }); - }); - }); - - describe("the waitFor method", function(){ - it("takes a timeout and waits long enough", function(done){ - this.timeout(2000); - var startTime = new Date().getTime(); - - helper.waitFor(function(){ - return false; - }, 1500).fail(function(){ - var duration = new Date().getTime() - startTime; - expect(duration).to.be.greaterThan(1400); - done(); - }); - }); - - it("takes an interval and checks on every interval", function(done){ - this.timeout(4000); - var checks = 0; - - helper.waitFor(function(){ - checks++; - return false; - }, 2000, 100).fail(function(){ - expect(checks).to.be.greaterThan(10); - expect(checks).to.be.lessThan(30); - done(); - }); - }); - - describe("returns a deferred object", function(){ - it("it calls done after success", function(done){ - helper.waitFor(function(){ - return true; - }).done(function(){ - done(); - }); - }); - - it("calls fail after failure", function(done){ - helper.waitFor(function(){ - return false; - },0).fail(function(){ - done(); - }); - }); - - xit("throws if you don't listen for fails", function(done){ - var onerror = window.onerror; - window.onerror = function(){ - window.onerror = onerror; - done(); - } - - helper.waitFor(function(){ - return false; - },100); - }); - }); - }); - - describe("the selectLines method", function(){ - // function to support tests, use a single way to represent whitespaces - var cleanText = function(text){ - return text - // IE replaces line breaks with a whitespace, so we need to unify its behavior - // for other browsers, to have all tests running for all browsers - .replace(/\n/gi, "") - .replace(/\s/gi, " "); - } - - before(function(done){ - helper.newPad(function() { - // create some lines to be used on the tests - var $firstLine = helper.padInner$("div").first(); - $firstLine.sendkeys("{selectall}some{enter}short{enter}lines{enter}to test{enter}{enter}"); - - // wait for lines to be split - helper.waitFor(function(){ - var $fourthLine = helper.padInner$("div").eq(3); - return $fourthLine.text() === "to test"; - }).done(done); - }); - - this.timeout(60000); - }); - - it("changes editor selection to be between startOffset of $startLine and endOffset of $endLine", function(done){ - var inner$ = helper.padInner$; - - var startOffset = 2; - var endOffset = 4; - - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(3); - - helper.selectLines($startLine, $endLine, startOffset, endOffset); - - var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort lines to t"); - - done(); - }); - - it("ends selection at beginning of $endLine when it is an empty line", function(done){ - var inner$ = helper.padInner$; - - var startOffset = 2; - var endOffset = 1; - - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(4); - - helper.selectLines($startLine, $endLine, startOffset, endOffset); - - var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort lines to test"); - - done(); - }); - - it("ends selection at beginning of $endLine when its offset is zero", function(done){ - var inner$ = helper.padInner$; - - var startOffset = 2; - var endOffset = 0; - - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(3); - - helper.selectLines($startLine, $endLine, startOffset, endOffset); - - var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort lines "); - - done(); - }); - - it("selects full line when offset is longer than line content", function(done){ - var inner$ = helper.padInner$; - - var startOffset = 2; - var endOffset = 50; - - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(3); - - helper.selectLines($startLine, $endLine, startOffset, endOffset); - - var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort lines to test"); - - done(); - }); - - it("selects all text between beginning of $startLine and end of $endLine when no offset is provided", function(done){ - var inner$ = helper.padInner$; - - var $lines = inner$("div"); - var $startLine = $lines.eq(1); - var $endLine = $lines.eq(3); - - helper.selectLines($startLine, $endLine); - - var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("short lines to test"); - - done(); - }); - }); -}); diff --git a/sources/tests/frontend/specs/importexport.js b/sources/tests/frontend/specs/importexport.js deleted file mode 100644 index 2dc002b..0000000 --- a/sources/tests/frontend/specs/importexport.js +++ /dev/null @@ -1,237 +0,0 @@ -describe("import functionality", function(){ - beforeEach(function(cb){ - helper.newPad(cb); // creates a new pad - this.timeout(60000); - }); - - function getinnertext(){ - var inner = helper.padInner$ - if(!inner){ - return "" - } - var newtext = "" - inner("div").each(function(line,el){ - newtext += el.innerHTML+"\n" - }) - return newtext - } - function importrequest(data,importurl,type){ - var success; - var error; - var result = $.ajax({ - url: importurl, - type: "post", - processData: false, - async: false, - contentType: 'multipart/form-data; boundary=boundary', - accepts: { - text: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" - }, - data: 'Content-Type: multipart/form-data; boundary=--boundary\r\n\r\n--boundary\r\nContent-Disposition: form-data; name="file"; filename="import.'+type+'"\r\nContent-Type: text/plain\r\n\r\n' + data + '\r\n\r\n--boundary', - error: function(res){ - error = res - } - }) - expect(error).to.be(undefined) - return result - } - function exportfunc(link){ - var exportresults = [] - $.ajaxSetup({ - async:false - }) - $.get(link+"/export/html",function(data){ - var start = data.indexOf("") - var end = data.indexOf("") - var html = data.substr(start+6,end-start-6) - exportresults.push(["html",html]) - }) - $.get(link+"/export/txt",function(data){ - exportresults.push(["txt",data]) - }) - return exportresults - } - - xit("import a pad with newlines from txt", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var textWithNewLines = 'imported text\nnewline' - importrequest(textWithNewLines,importurl,"txt") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('imported text\nnewline\n
      \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be("imported text
      newline

      ") - expect(results[1][1]).to.be("imported text\nnewline\n\n") - done() - }) - xit("import a pad with newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithNewLines = 'htmltext
      newline' - importrequest(htmlWithNewLines,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('htmltext\nnewline\n
      \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be("htmltext
      newline

      ") - expect(results[1][1]).to.be("htmltext\nnewline\n\n") - done() - }) - xit("import a pad with attributes from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithNewLines = 'htmltext
      newline' - importrequest(htmlWithNewLines,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('htmltext\nnewline\n
      \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('htmltext
      newline

      ') - expect(results[1][1]).to.be('htmltext\nnewline\n\n') - done() - }) - xit("import a pad with bullets from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
      • bullet line 1
      • bullet line 2
        • bullet2 line 1
        • bullet2 line 2
      ' - importrequest(htmlWithBullets,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ -
      • bullet line 1
      \n\ -
      • bullet line 2
      \n\ -
      • bullet2 line 1
      \n\ -
      • bullet2 line 2
      \n\ -
      \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
      • bullet line 1
      • bullet line 2
        • bullet2 line 1
        • bullet2 line 2

      ') - expect(results[1][1]).to.be('\t* bullet line 1\n\t* bullet line 2\n\t\t* bullet2 line 1\n\t\t* bullet2 line 2\n\n') - done() - }) - xit("import a pad with bullets and newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
      • bullet line 1

      • bullet line 2
        • bullet2 line 1

        • bullet2 line 2
      ' - importrequest(htmlWithBullets,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ -
      • bullet line 1
      \n\ -
      \n\ -
      • bullet line 2
      \n\ -
      • bullet2 line 1
      \n\ -
      \n\ -
      • bullet2 line 2
      \n\ -
      \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
      • bullet line 1

      • bullet line 2
        • bullet2 line 1

        • bullet2 line 2

      ') - expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t* bullet2 line 2\n\n') - done() - }) - xit("import a pad with bullets and newlines and attributes from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
      • bullet line 1

      • bullet line 2
        • bullet2 line 1

            • bullet4 line 2 bisu
            • bullet4 line 2 bs
            • bullet4 line 2 uuis
      ' - importrequest(htmlWithBullets,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ -
      • bullet line 1
      \n\
      \n\ -
      • bullet line 2
      \n\ -
      • bullet2 line 1
      \n
      \n\ -
      • bullet4 line 2 bisu
      \n\ -
      • bullet4 line 2 bs
      \n\ -
      • bullet4 line 2 uuis
      \n\ -
      \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
      • bullet line 1

      • bullet line 2
        • bullet2 line 1

            • bullet4 line 2 bisu
            • bullet4 line 2 bs
            • bullet4 line 2 uuis

      ') - expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t\t\t* bullet4 line 2 bisu\n\t\t\t\t* bullet4 line 2 bs\n\t\t\t\t* bullet4 line 2 uuis\n\n') - done() - }) - xit("import a pad with nested bullets from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
      • bullet line 1
      • bullet line 2
        • bullet2 line 1
            • bullet4 line 2
            • bullet4 line 2
            • bullet4 line 2
          • bullet3 line 1
      • bullet2 line 1
      ' - importrequest(htmlWithBullets,importurl,"html") - var oldtext=getinnertext() - helper.waitFor(function(){ - return oldtext != getinnertext() -// return expect(getinnertext()).to.be('\ -//
      • bullet line 1
      \n\ -//
      • bullet line 2
      \n\ -//
      • bullet2 line 1
      \n\ -//
      • bullet4 line 2
      \n\ -//
      • bullet4 line 2
      \n\ -//
      • bullet4 line 2
      \n\ -//
      \n') - }) - - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
      • bullet line 1
      • bullet line 2
        • bullet2 line 1
            • bullet4 line 2
            • bullet4 line 2
            • bullet4 line 2
          • bullet3 line 1
      • bullet2 line 1

      ') - expect(results[1][1]).to.be('\t* bullet line 1\n\t* bullet line 2\n\t\t* bullet2 line 1\n\t\t\t\t* bullet4 line 2\n\t\t\t\t* bullet4 line 2\n\t\t\t\t* bullet4 line 2\n\t\t\t* bullet3 line 1\n\t* bullet2 line 1\n\n') - done() - }) - xit("import a pad with 8 levels of bullets and newlines and attributes from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
      • bullet line 1

      • bullet line 2
        • bullet2 line 1

            • bullet4 line 2 bisu
            • bullet4 line 2 bs
            • bullet4 line 2 uuis
                    • foo
                    • foobar bs
              • foobar
        ' - importrequest(htmlWithBullets,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ -
        • bullet line 1
        \n\
        \n\ -
        • bullet line 2
        \n\ -
        • bullet2 line 1
        \n
        \n\ -
        • bullet4 line 2 bisu
        \n\ -
        • bullet4 line 2 bs
        \n\ -
        • bullet4 line 2 uuis
        \n\ -
        • foo
        \n\ -
        • foobar bs
        \n\ -
        • foobar
        \n\ -
        \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

              • bullet4 line 2 bisu
              • bullet4 line 2 bs
              • bullet4 line 2 uuis
                      • foo
                      • foobar bs
                • foobar

        ') - expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t\t\t* bullet4 line 2 bisu\n\t\t\t\t* bullet4 line 2 bs\n\t\t\t\t* bullet4 line 2 uuis\n\t\t\t\t\t\t\t\t* foo\n\t\t\t\t\t\t\t\t* foobar bs\n\t\t\t\t\t* foobar\n\n') - done() - }) - - xit("import a pad with ordered lists from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
        1. number 1 line 1
        1. number 2 line 2
        ' - importrequest(htmlWithBullets,importurl,"html") - -console.error(getinnertext()) - expect(getinnertext()).to.be('\ -
        1. number 1 line 1
        \n\ -
        1. number 2 line 2
        \n\ -
        \n') - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        1. number 1 line 1
        1. number 2 line 2
        ') - expect(results[1][1]).to.be('') - done() - }) - xit("import a pad with ordered lists and newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
        1. number 9 line 1

        1. number 10 line 2
          1. number 2 times line 1

          1. number 2 times line 2
        ' - importrequest(htmlWithBullets,importurl,"html") - expect(getinnertext()).to.be('\ -
        1. number 9 line 1
        \n\ -
        \n\ -
        1. number 10 line 2
        \n\ -
        1. number 2 times line 1
        \n\ -
        \n\ -
        1. number 2 times line 2
        \n\ -
        \n') - var results = exportfunc(helper.padChrome$.window.location.href) - console.error(results) - done() - }) - xit("import a pad with nested ordered lists and attributes and newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithBullets = '
        1. bold strikethrough italics underline line 1bold

        1. number 10 line 2
          1. number 2 times line 1

          1. number 2 times line 2
        ' - importrequest(htmlWithBullets,importurl,"html") - expect(getinnertext()).to.be('\ -
        1. bold strikethrough italics underline line 1bold
        \n\ -
        \n\ -
        1. number 10 line 2
        \n\ -
        1. number 2 times line 1
        \n\ -
        \n\ -
        1. number 2 times line 2
        \n\ -
        \n') - var results = exportfunc(helper.padChrome$.window.location.href) - console.error(results) - done() - }) -}) diff --git a/sources/tests/frontend/specs/importindents.js b/sources/tests/frontend/specs/importindents.js deleted file mode 100644 index 326d9e9..0000000 --- a/sources/tests/frontend/specs/importindents.js +++ /dev/null @@ -1,111 +0,0 @@ -describe("import indents functionality", function(){ - beforeEach(function(cb){ - helper.newPad(cb); // creates a new pad - this.timeout(60000); - }); - - function getinnertext(){ - var inner = helper.padInner$ - var newtext = "" - inner("div").each(function(line,el){ - newtext += el.innerHTML+"\n" - }) - return newtext - } - function importrequest(data,importurl,type){ - var success; - var error; - var result = $.ajax({ - url: importurl, - type: "post", - processData: false, - async: false, - contentType: 'multipart/form-data; boundary=boundary', - accepts: { - text: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" - }, - data: 'Content-Type: multipart/form-data; boundary=--boundary\r\n\r\n--boundary\r\nContent-Disposition: form-data; name="file"; filename="import.'+type+'"\r\nContent-Type: text/plain\r\n\r\n' + data + '\r\n\r\n--boundary', - error: function(res){ - error = res - } - }) - expect(error).to.be(undefined) - return result - } - function exportfunc(link){ - var exportresults = [] - $.ajaxSetup({ - async:false - }) - $.get(link+"/export/html",function(data){ - var start = data.indexOf("") - var end = data.indexOf("") - var html = data.substr(start+6,end-start-6) - exportresults.push(["html",html]) - }) - $.get(link+"/export/txt",function(data){ - exportresults.push(["txt",data]) - }) - return exportresults - } - - xit("import a pad with indents from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithIndents = '
        • indent line 1
        • indent line 2
          • indent2 line 1
          • indent2 line 2
        ' - importrequest(htmlWithIndents,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ -
        • indent line 1
        \n\ -
        • indent line 2
        \n\ -
        • indent2 line 1
        \n\ -
        • indent2 line 2
        \n\ -
        \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        • indent line 1
        • indent line 2
          • indent2 line 1
          • indent2 line 2

        ') - expect(results[1][1]).to.be('\tindent line 1\n\tindent line 2\n\t\tindent2 line 1\n\t\tindent2 line 2\n\n') - done() - }) - - xit("import a pad with indented lists and newlines from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithIndents = '
        • indent line 1

        • indent 1 line 2
          • indent 2 times line 1

          • indent 2 times line 2
        ' - importrequest(htmlWithIndents,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ -
        • indent line 1
        \n\ -
        \n\ -
        • indent 1 line 2
        \n\ -
        • indent 2 times line 1
        \n\ -
        \n\ -
        • indent 2 times line 2
        \n\ -
        \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        • indent line 1

        • indent 1 line 2
          • indent 2 times line 1

          • indent 2 times line 2

        ') - expect(results[1][1]).to.be('\tindent line 1\n\n\tindent 1 line 2\n\t\tindent 2 times line 1\n\n\t\tindent 2 times line 2\n\n') - done() - }) - xit("import a pad with 8 levels of indents and newlines and attributes from html", function(done){ - var importurl = helper.padChrome$.window.location.href+'/import' - var htmlWithIndents = '
        • indent line 1

        • indent line 2
          • indent2 line 1

              • indent4 line 2 bisu
              • indent4 line 2 bs
              • indent4 line 2 uuis
                      • foo
                      • foobar bs
                • foobar
          ' - importrequest(htmlWithIndents,importurl,"html") - helper.waitFor(function(){ - return expect(getinnertext()).to.be('\ -
          • indent line 1
          \n\
          \n\ -
          • indent line 2
          \n\ -
          • indent2 line 1
          \n
          \n\ -
          • indent4 line 2 bisu
          \n\ -
          • indent4 line 2 bs
          \n\ -
          • indent4 line 2 uuis
          \n\ -
          • foo
          \n\ -
          • foobar bs
          \n\ -
          • foobar
          \n\ -
          \n') - }) - var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
          • indent line 1

          • indent line 2
            • indent2 line 1

                • indent4 line 2 bisu
                • indent4 line 2 bs
                • indent4 line 2 uuis
                        • foo
                        • foobar bs
                  • foobar

          ') - expect(results[1][1]).to.be('\tindent line 1\n\n\tindent line 2\n\t\tindent2 line 1\n\n\t\t\t\tindent4 line 2 bisu\n\t\t\t\tindent4 line 2 bs\n\t\t\t\tindent4 line 2 uuis\n\t\t\t\t\t\t\t\tfoo\n\t\t\t\t\t\t\t\tfoobar bs\n\t\t\t\t\tfoobar\n\n') - done() - }) -}) diff --git a/sources/tests/frontend/specs/indentation.js b/sources/tests/frontend/specs/indentation.js deleted file mode 100644 index 9294cef..0000000 --- a/sources/tests/frontend/specs/indentation.js +++ /dev/null @@ -1,336 +0,0 @@ -describe("indentation button", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("indent text with keypress", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - //select this text element - $firstTextElement.sendkeys('{selectall}'); - - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); - e.keyCode = 9; // tab :| - inner$("#innerdocbody").trigger(e); - - helper.waitFor(function(){ - return inner$("div").first().find("ul li").length === 1; - }).done(done); - }); - - it("indent text with button", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - var $indentButton = chrome$(".buttonicon-indent"); - $indentButton.click(); - - helper.waitFor(function(){ - return inner$("div").first().find("ul li").length === 1; - }).done(done); - }); - - it("keeps the indent on enter for the new line", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - var $indentButton = chrome$(".buttonicon-indent"); - $indentButton.click(); - - //type a bit, make a line break and type again - var $firstTextElement = inner$("div span").first(); - $firstTextElement.sendkeys('line 1'); - $firstTextElement.sendkeys('{enter}'); - $firstTextElement.sendkeys('line 2'); - $firstTextElement.sendkeys('{enter}'); - - helper.waitFor(function(){ - return inner$("div span").first().text().indexOf("line 2") === -1; - }).done(function(){ - var $newSecondLine = inner$("div").first().next(); - var hasULElement = $newSecondLine.find("ul li").length === 1; - - expect(hasULElement).to.be(true); - expect($newSecondLine.text()).to.be("line 2"); - done(); - }); - }); - - it("indents text with spaces on enter if previous line ends with ':', '[', '(', or '{'", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //type a bit, make a line break and type again - var $firstTextElement = inner$("div").first(); - $firstTextElement.sendkeys("line with ':'{enter}"); - $firstTextElement.sendkeys("line with '['{enter}"); - $firstTextElement.sendkeys("line with '('{enter}"); - $firstTextElement.sendkeys("line with '{{}'{enter}"); - - helper.waitFor(function(){ - // wait for Etherpad to split four lines into separated divs - var $fourthLine = inner$("div").first().next().next().next(); - return $fourthLine.text().indexOf("line with '{'") === 0; - }).done(function(){ - // we validate bottom to top for easier implementation - - // curly braces - var $lineWithCurlyBraces = inner$("div").first().next().next().next(); - $lineWithCurlyBraces.sendkeys('{{}'); - pressEnter(); // cannot use sendkeys('{enter}') here, browser does not read the command properly - var $lineAfterCurlyBraces = inner$("div").first().next().next().next().next(); - expect($lineAfterCurlyBraces.text()).to.match(/\s{4}/); // tab === 4 spaces - - // parenthesis - var $lineWithParenthesis = inner$("div").first().next().next(); - $lineWithParenthesis.sendkeys('('); - pressEnter(); - var $lineAfterParenthesis = inner$("div").first().next().next().next(); - expect($lineAfterParenthesis.text()).to.match(/\s{4}/); - - // bracket - var $lineWithBracket = inner$("div").first().next(); - $lineWithBracket.sendkeys('['); - pressEnter(); - var $lineAfterBracket = inner$("div").first().next().next(); - expect($lineAfterBracket.text()).to.match(/\s{4}/); - - // colon - var $lineWithColon = inner$("div").first(); - $lineWithColon.sendkeys(':'); - pressEnter(); - var $lineAfterColon = inner$("div").first().next(); - expect($lineAfterColon.text()).to.match(/\s{4}/); - - done(); - }); - }); - - it("appends indentation to the indent of previous line if previous line ends with ':', '[', '(', or '{'", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //type a bit, make a line break and type again - var $firstTextElement = inner$("div").first(); - $firstTextElement.sendkeys(" line with some indentation and ':'{enter}"); - $firstTextElement.sendkeys("line 2{enter}"); - - helper.waitFor(function(){ - // wait for Etherpad to split two lines into separated divs - var $secondLine = inner$("div").first().next(); - return $secondLine.text().indexOf("line 2") === 0; - }).done(function(){ - var $lineWithColon = inner$("div").first(); - $lineWithColon.sendkeys(':'); - pressEnter(); - var $lineAfterColon = inner$("div").first().next(); - expect($lineAfterColon.text()).to.match(/\s{6}/); // previous line indentation + regular tab (4 spaces) - - done(); - }); - }); - - it("issue #2772 shows '*' when multiple indented lines receive a style and are outdented", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // make sure pad has more than one line - inner$("div").first().sendkeys("First{enter}Second{enter}"); - helper.waitFor(function(){ - return inner$("div").first().text().trim() === "First"; - }).done(function(){ - // indent first 2 lines - var $lines = inner$("div"); - var $firstLine = $lines.first(); - var $secondLine = $lines.slice(1,2); - helper.selectLines($firstLine, $secondLine); - - var $indentButton = chrome$(".buttonicon-indent"); - $indentButton.click(); - - helper.waitFor(function(){ - return inner$("div").first().find("ul li").length === 1; - }).done(function(){ - // apply bold - var $boldButton = chrome$(".buttonicon-bold"); - $boldButton.click(); - - helper.waitFor(function(){ - return inner$("div").first().find("b").length === 1; - }).done(function(){ - // outdent first 2 lines - var $outdentButton = chrome$(".buttonicon-outdent"); - $outdentButton.click(); - helper.waitFor(function(){ - return inner$("div").first().find("ul li").length === 0; - }).done(function(){ - // check if '*' is displayed - var $secondLine = inner$("div").slice(1,2); - expect($secondLine.text().trim()).to.be("Second"); - - done(); - }); - }); - }); - }); - }); - - /* - - it("makes text indented and outdented", function() { - - //get the inner iframe - var $inner = testHelper.$getPadInner(); - - //get the first text element out of the inner iframe - var firstTextElement = $inner.find("div").first(); - - //select this text element - testHelper.selectText(firstTextElement[0], $inner); - - //get the indentation button and click it - var $indentButton = testHelper.$getPadChrome().find(".buttonicon-indent"); - $indentButton.click(); - - //ace creates a new dom element when you press a button, so just get the first text element again - var newFirstTextElement = $inner.find("div").first(); - - // is there a list-indent class element now? - var firstChild = newFirstTextElement.children(":first"); - var isUL = firstChild.is('ul'); - - //expect it to be the beginning of a list - expect(isUL).to.be(true); - - var secondChild = firstChild.children(":first"); - var isLI = secondChild.is('li'); - //expect it to be part of a list - expect(isLI).to.be(true); - - //indent again - $indentButton.click(); - - var newFirstTextElement = $inner.find("div").first(); - - // is there a list-indent class element now? - var firstChild = newFirstTextElement.children(":first"); - var hasListIndent2 = firstChild.hasClass('list-indent2'); - - //expect it to be part of a list - expect(hasListIndent2).to.be(true); - - //make sure the text hasn't changed - expect(newFirstTextElement.text()).to.eql(firstTextElement.text()); - - - // test outdent - - //get the unindentation button and click it twice - var $outdentButton = testHelper.$getPadChrome().find(".buttonicon-outdent"); - $outdentButton.click(); - $outdentButton.click(); - - //ace creates a new dom element when you press a button, so just get the first text element again - var newFirstTextElement = $inner.find("div").first(); - - // is there a list-indent class element now? - var firstChild = newFirstTextElement.children(":first"); - var isUL = firstChild.is('ul'); - - //expect it not to be the beginning of a list - expect(isUL).to.be(false); - - var secondChild = firstChild.children(":first"); - var isLI = secondChild.is('li'); - //expect it to not be part of a list - expect(isLI).to.be(false); - - //make sure the text hasn't changed - expect(newFirstTextElement.text()).to.eql(firstTextElement.text()); - - - // Next test tests multiple line indentation - - //select this text element - testHelper.selectText(firstTextElement[0], $inner); - - //indent twice - $indentButton.click(); - $indentButton.click(); - - //get the first text element out of the inner iframe - var firstTextElement = $inner.find("div").first(); - - //select this text element - testHelper.selectText(firstTextElement[0], $inner); - - /* this test creates the below content, both should have double indentation - line1 - line2 - - - firstTextElement.sendkeys('{rightarrow}'); // simulate a keypress of enter - firstTextElement.sendkeys('{enter}'); // simulate a keypress of enter - firstTextElement.sendkeys('line 1'); // simulate writing the first line - firstTextElement.sendkeys('{enter}'); // simulate a keypress of enter - firstTextElement.sendkeys('line 2'); // simulate writing the second line - - //get the second text element out of the inner iframe - setTimeout(function(){ // THIS IS REALLY BAD - var secondTextElement = $('iframe').contents().find('iframe').contents().find('iframe').contents().find('body > div').get(1); // THIS IS UGLY - - // is there a list-indent class element now? - var firstChild = secondTextElement.children(":first"); - var isUL = firstChild.is('ul'); - - //expect it to be the beginning of a list - expect(isUL).to.be(true); - - var secondChild = secondChild.children(":first"); - var isLI = secondChild.is('li'); - //expect it to be part of a list - expect(isLI).to.be(true); - - //get the first text element out of the inner iframe - var thirdTextElement = $('iframe').contents().find('iframe').contents().find('iframe').contents().find('body > div').get(2); // THIS IS UGLY TOO - - // is there a list-indent class element now? - var firstChild = thirdTextElement.children(":first"); - var isUL = firstChild.is('ul'); - - //expect it to be the beginning of a list - expect(isUL).to.be(true); - - var secondChild = firstChild.children(":first"); - var isLI = secondChild.is('li'); - - //expect it to be part of a list - expect(isLI).to.be(true); - },1000); - });*/ - -}); - -function pressEnter(){ - var inner$ = helper.padInner$; - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - var e = inner$.Event(evtType); - e.keyCode = 13; // enter :| - inner$("#innerdocbody").trigger(e); -} diff --git a/sources/tests/frontend/specs/italic.js b/sources/tests/frontend/specs/italic.js deleted file mode 100644 index bf7f2bc..0000000 --- a/sources/tests/frontend/specs/italic.js +++ /dev/null @@ -1,73 +0,0 @@ -describe("italic some text", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("makes text italic using button", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - //select this text element - $firstTextElement.sendkeys('{selectall}'); - - //get the bold button and click it - var $boldButton = chrome$(".buttonicon-italic"); - $boldButton.click(); - - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); - - // is there a element now? - var isItalic = $newFirstTextElement.find("i").length === 1; - - //expect it to be bold - expect(isItalic).to.be(true); - - //make sure the text hasn't changed - expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); - - done(); - }); - - it("makes text italic using keypress", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - //select this text element - $firstTextElement.sendkeys('{selectall}'); - - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); - e.ctrlKey = true; // Control key - e.which = 105; // i - inner$("#innerdocbody").trigger(e); - - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); - - // is there a element now? - var isItalic = $newFirstTextElement.find("i").length === 1; - - //expect it to be bold - expect(isItalic).to.be(true); - - //make sure the text hasn't changed - expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); - - done(); - }); - -}); diff --git a/sources/tests/frontend/specs/language.js b/sources/tests/frontend/specs/language.js deleted file mode 100644 index 41a19d1..0000000 --- a/sources/tests/frontend/specs/language.js +++ /dev/null @@ -1,135 +0,0 @@ -function deletecookie(name) { - document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; -} - -describe("Language select and change", function(){ - // Destroy language cookies - deletecookie("language", null); - - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - // Destroy language cookies - it("makes text german", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); - $settingsButton.click(); - - //click the language button - var $language = chrome$("#languagemenu"); - var $languageoption = $language.find("[value=de]"); - - //select german - $languageoption.attr('selected','selected'); - $language.change(); - - helper.waitFor(function() { - return chrome$(".buttonicon-bold").parent()[0]["title"] == "Fett (Strg-B)"; - }) - .done(function(){ - //get the value of the bold button - var $boldButton = chrome$(".buttonicon-bold").parent(); - - //get the title of the bold button - var boldButtonTitle = $boldButton[0]["title"]; - - //check if the language is now german - expect(boldButtonTitle).to.be("Fett (Strg-B)"); - done(); - }); - }); - - it("makes text English", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); - $settingsButton.click(); - - //click the language button - var $language = chrome$("#languagemenu"); - //select english - $language.val("en"); - $language.change(); - - //get the value of the bold button - var $boldButton = chrome$(".buttonicon-bold").parent(); - - helper.waitFor(function() { return $boldButton[0]["title"] != "Fett (Strg+B)";}) - .done(function(){ - - //get the value of the bold button - var $boldButton = chrome$(".buttonicon-bold").parent(); - - //get the title of the bold button - var boldButtonTitle = $boldButton[0]["title"]; - - //check if the language is now English - expect(boldButtonTitle).to.be("Bold (Ctrl+B)"); - done(); - - }); - }); - - it("changes direction when picking an rtl lang", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); - $settingsButton.click(); - - //click the language button - var $language = chrome$("#languagemenu"); - var $languageoption = $language.find("[value=ar]"); - - //select arabic - // $languageoption.attr('selected','selected'); // Breaks the test.. - $language.val("ar"); - $languageoption.change(); - - helper.waitFor(function() { - return chrome$("html")[0]["dir"] != 'ltr'; - }) - .done(function(){ - // check if the document's direction was changed - expect(chrome$("html")[0]["dir"]).to.be("rtl"); - done(); - }); - }); - - it("changes direction when picking an ltr lang", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); - $settingsButton.click(); - - //click the language button - var $language = chrome$("#languagemenu"); - var $languageoption = $language.find("[value=en]"); - - //select english - //select arabic - $languageoption.attr('selected','selected'); - $language.val("en"); - $languageoption.change(); - - helper.waitFor(function() { - return chrome$("html")[0]["dir"] != 'rtl'; - }) - .done(function(){ - // check if the document's direction was changed - expect(chrome$("html")[0]["dir"]).to.be("ltr"); - done(); - }); - }); -}); diff --git a/sources/tests/frontend/specs/ordered_list.js b/sources/tests/frontend/specs/ordered_list.js deleted file mode 100644 index 57196fe..0000000 --- a/sources/tests/frontend/specs/ordered_list.js +++ /dev/null @@ -1,133 +0,0 @@ -describe("assign ordered list", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("inserts ordered list text", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist"); - $insertorderedlistButton.click(); - - helper.waitFor(function(){ - return inner$("div").first().find("ol li").length === 1; - }).done(done); - }); - - context('when user presses Ctrl+Shift+N', function() { - context('and pad shortcut is enabled', function() { - beforeEach(function() { - makeSureShortcutIsEnabled('cmdShiftN'); - triggerCtrlShiftShortcut('N'); - }); - - it('inserts unordered list', function(done) { - helper.waitFor(function() { - return helper.padInner$('div').first().find('ol li').length === 1; - }).done(done); - }); - }); - - context('and pad shortcut is disabled', function() { - beforeEach(function() { - makeSureShortcutIsDisabled('cmdShiftN'); - triggerCtrlShiftShortcut('N'); - }); - - it('does not insert unordered list', function(done) { - helper.waitFor(function() { - return helper.padInner$('div').first().find('ol li').length === 1; - }).done(function() { - expect().fail(function() { return 'Unordered list inserted, should ignore shortcut' }); - }).fail(function() { - done(); - }); - }); - }); - }); - - context('when user presses Ctrl+Shift+1', function() { - context('and pad shortcut is enabled', function() { - beforeEach(function() { - makeSureShortcutIsEnabled('cmdShift1'); - triggerCtrlShiftShortcut('1'); - }); - - it('inserts unordered list', function(done) { - helper.waitFor(function() { - return helper.padInner$('div').first().find('ol li').length === 1; - }).done(done); - }); - }); - - context('and pad shortcut is disabled', function() { - beforeEach(function() { - makeSureShortcutIsDisabled('cmdShift1'); - triggerCtrlShiftShortcut('1'); - }); - - it('does not insert unordered list', function(done) { - helper.waitFor(function() { - return helper.padInner$('div').first().find('ol li').length === 1; - }).done(function() { - expect().fail(function() { return 'Unordered list inserted, should ignore shortcut' }); - }).fail(function() { - done(); - }); - }); - }); - }); - - xit("issue #1125 keeps the numbered list on enter for the new line - EMULATES PASTING INTO A PAD", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist"); - $insertorderedlistButton.click(); - - //type a bit, make a line break and type again - var $firstTextElement = inner$("div span").first(); - $firstTextElement.sendkeys('line 1'); - $firstTextElement.sendkeys('{enter}'); - $firstTextElement.sendkeys('line 2'); - $firstTextElement.sendkeys('{enter}'); - - helper.waitFor(function(){ - return inner$("div span").first().text().indexOf("line 2") === -1; - }).done(function(){ - var $newSecondLine = inner$("div").first().next(); - var hasOLElement = $newSecondLine.find("ol li").length === 1; - console.log($newSecondLine.find("ol")); - expect(hasOLElement).to.be(true); - expect($newSecondLine.text()).to.be("line 2"); - var hasLineNumber = $newSecondLine.find("ol").attr("start") === 2; - expect(hasLineNumber).to.be(true); // This doesn't work because pasting in content doesn't work - done(); - }); - }); - - var triggerCtrlShiftShortcut = function(shortcutChar) { - var inner$ = helper.padInner$; - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE) { // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - var e = inner$.Event(evtType); - e.ctrlKey = true; - e.shiftKey = true; - e.which = shortcutChar.toString().charCodeAt(0); - inner$("#innerdocbody").trigger(e); - } - - var makeSureShortcutIsDisabled = function(shortcut) { - helper.padChrome$.window.clientVars.padShortcutEnabled[shortcut] = false; - } - var makeSureShortcutIsEnabled = function(shortcut) { - helper.padChrome$.window.clientVars.padShortcutEnabled[shortcut] = true; - } - -}); diff --git a/sources/tests/frontend/specs/pad_modal.js b/sources/tests/frontend/specs/pad_modal.js deleted file mode 100644 index 80752e4..0000000 --- a/sources/tests/frontend/specs/pad_modal.js +++ /dev/null @@ -1,131 +0,0 @@ -describe('Pad modal', function() { - context('when modal is a "force reconnect" message', function() { - var MODAL_SELECTOR = '#connectivity .slowcommit'; - - beforeEach(function(done) { - helper.newPad(function() { - // force a "slowcommit" error - helper.padChrome$.window.pad.handleChannelStateChange('DISCONNECTED', 'slowcommit'); - - // wait for modal to be displayed - var $modal = helper.padChrome$(MODAL_SELECTOR); - helper.waitFor(function() { - return $modal.is(':visible'); - }, 50000).done(done); - }); - - this.timeout(60000); - }); - - it('disables editor', function(done) { - expect(isEditorDisabled()).to.be(true); - - done(); - }); - - context('and user clicks on editor', function() { - beforeEach(function() { - clickOnPadInner(); - }); - - it('does not close the modal', function(done) { - var $modal = helper.padChrome$(MODAL_SELECTOR); - var modalIsVisible = $modal.is(':visible'); - - expect(modalIsVisible).to.be(true); - - done(); - }); - }); - - context('and user clicks on pad outer', function() { - beforeEach(function() { - clickOnPadOuter(); - }); - - it('does not close the modal', function(done) { - var $modal = helper.padChrome$(MODAL_SELECTOR); - var modalIsVisible = $modal.is(':visible'); - - expect(modalIsVisible).to.be(true); - - done(); - }); - }); - }); - - // we use "settings" here, but other modals have the same behaviour - context('when modal is not an error message', function() { - var MODAL_SELECTOR = '#settings'; - - beforeEach(function(done) { - helper.newPad(function() { - openSettingsAndWaitForModalToBeVisible(done); - }); - - this.timeout(60000); - }); - - it('does not disable editor', function(done) { - expect(isEditorDisabled()).to.be(false); - done(); - }); - - context('and user clicks on editor', function() { - beforeEach(function() { - clickOnPadInner(); - }); - - it('closes the modal', function(done) { - expect(isModalOpened(MODAL_SELECTOR)).to.be(false); - done(); - }); - }); - - context('and user clicks on pad outer', function() { - beforeEach(function() { - clickOnPadOuter(); - }); - - it('closes the modal', function(done) { - expect(isModalOpened(MODAL_SELECTOR)).to.be(false); - done(); - }); - }); - }); - - var clickOnPadInner = function() { - var $editor = helper.padInner$('#innerdocbody'); - $editor.click(); - } - - var clickOnPadOuter = function() { - var $lineNumbersColumn = helper.padOuter$('#sidedivinner'); - $lineNumbersColumn.click(); - } - - var openSettingsAndWaitForModalToBeVisible = function(done) { - helper.padChrome$('.buttonicon-settings').click(); - - // wait for modal to be displayed - var modalSelector = '#settings'; - helper.waitFor(function() { - return isModalOpened(modalSelector); - }, 10000).done(done); - } - - var isEditorDisabled = function() { - var editorDocument = helper.padOuter$("iframe[name='ace_inner']").get(0).contentDocument; - var editorBody = editorDocument.getElementById('innerdocbody'); - - var editorIsDisabled = editorBody.contentEditable === 'false' // IE/Safari - || editorDocument.designMode === 'off'; // other browsers - - return editorIsDisabled; - } - - var isModalOpened = function(modalSelector) { - var $modal = helper.padChrome$(modalSelector); - return $modal.is(':visible'); - } -}); diff --git a/sources/tests/frontend/specs/redo.js b/sources/tests/frontend/specs/redo.js deleted file mode 100644 index caa32fe..0000000 --- a/sources/tests/frontend/specs/redo.js +++ /dev/null @@ -1,76 +0,0 @@ -describe("undo button then redo button", function(){ - beforeEach(function(cb){ - helper.newPad(cb); // creates a new pad - this.timeout(60000); - }); - - it("redo some typing with button", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value - var newString = "Foo"; - - $firstTextElement.sendkeys(newString); // send line 1 to the pad - var modifiedValue = $firstTextElement.text(); // get the modified value - expect(modifiedValue).not.to.be(originalValue); // expect the value to change - - // get undo and redo buttons - var $undoButton = chrome$(".buttonicon-undo"); - var $redoButton = chrome$(".buttonicon-redo"); - // click the buttons - $undoButton.click(); // removes foo - $redoButton.click(); // resends foo - - helper.waitFor(function(){ - console.log(inner$("div span").first().text()); - return inner$("div span").first().text() === newString; - }).done(function(){ - var finalValue = inner$("div").first().text(); - expect(finalValue).to.be(modifiedValue); // expect the value to change - done(); - }); - }); - - it("redo some typing with keypress", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value - var newString = "Foo"; - - $firstTextElement.sendkeys(newString); // send line 1 to the pad - var modifiedValue = $firstTextElement.text(); // get the modified value - expect(modifiedValue).not.to.be(originalValue); // expect the value to change - - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); - e.ctrlKey = true; // Control key - e.which = 90; // z - inner$("#innerdocbody").trigger(e); - - var e = inner$.Event(evtType); - e.ctrlKey = true; // Control key - e.which = 121; // y - inner$("#innerdocbody").trigger(e); - - helper.waitFor(function(){ - console.log(inner$("div span").first().text()); - return inner$("div span").first().text() === newString; - }).done(function(){ - var finalValue = inner$("div").first().text(); - expect(finalValue).to.be(modifiedValue); // expect the value to change - done(); - }); - }); -}); - diff --git a/sources/tests/frontend/specs/responsiveness.js b/sources/tests/frontend/specs/responsiveness.js deleted file mode 100644 index ff7dace..0000000 --- a/sources/tests/frontend/specs/responsiveness.js +++ /dev/null @@ -1,80 +0,0 @@ -// Test for https://github.com/ether/etherpad-lite/issues/1763 - -// This test fails in Opera, IE and Safari -// Opera fails due to a weird way of handling the order of execution, yet actual performance seems fine -// Safari fails due the delay being too great yet the actual performance seems fine -// Firefox might panic that the script is taking too long so will fail -// IE will fail due to running out of memory as it can't fit 2M chars in memory. - -// Just FYI Google Docs crashes on large docs whilst trying to Save, it's likely the limitations we are -// experiencing are more to do with browser limitations than improper implementation. -// A ueber fix for this would be to have a separate lower cpu priority thread that handles operations that aren't -// visible to the user. - -// Adapted from John McLear's original test case. - -describe('Responsiveness of Editor', function() { - // create a new pad before each test run - beforeEach(function(cb) { - helper.newPad(cb); - this.timeout(6000); - }); - xit('Fast response to keypress in pad with large amount of contents', function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - var chars = '0000000000'; // row of placeholder chars - var amount = 200000; //number of blocks of chars we will insert - var length = (amount * (chars.length) +1); // include a counter for each space - var text = ''; // the text we're gonna insert - this.timeout(amount * 100); - - // get keys to send - var keyMultiplier = 10; // multiplier * 10 == total number of key events - var keysToSend = ''; - for(var i=0; i <= keyMultiplier; i++) { - keysToSend += chars; - } - - var textElement = inner$('div'); - textElement.sendkeys('{selectall}'); // select all - textElement.sendkeys('{del}'); // clear the pad text - - for(var i=0; i <= amount; i++) { - text = text + chars + ' '; // add the chars and space to the text contents - } - inner$('div').first().text(text); // Put the text contents into the pad - - helper.waitFor(function(){ // Wait for the new contents to be on the pad - return inner$('div').text().length > length; - }).done(function(){ - - expect( inner$('div').text().length ).to.be.greaterThan( length ); // has the text changed? - var start = new Date().getTime(); // get the start time - - // send some new text to the screen (ensure all 3 key events are sent) - var el = inner$('div').first(); - for(var i = 0; i < keysToSend.length; ++i) { - var x = keysToSend.charCodeAt(i); - ['keyup', 'keypress', 'keydown'].forEach(function(type) { - var e = $.Event(type); - e.keyCode = x; - el.trigger(e); - }); - } - - helper.waitFor(function(){ // Wait for the ability to process - return true; // Ghetto but works for now - }).done(function(){ - var end = new Date().getTime(); // get the current time - var delay = end - start; // get the delay as the current time minus the start time - - console.log('delay:', delay); - expect(delay).to.be.below(200); - done(); - }, 1000); - - }, 10000); - }); - -}); - diff --git a/sources/tests/frontend/specs/scroll.js b/sources/tests/frontend/specs/scroll.js deleted file mode 100644 index 096b06b..0000000 --- a/sources/tests/frontend/specs/scroll.js +++ /dev/null @@ -1,649 +0,0 @@ -describe('scroll when focus line is out of viewport', function () { - before(function (done) { - helper.newPad(function(){ - cleanPad(function(){ - forceUseMonospacedFont(); - scrollWhenPlaceCaretInTheLastLineOfViewport(); - createPadWithSeveralLines(function(){ - resizeEditorHeight(); - done(); - }); - }); - }); - this.timeout(20000); - }); - - context('when user presses any arrow keys on a line above the viewport', function(){ - context('and scroll percentage config is set to 0.2 on settings.json', function(){ - var lineCloseOfTopOfPad = 10; - before(function (done) { - setScrollPercentageWhenFocusLineIsOutOfViewport(0.2, true); - scrollEditorToBottomOfPad(); - - placeCaretInTheBeginningOfLine(lineCloseOfTopOfPad, function(){ // place caret in the 10th line - // warning: even pressing right arrow, the caret does not change of position - // the column where the caret is, it has not importance, only the line - pressAndReleaseRightArrow(); - done(); - }); - }); - - it('keeps the focus line scrolled 20% from the top of the viewport', function (done) { - // default behavior is to put the line in the top of viewport, but as - // scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.2, we have an extra 20% of lines scrolled - // (2 lines, which are the 20% of the 10 that are visible on viewport) - var firstLineOfViewport = getFirstLineVisibileOfViewport(); - expect(lineCloseOfTopOfPad).to.be(firstLineOfViewport + 2); - done(); - }); - }); - }); - - context('when user presses any arrow keys on a line below the viewport', function(){ - context('and scroll percentage config is set to 0.7 on settings.json', function(){ - var lineCloseToBottomOfPad = 50; - before(function (done) { - setScrollPercentageWhenFocusLineIsOutOfViewport(0.7); - - // firstly, scroll to make the lineCloseToBottomOfPad visible. After that, scroll to make it out of viewport - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lineCloseToBottomOfPad); // place caret in the 50th line - setTimeout(function() { - // warning: even pressing right arrow, the caret does not change of position - pressAndReleaseLeftArrow(); - done(); - }, 1000); - }); - - it('keeps the focus line scrolled 70% from the bottom of the viewport', function (done) { - // default behavior is to put the line in the top of viewport, but as - // scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.7, we have an extra 70% of lines scrolled - // (7 lines, which are the 70% of the 10 that are visible on viewport) - var lastLineOfViewport = getLastLineVisibleOfViewport(); - expect(lineCloseToBottomOfPad).to.be(lastLineOfViewport - 7); - done(); - }); - }); - }); - - context('when user presses arrow up on the first line of the viewport', function(){ - context('and percentageToScrollWhenUserPressesArrowUp is set to 0.3', function () { - var lineOnTopOfViewportWhenThePadIsScrolledDown; - before(function (done) { - setPercentageToScrollWhenUserPressesArrowUp(0.3); - - // we need some room to make the scroll up - scrollEditorToBottomOfPad(); - lineOnTopOfViewportWhenThePadIsScrolledDown = 91; - placeCaretAtTheEndOfLine(lineOnTopOfViewportWhenThePadIsScrolledDown); - setTimeout(function() { - // warning: even pressing up arrow, the caret does not change of position - pressAndReleaseUpArrow(); - done(); - }, 1000); - }); - - it('keeps the focus line scrolled 30% of the top of the viewport', function (done) { - // default behavior is to put the line in the top of viewport, but as - // PercentageToScrollWhenUserPressesArrowUp is set to 0.3, we have an extra 30% of lines scrolled - // (3 lines, which are the 30% of the 10 that are visible on viewport) - var firstLineOfViewport = getFirstLineVisibileOfViewport(); - expect(firstLineOfViewport).to.be(lineOnTopOfViewportWhenThePadIsScrolledDown - 3); - done(); - }) - }); - }); - - context('when user edits the last line of viewport', function(){ - context('and scroll percentage config is set to 0 on settings.json', function(){ - var lastLineOfViewportBeforeEnter = 10; - before(function () { - // the default value - resetScrollPercentageWhenFocusLineIsOutOfViewport(); - - // make sure the last line on viewport is the 10th one - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lastLineOfViewportBeforeEnter); - pressEnter(); - }); - - it('keeps the focus line on the bottom of the viewport', function (done) { - var lastLineOfViewportAfterEnter = getLastLineVisibleOfViewport(); - expect(lastLineOfViewportAfterEnter).to.be(lastLineOfViewportBeforeEnter + 1); - done(); - }); - }); - - context('and scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.3', function(){ // this value is arbitrary - var lastLineOfViewportBeforeEnter = 9; - before(function () { - setScrollPercentageWhenFocusLineIsOutOfViewport(0.3); - - // make sure the last line on viewport is the 10th one - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lastLineOfViewportBeforeEnter); - pressBackspace(); - }); - - it('scrolls 30% of viewport up', function (done) { - var lastLineOfViewportAfterEnter = getLastLineVisibleOfViewport(); - // default behavior is to scroll one line at the bottom of viewport, but as - // scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.3, we have an extra 30% of lines scrolled - // (3 lines, which are the 30% of the 10 that are visible on viewport) - expect(lastLineOfViewportAfterEnter).to.be(lastLineOfViewportBeforeEnter + 3); - done(); - }); - }); - - context('and it is set to a value that overflow the interval [0, 1]', function(){ - var lastLineOfViewportBeforeEnter = 10; - before(function(){ - var scrollPercentageWhenFocusLineIsOutOfViewport = 1.5; - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lastLineOfViewportBeforeEnter); - setScrollPercentageWhenFocusLineIsOutOfViewport(scrollPercentageWhenFocusLineIsOutOfViewport); - pressEnter(); - }); - - it('keeps the default behavior of moving the focus line on the bottom of the viewport', function (done) { - var lastLineOfViewportAfterEnter = getLastLineVisibleOfViewport(); - expect(lastLineOfViewportAfterEnter).to.be(lastLineOfViewportBeforeEnter + 1); - done(); - }); - }); - }); - - context('when user edits a line above the viewport', function(){ - context('and scroll percentage config is set to 0 on settings.json', function(){ - var lineCloseOfTopOfPad = 10; - before(function () { - // the default value - setScrollPercentageWhenFocusLineIsOutOfViewport(0); - - // firstly, scroll to make the lineCloseOfTopOfPad visible. After that, scroll to make it out of viewport - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lineCloseOfTopOfPad); // place caret in the 10th line - scrollEditorToBottomOfPad(); - pressBackspace(); // edit the line where the caret is, which is above the viewport - }); - - it('keeps the focus line on the top of the viewport', function (done) { - var firstLineOfViewportAfterEnter = getFirstLineVisibileOfViewport(); - expect(firstLineOfViewportAfterEnter).to.be(lineCloseOfTopOfPad); - done(); - }); - }); - - context('and scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.2', function(){ // this value is arbitrary - var lineCloseToBottomOfPad = 50; - before(function () { - // we force the line edited to be above the top of the viewport - setScrollPercentageWhenFocusLineIsOutOfViewport(0.2, true); // set scroll jump to 20% - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lineCloseToBottomOfPad); - scrollEditorToBottomOfPad(); - pressBackspace(); // edit line - }); - - it('scrolls 20% of viewport down', function (done) { - // default behavior is to scroll one line at the top of viewport, but as - // scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.2, we have an extra 20% of lines scrolled - // (2 lines, which are the 20% of the 10 that are visible on viewport) - var firstLineVisibileOfViewport = getFirstLineVisibileOfViewport(); - expect(lineCloseToBottomOfPad).to.be(firstLineVisibileOfViewport + 2); - done(); - }); - }); - }); - - context('when user places the caret at the last line visible of viewport', function(){ - var lastLineVisible; - context('and scroll percentage config is set to 0 on settings.json', function(){ - before(function (done) { - // reset to the default value - resetScrollPercentageWhenFocusLineIsOutOfViewport(); - - placeCaretInTheBeginningOfLine(0, function(){ // reset caret position - scrollEditorToTopOfPad(); - lastLineVisible = getLastLineVisibleOfViewport(); - placeCaretInTheBeginningOfLine(lastLineVisible, done); // place caret in the 9th line - }); - - }); - - it('does not scroll', function(done){ - setTimeout(function() { - var lastLineOfViewport = getLastLineVisibleOfViewport(); - var lineDoesNotScroll = lastLineOfViewport === lastLineVisible; - expect(lineDoesNotScroll).to.be(true); - done(); - }, 1000); - }); - }); - context('and scroll percentage config is set to 0.5 on settings.json', function(){ - before(function (done) { - setScrollPercentageWhenFocusLineIsOutOfViewport(0.5); - scrollEditorToTopOfPad(); - placeCaretInTheBeginningOfLine(0, function(){ // reset caret position - // this timeout inside a callback is ugly but it necessary to give time to aceSelectionChange - // realizes that the selection has been changed - setTimeout(function() { - lastLineVisible = getLastLineVisibleOfViewport(); - placeCaretInTheBeginningOfLine(lastLineVisible, done); // place caret in the 9th line - }, 1000); - }); - }); - - it('scrolls line to 50% of the viewport', function(done){ - helper.waitFor(function(){ - var lastLineOfViewport = getLastLineVisibleOfViewport(); - var lastLinesScrolledFiveLinesUp = lastLineOfViewport - 5 === lastLineVisible; - return lastLinesScrolledFiveLinesUp; - }).done(done); - }); - }); - }); - - // This is a special case. When user is selecting a text with arrow down or arrow left we have - // to keep the last line selected on focus - context('when the first line selected is out of the viewport and user presses shift arrow down', function(){ - var lastLineOfPad = 99; - before(function (done) { - scrollEditorToTopOfPad(); - - // make a selection bigger than the viewport height - var $firstLineOfSelection = getLine(0); - var $lastLineOfSelection = getLine(lastLineOfPad); - var lengthOfLastLine = $lastLineOfSelection.text().length; - helper.selectLines($firstLineOfSelection, $lastLineOfSelection, 0, lengthOfLastLine); - - // place the last line selected on the viewport - scrollEditorToBottomOfPad(); - - // press a key to make the selection goes down - // although we can't simulate the extending of selection. It's possible to send a key event - // which is captured on ace2_inner scroll function. - pressAndReleaseLeftArrow(true); - done(); - }); - - it('keeps the last line selected on focus', function (done) { - var lastLineOfSelectionIsVisible = isLineOnViewport(lastLineOfPad); - expect(lastLineOfSelectionIsVisible).to.be(true); - done(); - }); - }); - - // In this scenario we avoid the bouncing scroll. E.g Let's suppose we have a big line that is - // the size of the viewport, and its top is above the viewport. When user presses '<-', this line - // will scroll down because the top is out of the viewport. When it scrolls down, the bottom of - // line gets below the viewport so when user presses '<-' again it scrolls up to make the bottom - // of line visible. If user presses arrow keys more than one time, the editor will keep scrolling up and down - context('when the line height is bigger than the scroll amount percentage * viewport height', function(){ - var scrollOfEditorBeforePressKey; - var BIG_LINE_NUMBER = 0; - var MIDDLE_OF_BIG_LINE = 51; - before(function (done) { - createPadWithALineHigherThanViewportHeight(this, BIG_LINE_NUMBER, function(){ - setScrollPercentageWhenFocusLineIsOutOfViewport(0.5); // set any value to force scroll to outside to viewport - var $bigLine = getLine(BIG_LINE_NUMBER); - - // each line has about 5 chars, we place the caret in the middle of the line - helper.selectLines($bigLine, $bigLine, MIDDLE_OF_BIG_LINE, MIDDLE_OF_BIG_LINE); - - scrollEditorToLeaveTopAndBottomOfBigLineOutOfViewport($bigLine); - scrollOfEditorBeforePressKey = getEditorScroll(); - - // press a key to force to scroll - pressAndReleaseRightArrow(); - done(); - }); - }); - - // reset pad to the original text - after(function (done) { - this.timeout(5000); - cleanPad(function(){ - createPadWithSeveralLines(function(){ - resetEditorWidth(); - done(); - }); - }); - }); - - // as the editor.line is inside of the viewport, it should not scroll - it('should not scroll', function (done) { - var scrollOfEditorAfterPressKey = getEditorScroll(); - expect(scrollOfEditorAfterPressKey).to.be(scrollOfEditorBeforePressKey); - done(); - }); - }); - - // Some plugins, for example the ep_page_view, change the editor dimensions. This plugin, for example, - // adds padding-top to the ace_outer, which changes the viewport height - describe('integration with plugins which changes the margin of editor', function(){ - context('when editor dimensions changes', function(){ - before(function () { - // reset the size of editor. Now we show more than 10 lines as in the other tests - resetResizeOfEditorHeight(); - scrollEditorToTopOfPad(); - - // height of the editor viewport - var editorHeight = getEditorHeight(); - - // add a big padding-top, 50% of the viewport - var paddingTopOfAceOuter = editorHeight/2; - var chrome$ = helper.padChrome$; - var $outerIframe = chrome$('iframe'); - $outerIframe.css('padding-top', paddingTopOfAceOuter); - - // we set a big value to check if the scroll is made - setScrollPercentageWhenFocusLineIsOutOfViewport(1); - }); - - context('and user places the caret in the last line visible of the pad', function(){ - var lastLineVisible; - beforeEach(function (done) { - lastLineVisible = getLastLineVisibleOfViewport(); - placeCaretInTheBeginningOfLine(lastLineVisible, done); - }); - - it('scrolls the line where caret is', function(done){ - helper.waitFor(function(){ - var firstLineVisibileOfViewport = getFirstLineVisibileOfViewport(); - var linesScrolled = firstLineVisibileOfViewport !== 0; - return linesScrolled; - }).done(done); - }); - }); - }); - }); - - /* ********************* Helper functions/constants ********************* */ - var TOP_OF_PAGE = 0; - var BOTTOM_OF_PAGE = 5000; // we use a big value to force the page to be scrolled all the way down - var LINES_OF_PAD = 100; - var ENTER = 13; - var BACKSPACE = 8; - var LEFT_ARROW = 37; - var UP_ARROW = 38; - var RIGHT_ARROW = 39; - var LINES_ON_VIEWPORT = 10; - var WIDTH_OF_EDITOR_RESIZED = 100; - var LONG_TEXT_CHARS = 100; - - var cleanPad = function(callback) { - var inner$ = helper.padInner$; - var $padContent = inner$('#innerdocbody'); - $padContent.html(''); - - // wait for Etherpad to re-create first line - helper.waitFor(function(){ - var lineNumber = inner$('div').length; - return lineNumber === 1; - }, 2000).done(callback); - }; - - var createPadWithSeveralLines = function(done) { - var line = 'a
          '; - var $firstLine = helper.padInner$('div').first(); - var lines = line.repeat(LINES_OF_PAD); //arbitrary number, we need to create lines that is over the viewport - $firstLine.html(lines); - - helper.waitFor(function(){ - var linesCreated = helper.padInner$('div').length; - return linesCreated === LINES_OF_PAD; - }, 4000).done(done); - }; - - var createPadWithALineHigherThanViewportHeight = function(test, line, done) { - var viewportHeight = 160; //10 lines * 16px (height of line) - test.timeout(5000); - cleanPad(function(){ - // make the editor smaller to make test easier - // with that width the each line has about 5 chars - resizeEditorWidth(); - - // we create a line with 100 chars, which makes about 20 lines - setLongTextOnLine(line); - helper.waitFor(function () { - var $firstLine = getLine(line); - - var heightOfLine = $firstLine.get(0).getBoundingClientRect().height; - return heightOfLine >= viewportHeight; - }, 4000).done(done); - }); - }; - - var setLongTextOnLine = function(line) { - var $line = getLine(line); - var longText = 'a'.repeat(LONG_TEXT_CHARS); - $line.html(longText); - }; - - // resize the editor to make the tests easier - var resizeEditorHeight = function() { - var chrome$ = helper.padChrome$; - chrome$('#editorcontainer').css('height', getSizeOfViewport()); - }; - - // this makes about 5 chars per line - var resizeEditorWidth = function() { - var chrome$ = helper.padChrome$; - chrome$('#editorcontainer').css('width', WIDTH_OF_EDITOR_RESIZED); - }; - - var resetResizeOfEditorHeight = function() { - var chrome$ = helper.padChrome$; - chrome$('#editorcontainer').css('height', ''); - }; - - var resetEditorWidth = function () { - var chrome$ = helper.padChrome$; - chrome$('#editorcontainer').css('width', ''); - }; - - var getEditorHeight = function() { - var chrome$ = helper.padChrome$; - var $editor = chrome$('#editorcontainer'); - var editorHeight = $editor.get(0).clientHeight; - return editorHeight; - }; - - var getSizeOfViewport = function() { - return getLinePositionOnViewport(LINES_ON_VIEWPORT) - getLinePositionOnViewport(0); - }; - - var scrollPageTo = function(value) { - var outer$ = helper.padOuter$; - var $ace_outer = outer$('#outerdocbody').parent(); - $ace_outer.parent().scrollTop(value); - }; - - var scrollEditorToTopOfPad = function() { - scrollPageTo(TOP_OF_PAGE); - }; - - var scrollEditorToBottomOfPad = function() { - scrollPageTo(BOTTOM_OF_PAGE); - }; - - var scrollEditorToLeaveTopAndBottomOfBigLineOutOfViewport = function ($bigLine) { - var lineHeight = $bigLine.get(0).getBoundingClientRect().height; - var middleOfLine = lineHeight/2; - scrollPageTo(middleOfLine); - }; - - var getLine = function(lineNum) { - var inner$ = helper.padInner$; - var $line = inner$('div').eq(lineNum); - return $line; - }; - - var placeCaretAtTheEndOfLine = function(lineNum) { - var $targetLine = getLine(lineNum); - var lineLength = $targetLine.text().length; - helper.selectLines($targetLine, $targetLine, lineLength, lineLength); - }; - - var placeCaretInTheBeginningOfLine = function(lineNum, cb) { - var $targetLine = getLine(lineNum); - helper.selectLines($targetLine, $targetLine, 0, 0); - helper.waitFor(function() { - var $lineWhereCaretIs = getLineWhereCaretIs(); - return $targetLine.get(0) === $lineWhereCaretIs.get(0); - }).done(cb); - }; - - var getLineWhereCaretIs = function() { - var inner$ = helper.padInner$; - var nodeWhereCaretIs = inner$.document.getSelection().anchorNode; - var $lineWhereCaretIs = $(nodeWhereCaretIs).closest('div'); - return $lineWhereCaretIs; - }; - - var getFirstLineVisibileOfViewport = function() { - return _.find(_.range(0, LINES_OF_PAD - 1), isLineOnViewport); - }; - - var getLastLineVisibleOfViewport = function() { - return _.find(_.range(LINES_OF_PAD - 1, 0, -1), isLineOnViewport); - }; - - var pressKey = function(keyCode, shiftIsPressed){ - var inner$ = helper.padInner$; - var evtType; - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - evtType = 'keypress'; - }else{ - evtType = 'keydown'; - } - var e = inner$.Event(evtType); - e.shiftKey = shiftIsPressed; - e.keyCode = keyCode; - e.which = keyCode; // etherpad listens to 'which' - inner$('#innerdocbody').trigger(e); - }; - - var releaseKey = function(keyCode){ - var inner$ = helper.padInner$; - var evtType = 'keyup'; - var e = inner$.Event(evtType); - e.keyCode = keyCode; - e.which = keyCode; // etherpad listens to 'which' - inner$('#innerdocbody').trigger(e); - }; - - var pressEnter = function() { - pressKey(ENTER); - }; - - var pressBackspace = function() { - pressKey(BACKSPACE); - }; - - var pressAndReleaseUpArrow = function() { - pressKey(UP_ARROW); - releaseKey(UP_ARROW); - }; - - var pressAndReleaseRightArrow = function() { - pressKey(RIGHT_ARROW); - releaseKey(RIGHT_ARROW); - }; - - var pressAndReleaseLeftArrow = function(shiftIsPressed) { - pressKey(LEFT_ARROW, shiftIsPressed); - releaseKey(LEFT_ARROW); - }; - - var isLineOnViewport = function(lineNumber) { - // in the function scrollNodeVerticallyIntoView from ace2_inner.js, iframePadTop is used to calculate - // how much scroll is needed. Although the name refers to padding-top, this value is not set on the - // padding-top. - var iframePadTop = 8; - var $line = getLine(lineNumber); - var linePosition = $line.get(0).getBoundingClientRect(); - - // position relative to the current viewport - var linePositionTopOnViewport = linePosition.top - getEditorScroll() + iframePadTop; - var linePositionBottomOnViewport = linePosition.bottom - getEditorScroll(); - - var lineBellowTop = linePositionBottomOnViewport > 0; - var lineAboveBottom = linePositionTopOnViewport < getClientHeightVisible(); - var isVisible = lineBellowTop && lineAboveBottom; - - return isVisible; - }; - - var getEditorScroll = function () { - var outer$ = helper.padOuter$; - var scrollTopFirefox = outer$('#outerdocbody').parent().scrollTop(); // works only on firefox - var scrollTop = outer$('#outerdocbody').scrollTop() || scrollTopFirefox; - return scrollTop; - }; - - // clientHeight includes padding, so we have to subtract it and consider only the visible viewport - var getClientHeightVisible = function () { - var outer$ = helper.padOuter$; - var $ace_outer = outer$('#outerdocbody').parent(); - var ace_outerHeight = $ace_outer.get(0).clientHeight; - var ace_outerPaddingTop = getIntValueOfCSSProperty($ace_outer, 'padding-top'); - var paddingAddedWhenPageViewIsEnable = getPaddingAddedWhenPageViewIsEnable(); - var clientHeight = ace_outerHeight - ( ace_outerPaddingTop + paddingAddedWhenPageViewIsEnable); - - return clientHeight; - }; - - // ep_page_view changes the dimensions of the editor. We have to guarantee - // the viewport height is calculated right - var getPaddingAddedWhenPageViewIsEnable = function () { - var chrome$ = helper.padChrome$; - var $outerIframe = chrome$('iframe'); - var paddingAddedWhenPageViewIsEnable = parseInt($outerIframe.css('padding-top')); - return paddingAddedWhenPageViewIsEnable; - }; - - var getIntValueOfCSSProperty = function($element, property){ - var valueString = $element.css(property); - return parseInt(valueString) || 0; - }; - - var forceUseMonospacedFont = function () { - helper.padChrome$.window.clientVars.padOptions.useMonospaceFont = true; - }; - - var setScrollPercentageWhenFocusLineIsOutOfViewport = function(value, editionAboveViewport) { - var scrollSettings = helper.padChrome$.window.clientVars.scrollWhenFocusLineIsOutOfViewport; - if (editionAboveViewport) { - scrollSettings.percentage.editionAboveViewport = value; - }else{ - scrollSettings.percentage.editionBelowViewport = value; - } - }; - - var resetScrollPercentageWhenFocusLineIsOutOfViewport = function() { - var scrollSettings = helper.padChrome$.window.clientVars.scrollWhenFocusLineIsOutOfViewport; - scrollSettings.percentage.editionAboveViewport = 0; - scrollSettings.percentage.editionBelowViewport = 0; - }; - - var setPercentageToScrollWhenUserPressesArrowUp = function (value) { - var scrollSettings = helper.padChrome$.window.clientVars.scrollWhenFocusLineIsOutOfViewport; - scrollSettings.percentageToScrollWhenUserPressesArrowUp = value; - }; - - var scrollWhenPlaceCaretInTheLastLineOfViewport = function() { - var scrollSettings = helper.padChrome$.window.clientVars.scrollWhenFocusLineIsOutOfViewport; - scrollSettings.scrollWhenCaretIsInTheLastLineOfViewport = true; - }; - - var getLinePositionOnViewport = function(lineNumber) { - var $line = getLine(lineNumber); - var linePosition = $line.get(0).getBoundingClientRect(); - - // position relative to the current viewport - return linePosition.top - getEditorScroll(); - }; -}); - diff --git a/sources/tests/frontend/specs/select_formatting_buttons.js b/sources/tests/frontend/specs/select_formatting_buttons.js deleted file mode 100644 index 5fb9760..0000000 --- a/sources/tests/frontend/specs/select_formatting_buttons.js +++ /dev/null @@ -1,166 +0,0 @@ -describe("select formatting buttons when selection has style applied", function(){ - var STYLES = ['italic', 'bold', 'underline', 'strikethrough']; - var SHORTCUT_KEYS = ['I', 'B', 'U', '5']; // italic, bold, underline, strikethrough - var FIRST_LINE = 0; - - before(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - var applyStyleOnLine = function(style, line) { - var chrome$ = helper.padChrome$; - selectLine(line); - var $formattingButton = chrome$('.buttonicon-' + style); - $formattingButton.click(); - } - - var isButtonSelected = function(style) { - var chrome$ = helper.padChrome$; - var $formattingButton = chrome$('.buttonicon-' + style); - return $formattingButton.parent().hasClass('selected'); - } - - var selectLine = function(lineNumber, offsetStart, offsetEnd) { - var inner$ = helper.padInner$; - var $line = inner$("div").eq(lineNumber); - helper.selectLines($line, $line, offsetStart, offsetEnd); - } - - var placeCaretOnLine = function(lineNumber) { - var inner$ = helper.padInner$; - var $line = inner$("div").eq(lineNumber); - $line.sendkeys('{leftarrow}'); - } - - var undo = function() { - var $undoButton = helper.padChrome$(".buttonicon-undo"); - $undoButton.click(); - } - - var testIfFormattingButtonIsDeselected = function(style) { - it('deselects the ' + style + ' button', function(done) { - helper.waitFor(function(){ - return isButtonSelected(style) === false; - }).done(done) - }); - } - - var testIfFormattingButtonIsSelected = function(style) { - it('selects the ' + style + ' button', function(done) { - helper.waitFor(function(){ - return isButtonSelected(style); - }).done(done) - }); - } - - var applyStyleOnLineAndSelectIt = function(line, style, cb) { - applyStyleOnLineOnFullLineAndRemoveSelection(line, style, selectLine, cb); - } - - var applyStyleOnLineAndPlaceCaretOnit = function(line, style, cb) { - applyStyleOnLineOnFullLineAndRemoveSelection(line, style, placeCaretOnLine, cb); - } - - var applyStyleOnLineOnFullLineAndRemoveSelection = function(line, style, selectTarget, cb) { - applyStyleOnLine(style, line); - - // we have to give some time to Etherpad detects the selection changed - setTimeout(function() { - // remove selection from previous line - selectLine(line + 1); - setTimeout(function() { - // select the text or place the caret on a position that - // has the formatting text applied previously - selectTarget(line); - cb(); - }, 1000); - }, 1000); - } - - var pressFormattingShortcutOnSelection = function(key) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - //select this text element - $firstTextElement.sendkeys('{selectall}'); - - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); - e.ctrlKey = true; // Control key - e.which = key.charCodeAt(0); // I, U, B, 5 - inner$("#innerdocbody").trigger(e); - } - - STYLES.forEach(function(style){ - context('when selection is in a text with ' + style + ' applied', function(){ - before(function (done) { - this.timeout(4000); - applyStyleOnLineAndSelectIt(FIRST_LINE, style, done); - }); - - after(function () { - undo(); - }); - - testIfFormattingButtonIsSelected(style); - }); - - context('when caret is in a position with ' + style + ' applied', function(){ - before(function (done) { - this.timeout(4000); - applyStyleOnLineAndPlaceCaretOnit(FIRST_LINE, style, done); - }); - - after(function () { - undo(); - }); - - testIfFormattingButtonIsSelected(style) - }); - }); - - context('when user applies a style and the selection does not change', function() { - var style = STYLES[0]; // italic - before(function () { - applyStyleOnLine(style, FIRST_LINE); - }); - - // clean the style applied - after(function () { - applyStyleOnLine(style, FIRST_LINE); - }); - - it('selects the style button', function (done) { - expect(isButtonSelected(style)).to.be(true); - done(); - }); - }); - - SHORTCUT_KEYS.forEach(function(key, index){ - var styleOfTheShortcut = STYLES[index]; // italic, bold, ... - context('when user presses CMD + ' + key, function() { - before(function () { - pressFormattingShortcutOnSelection(key); - }); - - testIfFormattingButtonIsSelected(styleOfTheShortcut); - - context('and user presses CMD + ' + key + ' again', function() { - before(function () { - pressFormattingShortcutOnSelection(key); - }); - - testIfFormattingButtonIsDeselected(styleOfTheShortcut); - }); - }); - }); -}); diff --git a/sources/tests/frontend/specs/strikethrough.js b/sources/tests/frontend/specs/strikethrough.js deleted file mode 100644 index 9afcea0..0000000 --- a/sources/tests/frontend/specs/strikethrough.js +++ /dev/null @@ -1,36 +0,0 @@ -describe("strikethrough button", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("makes text strikethrough", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var $firstTextElement = inner$("div").first(); - - //select this text element - $firstTextElement.sendkeys('{selectall}'); - - //get the strikethrough button and click it - var $strikethroughButton = chrome$(".buttonicon-strikethrough"); - $strikethroughButton.click(); - - //ace creates a new dom element when you press a button, so just get the first text element again - var $newFirstTextElement = inner$("div").first(); - - // is there a element now? - var isstrikethrough = $newFirstTextElement.find("s").length === 1; - - //expect it to be strikethrough - expect(isstrikethrough).to.be(true); - - //make sure the text hasn't changed - expect($newFirstTextElement.text()).to.eql($firstTextElement.text()); - - done(); - }); -}); diff --git a/sources/tests/frontend/specs/timeslider.js b/sources/tests/frontend/specs/timeslider.js deleted file mode 100644 index cb37bac..0000000 --- a/sources/tests/frontend/specs/timeslider.js +++ /dev/null @@ -1,47 +0,0 @@ -//deactivated, we need a nice way to get the timeslider, this is ugly -xdescribe("timeslider button takes you to the timeslider of a pad", function(){ - beforeEach(function(cb){ - helper.newPad(cb); // creates a new pad - this.timeout(60000); - }); - - it("timeslider contained in URL", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value - var newValue = "Testing"+originalValue; - $firstTextElement.sendkeys("Testing"); // send line 1 to the pad - - var modifiedValue = $firstTextElement.text(); // get the modified value - expect(modifiedValue).not.to.be(originalValue); // expect the value to change - - helper.waitFor(function(){ - return modifiedValue !== originalValue; // The value has changed so we can.. - }).done(function(){ - - var $timesliderButton = chrome$("#timesliderlink"); - $timesliderButton.click(); // So click the timeslider link - - helper.waitFor(function(){ - var iFrameURL = chrome$.window.location.href; - if(iFrameURL){ - return iFrameURL.indexOf("timeslider") !== -1; - }else{ - return false; // the URL hasnt been set yet - } - }).done(function(){ - // click the buttons - var iFrameURL = chrome$.window.location.href; // get the url - var inTimeslider = iFrameURL.indexOf("timeslider") !== -1; - expect(inTimeslider).to.be(true); // expect the value to change - done(); - }); - - - }); - }); -}); - diff --git a/sources/tests/frontend/specs/timeslider_labels.js b/sources/tests/frontend/specs/timeslider_labels.js deleted file mode 100644 index d39685e..0000000 --- a/sources/tests/frontend/specs/timeslider_labels.js +++ /dev/null @@ -1,64 +0,0 @@ -describe("timeslider", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("Shows a date and time in the timeslider and make sure it doesn't include NaN", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // make some changes to produce 100 revisions - var revs = 10; - this.timeout(60000); - for(var i=0; i < revs; i++) { - setTimeout(function() { - // enter 'a' in the first text element - inner$("div").first().sendkeys('a'); - }, 200); - } - - setTimeout(function() { - // go to timeslider - $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider'); - - setTimeout(function() { - var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; - var $sliderBar = timeslider$('#ui-slider-bar'); - - var latestContents = timeslider$('#padcontent').text(); - - // Expect the date and time to be shown - - // Click somewhere on the timeslider - var e = new jQuery.Event('mousedown'); - e.clientX = e.pageX = 150; - e.clientY = e.pageY = 45; - $sliderBar.trigger(e); - - e = new jQuery.Event('mousedown'); - e.clientX = e.pageX = 150; - e.clientY = e.pageY = 40; - $sliderBar.trigger(e); - - e = new jQuery.Event('mousedown'); - e.clientX = e.pageX = 150; - e.clientY = e.pageY = 50; - $sliderBar.trigger(e); - - $sliderBar.trigger('mouseup') - - setTimeout(function() { - //make sure the text has changed - expect( timeslider$('#timer').text() ).not.to.eql( "" ); - expect( timeslider$('#revision_date').text() ).not.to.eql( "" ); - expect( timeslider$('#revision_label').text() ).not.to.eql( "" ); - var includesNaN = timeslider$('#revision_label').text().indexOf("NaN"); // NaN is bad. Naan ist gut - expect( includesNaN ).to.eql( -1 ); // not quite so tasty, I like curry. - done(); - }, 400); - }, 2000); - }, 2000); - }); -}); diff --git a/sources/tests/frontend/specs/timeslider_revisions.js b/sources/tests/frontend/specs/timeslider_revisions.js deleted file mode 100644 index 2afd2e9..0000000 --- a/sources/tests/frontend/specs/timeslider_revisions.js +++ /dev/null @@ -1,179 +0,0 @@ -describe("timeslider", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(6000); - }); - - it("loads adds a hundred revisions", function(done) { // passes - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // make some changes to produce 100 revisions - var timePerRev = 900 - , revs = 100; - this.timeout(revs*timePerRev+10000); - for(var i=0; i < revs; i++) { - setTimeout(function() { - // enter 'a' in the first text element - inner$("div").first().sendkeys('a'); - }, timePerRev*i); - } - chrome$('.buttonicon-savedRevision').click(); - - setTimeout(function() { - // go to timeslider - $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider'); - - setTimeout(function() { - var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; - var $sliderBar = timeslider$('#ui-slider-bar'); - - var latestContents = timeslider$('#padcontent').text(); - - // Click somewhere on the timeslider - var e = new jQuery.Event('mousedown'); - e.clientX = e.pageX = 150; - e.clientY = e.pageY = 45; - $sliderBar.trigger(e); - - e = new jQuery.Event('mousedown'); - e.clientX = e.pageX = 150; - e.clientY = e.pageY = 40; - $sliderBar.trigger(e); - - e = new jQuery.Event('mousedown'); - e.clientX = e.pageX = 150; - e.clientY = e.pageY = 50; - $sliderBar.trigger(e); - - $sliderBar.trigger('mouseup') - - setTimeout(function() { - //make sure the text has changed - expect( timeslider$('#padcontent').text() ).not.to.eql( latestContents ); - var starIsVisible = timeslider$('.star').is(":visible"); - expect( starIsVisible ).to.eql( true ); - done(); - }, 1000); - - }, 6000); - }, revs*timePerRev); - }); - - - // Disabled as jquery trigger no longer works properly - xit("changes the url when clicking on the timeslider", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // make some changes to produce 7 revisions - var timePerRev = 1000 - , revs = 20; - this.timeout(revs*timePerRev+10000); - for(var i=0; i < revs; i++) { - setTimeout(function() { - // enter 'a' in the first text element - inner$("div").first().sendkeys('a'); - }, timePerRev*i); - } - - setTimeout(function() { - // go to timeslider - $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider'); - - setTimeout(function() { - var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; - var $sliderBar = timeslider$('#ui-slider-bar'); - - var latestContents = timeslider$('#padcontent').text(); - var oldUrl = $('#iframe-container iframe')[0].contentWindow.location.hash; - - // Click somewhere on the timeslider - var e = new jQuery.Event('mousedown'); - e.clientX = e.pageX = 150; - e.clientY = e.pageY = 60; - $sliderBar.trigger(e); - - helper.waitFor(function(){ - return $('#iframe-container iframe')[0].contentWindow.location.hash != oldUrl; - }, 6000).always(function(){ - expect( $('#iframe-container iframe')[0].contentWindow.location.hash ).not.to.eql( oldUrl ); - done(); - }); - }, 6000); - }, revs*timePerRev); - }); - it("jumps to a revision given in the url", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - this.timeout(20000); - - // wait for the text to be loaded - helper.waitFor(function(){ - return inner$('body').text().length != 0; - }, 6000).always(function() { - var newLines = inner$('body div').length; - var oldLength = inner$('body').text().length + newLines / 2; - expect( oldLength ).to.not.eql( 0 ); - inner$("div").first().sendkeys('a'); - var timeslider$; - - // wait for our additional revision to be added - helper.waitFor(function(){ - // newLines takes the new lines into account which are strippen when using - // inner$('body').text(), one
          is used for one line in ACE. - var lenOkay = inner$('body').text().length + newLines / 2 != oldLength; - // this waits for the color to be added to our , which means that the revision - // was accepted by the server. - var colorOkay = inner$('span').first().attr('class').indexOf("author-") == 0; - return lenOkay && colorOkay; - }, 6000).always(function() { - // go to timeslider with a specific revision set - $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider#0'); - - // wait for the timeslider to be loaded - helper.waitFor(function(){ - try { - timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; - } catch(e){} - if(timeslider$){ - return timeslider$('#padcontent').text().length == oldLength; - } - }, 6000).always(function(){ - expect( timeslider$('#padcontent').text().length ).to.eql( oldLength ); - done(); - }); - }); - }); - }); - - it("checks the export url", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - this.timeout(11000); - inner$("div").first().sendkeys('a'); - - setTimeout(function() { - // go to timeslider - $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider#0'); - var timeslider$; - var exportLink; - - helper.waitFor(function(){ - try{ - timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; - }catch(e){} - if(!timeslider$) - return false; - exportLink = timeslider$('#exportplaina').attr('href'); - if(!exportLink) - return false; - return exportLink.substr(exportLink.length - 12) == "0/export/txt"; - }, 6000).always(function(){ - expect( exportLink.substr(exportLink.length - 12) ).to.eql( "0/export/txt" ); - done(); - }); - }, 2500); - }); -}); diff --git a/sources/tests/frontend/specs/undo.js b/sources/tests/frontend/specs/undo.js deleted file mode 100644 index b8b7c78..0000000 --- a/sources/tests/frontend/specs/undo.js +++ /dev/null @@ -1,69 +0,0 @@ -describe("undo button", function(){ - beforeEach(function(cb){ - helper.newPad(cb); // creates a new pad - this.timeout(60000); - }); - -/* - it("undo some typing by clicking undo button", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value - - $firstTextElement.sendkeys("foo"); // send line 1 to the pad - var modifiedValue = $firstTextElement.text(); // get the modified value - expect(modifiedValue).not.to.be(originalValue); // expect the value to change - - // get clear authorship button as a variable - var $undoButton = chrome$(".buttonicon-undo"); - // click the button - $undoButton.click(); - - helper.waitFor(function(){ - return inner$("div span").first().text() === originalValue; - }).done(function(){ - var finalValue = inner$("div span").first().text(); - expect(finalValue).to.be(originalValue); // expect the value to change - done(); - }); - }); -*/ - - it("undo some typing using a keypress", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - // get the first text element inside the editable space - var $firstTextElement = inner$("div span").first(); - var originalValue = $firstTextElement.text(); // get the original value - - $firstTextElement.sendkeys("foo"); // send line 1 to the pad - var modifiedValue = $firstTextElement.text(); // get the modified value - expect(modifiedValue).not.to.be(originalValue); // expect the value to change - - if(inner$(window)[0].bowser.firefox){ // if it's a mozilla browser - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); - e.ctrlKey = true; // Control key - e.which = 90; // z - inner$("#innerdocbody").trigger(e); - - helper.waitFor(function(){ - return inner$("div span").first().text() === originalValue; - }).done(function(){ - var finalValue = inner$("div span").first().text(); - expect(finalValue).to.be(originalValue); // expect the value to change - done(); - }); - }); - - -}); - diff --git a/sources/tests/frontend/specs/unordered_list.js b/sources/tests/frontend/specs/unordered_list.js deleted file mode 100644 index 4ea77b8..0000000 --- a/sources/tests/frontend/specs/unordered_list.js +++ /dev/null @@ -1,35 +0,0 @@ -describe("assign unordered list", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("insert unordered list text then removes by outdent", function(done){ - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - var originalText = inner$("div").first().text(); - - var $insertunorderedlistButton = chrome$(".buttonicon-insertunorderedlist"); - $insertunorderedlistButton.click(); - - helper.waitFor(function(){ - var newText = inner$("div").first().text(); - if(newText === originalText){ - return inner$("div").first().find("ul li").length === 1; - } - }).done(function(){ - - // remove indentation by bullet and ensure text string remains the same - chrome$(".buttonicon-outdent").click(); - helper.waitFor(function(){ - var newText = inner$("div").first().text(); - return (newText === originalText); - }).done(function(){ - done(); - }); - - }); - }); - -}); diff --git a/sources/tests/frontend/specs/urls_become_clickable.js b/sources/tests/frontend/specs/urls_become_clickable.js deleted file mode 100644 index b989717..0000000 --- a/sources/tests/frontend/specs/urls_become_clickable.js +++ /dev/null @@ -1,70 +0,0 @@ -describe("urls", function(){ - //create a new pad before each test run - beforeEach(function(cb){ - helper.newPad(cb); - this.timeout(60000); - }); - - it("when you enter an url, it becomes clickable", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var firstTextElement = inner$("div").first(); - - // simulate key presses to delete content - firstTextElement.sendkeys('{selectall}'); // select all - firstTextElement.sendkeys('{del}'); // clear the first line - firstTextElement.sendkeys('http://etherpad.org'); // insert a URL - - helper.waitFor(function(){ - return inner$("div").first().find("a").length === 1; - }, 2000).done(done); - }); - - it("when you enter a url containing a !, it becomes clickable and contains the whole URL", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var firstTextElement = inner$("div").first(); - var url = "http://etherpad.org/!foo"; - - // simulate key presses to delete content - firstTextElement.sendkeys('{selectall}'); // select all - firstTextElement.sendkeys('{del}'); // clear the first line - firstTextElement.sendkeys(url); // insert a URL - - helper.waitFor(function(){ - if(inner$("div").first().find("a").length === 1){ // if it contains an A link - if(inner$("div").first().find("a")[0].href === url){ - return true; - } - }; - }, 2000).done(done); - }); - - it("when you enter a url followed by a ], the ] is not included in the URL", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //get the first text element out of the inner iframe - var firstTextElement = inner$("div").first(); - var url = "http://etherpad.org/"; - - // simulate key presses to delete content - firstTextElement.sendkeys('{selectall}'); // select all - firstTextElement.sendkeys('{del}'); // clear the first line - firstTextElement.sendkeys(url); // insert a URL - firstTextElement.sendkeys(']'); // put a ] after it - - helper.waitFor(function(){ - if(inner$("div").first().find("a").length === 1){ // if it contains an A link - if(inner$("div").first().find("a")[0].href === url){ - return true; - } - }; - }, 2000).done(done); - }); - -}); diff --git a/sources/tests/frontend/travis/.gitignore b/sources/tests/frontend/travis/.gitignore deleted file mode 100644 index 68284f6..0000000 --- a/sources/tests/frontend/travis/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -sauce_connect.log -sauce_connect.log.* diff --git a/sources/tests/frontend/travis/remote_runner.js b/sources/tests/frontend/travis/remote_runner.js deleted file mode 100644 index f7b21ed..0000000 --- a/sources/tests/frontend/travis/remote_runner.js +++ /dev/null @@ -1,112 +0,0 @@ -var srcFolder = "../../../src/node_modules/"; -var wd = require(srcFolder + "wd"); -var async = require(srcFolder + "async"); - -var config = { - host: "ondemand.saucelabs.com" - , port: 80 - , username: process.env.SAUCE_USER - , accessKey: process.env.SAUCE_ACCESS_KEY -} - -var allTestsPassed = true; - -var sauceTestWorker = async.queue(function (testSettings, callback) { - var browser = wd.remote(config.host, config.port, config.username, config.accessKey); - var browserChain = browser.chain(); - var name = process.env.GIT_HASH + " - " + testSettings.browserName + " " + testSettings.version + ", " + testSettings.platform; - testSettings.name = name; - testSettings["public"] = true; - testSettings["build"] = process.env.GIT_HASH; - - browserChain.init(testSettings).get("http://localhost:9001/tests/frontend/", function(){ - var url = "https://saucelabs.com/jobs/" + browser.sessionID; - console.log("Remote sauce test '" + name + "' started! " + url); - - //tear down the test excecution - var stopSauce = function(success){ - getStatusInterval && clearInterval(getStatusInterval); - clearTimeout(timeout); - - browserChain.quit(); - - if(!success){ - allTestsPassed = false; - } - - var testResult = knownConsoleText.replace(/\[red\]/g,'\x1B[31m').replace(/\[yellow\]/g,'\x1B[33m') - .replace(/\[green\]/g,'\x1B[32m').replace(/\[clear\]/g, '\x1B[39m'); - testResult = testResult.split("\\n").map(function(line){ - return "[" + testSettings.browserName + (testSettings.version === "" ? '' : (" " + testSettings.version)) + "] " + line; - }).join("\n"); - - console.log(testResult); - console.log("Remote sauce test '" + name + "' finished! " + url); - - callback(); - } - - //timeout for the case the test hangs - var timeout = setTimeout(function(){ - stopSauce(false); - }, 60000 * 10); - - var knownConsoleText = ""; - var getStatusInterval = setInterval(function(){ - browserChain.eval("$('#console').text()", function(err, consoleText){ - if(!consoleText || err){ - return; - } - knownConsoleText = consoleText; - - if(knownConsoleText.indexOf("FINISHED") > 0){ - var success = knownConsoleText.indexOf("FAILED") === -1; - stopSauce(success); - } - }); - }, 5000); - }); -}, 5); //run 5 tests in parrallel - -// Firefox -sauceTestWorker.push({ - 'platform' : 'Linux' - , 'browserName' : 'firefox' - , 'version' : '' -}); - -// Chrome -sauceTestWorker.push({ - 'platform' : 'Linux' - , 'browserName' : 'googlechrome' - , 'version' : '' -}); - -/* -// IE 8 -sauceTestWorker.push({ - 'platform' : 'Windows 2003' - , 'browserName' : 'iexplore' - , 'version' : '8' -}); -*/ - -// IE 9 -sauceTestWorker.push({ - 'platform' : 'Windows XP' - , 'browserName' : 'iexplore' - , 'version' : '9' -}); - -// IE 10 -sauceTestWorker.push({ - 'platform' : 'Windows 2012' - , 'browserName' : 'iexplore' - , 'version' : '10' -}); - -sauceTestWorker.drain = function() { - setTimeout(function(){ - process.exit(allTestsPassed ? 0 : 1); - }, 3000); -} diff --git a/sources/tests/frontend/travis/runner.sh b/sources/tests/frontend/travis/runner.sh deleted file mode 100755 index 1ae5f6f..0000000 --- a/sources/tests/frontend/travis/runner.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -#Move to the base folder -cd `dirname $0` - -#start Etherpad -../../../bin/run.sh > /dev/null & -sleep 10 - -#start remote runner -node remote_runner.js -exit_code=$? - -kill $! -kill $(cat /tmp/sauce.pid) -sleep 30 - -exit $exit_code \ No newline at end of file diff --git a/sources/tests/frontend/travis/sauce_tunnel.sh b/sources/tests/frontend/travis/sauce_tunnel.sh deleted file mode 100755 index b19268d..0000000 --- a/sources/tests/frontend/travis/sauce_tunnel.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# download and unzip the sauce connector -curl https://saucelabs.com/downloads/sc-latest-linux.tar.gz > /tmp/sauce.tar.gz -tar zxf /tmp/sauce.tar.gz --directory /tmp -mv /tmp/sc-*-linux /tmp/sauce_connect - -# start the sauce connector in background and make sure it doesn't output the secret key -(/tmp/sauce_connect/bin/sc --user $SAUCE_USERNAME --key $SAUCE_ACCESS_KEY --pidfile /tmp/sauce.pid --readyfile /tmp/tunnel > /dev/null )& - -# wait for the tunnel to build up -while [ ! -e "/tmp/tunnel" ] - do - sleep 1 -done diff --git a/sources/var/.gitignore b/sources/var/.gitignore deleted file mode 100644 index 91f8c09..0000000 --- a/sources/var/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -sqlite.db -minified*