Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Matheus Faustino 2018-08-06 22:51:52 -03:00
commit b2ca87079c
81 changed files with 5496 additions and 4765 deletions

4
.gitignore vendored
View File

@ -1,3 +1,7 @@
.DS_Store .DS_Store
pull_locales_login.rb pull_locales_login.rb
.vscode .vscode
node_modules/
package-lock.json
yarn.lock
*.zip

View File

@ -45,13 +45,13 @@ See our [contributing](./.github/CONTRIBUTING.md) page for more details.
## License ## License
Inherited code from the original [Stylish](https://github.com/stylish-userstyles/stylish/): Inherited code from the original [Stylish](https://github.com/stylish-userstyles/stylish/):<br>
Copyright &copy; 2005-2014 [Jason Barnabe](jason.barnabe@gmail.com) Copyright &copy; 2005-2014 [Jason Barnabe](jason.barnabe@gmail.com)
Current Stylus: Current Stylus:<br>
Copyright &copy; 2017-2018 [Stylus Team](https://github.com/openstyles/stylus/graphs/contributors) Copyright &copy; 2017-2018 [Stylus Team](https://github.com/openstyles/stylus/graphs/contributors)
**[GNU GPLv3](./LICENSE)** **[GNU GPLv3](./LICENSE)**<br>
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or

View File

@ -634,6 +634,10 @@
"message": "Alle verfügbaren Updates Installieren", "message": "Alle verfügbaren Updates Installieren",
"description": "" "description": ""
}, },
"styleBeautifyPreserveNewlines": {
"message": "Leerzeilen schützen",
"description": "CSS-beautifier option"
},
"clickToUninstall": { "clickToUninstall": {
"message": "Klicken zum Deinstallieren", "message": "Klicken zum Deinstallieren",
"description": "Label for the overlay on a style thumbnail when installed via inline search in the popup" "description": "Label for the overlay on a style thumbnail when installed via inline search in the popup"
@ -843,7 +847,7 @@
"description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info" "description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info"
}, },
"searchStylesHelp": { "searchStylesHelp": {
"message": "Die </>-Taste (Numpad) fokussiert das Suchfeld.\nEinfacher Text: Sucht im Namen, Quelltext, Homepage und anvisierten URLs. Wörter mit weniger als 3 Buchstaben werden ignoriert.\nURL suchen: Stelle <url:> voran, z.B. <url:https://github.com/openstyles/stylus>\nReguläre Ausdrücke: Nutze Slash und Flags, z.B. </body.*?\\ba\\b/simguy>\nSuche nach genauem Ausdruck: Anführungszeichen verwenden, z.B. <\".header ~ div\">", "message": "Die </>-Taste (Numpad) fokussiert das Suchfeld.\nEinfacher Text: Sucht im Namen, Quelltext, Homepage und anvisierten URLs. Wörter mit weniger als 3 Buchstaben werden ignoriert.\nStyles, die auf eine URL passen: Stelle der Suche <url:> voran, z.B. <url:https://github.com/openstyles/stylus>\nReguläre Ausdrücke: Nutze Slash und Flags, z.B. </body.*?\\ba\\b/simguy>\nSuche nach genauem Ausdruck: Anführungszeichen verwenden, z.B. <\".header ~ div\"> ",
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page" "description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page"
}, },
"findStyles": { "findStyles": {

View File

@ -205,6 +205,14 @@
"configOnChangeTooltip": { "configOnChangeTooltip": {
"message": "Autosave and apply changes automatically" "message": "Autosave and apply changes automatically"
}, },
"genericAdd": {
"message": "Add",
"description": "Used in various places for an action that adds something"
},
"genericClone": {
"message": "Clone",
"description": "Used in various places for an action that clones something"
},
"genericError": { "genericError": {
"message": "Error", "message": "Error",
"description": "Used in various places to indicate some error occurred." "description": "Used in various places to indicate some error occurred."
@ -520,6 +528,9 @@
"message": "Check for updates", "message": "Check for updates",
"description": "Label for the checkbox to save current URL for update check" "description": "Label for the checkbox to save current URL for update check"
}, },
"installUpdateUnavailable": {
"message": "To enable check for updates, drop the file on the tab strip or specify @updateURL in the style metadata."
},
"license": { "license": {
"message": "License", "message": "License",
"description": "Label for the license" "description": "Label for the license"
@ -536,6 +547,10 @@
"message": "Wiki", "message": "Wiki",
"description": "Wiki link text on the manage page e.g. https://github.com/openstyles/stylus/wiki" "description": "Wiki link text on the manage page e.g. https://github.com/openstyles/stylus/wiki"
}, },
"linkTranslate": {
"message": "Translate",
"description": "Transifex link text on the manage page"
},
"linterConfigPopupTitle": { "linterConfigPopupTitle": {
"message": "Set $linter$ rules configuration", "message": "Set $linter$ rules configuration",
"description": "Stylelint or CSSLint popup header", "description": "Stylelint or CSSLint popup header",
@ -603,6 +618,9 @@
"message": "An error occurred while watching the file", "message": "An error occurred while watching the file",
"description": "The label of live-reload error" "description": "The label of live-reload error"
}, },
"liveReloadUnavailable": {
"message": "To enable live reload, drop the file on the tab strip (the area where the tab titles are shown)."
},
"manageFilters": { "manageFilters": {
"message": "Filters", "message": "Filters",
"description": "Label for filters container" "description": "Label for filters container"
@ -821,7 +839,7 @@
"description": "Label for the search filter textbox on the Manage styles page" "description": "Label for the search filter textbox on the Manage styles page"
}, },
"searchStylesHelp": { "searchStylesHelp": {
"message": "</> key focuses the search field.\nPlain text: search within the name, code, homepage URL and sites it is applied to. Words with less than 3 letters are ignored.\nMatching URL: prefix the search with <url:>, e.g. <url:https://github.com/openstyles/stylus>\nRegular expressions: include slashes and flags, e.g. </body.*?\\ba\\b/simguy>\nExact words: wrap the query in double quotes, e.g. <\".header ~ div\">", "message": "</> key focuses the search field.\nPlain text: search within the name, code, homepage URL and sites it is applied to. Words with less than 3 letters are ignored.\nStyles matching a full URL: prefix the search with <url:>, e.g. <url:https://github.com/openstyles/stylus>\nRegular expressions: include slashes and flags, e.g. </body.*?\\ba\\b/simguy>\nExact words: wrap the query in double quotes, e.g. <\".header ~ div\">",
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page" "description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page"
}, },
"sectionAdd": { "sectionAdd": {
@ -840,6 +858,10 @@
"message": "Remove section", "message": "Remove section",
"description": "Label for the button to remove a section" "description": "Label for the button to remove a section"
}, },
"sectionRestore": {
"message": "Restore removed section",
"description": "Label for the button to restore a removed section"
},
"shortcuts": { "shortcuts": {
"message": "Shortcuts", "message": "Shortcuts",
"description": "Go to shortcut configuration" "description": "Go to shortcut configuration"
@ -929,6 +951,10 @@
"message": "Indent @media, @supports", "message": "Indent @media, @supports",
"description": "CSS-beautifier option" "description": "CSS-beautifier option"
}, },
"styleBeautifyPreserveNewlines": {
"message": "Preserve new lines",
"description": "CSS-beautifier option"
},
"styleCancelEditLabel": { "styleCancelEditLabel": {
"message": "Back to manage", "message": "Back to manage",
"description": "Label for cancel button for style editing" "description": "Label for cancel button for style editing"

View File

@ -12,7 +12,7 @@
"description": "Default CodeMirror CSS theme option on the edit style page" "description": "Default CodeMirror CSS theme option on the edit style page"
}, },
"styleRegexpTestTitle": { "styleRegexpTestTitle": {
"message": "Lijst van overeenkomende geopende tabbladen (klik op de URL om het tabblad te focussen)", "message": "Lijst van overeenkomende geopende tabbladen (klik op de URL om de focus op het tabblad te leggen)",
"description": "RegExp test report: title of the report" "description": "RegExp test report: title of the report"
}, },
"bckpInstStyles": { "bckpInstStyles": {
@ -28,7 +28,7 @@
"description": "Checkbox to show only Usercss styles" "description": "Checkbox to show only Usercss styles"
}, },
"sortStylesHelp": { "sortStylesHelp": {
"message": "Kies de sorteermethode voor de geïnstalleerde items uit het uitrolmenu. De standaard instelling past een oplopende sortering (A-Z) to op de items. Sorteren op \"Titel - Aflopend\" past het omgekeerde (Z-A) toe.\nDe andere keuzes laten je sorteren op basis van meerdere criteria. Denk aan het sorteren van een tabel met meerdere kolommen en elke categorie in een selectie (tussen de plus-tekens) is een kolom of groep.\nVoorbeeld: als de instelling is \"Ingeschakeld (eerst) + Titel\", dan worden de ingeschakelde items bovenaan geplaatst en de rest wordt oplopend gesorteerd (A-Z).", "message": "Kies de toe te passen sorteermethode voor de geïnstalleerde items vanuit het vervolgkeuzemenu. De standaardinstelling past een oplopende sortering (A-Z) op de itemtitels toe. Sorteren op Titel - Aflopend past het omgekeerde (Z-A) toe.\nAndere keuzes laten u items sorteren op basis van meerdere criteria. Denk hierbij aan het sorteren van een tabel met meerdere kolommen, en elke categorie in een selectie (tussen de plustekens) stelt een kolom of groep voor.\nVoorbeeld: als de instelling Ingeschakeld (eerst) + Titel is, worden de ingeschakelde items bovenaan geplaatst en worden zowel de in- als uitgeschakelde items apart oplopend gesorteerd (A-Z).",
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the sort input field on the Manage styles page" "description": "Text in the minihelp displayed when clicking (i) icon to the right of the sort input field on the Manage styles page"
}, },
"sortLabelTitleAsc": { "sortLabelTitleAsc": {
@ -36,11 +36,11 @@
"description": "Text added to option group to indicate a block of options that apply a title ascending (A to Z) sort" "description": "Text added to option group to indicate a block of options that apply a title ascending (A to Z) sort"
}, },
"optionsUpdateInterval": { "optionsUpdateInterval": {
"message": "Automatisch bijwerken-periode voor gebruikersstijlen (geef 0 op om dit uit te schakelen)", "message": "Interval voor automatisch bijwerken van gebruikersstijlen in uren (geef 0 op om dit uit te schakelen)",
"description": "" "description": ""
}, },
"unreachableAMOHintNewFF": { "unreachableAMOHintNewFF": {
"message": "In Firefox 60 en hoger moet je ook de AMO-domeinnaam verwijderen uit <extensions.webextensions.restrictedDomains> in <about:config>.", "message": "In Firefox 60 en hoger moet u ook het AMO-domein uit <extensions.webextensions.restrictedDomains> verwijderen in <about:config>.",
"description": "Note in the popup when opened on addons.mozilla.org in Firefox >= 59" "description": "Note in the popup when opened on addons.mozilla.org in Firefox >= 59"
}, },
"sortDateOldestFirst": { "sortDateOldestFirst": {
@ -72,7 +72,7 @@
"description": "" "description": ""
}, },
"updateCheckHistory": { "updateCheckHistory": {
"message": "Updatecontrole-geschiedenis", "message": "Geschiedenis van updatecontroles",
"description": "" "description": ""
}, },
"cm_tabSize": { "cm_tabSize": {
@ -84,7 +84,7 @@
"description": "Label for the button to enable a style" "description": "Label for the button to enable a style"
}, },
"styleMissingName": { "styleMissingName": {
"message": "Vul een naam in", "message": "Voer een naam in",
"description": "Error displayed when user saves without providing a name" "description": "Error displayed when user saves without providing a name"
}, },
"genericHistoryLabel": { "genericHistoryLabel": {
@ -92,11 +92,11 @@
"description": "Used in various places to show a history log of something" "description": "Used in various places to show a history log of something"
}, },
"shortcutsNote": { "shortcutsNote": {
"message": "Sneltoetsen opgeven", "message": "Sneltoetsen definiëren",
"description": "" "description": ""
}, },
"appliesDomainOption": { "appliesDomainOption": {
"message": "URL's op het domein", "message": "URLs op het domein",
"description": "Option to make the style apply to the entered string as a domain" "description": "Option to make the style apply to the entered string as a domain"
}, },
"checkForUpdate": { "checkForUpdate": {
@ -104,23 +104,23 @@
"description": "Label for the button to check a single style for an update" "description": "Label for the button to check a single style for an update"
}, },
"styleNotAppliedRegexpProblemTooltip": { "styleNotAppliedRegexpProblemTooltip": {
"message": "Stijl is niet toegepast vanwege onjuist gebruik van 'regexp()'", "message": "Stijl is niet toegepast vanwege onjuist gebruik van regexp()",
"description": "Tooltip in the popup for styles that were not applied at all" "description": "Tooltip in the popup for styles that were not applied at all"
}, },
"colorpickerSwitchFormatTooltip": { "colorpickerSwitchFormatTooltip": {
"message": "Schakel tussen formaten: HEX -> RGB -> HSL.\nShift-klik om de volgorde om te draaien.\nWerkt ook met de toetsen PgUp (PageUp) en PgDn (PageDown).", "message": "Indelingen omschakelen: HEX -> RGB -> HSL.\nShift-klik om de volgorde om te keren.\nWerkt ook met de toetsen PgUp (PageUp) en PgDn (PageDown).",
"description": "Tooltip for the switch button in the color picker popup in the style editor." "description": "Tooltip for the switch button in the color picker popup in the style editor."
}, },
"styleRegexpInvalidExplanation": { "styleRegexpInvalidExplanation": {
"message": "Sommige 'regexp()'-regels kunnen niet worden gecompileerd.", "message": "Sommige regexp()-regels konden niet worden gecompileerd.",
"description": "" "description": ""
}, },
"optionsIconDark": { "optionsIconDark": {
"message": "Donkere browserthema's", "message": "Donkere browserthemas",
"description": "" "description": ""
}, },
"styleFromMozillaFormatError": { "styleFromMozillaFormatError": {
"message": "Importeren uit Mozilla-indeling mislukt", "message": "Importeren vanuit Mozilla-opmaak mislukt",
"description": "Label for the import error" "description": "Label for the import error"
}, },
"importAppendLabel": { "importAppendLabel": {
@ -140,25 +140,21 @@
"description": "Text after the number of styles added in the report shown after importing styles" "description": "Text after the number of styles added in the report shown after importing styles"
}, },
"styleFromMozillaFormatPrompt": { "styleFromMozillaFormatPrompt": {
"message": "Plak de Mozilla-opmaakcode", "message": "Plak de code in Mozilla-opmaak",
"description": "Prompt in the dialog displayed after clicking 'Import from Mozilla format' button" "description": "Prompt in the dialog displayed after clicking 'Import from Mozilla format' button"
}, },
"dragDropMessage": { "dragDropMessage": {
"message": "Versleep je back-upbestand naar deze pagina om het te importeren.", "message": "Sleep uw back-upbestand naar deze pagina om het te importeren.",
"description": "Drag'n'drop message" "description": "Drag'n'drop message"
}, },
"styleRegexpTestNote": { "styleRegexpTestNote": {
"message": "Let op: gebruik een enkele \\ voor het omzeilen in het regexp-invoerveld, welke automatisch omgezet zal worden naar \\\\ in de stijlcode, zoals opgegeven in de specificatie voor citaten in CSS.", "message": "Let op: gebruik een enkele \\ voor het gebruik van escapetekens in het regexp-invoerveld. Deze worden automatisch omgezet naar \\\\ in de stijlcode volgens de specificatie voor tekenreeksen tussen aanhalingstekens in CSS.",
"description": "RegExp test report: a note displayed at the bottom of the dialog" "description": "RegExp test report: a note displayed at the bottom of the dialog"
}, },
"helpAlt": { "helpAlt": {
"message": "Hulp", "message": "Hulp",
"description": "Alternate text for help buttons" "description": "Alternate text for help buttons"
}, },
"confirmOK": {
"message": "Oké",
"description": ""
},
"search": { "search": {
"message": "Zoeken", "message": "Zoeken",
"description": "Label before the search input field in the editor shown on Ctrl-F" "description": "Label before the search input field in the editor shown on Ctrl-F"
@ -168,7 +164,7 @@
"description": "Used in various lists/options to indicate that something is enabled" "description": "Used in various lists/options to indicate that something is enabled"
}, },
"previewTooltip": { "previewTooltip": {
"message": "Past de wijzigingen tijdelijk toe zonder deze op te slaan.\nSla de stijl op om de wijzigingen permanent door te voeren.", "message": "Past de wijzigingen tijdelijk toe zonder deze op te slaan.\nSla de stijl op om de wijzigingen permanent te maken.",
"description": "Tooltip for the checkbox in style editor to enable live preview while editing." "description": "Tooltip for the checkbox in style editor to enable live preview while editing."
}, },
"manageFaviconsGray": { "manageFaviconsGray": {
@ -176,7 +172,7 @@
"description": "Label for the checkbox that toggles grayed out mode of applies-to favicons in the new UI on manage page" "description": "Label for the checkbox that toggles grayed out mode of applies-to favicons in the new UI on manage page"
}, },
"versionInvalidOlder": { "versionInvalidOlder": {
"message": "Deze versie is ouder dan de geïnstalleerde stijl.", "message": "De versie is ouder dan de geïnstalleerde stijl.",
"description": "Displayed when the version of style is older than the installed one" "description": "Displayed when the version of style is older than the installed one"
}, },
"confirmYes": { "confirmYes": {
@ -184,7 +180,7 @@
"description": "'Yes' button in a confirm dialog" "description": "'Yes' button in a confirm dialog"
}, },
"findStylesForSite": { "findStylesForSite": {
"message": "Meer stijlen zoeken voor deze website", "message": "Meer stijlen voor deze website zoeken",
"description": "Text for a link that gets a list of styles for the current site" "description": "Text for a link that gets a list of styles for the current site"
}, },
"manageHeading": { "manageHeading": {
@ -196,7 +192,7 @@
"description": "Label for the CSS-beautifier button on the edit style page" "description": "Label for the CSS-beautifier button on the edit style page"
}, },
"styleRegexpProblemTooltip": { "styleRegexpProblemTooltip": {
"message": "Aantal secties dat niet toegepast wordt vanwege onjuist gebruik van 'regexp()'", "message": "Aantal secties dat niet wordt toegepast vanwege onjuist gebruik van regexp()",
"description": "Tooltip in the popup for styles that were applied only partially" "description": "Tooltip in the popup for styles that were applied only partially"
}, },
"styleEnabledLabel": { "styleEnabledLabel": {
@ -212,7 +208,7 @@
"description": "Icon tooltip to indicate that it opens a popup with the selected linter configuration" "description": "Icon tooltip to indicate that it opens a popup with the selected linter configuration"
}, },
"styleToMozillaFormatHelp": { "styleToMozillaFormatHelp": {
"message": "De Mozilla-opmaak van de code kan worden gebruikt met Stylish voor Firefox en worden ingezonden naar userstyles.org", "message": "De Mozilla-opmaak van de code kan bij userstyles.org worden ingediend en met het klassieke Stylish voor Firefox worden gebruikt.",
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format" "description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
}, },
"sectionAdd": { "sectionAdd": {
@ -244,7 +240,7 @@
"description": "" "description": ""
}, },
"cm_autoCloseBracketsTooltip": { "cm_autoCloseBracketsTooltip": {
"message": "Automatisch sluitingen toevoegen bij het openen van ()[]{}''\"\"", "message": "Automatisch sluitteken toevoegen by typen van een openingsteken uit ()[]{}''\"\"",
"description": "Label for the checkbox in the style editor." "description": "Label for the checkbox in the style editor."
}, },
"retrieveBckp": { "retrieveBckp": {
@ -252,7 +248,7 @@
"description": "" "description": ""
}, },
"cm_selectByTokens": { "cm_selectByTokens": {
"message": "Dubbelklikken selecteert sleutels", "message": "Dubbelklikken selecteert tokens",
"description": "Label for the checkbox in the editor." "description": "Label for the checkbox in the editor."
}, },
"confirmStop": { "confirmStop": {
@ -272,11 +268,11 @@
"description": "Label for the button to add an 'applies' entry" "description": "Label for the button to add an 'applies' entry"
}, },
"appliesRegexpOption": { "appliesRegexpOption": {
"message": "URL's overeenkomend met de regexp", "message": "URLs overeenkomend met de regexp",
"description": "Option to make the style apply to the entered string as a regular expression" "description": "Option to make the style apply to the entered string as a regular expression"
}, },
"optionsAdvancedExposeIframesNote": { "optionsAdvancedExposeIframesNote": {
"message": "Legt het bovenliggende domein van de site bloot in elk iframe.\nSchakelt schrijven in voor iframe-specifieke CSS, zoals:\nhtml[stylus-iframe$=\"twitter.com\"] h1 { display:none }", "message": "Legt het bovenliggende domein van de website bloot in elk iframe.\nSchakelt schrijven in voor iframe-specifieke CSS, zoals:\nhtml[stylus-iframe$=\"twitter.com\"] h1 { display:none }",
"description": "" "description": ""
}, },
"importReportLegendUpdatedCode": { "importReportLegendUpdatedCode": {
@ -284,7 +280,7 @@
"description": "Text after the number of styles with updated code (meta info is unchanged) in the report shown after importing styles" "description": "Text after the number of styles with updated code (meta info is unchanged) in the report shown after importing styles"
}, },
"styleInstall": { "styleInstall": {
"message": "'$stylename$' installeren in Stylus?", "message": "$stylename$ installeren in Stylus?",
"description": "Confirmation when installing a style", "description": "Confirmation when installing a style",
"placeholders": { "placeholders": {
"stylename": { "stylename": {
@ -293,7 +289,7 @@
} }
}, },
"optionsBadgeDisabled": { "optionsBadgeDisabled": {
"message": "Achtergrondkleur indien uitgeschakeld", "message": "Achtergrondkleur wanneer uitgeschakeld",
"description": "" "description": ""
}, },
"optionsCheck": { "optionsCheck": {
@ -301,7 +297,7 @@
"description": "" "description": ""
}, },
"manageOnlyLocal": { "manageOnlyLocal": {
"message": "Alleen lokaal gecreëerde stijlen", "message": "Alleen lokaal aangemaakte stijlen",
"description": "Checkbox to show only locally created styles i.e. non-updatable" "description": "Checkbox to show only locally created styles i.e. non-updatable"
}, },
"styleMetaErrorPreprocessor": { "styleMetaErrorPreprocessor": {
@ -314,7 +310,7 @@
} }
}, },
"searchNumberOfResults2": { "searchNumberOfResults2": {
"message": "Aantal overeenkomsten in code en 'toepasbaar op'-items", "message": "Aantal overeenkomsten in code en Van toepassing op-waarden",
"description": "Tooltip for the number of found search results in the editor shown on Ctrl-F" "description": "Tooltip for the number of found search results in the editor shown on Ctrl-F"
}, },
"linterIssuesHelp": { "linterIssuesHelp": {
@ -335,11 +331,11 @@
"description": "Label for the search filter textbox on the Manage styles page" "description": "Label for the search filter textbox on the Manage styles page"
}, },
"optionsUpdateImportNote": { "optionsUpdateImportNote": {
"message": "Als je stijlen importeert uit een oudere versie of uit Stylish, controleer dan eenmalig op updates in de stijlbeheerder om er zeker van te zijn dat alle stijlen zijn bijgewerkt.", "message": "Als u stijlen vanuit een oudere versie of vanuit Stylish importeert, controleer dan eenmalig op updates in de stijlbeheerder om er zeker van te zijn dat alle stijlen zijn bijgewerkt.",
"description": "" "description": ""
}, },
"checkAllUpdatesForce": { "checkAllUpdatesForce": {
"message": "Ik heb geen stijlen bewerkt; controleer opnieuw!", "message": "Ik heb geen stijlen bewerkt; opnieuw controleren!",
"description": "Label for the button to apply all detected updates" "description": "Label for the button to apply all detected updates"
}, },
"manageOnlyNonUsercss": { "manageOnlyNonUsercss": {
@ -351,15 +347,15 @@
"description": "The label of live-reload feature" "description": "The label of live-reload feature"
}, },
"linkGetStyles": { "linkGetStyles": {
"message": "Verkrijg stijlen", "message": "Stijlen verkrijgen",
"description": "Help link text on the manage page e.g. https://userstyles.org" "description": "Help link text on the manage page e.g. https://userstyles.org"
}, },
"unreachableFileHint": { "unreachableFileHint": {
"message": "Stylus kan toegang krijgen tot URL's beginnend met file://, maar alleen als je een vinkje zet in het juiste selectievakje op de pagina chrome://extensions", "message": "Stylus kan URLs die met file:// beginnen alleen benaderen als u het selectievakje hiervoor op de pagina chrome://extensions aanvinkt.",
"description": "Note in the toolbar popup for file:// URLs" "description": "Note in the toolbar popup for file:// URLs"
}, },
"sortLabel": { "sortLabel": {
"message": "Selecteer een sorteermethode om toe te passen op geïnstalleerde stijlen", "message": "Selecteer een sorteermethode om op geïnstalleerde stijlen toe te passen",
"description": "Title on the sort select to indicate it is used for sorting entries" "description": "Title on the sort select to indicate it is used for sorting entries"
}, },
"disableStyleLabel": { "disableStyleLabel": {
@ -371,7 +367,7 @@
"description": "Label for the checkbox controlling toolbar badge text." "description": "Label for the checkbox controlling toolbar badge text."
}, },
"manageFavicons": { "manageFavicons": {
"message": "Favicons in 'toepasbaar op'-kolom", "message": "Favicons in kolom Van toepassing op",
"description": "Label for the checkbox that toggles applies-to favicons in the new UI on manage page" "description": "Label for the checkbox that toggles applies-to favicons in the new UI on manage page"
}, },
"paginationCurrent": { "paginationCurrent": {
@ -379,15 +375,15 @@
"description": "Tooltip for the current page index in search results" "description": "Tooltip for the current page index in search results"
}, },
"menuShowBadge": { "menuShowBadge": {
"message": "Teller tonen voor actieve stijlen", "message": "Aantal actieve stijlen tonen",
"description": "Label (must be very short) for the checkbox in the toolbar button context menu controlling toolbar badge text." "description": "Label (must be very short) for the checkbox in the toolbar button context menu controlling toolbar badge text."
}, },
"popupHotkeysInfo": { "popupHotkeysInfo": {
"message": "<1>-<9>, <0>, ook op het numpad - schakelt naar de Nth-stijl (0 is 10)\n<A>-<Z> schakelt naar de eerste stijl die begint met de letter\n<Shift> opent de bewerker i.p.v. deze om te schakelen\n<Numpad +> schakelt opgesomde stijlen in\n<Numpad > schakelt opgesomde stijlen uit\n<Numpad *> en <`> (accent grave) - schakelt tussen initieel ingeschakelde stijlen; niet van toepassing op stijlen die zijn ingeschakeld met het pop-upvenster geopend, zodat je de initiële selectie kunt herstellen na het uitproberen: schakel alles uit en schakel dan naar bijv.<Numpad > <Numpad *>\nMeer informatie is te vinden op de wiki", "message": "<1>-<9>, <0>, ook op het numerieke toetsenbord - schakelt naar de Ne stijl (0 is 10)\n<A>-<Z> schakelt naar de eerste stijl die met de letter begint\n<Shift> opent de editor i.p.v. deze in/uit te schakelen\n<Numpad +> schakelt opgesomde stijlen in\n<Numpad > schakelt opgesomde stijlen uit\n<Numpad *> en <`> (accent grave) - schakelt tussen initieel ingeschakelde stijlen; niet van toepassing op stijlen die zijn ingeschakeld met het pop-upvenster geopend, zodat u na het uitproberen de initiële selectie kunt herstellen: schakel alles uit en schakel dan om, m.a.w. <Numpad > <Numpad *>\nMeer info is te vinden in de wiki",
"description": "NOTE1: preserve < and > symbols so that <hotkey> is styled as a key.\nNOTE2: the last line is displayed as a text of the link to the wiki page.\nNOTE3: this is the list of hotkeys displayed after clicking the right edge of the extension popup." "description": "NOTE1: preserve < and > symbols so that <hotkey> is styled as a key.\nNOTE2: the last line is displayed as a text of the link to the wiki page.\nNOTE3: this is the list of hotkeys displayed after clicking the right edge of the extension popup."
}, },
"cm_lineWrapping": { "cm_lineWrapping": {
"message": "Woordomslag", "message": "Tekstterugloop",
"description": "Label for the checkbox controlling word wrap option for the style editor." "description": "Label for the checkbox controlling word wrap option for the style editor."
}, },
"styleCancelEditLabel": { "styleCancelEditLabel": {
@ -395,7 +391,7 @@
"description": "Label for cancel button for style editing" "description": "Label for cancel button for style editing"
}, },
"styleChangesNotSaved": { "styleChangesNotSaved": {
"message": "Je hebt wijzigingen aangebracht in deze stijl zonder ze op te slaan.", "message": "U hebt wijzigingen in deze stijl aangebracht zonder op te slaan.",
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving" "description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
}, },
"importLabel": { "importLabel": {
@ -415,15 +411,15 @@
"description": "Used in various places to indicate some error occurred." "description": "Used in various places to indicate some error occurred."
}, },
"applyAllUpdates": { "applyAllUpdates": {
"message": "Alle bijwerkingen toepassen", "message": "Alle updates toepassen",
"description": "Label for the button to apply all detected updates" "description": "Label for the button to apply all detected updates"
}, },
"optionsReset": { "optionsReset": {
"message": "Opties terugzetten op standaardwaarden", "message": "Opties terugzetten naar standaardwaarden",
"description": "" "description": ""
}, },
"deleteStyleConfirm": { "deleteStyleConfirm": {
"message": "Weet je zeker dat je deze stijl wilt verwijderen?", "message": "Weet u zeker dat u deze stijl wilt verwijderen?",
"description": "Confirmation before deleting a style" "description": "Confirmation before deleting a style"
}, },
"optionsCustomizePopup": { "optionsCustomizePopup": {
@ -443,7 +439,7 @@
"description": "Heading for options section on manage page." "description": "Heading for options section on manage page."
}, },
"appliesDisplay": { "appliesDisplay": {
"message": "Toepasbaar op: $applies$", "message": "Van toepassing op: $applies$",
"description": "Text on the manage screen to describe what the style applies to", "description": "Text on the manage screen to describe what the style applies to",
"placeholders": { "placeholders": {
"applies": { "applies": {
@ -452,7 +448,7 @@
} }
}, },
"optionsIconLight": { "optionsIconLight": {
"message": "Lichte browserthema's", "message": "Lichte browserthemas",
"description": "" "description": ""
}, },
"openStylesManager": { "openStylesManager": {
@ -460,7 +456,7 @@
"description": "Label for the style maanger opener in the browser action context menu." "description": "Label for the style maanger opener in the browser action context menu."
}, },
"styleUpdate": { "styleUpdate": {
"message": "Weet je zeker dat je '$stylename$' wilt bijwerken?", "message": "Weet u zeker dat u $stylename$ wilt bijwerken?",
"description": "Confirmation when updating a style", "description": "Confirmation when updating a style",
"placeholders": { "placeholders": {
"stylename": { "stylename": {
@ -494,23 +490,23 @@
} }
}, },
"updateCheckSucceededNoUpdate": { "updateCheckSucceededNoUpdate": {
"message": "Stijl is actueel.", "message": "Stijl is up-to-date.",
"description": "Text that displays when an update check completed and no update is available" "description": "Text that displays when an update check completed and no update is available"
}, },
"appliesUrlPrefixOption": { "appliesUrlPrefixOption": {
"message": "URL's beginnend met", "message": "URLs beginnend met",
"description": "Option to make the style apply to the entered string as a URL prefix" "description": "Option to make the style apply to the entered string as a URL prefix"
}, },
"cm_matchHighlightToken": { "cm_matchHighlightToken": {
"message": "Sleutel onder cursor", "message": "Token onder cursor",
"description": "Style editor's 'highglight' drop-down list option: highlight the occurrences of the word/token under cursor even if nothing is selected" "description": "Style editor's 'highglight' drop-down list option: highlight the occurrences of the word/token under cursor even if nothing is selected"
}, },
"searchRegexp": { "searchRegexp": {
"message": "Gebruik /re/-syntax voor regexp-zoeken", "message": "Gebruik /re/-syntaxis voor regexp-zoeken",
"description": "Label after the search input field in the editor shown on Ctrl-F" "description": "Label after the search input field in the editor shown on Ctrl-F"
}, },
"popupBordersTooltip": { "popupBordersTooltip": {
"message": "Handig voor donkere thema's in Chrome, omdat zijranden niet meer worden gerenderd", "message": "Handig voor donkere themas in Chrome, omdat zijranden niet meer worden gerenderd",
"description": "" "description": ""
}, },
"updateCheckManualUpdateHint": { "updateCheckManualUpdateHint": {
@ -518,7 +514,7 @@
"description": "Additional text displayed when an update check skipped updating the style to avoid losing local modifications" "description": "Additional text displayed when an update check skipped updating the style to avoid losing local modifications"
}, },
"toggleStyle": { "toggleStyle": {
"message": "Stijl inschakelen/uitschakelen", "message": "Stijl in-/uitschakelen",
"description": "Label for the checkbox to enable/disable a style" "description": "Label for the checkbox to enable/disable a style"
}, },
"searchNumberOfResults": { "searchNumberOfResults": {
@ -526,7 +522,7 @@
"description": "Tooltip for the number of found search results in the editor shown on Ctrl-F" "description": "Tooltip for the number of found search results in the editor shown on Ctrl-F"
}, },
"importReplaceTooltip": { "importReplaceTooltip": {
"message": "Verwerp de inhoud van de huidige stijl en overschrijf het met de geïmporteerde stijl", "message": "Inhoud van huidige stijl verwerpen en met de geïmporteerde stijl overschrijven",
"description": "Label for the button to import and overwrite current style" "description": "Label for the button to import and overwrite current style"
}, },
"installUpdateFromLabel": { "installUpdateFromLabel": {
@ -538,11 +534,11 @@
"description": "Tooltip for the resize grip in style editor" "description": "Tooltip for the resize grip in style editor"
}, },
"popupStylesFirst": { "popupStylesFirst": {
"message": "Stijlen vóór commando's opsommen", "message": "Stijlen vóór opdrachten",
"description": "Label for the checkbox controlling section order in the popup." "description": "Label for the checkbox controlling section order in the popup."
}, },
"sectionHelp": { "sectionHelp": {
"message": "Secties stellen je in staat om andere stukken code toe te passen op andere URL's in dezelfde stijl. Bijv.: een enkele stijl kan de startpagina van een site aanpassen op een bepaalde manier, terwijl de rest van de site op een andere manier wordt aangepast.", "message": "Met secties kunt u verschillende stukjes code definiëren en op verschillende groepen URLs in dezelfde stijl toepassen. Een enkele stijl kan bijvoorbeeld de startpagina van een website op een bepaalde manier wijzigen, terwijl de rest van de website op een andere manier wordt gewijzigd.",
"description": "Help text for sections" "description": "Help text for sections"
}, },
"noStylesForSite": { "noStylesForSite": {
@ -590,7 +586,7 @@
"description": "Text after the number of styles with updated meta info like name/url in the report shown after importing styles" "description": "Text after the number of styles with updated meta info like name/url in the report shown after importing styles"
}, },
"appliesLabel": { "appliesLabel": {
"message": "Toepasbaar op", "message": "Van toepassing op",
"description": "Label for 'applies to' fields on the edit/add screen" "description": "Label for 'applies to' fields on the edit/add screen"
}, },
"sortLabelTitleDesc": { "sortLabelTitleDesc": {
@ -602,7 +598,7 @@
"description": "Go to Options UI" "description": "Go to Options UI"
}, },
"usercssConfigIncomplete": { "usercssConfigIncomplete": {
"message": "De stijl is bijgewerkt of verwijderd nadat het configuratievenster werd getoond. Deze variabelen zijn niet opgeslagen om corruptie te voorkomen:", "message": "De stijl is bijgewerkt of verwijderd nadat het configuratievenster werd getoond. Om beschadiging van metagegevens van de extensie te voorkomen, zijn deze variabelen niet opgeslagen:",
"description": "" "description": ""
}, },
"openManage": { "openManage": {
@ -610,7 +606,7 @@
"description": "Link to open the manage page." "description": "Link to open the manage page."
}, },
"updateCheckFailBadResponseCode": { "updateCheckFailBadResponseCode": {
"message": "Update mislukt: server kwam terug met $code$.", "message": "Update mislukt: server gaf code $code$ als antwoord.",
"description": "Text that displays when an update check failed because the response code indicates an error", "description": "Text that displays when an update check failed because the response code indicates an error",
"placeholders": { "placeholders": {
"code": { "code": {
@ -627,19 +623,23 @@
"description": "Label for the button to install an update for a single style" "description": "Label for the button to install an update for a single style"
}, },
"syncStorageErrorSaving": { "syncStorageErrorSaving": {
"message": "De waarde kan niet worden opgeslagen. Probeer het aantal tekst te verminderen.", "message": "De waarde kan niet worden opgeslagen. Probeer de hoeveelheid tekst te verminderen.",
"description": "Displayed when trying to save an excessively big value via storage.sync API" "description": "Displayed when trying to save an excessively big value via storage.sync API"
}, },
"optionsCheckUpdate": { "optionsCheckUpdate": {
"message": "Controleren op updates en deze installeren", "message": "Controleren op updates en deze installeren",
"description": "" "description": ""
}, },
"styleBeautifyPreserveNewlines": {
"message": "Nieuwe regels behouden",
"description": "CSS-beautifier option"
},
"clickToUninstall": { "clickToUninstall": {
"message": "Klik om te deïnstalleren", "message": "Klik om te de-installeren",
"description": "Label for the overlay on a style thumbnail when installed via inline search in the popup" "description": "Label for the overlay on a style thumbnail when installed via inline search in the popup"
}, },
"filteredStyles": { "filteredStyles": {
"message": "$numShown$ van de $numTotal$ wordt/worden getoond", "message": "$numShown$ van de $numTotal$ getoond",
"description": "TL note - make this message short", "description": "TL note - make this message short",
"placeholders": { "placeholders": {
"numTotal": { "numTotal": {
@ -655,7 +655,7 @@
"description": "Title of the report shown after importing styles" "description": "Title of the report shown after importing styles"
}, },
"unreachableAMOHint": { "unreachableAMOHint": {
"message": "Open, om te machtigen, <about:config>, klik met de rechtermuisknop op de lijst, kies dan voor 'Nieuw' --> 'Boolean' en plak <privacy.resistFingerprinting.block_mozAddonManager> . Klik daarna op Oké --> <true> --> Oké en herlaad de <addons.mozilla.org>-pagina.", "message": "Toestemming verlenen: open <about:config>, klik met de rechtermuisknop op de lijst, klik op Nieuw -> Boolean en plak <privacy.resistFingerprinting.block_mozAddonManager>. Klik daarna op OK -> <true> -> OK en vernieuw de pagina <addons.mozilla.org>.",
"description": "Note in the popup when opened on addons.mozilla.org in Firefox >= 59" "description": "Note in the popup when opened on addons.mozilla.org in Firefox >= 59"
}, },
"styleMozillaFormatHeading": { "styleMozillaFormatHeading": {
@ -667,11 +667,11 @@
"description": "Label for the drop-down list controlling the automatic highlighting of current word/selection occurrences in the style editor." "description": "Label for the drop-down list controlling the automatic highlighting of current word/selection occurrences in the style editor."
}, },
"styleRegexpPartialExplanation": { "styleRegexpPartialExplanation": {
"message": "Deze stijl gebruikt gedeeltelijk overeenkomende regexps. Dit is in strijd met de <a href='https://developer.mozilla.org/docs/Web/CSS/@document'>CSS4 @document-specificatie</a>, welke een volledige URL-overeenkomst vereist. De getroffen CSS-secties zijn niet toegepast op de pagina. Deze stijl is waarschijnlijk gecreëerd met Stylish-voor-Chrome, welke onjuist controleert op 'regexp()'-regels sinds de allereerste versie (bekende fout).", "message": "Deze stijl gebruikt gedeeltelijk overeenkomende regexps. Dit is in strijd met de <a href='https://developer.mozilla.org/docs/Web/CSS/@document'>CSS4 @document-specificatie</a>, die een volledige URL-overeenkomst vereist. De getroffen CSS-secties zijn niet op de pagina toegepast. Deze stijl is waarschijnlijk met Stylish-for-Chrome gemaakt, dat sinds de allereerste versie op een onjuiste manier regexp()-regels controleert (bekende fout).",
"description": "" "description": ""
}, },
"linterCSSLintSettings": { "linterCSSLintSettings": {
"message": "(stel regel in als volgt: 0 = uitgeschakeld; 1 = waarschuwing; 2 = fout)", "message": "(stel regel als volgt in: 0 = uitgeschakeld; 1 = waarschuwing; 2 = fout)",
"description": "CSSLint rule config values" "description": "CSSLint rule config values"
}, },
"usercssReplaceTemplateSectionBody": { "usercssReplaceTemplateSectionBody": {
@ -679,7 +679,7 @@
"description": "The code placeholder comment in a new style created by clicking 'Write style' in the popup" "description": "The code placeholder comment in a new style created by clicking 'Write style' in the popup"
}, },
"searchResultNoneFound": { "searchResultNoneFound": {
"message": "Geen stijlen gevonden voor deze website.", "message": "Geen stijlen voor deze website gevonden.",
"description": "Error text in the popup when inline search didn't find any site-specific styles" "description": "Error text in the popup when inline search didn't find any site-specific styles"
}, },
"styleBeautifyIndentConditional": { "styleBeautifyIndentConditional": {
@ -687,7 +687,7 @@
"description": "CSS-beautifier option" "description": "CSS-beautifier option"
}, },
"unreachableContentScript": { "unreachableContentScript": {
"message": "Kan niet communiceren met de pagina. Probeer het tabblad te herladen.", "message": "Kon niet met de pagina communiceren. Probeer het tabblad te vernieuwen.",
"description": "Note in the toolbar popup usually on file:// URLs after [re]loading Stylus" "description": "Note in the toolbar popup usually on file:// URLs after [re]loading Stylus"
}, },
"sectionRemove": { "sectionRemove": {
@ -699,11 +699,11 @@
"description": "Label for the checkbox that turns all enabled styles off." "description": "Label for the checkbox that turns all enabled styles off."
}, },
"appliesLineWidgetLabel": { "appliesLineWidgetLabel": {
"message": "Toont 'Toepasbaar op'-informatie", "message": "Van toepassing op-info weergeven",
"description": "Label for the checkbox to display applies-to information in the single editor" "description": "Label for the checkbox to display applies-to information in the single editor"
}, },
"updateCheckSkippedMaybeLocallyEdited": { "updateCheckSkippedMaybeLocallyEdited": {
"message": "Deze stijl is waarschijnlijk lokaal bewerkt.", "message": "Deze stijl is mogelijk lokaal bewerkt.",
"description": "Text that displays when an update check skipped updating the style to avoid losing possible local modifications" "description": "Text that displays when an update check skipped updating the style to avoid losing possible local modifications"
}, },
"undoGlobal": { "undoGlobal": {
@ -727,15 +727,15 @@
"description": "Label for the checkbox in style editor to enable live preview while editing." "description": "Label for the checkbox in style editor to enable live preview while editing."
}, },
"paginationTotal": { "paginationTotal": {
"message": "Totaal aantal pagina's", "message": "Totale aantal paginas",
"description": "" "description": ""
}, },
"cm_selectByTokensTooltip": { "cm_selectByTokensTooltip": {
"message": "Voorbeeldsleutels: .foo-bar-2 #aabbcc 0.32 !important\nIndien uitgeschakeld: punctuatieloze woorden worden geselecteerd.", "message": "Voorbeelden van tokens: .foo-bar-2 #aabbcc 0.32 !important\nWanneer uitgeschakeld: door interpunctie gescheiden woorden worden geselecteerd.",
"description": "" "description": ""
}, },
"checkingForUpdate": { "checkingForUpdate": {
"message": "Bezig met controleren...", "message": "Controleren...",
"description": "Text to display when checking a style for an update" "description": "Text to display when checking a style for an update"
}, },
"styleRegexpTestFull": { "styleRegexpTestFull": {
@ -743,7 +743,7 @@
"description": "RegExp test report: label for the fully matching expressions" "description": "RegExp test report: label for the fully matching expressions"
}, },
"manageMaxTargets": { "manageMaxTargets": {
"message": "Aantal 'toepasbaar op'-items", "message": "Aantal Van toepassing op-items",
"description": "Label for the numeric input box to limit max number of applies-to targets in the new UI on manage page" "description": "Label for the numeric input box to limit max number of applies-to targets in the new UI on manage page"
}, },
"searchResultRating": { "searchResultRating": {
@ -755,19 +755,19 @@
"description": "Used in various parts of the UI to indicate if something is unknown (e.g. an unknown date)" "description": "Used in various parts of the UI to indicate if something is unknown (e.g. an unknown date)"
}, },
"popupManageTooltip": { "popupManageTooltip": {
"message": "Shift-klik of rechtsklik opent de beheerder met stijlen die toepasbaar zijn op de huidige site", "message": "Shift-klik of rechtsklik opent de beheerder met stijlen die op de huidige website van toepassing zijn",
"description": "Tooltip for the 'Manage' button in the popup." "description": "Tooltip for the 'Manage' button in the popup."
}, },
"manageFaviconsHelp": { "manageFaviconsHelp": {
"message": "Stylus gebruikt een externe dienst https://www.google.com/s2/favicons", "message": "Stylus gebruikt een externe dienst: https://www.google.com/s2/favicons",
"description": "Label for the checkbox that toggles applies-to favicons in the new UI on manage page" "description": "Label for the checkbox that toggles applies-to favicons in the new UI on manage page"
}, },
"paginationEstimated": { "paginationEstimated": {
"message": "Geschatte aantal pagina's", "message": "Geschatte aantal paginas",
"description": "Tooltip for the total page count in search results" "description": "Tooltip for the total page count in search results"
}, },
"styleInstallOverwrite": { "styleInstallOverwrite": {
"message": "'$stylename$' is al geïnstalleerd. Overschrijven?\nVersie: $oldVersion$ -> $newVersion$", "message": "$stylename$ is al geïnstalleerd. Overschrijven?\nVersie: $oldVersion$ -> $newVersion$",
"description": "Confirmation when re-installing a style", "description": "Confirmation when re-installing a style",
"placeholders": { "placeholders": {
"stylename": { "stylename": {
@ -790,7 +790,7 @@
"description": "Stylelint or CSSLint rules label added immediately before a link" "description": "Stylelint or CSSLint rules label added immediately before a link"
}, },
"styleUpdateDiscardChanges": { "styleUpdateDiscardChanges": {
"message": "Deze stijl is gewijzigd buiten de bewerker om. Wil je de stijl herladen?", "message": "Deze stijl is buiten de editor om gewijzigd. Wilt u de stijl opnieuw laden?",
"description": "Confirmation to update the style in the editor" "description": "Confirmation to update the style in the editor"
}, },
"optionsResetButton": { "optionsResetButton": {
@ -802,7 +802,7 @@
"description": "Tooltip for the '->' (next page) button in search results" "description": "Tooltip for the '->' (next page) button in search results"
}, },
"searchResultInstallCount": { "searchResultInstallCount": {
"message": "Totaal aantal installaties", "message": "Totale aantal installaties",
"description": "Text for label that shows the number of times a search result was installed" "description": "Text for label that shows the number of times a search result was installed"
}, },
"externalUsercssDocument": { "externalUsercssDocument": {
@ -810,11 +810,11 @@
"description": "Label for the external link to usercss documentation" "description": "Label for the external link to usercss documentation"
}, },
"optionsAdvancedContextDelete": { "optionsAdvancedContextDelete": {
"message": "'Verwijderen' toevoegen aan rechtermuisknopmenu van bewerker", "message": "Verwijderen toevoegen in contextmenu van editor",
"description": "" "description": ""
}, },
"linterConfigPopupTitle": { "linterConfigPopupTitle": {
"message": "$linter$-regelsconfiguratie instellen", "message": "$linter$-regelconfiguratie instellen",
"description": "Stylelint or CSSLint popup header", "description": "Stylelint or CSSLint popup header",
"placeholders": { "placeholders": {
"linter": { "linter": {
@ -823,7 +823,7 @@
} }
}, },
"configureStyle": { "configureStyle": {
"message": "Instellen", "message": "Configureren",
"description": "Label for the button to configure usercss userstyle" "description": "Label for the button to configure usercss userstyle"
}, },
"importReportLegendUpdatedBoth": { "importReportLegendUpdatedBoth": {
@ -839,15 +839,15 @@
"description": "RegExp test button label in the editor shown when applies-to list has a regexp value" "description": "RegExp test button label in the editor shown when applies-to list has a regexp value"
}, },
"appliesHelp": { "appliesHelp": {
"message": "Gebruik de 'Toepasbaar op'-functies om de URL's te limiteren in de sectie.", "message": "Gebruik de Van toepassing op-functies om de URLs voor de code in deze sectie te beperken.",
"description": "Help text for 'applies to' section" "description": "Help text for 'applies to' section"
}, },
"linkGetHelp": { "linkGetHelp": {
"message": "Verkrijg hulp", "message": "Hulp verkrijgen",
"description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info" "description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info"
}, },
"searchStylesHelp": { "searchStylesHelp": {
"message": "</>-toets focust het zoekvak.\nPlatte tekst: zoeken in de naam, code, website-URL en de sites waarop het wordt toegepast. Woorden met minder dan 3 letters worden genegeerd.\nOvereenkomende URL: begin de zoekopdracht met <url:>, bijv. <url:https://github.com/openstyles/stylus>\nReguliere expressies: inclusief schuine strepen en vlaggen, bijv. </body.*?\\ba\\b/simguy>\nExacte woorden: gebruik dubbele aanhalingstekens in de zoekterm, bijv. <\".header ~ div\">", "message": "</>-toets legt de focus in het zoekvak.\nPlatte tekst: zoeken in de naam, code, website-URL en de websites waarop het wordt toegepast. Woorden met minder dan 3 letters worden genegeerd.\nStijlen die met een volledige URL overeenkomen: begin de zoekopdracht met <url:>, bv. <url:https://github.com/openstyles/stylus>\nReguliere expressies: voeg schuine strepen en vlaggen toe, bv. </body.*?\\ba\\b/simguy>\nExacte woorden: gebruik dubbele aanhalingstekens in de zoekterm, bv. <\".header ~ div\">",
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page" "description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page"
}, },
"findStyles": { "findStyles": {
@ -863,7 +863,7 @@
"description": "Label for the context menu item in the editor to delete selected text" "description": "Label for the context menu item in the editor to delete selected text"
}, },
"cm_autocompleteOnTyping": { "cm_autocompleteOnTyping": {
"message": "Auto-aanvullen tijdens typen", "message": "Automatisch aanvullen tijdens typen",
"description": "Label for the checkbox in the style editor." "description": "Label for the checkbox in the style editor."
}, },
"unreachableAMO": { "unreachableAMO": {
@ -901,7 +901,7 @@
"description": "Checkbox to show only disabled styles" "description": "Checkbox to show only disabled styles"
}, },
"stylusUnavailableForURLdetails": { "stylusUnavailableForURLdetails": {
"message": "Omwille van beveiligingsredenen, verbiedt de browser extensies op ingebouwde pagina's (zoals chrome://version, de standaard nieuwe tabblad-pagina sinds Chrome 61, about:addons, enz.) alsmede andere extensiepagina's. Elke browser beperkt ook de toegang tot de extensiegalerij (zoals de Chrome Web Store of AMO).", "message": "Als beveiligingsmaatregel verbiedt de browser dat extensies effect hebben op ingebouwde paginas (zoals chrome://version, de standaard nieuw-tabbladpagina sinds Chrome 61, about:addons, enz.), evenals op paginas van andere extensies. Ook beperkt elke browser toegang tot de eigen extensiegalerij (zoals de Chrome Web Store of AMO).",
"description": "Sub-note in the toolbar pop-up when on a URL Stylus can't affect" "description": "Sub-note in the toolbar pop-up when on a URL Stylus can't affect"
}, },
"cm_matchHighlightSelection": { "cm_matchHighlightSelection": {
@ -909,11 +909,11 @@
"description": "Style editor's 'highglight' drop-down list option: highlight the occurrences of currently selected text" "description": "Style editor's 'highglight' drop-down list option: highlight the occurrences of currently selected text"
}, },
"updateAllCheckSucceededSomeEdited": { "updateAllCheckSucceededSomeEdited": {
"message": "Sommige stijlen die kunnen worden bijgewerkt zijn niet gecontroleerd om mogelijke lokale bewerkingen te behouden. Updates kunnen worden geforceerd door de stijlen individueel te controleren of door alle stijlen opnieuw te controleren (lokale bewerkingen worden overschreven).", "message": "Sommige stijlen die kunnen worden bijgewerkt zijn niet gecontroleerd, om mogelijke lokale bewerkingen te behouden. Updates kunnen worden geforceerd door de stijlen individueel te controleren, of door alle stijlen opnieuw te controleren (lokale bewerkingen worden overschreven).",
"description": "Text that displays when an update all check completed and no updates are available" "description": "Text that displays when an update all check completed and no updates are available"
}, },
"stylusUnavailableForURL": { "stylusUnavailableForURL": {
"message": "Stylus werkt niet op pagina's als deze.", "message": "Stylus werkt niet op paginas als deze.",
"description": "Note in the toolbar pop-up when on a URL Stylus can't affect" "description": "Note in the toolbar pop-up when on a URL Stylus can't affect"
}, },
"popupBorders": { "popupBorders": {
@ -929,11 +929,11 @@
"description": "Title of the page for adding styles" "description": "Title of the page for adding styles"
}, },
"externalLink": { "externalLink": {
"message": "Externe link", "message": "Externe koppeling",
"description": "Label for external links" "description": "Label for external links"
}, },
"externalHomepage": { "externalHomepage": {
"message": "Website", "message": "Startpagina",
"description": "Label for the external link to style's homepage" "description": "Label for the external link to style's homepage"
}, },
"importReplaceLabel": { "importReplaceLabel": {
@ -945,11 +945,11 @@
"description": "Used in various places to select/perform the next step/action" "description": "Used in various places to select/perform the next step/action"
}, },
"popupOpenEditInWindowTooltip": { "popupOpenEditInWindowTooltip": {
"message": "Wordt tevens ingeschakeld door het losmaken van het bewerker-tabblad,\nen uitgeschakeld door het vastmaken van een los bewerker-tabblad aan een ander venster.", "message": "Wordt tevens ingeschakeld door het losmaken van het editor-tabblad,\nen uitgeschakeld door het vastmaken van een los editor-tabblad aan een ander venster.",
"description": "Label for the checkbox controlling 'edit' action behavior in the popup." "description": "Label for the checkbox controlling 'edit' action behavior in the popup."
}, },
"dbError": { "dbError": {
"message": "Er is een fout opgetreden bij het gebruiken van de Stylus-database. Wil je een webpagina met mogelijke oplossingen bezoeken?", "message": "Er is een fout opgetreden bij het gebruiken van de Stylus-database. Wilt u een webpagina met mogelijke oplossingen bezoeken?",
"description": "Prompt when a DB error is encountered" "description": "Prompt when a DB error is encountered"
}, },
"dateInstalled": { "dateInstalled": {
@ -969,11 +969,11 @@
"description": "Tooltip for the button to import a style and append to the existing sections" "description": "Tooltip for the button to import a style and append to the existing sections"
}, },
"liveReloadInstallHint": { "liveReloadInstallHint": {
"message": "Live-herladen is ingeschakeld. De geïnstalleerde stijl zal automatisch worden bijgewerkt bij externe wijzigingen als zowel dit tabblad als het tabblad van het bronbestand geopend zijn.", "message": "Live herladen is ingeschakeld. De geïnstalleerde stijl zal bij externe wijzigingen automatisch worden bijgewerkt als zowel dit tabblad als het tabblad van het bronbestand zijn geopend.",
"description": "The label of live-reload feature" "description": "The label of live-reload feature"
}, },
"editorStylesButton": { "editorStylesButton": {
"message": "Bewerkerstijlen zoeken", "message": "Editorstijlen zoeken",
"description": "Find styles for the editor" "description": "Find styles for the editor"
}, },
"optionsOpen": { "optionsOpen": {
@ -984,6 +984,10 @@
"message": "Druk op een sneltoets", "message": "Druk op een sneltoets",
"description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short" "description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short"
}, },
"cm_linter": {
"message": "CSS-linter",
"description": "Select the linter to check for CSS issues"
},
"styleRegexpTestInvalid": { "styleRegexpTestInvalid": {
"message": "Ongeldige regexps overgeslagen", "message": "Ongeldige regexps overgeslagen",
"description": "RegExp test report: label for the invalid expressions" "description": "RegExp test report: label for the invalid expressions"
@ -1001,11 +1005,11 @@
"description": "Text for label that shows the number of times a search result was installed during last week" "description": "Text for label that shows the number of times a search result was installed during last week"
}, },
"replaceAll": { "replaceAll": {
"message": "Alles vervangen", "message": "Alle vervangen",
"description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey" "description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey"
}, },
"importReportUnchanged": { "importReportUnchanged": {
"message": "Er is niks gewijzigd.", "message": "Er is niets gewijzigd.",
"description": "Message in the report shown after importing styles" "description": "Message in the report shown after importing styles"
}, },
"confirmDiscardChanges": { "confirmDiscardChanges": {
@ -1029,11 +1033,11 @@
"description": "Go to line or line:column on Ctrl-G in style code editor" "description": "Go to line or line:column on Ctrl-G in style code editor"
}, },
"manageOnlyLocalTooltip": { "manageOnlyLocalTooltip": {
"message": "(de stijlen die niet geïnstalleerd zijn via userstyles.org)", "message": "(de stijlen die niet via userstyles.org zijn geïnstalleerd)",
"description": "Tooltip for the checkbox to show only locally created styles i.e. non-updatable" "description": "Tooltip for the checkbox to show only locally created styles i.e. non-updatable"
}, },
"checkAllUpdates": { "checkAllUpdates": {
"message": "Controleer alle stijlen op updates", "message": "Alle stijlen controleren op updates",
"description": "Label for the button to check all styles for updates" "description": "Label for the button to check all styles for updates"
}, },
"openOptionsManage": { "openOptionsManage": {
@ -1045,7 +1049,7 @@
"description": "Tooltip for the colored squares shown before CSS colors in the style editor." "description": "Tooltip for the colored squares shown before CSS colors in the style editor."
}, },
"optionsCustomizeBadge": { "optionsCustomizeBadge": {
"message": "Badge op het werkbalkpictogram", "message": "Badge op werkbalkpictogram",
"description": "" "description": ""
}, },
"sortDateNewestFirst": { "sortDateNewestFirst": {
@ -1057,7 +1061,7 @@
"description": "Tooltip for the '<-' button in search results" "description": "Tooltip for the '<-' button in search results"
}, },
"installUpdateFrom": { "installUpdateFrom": {
"message": "De stijl wordt momenteel bijgewerkt via $url$", "message": "De stijl wordt momenteel bijgewerkt vanaf $url$",
"description": "Label to describe where the style gets update", "description": "Label to describe where the style gets update",
"placeholders": { "placeholders": {
"url": { "url": {
@ -1078,7 +1082,7 @@
"description": "" "description": ""
}, },
"cm_autoCloseBrackets": { "cm_autoCloseBrackets": {
"message": "Haken en citaten automatisch sluiten", "message": "Haakjes en aanhalingstekens automatisch sluiten",
"description": "Label for the checkbox in the style editor." "description": "Label for the checkbox in the style editor."
}, },
"installButtonReinstall": { "installButtonReinstall": {
@ -1086,7 +1090,7 @@
"description": "Label for reinstall button" "description": "Label for reinstall button"
}, },
"linterInvalidConfigError": { "linterInvalidConfigError": {
"message": "Niet opgeslagen vanwege ongeldige configuratie-instellingen:", "message": "Niet opgeslagen vanwege deze ongeldige configuratie-instellingen:",
"description": "Invalid linter config will show a message followed by a list of invalid entries" "description": "Invalid linter config will show a message followed by a list of invalid entries"
}, },
"confirmNo": { "confirmNo": {
@ -1107,11 +1111,11 @@
"description": "Tooltip for the 'Aa' icon that enables case-sensitive search in the editor shown on Ctrl-F" "description": "Tooltip for the 'Aa' icon that enables case-sensitive search in the editor shown on Ctrl-F"
}, },
"appliesLineWidgetWarning": { "appliesLineWidgetWarning": {
"message": "Werkt niet met minified CSS", "message": "Werkt niet met verkleinde CSS",
"description": "A warning that applies-to information won't show properly with minified CSS" "description": "A warning that applies-to information won't show properly with minified CSS"
}, },
"configureStyleOnHomepage": { "configureStyleOnHomepage": {
"message": "Instellen op startpagina", "message": "Configureren op startpagina",
"description": "Label for the button to configure userstyles.org userstyle" "description": "Label for the button to configure userstyles.org userstyle"
}, },
"undo": { "undo": {
@ -1119,7 +1123,7 @@
"description": "Button label" "description": "Button label"
}, },
"usercssReplaceTemplateConfirmation": { "usercssReplaceTemplateConfirmation": {
"message": "Wil je het standaard sjabloon voor nieuwe Usercss-stijlen vervangen door de huidige code?", "message": "Wilt u de standaardsjabloon voor nieuwe Usercss-stijlen vervangen door de huidige code?",
"description": "" "description": ""
}, },
"cm_keyMap": { "cm_keyMap": {
@ -1139,11 +1143,11 @@
"description": "Label for the checkbox that toggles the new UI on manage page" "description": "Label for the checkbox that toggles the new UI on manage page"
}, },
"unreachableAMOHintOldFF": { "unreachableAMOHintOldFF": {
"message": "Alleen Firefox 59 en hoger kunnen worden geconfigureerd om WebExtensies stijlelementen toe te laten voegen op met CSP-beveiligde websites als deze.", "message": "Alleen Firefox 59 en hoger kunnen worden geconfigureerd om WebExtensions stijlelementen te laten toevoegen op door CSP beveiligde websites zoals deze.",
"description": "Note in the popup when opened on addons.mozilla.org in Firefox < 59" "description": "Note in the popup when opened on addons.mozilla.org in Firefox < 59"
}, },
"importReportUndoneTitle": { "importReportUndoneTitle": {
"message": "Het importeren is ongedaan gemaakt", "message": "Importeren is ongedaan gemaakt",
"description": "Title of the message box shown after undoing the import of styles" "description": "Title of the message box shown after undoing the import of styles"
}, },
"genericDisabledLabel": { "genericDisabledLabel": {
@ -1196,7 +1200,7 @@
"description": "Label for update button" "description": "Label for update button"
}, },
"backupButtons": { "backupButtons": {
"message": "Back-uppen", "message": "Back-up",
"description": "Heading for backup" "description": "Heading for backup"
}, },
"manageOnlyEnabled": { "manageOnlyEnabled": {
@ -1220,27 +1224,27 @@
"description": "Label for the style editor's CSS theme." "description": "Label for the style editor's CSS theme."
}, },
"findStylesInlineTooltip": { "findStylesInlineTooltip": {
"message": "Zoekresultaten tonen in dit venster.", "message": "Zoekresultaten binnen dit venster weergeven",
"description": "Text for a checkbox that displays search results within the Stylus popup." "description": "Text for a checkbox that displays search results within the Stylus popup."
}, },
"popupOpenEditInWindow": { "popupOpenEditInWindow": {
"message": "Bewerker openen in nieuw venster", "message": "Editor openen in nieuw venster",
"description": "Label for the checkbox controlling 'edit' action behavior in the popup." "description": "Label for the checkbox controlling 'edit' action behavior in the popup."
}, },
"appliesRemoveError": { "appliesRemoveError": {
"message": "Laatste 'toepasbaar op'-vermelding kan niet worden verwijderd", "message": "Kan laatste Van toepassing op-item niet verwijderen",
"description": "Error displayed when the last 'applies' is going to be removed" "description": "Error displayed when the last 'applies' is going to be removed"
}, },
"backupMessage": { "backupMessage": {
"message": "Selecteer een bestand of versleep het naar deze pagina.", "message": "Selecteer een bestand of sleep het naar deze pagina.",
"description": "Message for backup" "description": "Message for backup"
}, },
"importReportUndone": { "importReportUndone": {
"message": "stijlen zijn teruggedraaid", "message": "stijlen zijn teruggezet",
"description": "Text after the number of styles reverted in the message box shown after undoing the import of styles" "description": "Text after the number of styles reverted in the message box shown after undoing the import of styles"
}, },
"helpKeyMapCommand": { "helpKeyMapCommand": {
"message": "Voer een commandonaam in", "message": "Typ een opdrachtnaam",
"description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short" "description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short"
}, },
"linterResetMessage": { "linterResetMessage": {
@ -1248,7 +1252,7 @@
"description": "Reset button tooltip to inform user on how to undo an accidental reset" "description": "Reset button tooltip to inform user on how to undo an accidental reset"
}, },
"description": { "description": {
"message": "Voorzie het web van een ander uiterlijk met Stylus, een gebruikersstijlbeheerder. Stylus stelt je in staat om eenvoudig thema's en stijlen te installeren voor vele populaire websites.", "message": "Voorzie het web van een ander uiterlijk met Stylus, een gebruikersstijlbeheerder. Met Stylus kunt u eenvoudig themas en stijlen voor veel populaire websites installeren.",
"description": "Extension description" "description": "Extension description"
}, },
"confirmClose": { "confirmClose": {
@ -1256,7 +1260,7 @@
"description": "'Close' button in a confirm dialog" "description": "'Close' button in a confirm dialog"
}, },
"usercssReplaceTemplateName": { "usercssReplaceTemplateName": {
"message": "Lege @name vervangt het standaard sjabloon", "message": "Lege @name vervangt de standaardsjabloon",
"description": "The text shown after @name when creating a new Usercss style" "description": "The text shown after @name when creating a new Usercss style"
} }
} }

View File

@ -642,6 +642,10 @@
"message": "Sprawdź i zainstaluj wszystkie dostępne aktualizacje", "message": "Sprawdź i zainstaluj wszystkie dostępne aktualizacje",
"description": "" "description": ""
}, },
"styleBeautifyPreserveNewlines": {
"message": "Zachowaj nowe linie",
"description": "CSS-beautifier option"
},
"clickToUninstall": { "clickToUninstall": {
"message": "Kliknij, aby odinstalować", "message": "Kliknij, aby odinstalować",
"description": "Label for the overlay on a style thumbnail when installed via inline search in the popup" "description": "Label for the overlay on a style thumbnail when installed via inline search in the popup"
@ -859,7 +863,7 @@
"description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info" "description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info"
}, },
"searchStylesHelp": { "searchStylesHelp": {
"message": "Klawisz </> uaktywnia pole wyszukiwania.\nZwykły tekst: szukaj w nazwie, kodzie, adresie URL strony głównej oraz stosownych witrynach. Słowa zawierające mniej niż 3 litery są ignorowane.\nPasujący adres URL: szukaj przy pomocy przedrostka <url:>, np. <url:https://github.com/openstyles/stylus>\nWyrażenia regularne: umieść ukośniki i flagi, np. </body.*?\\ba\\b/simguy>\nDokładne słowa: zawiń zapytanie w podwójny cudzysłów, np. <\".header ~ div\">", "message": "Klawisz </> uaktywnia pole wyszukiwania.\nZwykły tekst: szukaj w nazwie, kodzie, adresie URL strony głównej oraz stosownych witrynach. Słowa zawierające mniej niż 3 litery są ignorowane.\nStyle pasujące do pełnego adresu URL: szukaj przy pomocy przedrostka <url:>, np. <url:https://github.com/openstyles/stylus>\nWyrażenia regularne: umieść ukośniki i flagi, np. </body.*?\\ba\\b/simguy>\nDokładne słowa: zawiń zapytanie w podwójny cudzysłów, np. <\".header ~ div\">",
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page" "description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page"
}, },
"findStyles": { "findStyles": {

View File

@ -8,11 +8,11 @@
"description": "Label for the CSS linter issues block on the style edit page" "description": "Label for the CSS linter issues block on the style edit page"
}, },
"defaultTheme": { "defaultTheme": {
"message": "padrão", "message": "predefinição",
"description": "Default CodeMirror CSS theme option on the edit style page" "description": "Default CodeMirror CSS theme option on the edit style page"
}, },
"styleRegexpTestTitle": { "styleRegexpTestTitle": {
"message": "Lista de separadores abertos correspondentes (clica no URL para focar no separador)", "message": "Lista de separadores correspondentes abertos (clique no URL para focar no separador)",
"description": "RegExp test report: title of the report" "description": "RegExp test report: title of the report"
}, },
"bckpInstStyles": { "bckpInstStyles": {
@ -23,6 +23,14 @@
"message": "Ordenar conteúdos", "message": "Ordenar conteúdos",
"description": "Label for the sort info popup on the Manage styles page" "description": "Label for the sort info popup on the Manage styles page"
}, },
"sortStylesHelp": {
"message": "Escolha o tipo de ordenação a ser aplicado às entradas instaladas na lista suspensa de ordenação. A configuração predefinida aplica uma ordem crescente (A a Z) aos títulos de entrada. As ordenações dentro do grupo \"Título Decrescente\" aplicarão uma classificação decrescente (Z a A) ao título. Existem outras predefinições que permitirão classificar as entradas por vários critérios. Pense sobre isso como ordenar uma tabela com várias colunas e cada categoria em uma seleção (entre os sinais de mais) representa uma coluna ou grupo. Por exemplo, se a configuração for \"Ativado (primeiro) + Título\", as entradas serão ordenadas de modo que todas as entradas ativadas sejam classificadas no topo da lista, então uma classificação crescente de título de entrada (A a Z) será aplicada a ambas as entradas ativadas e desativadas separadamente.",
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the sort input field on the Manage styles page"
},
"optionsUpdateInterval": {
"message": "Intervalo de atualização automática do estilo de usuário em horas (especifique 0 para desativar)",
"description": ""
},
"exportLabel": { "exportLabel": {
"message": "Exportar", "message": "Exportar",
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)" "description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
@ -44,7 +52,7 @@
"description": "" "description": ""
}, },
"cm_tabSize": { "cm_tabSize": {
"message": "Tamanho do tab", "message": "Tamanho da tabulação",
"description": "Label for the text box controlling tab size option for the style editor." "description": "Label for the text box controlling tab size option for the style editor."
}, },
"enableStyleLabel": { "enableStyleLabel": {
@ -60,7 +68,7 @@
"description": "Used in various places to show a history log of something" "description": "Used in various places to show a history log of something"
}, },
"shortcutsNote": { "shortcutsNote": {
"message": "Definir atalhos de teclad", "message": "Definir atalhos de teclado",
"description": "" "description": ""
}, },
"appliesDomainOption": { "appliesDomainOption": {
@ -72,7 +80,7 @@
"description": "Label for the button to check a single style for an update" "description": "Label for the button to check a single style for an update"
}, },
"styleRegexpInvalidExplanation": { "styleRegexpInvalidExplanation": {
"message": "Algumas regras 'regexp()' que não podiam ser compiladas de todo", "message": "Algumas regras de 'regexp()' que não puderam ser compiladas.",
"description": "" "description": ""
}, },
"importAppendLabel": { "importAppendLabel": {
@ -120,13 +128,17 @@
"description": "Text for a link that gets a list of styles for the current site" "description": "Text for a link that gets a list of styles for the current site"
}, },
"manageHeading": { "manageHeading": {
"message": "Estilos instalados", "message": "Estilos Instalados",
"description": "Heading for the manage page" "description": "Heading for the manage page"
}, },
"styleBeautify": { "styleBeautify": {
"message": "Embelezar", "message": "Embelezar",
"description": "Label for the CSS-beautifier button on the edit style page" "description": "Label for the CSS-beautifier button on the edit style page"
}, },
"styleRegexpProblemTooltip": {
"message": "Número de secções não aplicadas devido ao uso incorreto de 'regexp ()'",
"description": "Tooltip in the popup for styles that were applied only partially"
},
"styleEnabledLabel": { "styleEnabledLabel": {
"message": "Ativado", "message": "Ativado",
"description": "Label for the enabled state of styles" "description": "Label for the enabled state of styles"
@ -136,7 +148,7 @@
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format" "description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
}, },
"sectionAdd": { "sectionAdd": {
"message": "Adicionar outra seção", "message": "Adicionar outra secção",
"description": "Label for the button to add a section" "description": "Label for the button to add a section"
}, },
"styleSaveLabel": { "styleSaveLabel": {
@ -151,6 +163,10 @@
"message": "Apagar", "message": "Apagar",
"description": "" "description": ""
}, },
"confirmDefault": {
"message": "Use predefinição",
"description": "'Set to default' button in a confirm dialog"
},
"confirmCancel": { "confirmCancel": {
"message": "Cancelar", "message": "Cancelar",
"description": "" "description": ""
@ -168,7 +184,7 @@
"description": "Text for link in toolbar pop-up to write a new style for the current URL" "description": "Text for link in toolbar pop-up to write a new style for the current URL"
}, },
"optionsSubheading": { "optionsSubheading": {
"message": "Mais opções", "message": "Mais Opções",
"description": "Subheading for options section on manage page." "description": "Subheading for options section on manage page."
}, },
"appliesAdd": { "appliesAdd": {
@ -176,7 +192,7 @@
"description": "Label for the button to add an 'applies' entry" "description": "Label for the button to add an 'applies' entry"
}, },
"appliesRegexpOption": { "appliesRegexpOption": {
"message": "URLs a combinar com o regexp", "message": "URLs correspondentes ao regexp",
"description": "Option to make the style apply to the entered string as a regular expression" "description": "Option to make the style apply to the entered string as a regular expression"
}, },
"importReportLegendUpdatedCode": { "importReportLegendUpdatedCode": {
@ -208,6 +224,10 @@
"message": "Verifica outra vez, eu não editei nenhum estilo!", "message": "Verifica outra vez, eu não editei nenhum estilo!",
"description": "Label for the button to apply all detected updates" "description": "Label for the button to apply all detected updates"
}, },
"liveReloadLabel": {
"message": "Recarregamento dinâmico",
"description": "The label of live-reload feature"
},
"linkGetStyles": { "linkGetStyles": {
"message": "Obter estilos", "message": "Obter estilos",
"description": "Help link text on the manage page e.g. https://userstyles.org" "description": "Help link text on the manage page e.g. https://userstyles.org"
@ -216,6 +236,10 @@
"message": "O Stylus pode acessar URLs file:// apenas se ativares a checkbox correspondente para a extensão Stylus na página chrome://extensions", "message": "O Stylus pode acessar URLs file:// apenas se ativares a checkbox correspondente para a extensão Stylus na página chrome://extensions",
"description": "Note in the toolbar popup for file:// URLs" "description": "Note in the toolbar popup for file:// URLs"
}, },
"sortLabel": {
"message": "Selecione uma ordenação para aplicar aos estilos instalados",
"description": "Title on the sort select to indicate it is used for sorting entries"
},
"disableStyleLabel": { "disableStyleLabel": {
"message": "Desativar", "message": "Desativar",
"description": "Label for the button to disable a style" "description": "Label for the button to disable a style"
@ -265,7 +289,7 @@
"description": "Label for the button to apply all detected updates" "description": "Label for the button to apply all detected updates"
}, },
"optionsReset": { "optionsReset": {
"message": "Restabelecer as opções aos valores iniciais", "message": "Restabelecer as opções aos valores predefinidos",
"description": "" "description": ""
}, },
"optionsCustomizeUpdate": { "optionsCustomizeUpdate": {
@ -307,7 +331,7 @@
} }
}, },
"styleSectionsTitle": { "styleSectionsTitle": {
"message": "Seções", "message": "Secções",
"description": "Title for the style sections section" "description": "Title for the style sections section"
}, },
"editStyleTitle": { "editStyleTitle": {
@ -348,7 +372,7 @@
"description": "Label for the checkbox controlling section order in the popup." "description": "Label for the checkbox controlling section order in the popup."
}, },
"sectionHelp": { "sectionHelp": {
"message": "As seções deixam definir diferentes peças de código a aplicar em diferentes conjuntos de URLs no mesmo estilo. Por exemplo, um só estilo pode mudar a página principal de um site de uma maneira, enquanto muda o resto do site de outra.", "message": "As secções deixam definir diferentes peças de código a aplicar em diferentes conjuntos de URLs no mesmo estilo. Por exemplo, um só estilo pode mudar a página principal de um site de uma maneira, enquanto muda o resto do site de outra maneira.",
"description": "Help text for sections" "description": "Help text for sections"
}, },
"noStylesForSite": { "noStylesForSite": {
@ -425,15 +449,19 @@
"description": "Label for the drop-down list controlling the automatic highlighting of current word/selection occurrences in the style editor." "description": "Label for the drop-down list controlling the automatic highlighting of current word/selection occurrences in the style editor."
}, },
"styleRegexpPartialExplanation": { "styleRegexpPartialExplanation": {
"message": "Este estilo usa regexps parcialmente correspondentes em violação da <a href='https://developer.mozilla.org/docs/Web/CSS/@document'>CSS4 @document specification</a> que requere um URL inteiro. As seções de CSS afetadas não foram aplicadas nesta página. Este estilo foi provavelmente criado no Stylish-for-Chrome o qual verifica incorretamente as regras 'regexp()' desde a primeira versão (bug conhecido).", "message": "Este estilo usa regexps parcialmente correspondentes em violação da <a href='https://developer.mozilla.org/docs/Web/CSS/@document'>CSS4 @document specification</a> que requer um URL inteiro. As secções de CSS afetadas não foram aplicadas nesta página. Este estilo foi provavelmente criado no Stylish-for-Chrome o qual verifica incorretamente as regras 'regexp()' desde a primeira versão (bug conhecido).",
"description": "" "description": ""
}, },
"styleBeautifyIndentConditional": { "styleBeautifyIndentConditional": {
"message": "Indentar @media, @supports", "message": "Indentar @media, @supports",
"description": "CSS-beautifier option" "description": "CSS-beautifier option"
}, },
"unreachableContentScript": {
"message": "Não foi possível comunicar com a página. Tente recarregar o separador.",
"description": "Note in the toolbar popup usually on file:// URLs after [re]loading Stylus"
},
"sectionRemove": { "sectionRemove": {
"message": "Remover seção", "message": "Remover secção",
"description": "Label for the button to remove a section" "description": "Label for the button to remove a section"
}, },
"disableAllStyles": { "disableAllStyles": {
@ -445,7 +473,7 @@
"description": "Text that displays when an update check skipped updating the style to avoid losing possible local modifications" "description": "Text that displays when an update check skipped updating the style to avoid losing possible local modifications"
}, },
"undoGlobal": { "undoGlobal": {
"message": "Desfazer em todas as seções", "message": "Anular em todas as secções",
"description": "CSS-beautify global Undo button label" "description": "CSS-beautify global Undo button label"
}, },
"genericTitle": { "genericTitle": {
@ -456,6 +484,10 @@
"message": "Atualização completa.", "message": "Atualização completa.",
"description": "Text that displays when an update completed" "description": "Text that displays when an update completed"
}, },
"previewLabel": {
"message": "Pré-visualização dinâmica",
"description": "Label for the checkbox in style editor to enable live preview while editing."
},
"checkingForUpdate": { "checkingForUpdate": {
"message": "A verificar...", "message": "A verificar...",
"description": "Text to display when checking a style for an update" "description": "Text to display when checking a style for an update"
@ -493,7 +525,7 @@
"description": "Label for the checkbox controlling smart indentation option for the style editor." "description": "Label for the checkbox controlling smart indentation option for the style editor."
}, },
"appliesHelp": { "appliesHelp": {
"message": "Usa os controlos \"Aplica-se a\" para limitar a que URLs o código nesta seção se aplica.", "message": "Use os controlos \"Aplica-se a\" para limitar a que URLs o código nesta secção se aplica.",
"description": "Help text for 'applies to' section" "description": "Help text for 'applies to' section"
}, },
"linkGetHelp": { "linkGetHelp": {
@ -501,7 +533,7 @@
"description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info" "description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info"
}, },
"editStyleHeading": { "editStyleHeading": {
"message": "Editar estil", "message": "Editar Estilo",
"description": "Title of the page for editing styles" "description": "Title of the page for editing styles"
}, },
"editDeleteText": { "editDeleteText": {
@ -532,6 +564,10 @@
"message": "Substituir estil", "message": "Substituir estil",
"description": "Label for the button to import and overwrite current style" "description": "Label for the button to import and overwrite current style"
}, },
"popupOpenEditInWindowTooltip": {
"message": "Também ativado ao desanexar o separador do editor de uma janela do browser, e desativado por anexar um separador único do editor a outra janela.",
"description": "Label for the checkbox controlling 'edit' action behavior in the popup."
},
"dbError": { "dbError": {
"message": "Ocorreu um erro ao usar a base de dados do Stylus. Gostarias de visitar um website com soluções possíveis?", "message": "Ocorreu um erro ao usar a base de dados do Stylus. Gostarias de visitar um website com soluções possíveis?",
"description": "Prompt when a DB error is encountered" "description": "Prompt when a DB error is encountered"
@ -552,8 +588,12 @@
"message": "Anexar o estilo importado ao estilo atual", "message": "Anexar o estilo importado ao estilo atual",
"description": "Tooltip for the button to import a style and append to the existing sections" "description": "Tooltip for the button to import a style and append to the existing sections"
}, },
"liveReloadInstallHint": {
"message": "O recarregamento dinâmico está ativado para que o estilo instalado seja atualizado automaticamente em alterações externas enquanto esse separador e o separador do arquivo de origem estiverem abertos.",
"description": "The label of live-reload feature"
},
"editorStylesButton": { "editorStylesButton": {
"message": "Encontrar editor de estilos", "message": "Encontrar estilos para o editor",
"description": "Find styles for the editor" "description": "Find styles for the editor"
}, },
"optionsOpen": { "optionsOpen": {
@ -561,7 +601,7 @@
"description": "" "description": ""
}, },
"helpKeyMapHotkey": { "helpKeyMapHotkey": {
"message": "Carrega numa tecla de atalho", "message": "Prima uma tecla de atalho",
"description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short" "description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short"
}, },
"dateUpdated": { "dateUpdated": {
@ -573,7 +613,7 @@
"description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey" "description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey"
}, },
"importReportUnchanged": { "importReportUnchanged": {
"message": "Nada foi mudado", "message": "Nada foi alterado.",
"description": "Message in the report shown after importing styles" "description": "Message in the report shown after importing styles"
}, },
"confirmDiscardChanges": { "confirmDiscardChanges": {
@ -626,9 +666,13 @@
"description": "'No' button in a confirm dialog" "description": "'No' button in a confirm dialog"
}, },
"undo": { "undo": {
"message": "Desfazer", "message": "Anular",
"description": "Button label" "description": "Button label"
}, },
"usercssReplaceTemplateConfirmation": {
"message": "Substituir o modelo predefinido para novos estilos de Usercss com o código atual?",
"description": ""
},
"cm_keyMap": { "cm_keyMap": {
"message": "Mapa de teclado", "message": "Mapa de teclado",
"description": "Label for the drop-down list controlling the keymap for the style editor." "description": "Label for the drop-down list controlling the keymap for the style editor."
@ -638,7 +682,7 @@
"description": "Label for the checkbox that toggles the new UI on manage page" "description": "Label for the checkbox that toggles the new UI on manage page"
}, },
"importReportUndoneTitle": { "importReportUndoneTitle": {
"message": "Importação foi desfeita", "message": "A Importação foi anulada",
"description": "Title of the message box shown after undoing the import of styles" "description": "Title of the message box shown after undoing the import of styles"
}, },
"genericDisabledLabel": { "genericDisabledLabel": {
@ -646,7 +690,7 @@
"description": "Used in various lists/options to indicate that something is disabled" "description": "Used in various lists/options to indicate that something is disabled"
}, },
"cm_indentWithTabs": { "cm_indentWithTabs": {
"message": "Usar tabs com indentação inteligente", "message": "Usar tabulação com indentação inteligente",
"description": "Label for the checkbox controlling tabs with smart indentation option for the style editor." "description": "Label for the checkbox controlling tabs with smart indentation option for the style editor."
}, },
"replaceWith": { "replaceWith": {
@ -697,8 +741,16 @@
"message": "Escreve um nome de comando", "message": "Escreve um nome de comando",
"description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short" "description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short"
}, },
"linterResetMessage": {
"message": "Para anular a redefinição acidental, prima Ctrl-Z (ou Cmd-Z) na caixa de texto",
"description": "Reset button tooltip to inform user on how to undo an accidental reset"
},
"description": { "description": {
"message": "Redesenha a web com o Stylus, um gerenciador dos estilos do utilizador [user styles]. O Stylus permite-te instalar facilmente temas e skins em muitos sites populares.", "message": "Redesenha a web com o Stylus, um gerenciador dos estilos do utilizador [user styles]. O Stylus permite-te instalar facilmente temas e skins em muitos sites populares.",
"description": "Extension description" "description": "Extension description"
},
"usercssReplaceTemplateName": {
"message": "@name vazio substitui o modelo predefinido",
"description": "The text shown after @name when creating a new Usercss style"
} }
} }

View File

@ -646,6 +646,10 @@
"message": "Найти и установить обновления стилей", "message": "Найти и установить обновления стилей",
"description": "" "description": ""
}, },
"styleBeautifyPreserveNewlines": {
"message": "Беречь пустые строки",
"description": "CSS-beautifier option"
},
"clickToUninstall": { "clickToUninstall": {
"message": "Нажмите, чтобы удалить стиль", "message": "Нажмите, чтобы удалить стиль",
"description": "Label for the overlay on a style thumbnail when installed via inline search in the popup" "description": "Label for the overlay on a style thumbnail when installed via inline search in the popup"
@ -863,7 +867,7 @@
"description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info" "description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info"
}, },
"searchStylesHelp": { "searchStylesHelp": {
"message": "Клавиша </> переходит к строке поиска.\nОбычный поиск: ищет в имени, тексте, адресе установки, целевых сайтах. Слова короче трех символов игнорируются.\nСтили для сайта: укажите <url:> перед адресом, т.е. <url:https://github.com/openstyles/stylus>\nРегулярки: заключите в слэши, добавьте флаги, т.е. </body.*?\\ba\\b/simguy>\nТочный поиск: заключите в двойные кавычки, т.е. <\".header ~ div\">", "message": "Клавиша </> переходит к строке поиска.\nОбычный поиск: ищет в имени, тексте, адресе установки, целевых сайтах. Слова короче трех символов игнорируются.\nСтили для сайта: укажите <url:> перед полным адресом сайта, т.е. <url:https://github.com/openstyles/stylus>\nРегулярки: заключите в слэши, добавьте флаги, т.е. </body.*?\\ba\\b/simguy>\nТочный поиск: заключите в двойные кавычки, т.е. <\".header ~ div\">",
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page" "description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page"
}, },
"findStyles": { "findStyles": {

View File

@ -8,7 +8,7 @@
"description": "Label for the CSS linter issues block on the style edit page" "description": "Label for the CSS linter issues block on the style edit page"
}, },
"defaultTheme": { "defaultTheme": {
"message": "默認", "message": "預設",
"description": "Default CodeMirror CSS theme option on the edit style page" "description": "Default CodeMirror CSS theme option on the edit style page"
}, },
"styleRegexpTestTitle": { "styleRegexpTestTitle": {
@ -48,7 +48,7 @@
"description": "Text added to indicate that sorting a date would add the oldest entries at the top" "description": "Text added to indicate that sorting a date would add the oldest entries at the top"
}, },
"exportLabel": { "exportLabel": {
"message": "出", "message": "出",
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)" "description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
}, },
"installButton": { "installButton": {
@ -64,11 +64,11 @@
"description": "Setting linter config with invalid JSON" "description": "Setting linter config with invalid JSON"
}, },
"popupHotkeysTooltip": { "popupHotkeysTooltip": {
"message": "點選以檢視可用的快鍵", "message": "點選以檢視可用的快鍵",
"description": "Tooltip displayed when hovering the right edge of the extension popup" "description": "Tooltip displayed when hovering the right edge of the extension popup"
}, },
"optionsBadgeNormal": { "optionsBadgeNormal": {
"message": "背景色", "message": "背景",
"description": "" "description": ""
}, },
"updateCheckHistory": { "updateCheckHistory": {
@ -92,7 +92,7 @@
"description": "Used in various places to show a history log of something" "description": "Used in various places to show a history log of something"
}, },
"shortcutsNote": { "shortcutsNote": {
"message": "定義鍵盤快捷鍵", "message": "自訂鍵盤快速鍵",
"description": "" "description": ""
}, },
"appliesDomainOption": { "appliesDomainOption": {
@ -112,7 +112,7 @@
"description": "Tooltip for the switch button in the color picker popup in the style editor." "description": "Tooltip for the switch button in the color picker popup in the style editor."
}, },
"styleRegexpInvalidExplanation": { "styleRegexpInvalidExplanation": {
"message": "部份 'regexp()' 則可能不再能被編譯。", "message": "部份 'regexp()' 則可能不再能被編譯。",
"description": "" "description": ""
}, },
"optionsIconDark": { "optionsIconDark": {
@ -140,7 +140,7 @@
"description": "Text after the number of styles added in the report shown after importing styles" "description": "Text after the number of styles added in the report shown after importing styles"
}, },
"styleFromMozillaFormatPrompt": { "styleFromMozillaFormatPrompt": {
"message": "貼Mozilla格式代碼", "message": "Mozilla 格式代碼",
"description": "Prompt in the dialog displayed after clicking 'Import from Mozilla format' button" "description": "Prompt in the dialog displayed after clicking 'Import from Mozilla format' button"
}, },
"dragDropMessage": { "dragDropMessage": {
@ -148,11 +148,11 @@
"description": "Drag'n'drop message" "description": "Drag'n'drop message"
}, },
"styleRegexpTestNote": { "styleRegexpTestNote": {
"message": "注意:使用單個 \\ 來在正規表式的輸入欄位中逃脫,其將會根據在 CSS 中的引用字串的規定,自動在樣式代碼中轉換為 \\\\。", "message": "注意:使用單個 \\ 來在正規表式的輸入欄位中逃脫,其將會根據在 CSS 中的引用字串的規定,自動在樣式代碼中轉換為 \\\\。",
"description": "RegExp test report: a note displayed at the bottom of the dialog" "description": "RegExp test report: a note displayed at the bottom of the dialog"
}, },
"helpAlt": { "helpAlt": {
"message": "幫助", "message": "說明",
"description": "Alternate text for help buttons" "description": "Alternate text for help buttons"
}, },
"confirmOK": { "confirmOK": {
@ -160,7 +160,7 @@
"description": "" "description": ""
}, },
"search": { "search": {
"message": "搜", "message": "搜",
"description": "Label before the search input field in the editor shown on Ctrl-F" "description": "Label before the search input field in the editor shown on Ctrl-F"
}, },
"genericEnabledLabel": { "genericEnabledLabel": {
@ -216,7 +216,7 @@
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format" "description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
}, },
"sectionAdd": { "sectionAdd": {
"message": "再加一個樣式段", "message": "再一個樣式段",
"description": "Label for the button to add a section" "description": "Label for the button to add a section"
}, },
"styleRegexpTestPartial": { "styleRegexpTestPartial": {
@ -224,7 +224,7 @@
"description": "RegExp test report: label for the partially matching expressions" "description": "RegExp test report: label for the partially matching expressions"
}, },
"styleSaveLabel": { "styleSaveLabel": {
"message": "存", "message": "存",
"description": "Label for save button for style editing" "description": "Label for save button for style editing"
}, },
"genericSavedMessage": { "genericSavedMessage": {
@ -252,7 +252,7 @@
"description": "" "description": ""
}, },
"cm_selectByTokens": { "cm_selectByTokens": {
"message": "雙擊選取 token", "message": "按兩下選取 token",
"description": "Label for the checkbox in the editor." "description": "Label for the checkbox in the editor."
}, },
"confirmStop": { "confirmStop": {
@ -268,11 +268,11 @@
"description": "Subheading for options section on manage page." "description": "Subheading for options section on manage page."
}, },
"appliesAdd": { "appliesAdd": {
"message": "添加", "message": "新增",
"description": "Label for the button to add an 'applies' entry" "description": "Label for the button to add an 'applies' entry"
}, },
"appliesRegexpOption": { "appliesRegexpOption": {
"message": "匹配正則表示式的網址", "message": "比對正規表示式的網址",
"description": "Option to make the style apply to the entered string as a regular expression" "description": "Option to make the style apply to the entered string as a regular expression"
}, },
"optionsAdvancedExposeIframesNote": { "optionsAdvancedExposeIframesNote": {
@ -293,7 +293,7 @@
} }
}, },
"optionsBadgeDisabled": { "optionsBadgeDisabled": {
"message": "停用時的背景色", "message": "停用時的背景",
"description": "" "description": ""
}, },
"optionsCheck": { "optionsCheck": {
@ -331,7 +331,7 @@
"description": "The error message to show when stylus failed to parse usercss" "description": "The error message to show when stylus failed to parse usercss"
}, },
"searchStyles": { "searchStyles": {
"message": "搜內容", "message": "搜內容",
"description": "Label for the search filter textbox on the Manage styles page" "description": "Label for the search filter textbox on the Manage styles page"
}, },
"optionsUpdateImportNote": { "optionsUpdateImportNote": {
@ -363,7 +363,7 @@
"description": "Title on the sort select to indicate it is used for sorting entries" "description": "Title on the sort select to indicate it is used for sorting entries"
}, },
"disableStyleLabel": { "disableStyleLabel": {
"message": "用", "message": "用",
"description": "Label for the button to disable a style" "description": "Label for the button to disable a style"
}, },
"prefShowBadge": { "prefShowBadge": {
@ -399,11 +399,11 @@
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving" "description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
}, },
"importLabel": { "importLabel": {
"message": "入", "message": "入",
"description": "Label for the button to import a style ('edit' page) or all styles ('manage' page)" "description": "Label for the button to import a style ('edit' page) or all styles ('manage' page)"
}, },
"shortcuts": { "shortcuts": {
"message": "快鍵", "message": "快鍵",
"description": "Go to shortcut configuration" "description": "Go to shortcut configuration"
}, },
"updateCheckFailServerUnreachable": { "updateCheckFailServerUnreachable": {
@ -514,7 +514,7 @@
"description": "Style editor's 'highglight' drop-down list option: highlight the occurrences of the word/token under cursor even if nothing is selected" "description": "Style editor's 'highglight' drop-down list option: highlight the occurrences of the word/token under cursor even if nothing is selected"
}, },
"searchRegexp": { "searchRegexp": {
"message": "使用/re/句法正則表達式搜索", "message": "使用/re/語法正規表示式搜尋",
"description": "Label after the search input field in the editor shown on Ctrl-F" "description": "Label after the search input field in the editor shown on Ctrl-F"
}, },
"popupBordersTooltip": { "popupBordersTooltip": {
@ -542,7 +542,7 @@
"description": "Label for the checkbox to save current URL for update check" "description": "Label for the checkbox to save current URL for update check"
}, },
"cm_resizeGripHint": { "cm_resizeGripHint": {
"message": "雙擊以最大化/復原高度", "message": "按兩下以最大化/還原高度",
"description": "Tooltip for the resize grip in style editor" "description": "Tooltip for the resize grip in style editor"
}, },
"popupStylesFirst": { "popupStylesFirst": {
@ -554,7 +554,7 @@
"description": "Help text for sections" "description": "Help text for sections"
}, },
"noStylesForSite": { "noStylesForSite": {
"message": "前網站沒有安裝任何樣式。", "message": "前網站沒有安裝任何樣式。",
"description": "Text displayed when no styles are installed for the current site" "description": "Text displayed when no styles are installed for the current site"
}, },
"appliesDisplayTruncatedSuffix": { "appliesDisplayTruncatedSuffix": {
@ -574,7 +574,7 @@
"description": "Title of the popup with the style code in Mozilla format, shown after pressing the Export button on Edit style page" "description": "Title of the popup with the style code in Mozilla format, shown after pressing the Export button on Edit style page"
}, },
"cm_colorpicker": { "cm_colorpicker": {
"message": "用於 CSS 色彩的顏色挑選器", "message": "用於 CSS 色彩的色彩選擇器",
"description": "Label for the checkbox controlling colorpicker option for the style editor." "description": "Label for the checkbox controlling colorpicker option for the style editor."
}, },
"filteredStylesAllHidden": { "filteredStylesAllHidden": {
@ -586,7 +586,7 @@
"description": "Label for toolbar pop-up that precedes the links to write a new style" "description": "Label for toolbar pop-up that precedes the links to write a new style"
}, },
"replace": { "replace": {
"message": "替換", "message": "取代",
"description": "Label before the replace input field in the editor shown on Ctrl-H" "description": "Label before the replace input field in the editor shown on Ctrl-H"
}, },
"styleRegexpTestNone": { "styleRegexpTestNone": {
@ -646,6 +646,10 @@
"message": "檢查並安裝所有可用的更新", "message": "檢查並安裝所有可用的更新",
"description": "" "description": ""
}, },
"styleBeautifyPreserveNewlines": {
"message": "保留新行",
"description": "CSS-beautifier option"
},
"clickToUninstall": { "clickToUninstall": {
"message": "點選以解除安裝", "message": "點選以解除安裝",
"description": "Label for the overlay on a style thumbnail when installed via inline search in the popup" "description": "Label for the overlay on a style thumbnail when installed via inline search in the popup"
@ -679,7 +683,7 @@
"description": "Label for the drop-down list controlling the automatic highlighting of current word/selection occurrences in the style editor." "description": "Label for the drop-down list controlling the automatic highlighting of current word/selection occurrences in the style editor."
}, },
"styleRegexpPartialExplanation": { "styleRegexpPartialExplanation": {
"message": "這個樣式使用部份符合的正規表式,違反了 <a href='https://developer.mozilla.org/docs/Web/CSS/@document'>CSS4 @document 規範</a>,其需要完整的 URL 符合。授影響的 CSS 不會討用在頁面上。這個樣式由 Chrome Stylish 所建立,其在早期版本不正確地檢查 'regexp()' 規則(已知的臭蟲)。", "message": "這個樣式使用部份符合的正規表式,違反了 <a href='https://developer.mozilla.org/docs/Web/CSS/@document'>CSS4 @document 規範</a>,其需要完整的 URL 符合。授影響的 CSS 不會討用在頁面上。這個樣式由 Chrome Stylish 所建立,其在早期版本不正確地檢查 'regexp()' 規則(已知的臭蟲)。",
"description": "" "description": ""
}, },
"linterCSSLintSettings": { "linterCSSLintSettings": {
@ -719,7 +723,7 @@
"description": "Text that displays when an update check skipped updating the style to avoid losing possible local modifications" "description": "Text that displays when an update check skipped updating the style to avoid losing possible local modifications"
}, },
"undoGlobal": { "undoGlobal": {
"message": "撤銷(全局", "message": "還原(全域",
"description": "CSS-beautify global Undo button label" "description": "CSS-beautify global Undo button label"
}, },
"optionsCustomizeIcon": { "optionsCustomizeIcon": {
@ -847,11 +851,11 @@
"description": "Text after the number of styles updated entirely in the report shown after importing styles" "description": "Text after the number of styles updated entirely in the report shown after importing styles"
}, },
"cm_smartIndent": { "cm_smartIndent": {
"message": "使用智能縮進", "message": "使用智慧縮排",
"description": "Label for the checkbox controlling smart indentation option for the style editor." "description": "Label for the checkbox controlling smart indentation option for the style editor."
}, },
"styleRegexpTestButton": { "styleRegexpTestButton": {
"message": "正規表式測試", "message": "正規表式測試",
"description": "RegExp test button label in the editor shown when applies-to list has a regexp value" "description": "RegExp test button label in the editor shown when applies-to list has a regexp value"
}, },
"appliesHelp": { "appliesHelp": {
@ -863,7 +867,7 @@
"description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info" "description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info"
}, },
"searchStylesHelp": { "searchStylesHelp": {
"message": "</> 鍵聚焦於搜尋欄。\n純文字搜尋名字、程式碼、首頁 URL 與其套用到的頁面。少於三個字母的單字會被忽略。\n符合的 URL以 <url:> 為前綴來搜尋,例如:<url:https://github.com/openstyles/stylus>\n正規表達式包含斜線與旗標例如 </body.*?\\ba\\b/simguy>\n精確的單字:以雙引號包住要搜尋的文字,例如 <\".header ~ div\">", "message": "</> 鍵讓焦點置於搜尋欄。\n純文字搜尋名稱、程式碼、首頁 URL與其適用的網頁。少於 3 個字母的單字會被忽略。\n符合完整 URL 的樣式:使用前綴搜尋 <url:>,例如 <url:https://github.com/openstyles/stylus>\n正規表達式包含斜線與旗標例如 </body.*?\\ba\\b/simguy>\n精確字詞:用英文雙引號包裝查詢,例如 <\".header ~ div\">",
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page" "description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page"
}, },
"findStyles": { "findStyles": {
@ -900,7 +904,7 @@
"description": "Error displayed when the value of @select is invalid" "description": "Error displayed when the value of @select is invalid"
}, },
"styleMetaErrorColor": { "styleMetaErrorColor": {
"message": "$color$是無效的色", "message": "$color$是無效的",
"description": "Error displayed when the value of @var color is invalid", "description": "Error displayed when the value of @var color is invalid",
"placeholders": { "placeholders": {
"color": { "color": {
@ -949,7 +953,7 @@
"description": "Checkbox to show only styles that have updates after check-all-styles-for-updates was performed" "description": "Checkbox to show only styles that have updates after check-all-styles-for-updates was performed"
}, },
"addStyleTitle": { "addStyleTitle": {
"message": "添加樣式", "message": "新增樣式",
"description": "Title of the page for adding styles" "description": "Title of the page for adding styles"
}, },
"externalLink": { "externalLink": {
@ -1005,11 +1009,11 @@
"description": "" "description": ""
}, },
"helpKeyMapHotkey": { "helpKeyMapHotkey": {
"message": "按下鍵", "message": "按下快速鍵",
"description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short" "description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short"
}, },
"styleRegexpTestInvalid": { "styleRegexpTestInvalid": {
"message": "已跳過無效的正規表式", "message": "已跳過無效的正規表式",
"description": "RegExp test report: label for the invalid expressions" "description": "RegExp test report: label for the invalid expressions"
}, },
"dateUpdated": { "dateUpdated": {
@ -1025,7 +1029,7 @@
"description": "Text for label that shows the number of times a search result was installed during last week" "description": "Text for label that shows the number of times a search result was installed during last week"
}, },
"replaceAll": { "replaceAll": {
"message": "替換所有", "message": "取代所有",
"description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey" "description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey"
}, },
"importReportUnchanged": { "importReportUnchanged": {
@ -1065,7 +1069,7 @@
"description": "Go to Options UI" "description": "Go to Options UI"
}, },
"colorpickerTooltip": { "colorpickerTooltip": {
"message": "開啟顏色挑選器", "message": "開啟色彩選擇器",
"description": "Tooltip for the colored squares shown before CSS colors in the style editor." "description": "Tooltip for the colored squares shown before CSS colors in the style editor."
}, },
"optionsCustomizeBadge": { "optionsCustomizeBadge": {
@ -1139,7 +1143,7 @@
"description": "Label for the button to configure userstyles.org userstyle" "description": "Label for the button to configure userstyles.org userstyle"
}, },
"undo": { "undo": {
"message": "撤銷", "message": "還原",
"description": "Button label" "description": "Button label"
}, },
"usercssReplaceTemplateConfirmation": { "usercssReplaceTemplateConfirmation": {
@ -1159,7 +1163,7 @@
"description": "'Save' button in a confirm dialog" "description": "'Save' button in a confirm dialog"
}, },
"manageNewUI": { "manageNewUI": {
"message": "新的管理介面佈局", "message": "新的管理介面配置",
"description": "Label for the checkbox that toggles the new UI on manage page" "description": "Label for the checkbox that toggles the new UI on manage page"
}, },
"unreachableAMOHintOldFF": { "unreachableAMOHintOldFF": {
@ -1175,11 +1179,11 @@
"description": "Used in various lists/options to indicate that something is disabled" "description": "Used in various lists/options to indicate that something is disabled"
}, },
"cm_indentWithTabs": { "cm_indentWithTabs": {
"message": "用Tab鍵智能縮進", "message": "用 Tab 鍵智慧縮排",
"description": "Label for the checkbox controlling tabs with smart indentation option for the style editor." "description": "Label for the checkbox controlling tabs with smart indentation option for the style editor."
}, },
"replaceWith": { "replaceWith": {
"message": "替換為", "message": "取代為",
"description": "Label before the replace-with input field in the editor shown on Ctrl-H etc." "description": "Label before the replace-with input field in the editor shown on Ctrl-H etc."
}, },
"liveReloadError": { "liveReloadError": {

View File

@ -119,22 +119,15 @@ prefs.subscribe(['iconset'], () =>
})); }));
// ************************************************************************* // *************************************************************************
{ chrome.runtime.onInstalled.addListener(({reason}) => {
const onInstall = ({reason}) => { if (reason !== 'update') return;
chrome.runtime.onInstalled.removeListener(onInstall);
if (reason === 'update') {
// translations may change // translations may change
localStorage.L10N = JSON.stringify({ localStorage.L10N = JSON.stringify({
browserUIlanguage: chrome.i18n.getUILanguage(), browserUIlanguage: chrome.i18n.getUILanguage(),
}); });
// themes may change // themes may change
delete localStorage.codeMirrorThemes; delete localStorage.codeMirrorThemes;
} });
};
// bind for 60 seconds max and auto-unbind if it's a normal run
chrome.runtime.onInstalled.addListener(onInstall);
setTimeout(onInstall, 60e3, {reason: 'unbindme'});
}
// ************************************************************************* // *************************************************************************
// browser commands // browser commands

View File

@ -235,7 +235,7 @@
if (!Array.isArray(sections)) continue; if (!Array.isArray(sections)) continue;
applySections(id, sections.map(({code}) => code).join('\n')); applySections(id, sections.map(({code}) => code).join('\n'));
} }
docRootObserver.start({sort: true}); docRootObserver.firstStart();
} }
if (!isOwnPage && !docRewriteObserver && styleElements.size) { if (!isOwnPage && !docRewriteObserver && styleElements.size) {
@ -419,6 +419,7 @@
function initDocRootObserver() { function initDocRootObserver() {
let lastRestorationTime = 0; let lastRestorationTime = 0;
let restorationCounter = 0; let restorationCounter = 0;
let scheduledSort = false;
let observing = false; let observing = false;
let sorting = false; let sorting = false;
let observer; let observer;
@ -430,13 +431,16 @@
function init() { function init() {
observer = new MutationObserver(sortStyleElements); observer = new MutationObserver(sortStyleElements);
docRootObserver = {start, stop, evade, disconnect: stop}; docRootObserver = {firstStart, start, stop, evade, disconnect: stop};
setTimeout(sortStyleElements); setTimeout(sortStyleElements);
} }
function start({sort = false} = {}) { function firstStart() {
if (sort && sortStyleMap()) { if (sortStyleMap()) {
sortStyleElements(); sortStyleElements();
} }
start();
}
function start() {
if (!observing && ROOT && observer) { if (!observing && ROOT && observer) {
observer.observe(ROOT, {childList: true}); observer.observe(ROOT, {childList: true});
observing = true; observing = true;
@ -476,10 +480,12 @@
return true; return true;
} }
} }
function sortStyleElements() { function sortStyleElements({force} = {}) {
if (!observing) { if (!observing ||
!force && scheduledSort) {
return; return;
} }
scheduledSort = false;
let prevExpected = document.documentElement.lastElementChild; let prevExpected = document.documentElement.lastElementChild;
while (prevExpected && isSkippable(prevExpected, true)) { while (prevExpected && isSkippable(prevExpected, true)) {
prevExpected = prevExpected.previousElementSibling; prevExpected = prevExpected.previousElementSibling;
@ -487,6 +493,11 @@
if (!prevExpected) { if (!prevExpected) {
return; return;
} }
if (!CHROME && !force && window !== top) {
requestAnimationFrame(() => sortStyleElements({force: true}));
scheduledSort = true;
return;
}
for (const el of styleElements.values()) { for (const el of styleElements.values()) {
if (!isMovable(el)) { if (!isMovable(el)) {
continue; continue;

View File

@ -121,7 +121,7 @@
</template> </template>
<template data-id="section"> <template data-id="section">
<div> <div class="section">
<label i18n-text="sectionCode" class="code-label"></label> <label i18n-text="sectionCode" class="code-label"></label>
<br> <br>
<div class="applies-to"> <div class="applies-to">
@ -134,13 +134,23 @@
</div> </div>
<div class="edit-actions"> <div class="edit-actions">
<button class="remove-section" i18n-text="sectionRemove"></button> <button class="remove-section" i18n-text="sectionRemove"></button>
<button class="add-section" i18n-text="sectionAdd"></button> <button class="add-section" i18n-long-text="sectionAdd" i18n-short-text="genericAdd"></button>
<button class="clone-section" i18n-text="genericClone"></button>
<button class="move-section-up"></button>
<button class="move-section-down"></button>
<button class="beautify-section" i18n-text="styleBeautify"></button> <button class="beautify-section" i18n-text="styleBeautify"></button>
<button class="test-regexp" i18n-text="styleRegexpTestButton"></button> <button class="test-regexp" i18n-text="styleRegexpTestButton"></button>
</div> </div>
</div> </div>
</template> </template>
<!-- not using DIV to make our CSS work for #sections > div:only-of-type .remove-section -->
<template data-id="deletedSection">
<p class="deleted-section">
<button class="restore-section" i18n-text="sectionRestore"></button>
</p>
</template>
<template data-id="searchReplaceDialog"> <template data-id="searchReplaceDialog">
<div id="search-replace-dialog"> <div id="search-replace-dialog">
<div data-type="main"> <div data-type="main">

View File

@ -29,7 +29,7 @@ function createAppliesToLineWidget(cm) {
$create('label', t('appliesLabel')), $create('label', t('appliesLabel')),
$create('ul.applies-to-list'), $create('ul.applies-to-list'),
]), ]),
listItem: template.appliesTo, listItem: template.appliesTo.cloneNode(true),
appliesToEverything: appliesToEverything:
$create('li.applies-to-everything', t('appliesToEverything')), $create('li.applies-to-everything', t('appliesToEverything')),
}; };

View File

@ -16,45 +16,53 @@ function beautify(event) {
function doBeautify() { function doBeautify() {
const tabs = prefs.get('editor.indentWithTabs'); const tabs = prefs.get('editor.indentWithTabs');
const options = prefs.get('editor.beautify'); const options = prefs.get('editor.beautify');
for (const k of Object.keys(prefs.defaults['editor.beautify'])) {
if (!(k in options)) options[k] = prefs.defaults['editor.beautify'][k];
}
options.indent_size = tabs ? 1 : prefs.get('editor.tabSize'); options.indent_size = tabs ? 1 : prefs.get('editor.tabSize');
options.indent_char = tabs ? '\t' : ' '; options.indent_char = tabs ? '\t' : ' ';
const section = getSectionForChild(event.target); const section = getSectionForChild(event.target);
const scope = section ? [section.CodeMirror] : editors; const scope = section ? [section.CodeMirror] : editors;
showHelp(t('styleBeautify'), '<div class="beautify-options">' + showHelp(t('styleBeautify'),
optionHtml('.selector1,', 'selector_separator_newline') + $create([
optionHtml('.selector2', 'newline_before_open_brace') + $create('.beautify-options', [
optionHtml('{', 'newline_after_open_brace') + $createOption('.selector1,', 'selector_separator_newline'),
optionHtml('border: none;', 'newline_between_properties', true) + $createOption('.selector2', 'newline_before_open_brace'),
optionHtml('display: block;', 'newline_before_close_brace', true) + $createOption('{', 'newline_after_open_brace'),
optionHtml('}', 'newline_between_rules') + $createOption('border: none;', 'newline_between_properties', true),
`<label style="display: block; clear: both;"> $createOption('display: block;', 'newline_before_close_brace', true),
<input data-option="indent_conditional" type="checkbox" $createOption('}', 'newline_between_rules'),
${options.indent_conditional !== false ? 'checked' : ''}> $createLabeledCheckbox('preserve_newlines', 'styleBeautifyPreserveNewlines'),
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>` + $createLabeledCheckbox('indent_conditional', 'styleBeautifyIndentConditional'),
t('styleBeautifyIndentConditional') + '</label>' + ]),
'</div>' + $create('.buttons', [
'<div><button role="undo"></button></div>'); $create('button', {
attributes: {role: 'close'},
$('#help-popup').className = 'wide'; onclick: showHelp.close,
}, t('confirmClose')),
const undoButton = $('#help-popup button[role="undo"]'); $create('button', {
undoButton.textContent = t(scope.length === 1 ? 'undo' : 'undoGlobal'); attributes: {role: 'undo'},
undoButton.addEventListener('click', () => { onclick() {
let undoable = false; let undoable = false;
scope.forEach(cm => { for (const cm of scope) {
if (cm.beautifyChange && cm.beautifyChange[cm.changeGeneration()]) { const data = cm.beautifyChange;
delete cm.beautifyChange[cm.changeGeneration()]; if (!data || !data[cm.changeGeneration()]) continue;
delete data[cm.changeGeneration()];
const {scrollX, scrollY} = window; const {scrollX, scrollY} = window;
cm.undo(); cm.undo();
cm.scrollIntoView(cm.getCursor()); cm.scrollIntoView(cm.getCursor());
window.scrollTo(scrollX, scrollY); window.scrollTo(scrollX, scrollY);
undoable |= cm.beautifyChange[cm.changeGeneration()]; undoable |= data[cm.changeGeneration()];
} }
}); this.disabled = !undoable;
undoButton.disabled = !undoable; },
}); }, t(scope.length === 1 ? 'undo' : 'undoGlobal')),
]),
]));
$('#help-popup').className = 'wide';
scope.forEach(cm => { scope.forEach(cm => {
setTimeout(() => { setTimeout(() => {
@ -77,9 +85,9 @@ function beautify(event) {
cm.setSelections(selections); cm.setSelections(selections);
window.scrollTo(scrollX, scrollY); window.scrollTo(scrollX, scrollY);
cm.beautifyChange[cm.changeGeneration()] = true; cm.beautifyChange[cm.changeGeneration()] = true;
undoButton.disabled = false; $('#help-popup button[role="close"]').disabled = false;
} }
}, 0); });
}); });
$('.beautify-options').onchange = ({target}) => { $('.beautify-options').onchange = ({target}) => {
@ -91,21 +99,41 @@ function beautify(event) {
doBeautify(); doBeautify();
}; };
function optionHtml(label, optionName, indent) { function $createOption(label, optionName, indent) {
const value = options[optionName]; const value = options[optionName];
return '<div newline="' + value.toString() + '">' + return (
'<span' + (indent ? ' indent' : '') + '>' + label + '</span>' + $create('div', {attributes: {newline: value}}, [
'<div class="select-resizer">' + $create('span', indent ? {attributes: {indent: ''}} : {}, label),
'<select data-option="' + optionName + '">' + $create('div.select-resizer', [
'<option' + (value ? '' : ' selected') + '>&nbsp;</option>' + $create('select', {dataset: {option: optionName}}, [
'<option' + (value ? ' selected' : '') + '>\\n</option>' + $create('option', {selected: !value}, '\xA0'),
'</select>' + $create('option', {selected: value}, '\\n'),
'<svg class="svg-icon select-arrow" viewBox="0 0 1792 1792">' + ]),
'<path fill-rule="evenodd" d="M1408 704q0 26-19 45l-448 448q-19 19-45 ' + $create('SVG:svg.svg-icon.select-arrow', {viewBox: '0 0 1792 1792'}, [
'19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>' + $create('SVG:path', {
'</svg>' + 'fill-rule': 'evenodd',
'</div>' + 'd': 'M1408 704q0 26-19 45l-448 448q-19 19-45 ' +
'</div>'; '19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z'
}),
]),
]),
])
);
}
function $createLabeledCheckbox(optionName, i18nKey) {
return (
$create('label', {style: 'display: block; clear: both;'}, [
$create('input', {
type: 'checkbox',
dataset: {option: optionName},
checked: options[optionName] !== false
}),
$create('SVG:svg.svg-icon.checked',
$create('SVG:use', {'xlink:href': '#svg-icon-checked'})),
t(i18nKey),
])
);
} }
} }
} }

View File

@ -482,6 +482,7 @@ onDOMscriptReady('/codemirror.js').then(() => {
if (!chrome.runtime.getPackageDirectoryEntry) { if (!chrome.runtime.getPackageDirectoryEntry) {
const themes = [ const themes = [
chrome.i18n.getMessage('defaultTheme'), chrome.i18n.getMessage('defaultTheme'),
/* populate-theme-start */
'3024-day', '3024-day',
'3024-night', '3024-night',
'abcdef', 'abcdef',
@ -493,17 +494,21 @@ onDOMscriptReady('/codemirror.js').then(() => {
'blackboard', 'blackboard',
'cobalt', 'cobalt',
'colorforth', 'colorforth',
'darcula',
'dracula', 'dracula',
'duotone-dark', 'duotone-dark',
'duotone-light', 'duotone-light',
'eclipse', 'eclipse',
'elegant', 'elegant',
'erlang-dark', 'erlang-dark',
'gruvbox-dark',
'hopscotch', 'hopscotch',
'icecoder', 'icecoder',
'idea',
'isotope', 'isotope',
'lesser-dark', 'lesser-dark',
'liquibyte', 'liquibyte',
'lucario',
'material', 'material',
'mbo', 'mbo',
'mdn-like', 'mdn-like',
@ -522,6 +527,7 @@ onDOMscriptReady('/codemirror.js').then(() => {
'seti', 'seti',
'shadowfox', 'shadowfox',
'solarized', 'solarized',
'ssms',
'the-matrix', 'the-matrix',
'tomorrow-night-bright', 'tomorrow-night-bright',
'tomorrow-night-eighties', 'tomorrow-night-eighties',
@ -532,6 +538,7 @@ onDOMscriptReady('/codemirror.js').then(() => {
'xq-light', 'xq-light',
'yeti', 'yeti',
'zenburn', 'zenburn',
/* populate-theme-end */
]; ];
localStorage.codeMirrorThemes = themes.join(' '); localStorage.codeMirrorThemes = themes.join(' ');
return Promise.resolve(themes); return Promise.resolve(themes);
@ -611,14 +618,56 @@ onDOMscriptReady('/codemirror.js').then(() => {
const me = this instanceof Node ? this : $('#editor.livePreview'); const me = this instanceof Node ? this : $('#editor.livePreview');
const previewing = me.checked; const previewing = me.checked;
editors.forEach(cm => cm[previewing ? 'on' : 'off']('changes', updatePreview)); editors.forEach(cm => cm[previewing ? 'on' : 'off']('changes', updatePreview));
const addRemove = previewing ? 'addEventListener' : 'removeEventListener'; const addRemove = EventTarget.prototype[previewing ? 'addEventListener' : 'removeEventListener'];
$('#enabled')[addRemove]('change', updatePreview); addRemove.call($('#enabled'), 'change', updatePreview);
$('#sections')[addRemove]('change', updatePreview); if (!editor) {
for (const el of $$('#sections .applies-to')) {
addRemove.call(el, 'input', updatePreview);
}
toggleLivePreviewSectionsObserver(previewing);
}
if (!previewing || document.body.classList.contains('dirty')) { if (!previewing || document.body.classList.contains('dirty')) {
updatePreview(null, previewing); updatePreview(null, previewing);
} }
} }
/**
* Observes newly added section elements, and sets these event listeners:
* 1. 'changes' on CodeMirror inside
* 2. 'input' on .applies-to inside
* The goal is to avoid listening to 'input' on the entire #sections tree,
* which would trigger updatePreview() twice on any keystroke -
* both for the synthetic event from CodeMirror and the original event.
* Side effects:
* two expando properties on #sections
* 1. __livePreviewObserver
* 2. __livePreviewObserverEnabled
* @param {Boolean} enable
*/
function toggleLivePreviewSectionsObserver(enable) {
const sections = $('#sections');
const observing = sections.__livePreviewObserverEnabled;
let mo = sections.__livePreviewObserver;
if (enable && !mo) {
sections.__livePreviewObserver = mo = new MutationObserver(mutations => {
for (const {addedNodes} of mutations) {
for (const node of addedNodes) {
const el = node.children && $('.applies-to', node);
if (el) el.addEventListener('input', updatePreview);
if (node.CodeMirror) node.CodeMirror.on('changes', updatePreview);
}
}
});
}
if (enable && !observing) {
mo.observe(sections, {childList: true});
sections.__livePreviewObserverEnabled = true;
} else if (!enable && observing) {
mo.disconnect();
sections.__livePreviewObserverEnabled = false;
}
}
function updatePreview(data, previewing) { function updatePreview(data, previewing) {
if (previewing !== true && previewing !== false) { if (previewing !== true && previewing !== false) {
if (data instanceof Event && !data.target.matches('.style-contributor')) return; if (data instanceof Event && !data.target.matches('.style-contributor')) return;
@ -637,7 +686,8 @@ onDOMscriptReady('/codemirror.js').then(() => {
}).then(() => { }).then(() => {
errors.classList.add('hidden'); errors.classList.add('hidden');
}).catch(err => { }).catch(err => {
if (err && editor && !Number.isNaN(err.index)) { if (Array.isArray(err)) err = err.join('\n');
if (err && editor && !isNaN(err.index)) {
const pos = editors[0].posFromIndex(err.index); const pos = editors[0].posFromIndex(err.index);
err = `${pos.line}:${pos.ch} ${err}`; err = `${pos.line}:${pos.ch} ${err}`;
} }

View File

@ -264,16 +264,22 @@ input:invalid {
margin-top: 4em; margin-top: 4em;
} }
/************ content ***********/ /************ content ***********/
#sections > div { #sections > * {
margin: 0.7rem; margin: 0.7rem;
padding: 1rem 1rem .3rem; padding: 1rem 1rem .3rem;
} }
#sections > div:first-of-type { #sections > *:first-child {
padding: 0 1rem .3rem; padding: 0 1rem .3rem;
} }
#sections > div:not(:first-of-type) { #sections > *:not(:first-child) {
border-top: 2px solid hsl(0, 0%, 80%); border-top: 2px solid hsl(0, 0%, 80%);
} }
.add-section:after {
content: attr(short-text);
}
#sections > div:only-of-type .add-section:after {
content: attr(long-text);
}
#sections > div:only-of-type .remove-section { #sections > div:only-of-type .remove-section {
display: none; display: none;
} }
@ -291,17 +297,35 @@ input:invalid {
#sections { #sections {
counter-reset: codebox; counter-reset: codebox;
} }
#sections > div > label { #sections > .section > label {
animation: 2s highlight; animation: 2s highlight;
animation-play-state: paused; animation-play-state: paused;
animation-direction: reverse; animation-direction: reverse;
animation-fill-mode: both; animation-fill-mode: both;
} }
#sections > div > label::after { #sections > .section > label::after {
counter-increment: codebox; counter-increment: codebox;
content: counter(codebox); content: counter(codebox);
margin-left: 0.25rem; margin-left: 0.25rem;
} }
.section:only-of-type .move-section-up,
.section:only-of-type .move-section-down {
display: none;
}
.move-section-up:after {
content: "";
display: block;
border-style: solid;
border-width: 0 .3em .5em .3em;
border-color: transparent transparent currentColor transparent;
}
.move-section-down:after {
content: "";
display: block;
border-style: solid;
border-width: .5em .3em 0 .3em;
border-color: currentColor transparent transparent transparent;
}
/* code */ /* code */
.code { .code {
height: 10rem; height: 10rem;
@ -563,15 +587,6 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
right: 4px; right: 4px;
top: .5em; top: .5em;
} }
#help-popup .saved-message {
display: none;
color: #090;
margin-left: 10px;
font-weight: bold;
}
#help-popup .saved-message.show {
display: inline-block;
}
.keymap-list { .keymap-list {
font-size: 12px; font-size: 12px;
@ -590,13 +605,19 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
padding-right: 0.5rem; padding-right: 0.5rem;
} }
#help-popup .buttons {
text-align: center;
}
.non-windows #help-popup .buttons {
direction: rtl;
text-align: right;
}
#help-popup button[name^="import"] { #help-popup button[name^="import"] {
line-height: 1.5rem; line-height: 1.5rem;
padding: 0 0.5rem; padding: 0 0.5rem;
margin: 0.5rem 0 0 0.5rem; margin: 0.5rem 0 0 0.5rem;
pointer-events: none; pointer-events: none;
opacity: 0.5; opacity: 0.5;
float: right;
} }
#help-popup.ready button[name^="import"] { #help-popup.ready button[name^="import"] {
pointer-events: all; pointer-events: all;
@ -732,7 +753,7 @@ html:not(.usercss) .usercss-only,
} }
#sections .single-editor, #sections .single-editor,
#sections > div.single-editor:first-of-type { #sections > .single-editor:first-child {
margin: 0; margin: 0;
padding: 0; padding: 0;
display: flex; display: flex;
@ -911,11 +932,11 @@ html:not(.usercss) .usercss-only,
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
} }
#sections > div { #sections > * {
margin: 0 .5rem .5rem; margin: 0 .5rem .5rem;
padding: .5rem 0 0; padding: .5rem 0 0;
} }
#sections > div:first-of-type { #sections > *:first-child {
margin: .5rem; margin: .5rem;
padding: 0; padding: 0;
} }

View File

@ -7,6 +7,7 @@ global setupCodeMirror
global beautify global beautify
global initWithSectionStyle addSections removeSection getSectionsHashes global initWithSectionStyle addSections removeSection getSectionsHashes
global sectionsToMozFormat global sectionsToMozFormat
global moveFocus
*/ */
'use strict'; 'use strict';
@ -24,7 +25,8 @@ const CssToProperty = {'url': 'urls', 'url-prefix': 'urlPrefixes', 'domain': 'do
let editor; let editor;
window.onbeforeunload = beforeUnload;
document.addEventListener('visibilitychange', beforeUnload);
chrome.runtime.onMessage.addListener(onRuntimeMessage); chrome.runtime.onMessage.addListener(onRuntimeMessage);
preinit(); preinit();
@ -175,7 +177,8 @@ function onRuntimeMessage(request) {
break; break;
case 'styleDeleted': case 'styleDeleted':
if (styleId === request.id || editor && editor.getStyle().id === request.id) { if (styleId === request.id || editor && editor.getStyle().id === request.id) {
window.onbeforeunload = () => {}; document.removeEventListener('visibilitychange', beforeUnload);
window.onbeforeunload = null;
closeCurrentTab(); closeCurrentTab();
break; break;
} }
@ -191,24 +194,27 @@ function onRuntimeMessage(request) {
} }
} }
/**
* Invoked for 'visibilitychange' event by default.
* Invoked for 'beforeunload' event when the style is modified and unsaved.
* See https://developers.google.com/web/updates/2018/07/page-lifecycle-api#legacy-lifecycle-apis-to-avoid
* > Never add a beforeunload listener unconditionally or use it as an end-of-session signal.
* > Only add it when a user has unsaved work, and remove it as soon as that work has been saved.
*/
function beforeUnload() { function beforeUnload() {
if (saveSizeOnClose) { if (saveSizeOnClose) rememberWindowSize();
rememberWindowSize(); const activeElement = document.activeElement;
} if (activeElement) {
document.activeElement.blur(); // blurring triggers 'change' or 'input' event if needed
if (isClean()) { activeElement.blur();
return; // refocus if unloading was canceled
setTimeout(() => activeElement.focus());
} }
const isDirty = editor ? editor.isDirty() : !isCleanGlobal();
if (isDirty) {
updateLintReportIfEnabled(null, 0); updateLintReportIfEnabled(null, 0);
// neither confirm() nor custom messages work in modern browsers but just in case // neither confirm() nor custom messages work in modern browsers but just in case
return t('styleChangesNotSaved'); return t('styleChangesNotSaved');
function isClean() {
if (editor) {
return !editor.isDirty();
} else {
return isCleanGlobal();
}
} }
} }
@ -331,7 +337,7 @@ function isCleanGlobal() {
function setCleanGlobal() { function setCleanGlobal() {
setCleanItem($('#sections'), true); setCleanItem($('#sections'), true);
$$('#header, #sections > div').forEach(setCleanSection); $$('#header, #sections > .section').forEach(setCleanSection);
// forget the dirty applies-to ids from a deleted section after the style was saved // forget the dirty applies-to ids from a deleted section after the style was saved
dirty = {}; dirty = {};
} }
@ -405,6 +411,7 @@ function updateTitle() {
const clean = isCleanGlobal(); const clean = isCleanGlobal();
const title = styleId === null ? t('addStyleTitle') : t('editStyleTitle', [name]); const title = styleId === null ? t('addStyleTitle') : t('editStyleTitle', [name]);
document.title = clean ? title : DIRTY_TITLE.replace('$', title); document.title = clean ? title : DIRTY_TITLE.replace('$', title);
window.onbeforeunload = clean ? null : beforeUnload;
$('#save-button').disabled = clean; $('#save-button').disabled = clean;
} }
@ -426,19 +433,19 @@ function toMozillaFormat() {
function fromMozillaFormat() { function fromMozillaFormat() {
const popup = showCodeMirrorPopup(t('styleFromMozillaFormatPrompt'), const popup = showCodeMirrorPopup(t('styleFromMozillaFormatPrompt'),
$create([ $create('.buttons', [
$create('button', {
name: 'import-append',
textContent: t('importAppendLabel'),
title: 'Ctrl-Enter:\n' + t('importAppendTooltip'),
onclick: doImport,
}),
$create('button', { $create('button', {
name: 'import-replace', name: 'import-replace',
textContent: t('importReplaceLabel'), textContent: t('importReplaceLabel'),
title: 'Ctrl-Shift-Enter:\n' + t('importReplaceTooltip'), title: 'Ctrl-Shift-Enter:\n' + t('importReplaceTooltip'),
onclick: () => doImport({replaceOldStyle: true}), onclick: () => doImport({replaceOldStyle: true}),
}), }),
$create('button', {
name: 'import-append',
textContent: t('importAppendLabel'),
title: 'Ctrl-Enter:\n' + t('importAppendTooltip'),
onclick: doImport,
}),
])); ]));
const contents = $('.contents', popup); const contents = $('.contents', popup);
contents.insertBefore(popup.codebox.display.wrapper, contents.firstElementChild); contents.insertBefore(popup.codebox.display.wrapper, contents.firstElementChild);
@ -596,7 +603,7 @@ function showCodeMirrorPopup(title, html, options) {
let cm = popup.codebox = CodeMirror($('.contents', popup), Object.assign({ let cm = popup.codebox = CodeMirror($('.contents', popup), Object.assign({
mode: 'css', mode: 'css',
lineNumbers: true, lineNumbers: true,
lineWrapping: true, lineWrapping: prefs.get('editor.lineWrapping'),
foldGutter: true, foldGutter: true,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'], gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
matchBrackets: true, matchBrackets: true,
@ -606,16 +613,29 @@ function showCodeMirrorPopup(title, html, options) {
keyMap: prefs.get('editor.keyMap') keyMap: prefs.get('editor.keyMap')
}, options)); }, options));
cm.focus(); cm.focus();
const rerouteOn = () => cm.rerouteHotkeys(false); cm.rerouteHotkeys(false);
const rerouteOff = () => cm.rerouteHotkeys(true);
cm.on('focus', rerouteOn); document.documentElement.style.pointerEvents = 'none';
cm.on('blur', rerouteOff); popup.style.pointerEvents = 'auto';
const onKeyDown = event => {
if (event.which === 9 && !event.ctrlKey && !event.altKey && !event.metaKey) {
const search = $('#search-replace-dialog');
const area = search && search.contains(document.activeElement) ? search : popup;
moveFocus(area, event.shiftKey ? -1 : 1);
event.preventDefault();
}
};
window.addEventListener('keydown', onKeyDown, true);
window.addEventListener('closeHelp', function _() { window.addEventListener('closeHelp', function _() {
window.removeEventListener('closeHelp', _); window.removeEventListener('closeHelp', _);
cm.off('focus', rerouteOn); window.removeEventListener('keydown', onKeyDown, true);
cm.off('blur', rerouteOff); document.documentElement.style.removeProperty('pointer-events');
cm.rerouteHotkeys(true);
cm = popup.codebox = null; cm = popup.codebox = null;
}); });
return popup; return popup;
} }

View File

@ -565,6 +565,7 @@ onDOMready().then(() => {
Object.assign(dialog, DIALOG_PROPS.dialog); Object.assign(dialog, DIALOG_PROPS.dialog);
dialog.addEventListener('focusout', EVENTS.onfocusout); dialog.addEventListener('focusout', EVENTS.onfocusout);
dialog.dataset.type = type; dialog.dataset.type = type;
dialog.style.pointerEvents = 'auto';
const content = $('[data-type="content"]', dialog); const content = $('[data-type="content"]', dialog);
content.parentNode.replaceChild(template[type].cloneNode(true), content); content.parentNode.replaceChild(template[type].cloneNode(true), content);

View File

@ -5,7 +5,7 @@
CodeMirror.registerHelper('lint', 'csslint', invokeHelper); CodeMirror.registerHelper('lint', 'csslint', invokeHelper);
CodeMirror.registerHelper('lint', 'stylelint', invokeHelper); CodeMirror.registerHelper('lint', 'stylelint', invokeHelper);
const cookResults = { const COOKS = {
csslint: results => csslint: results =>
results.map(({line, col: ch, message, rule, type: severity}) => line && { results.map(({line, col: ch, message, rule, type: severity}) => line && {
message, message,
@ -15,9 +15,9 @@
severity, severity,
}).filter(Boolean), }).filter(Boolean),
stylelint: ({results}) => stylelint({results}, cm) {
!results[0] && [] || if (!results[0]) return [];
results[0].warnings.map(({line, column: ch, text, severity}) => ({ const output = results[0].warnings.map(({line, column: ch, text, severity}) => ({
from: {line: line - 1, ch: ch - 1}, from: {line: line - 1, ch: ch - 1},
to: {line: line - 1, ch}, to: {line: line - 1, ch},
message: text message: text
@ -26,12 +26,18 @@
.replace(/\s*\([^(]+\)$/, ''), // strip the rule, .replace(/\s*\([^(]+\)$/, ''), // strip the rule,
rule: text.replace(/^.*?\s*\(([^(]+)\)$/, '$1'), rule: text.replace(/^.*?\s*\(([^(]+)\)$/, '$1'),
severity, severity,
})), }));
return cm.doc.mode.name !== 'stylus' ?
output :
output.filter(({message}) =>
!message.includes('"@css"') || !message.includes('(at-rule-no-unknown)'));
},
}; };
function invokeHelper(code) { function invokeHelper(code, options, cm) {
const config = linterConfig.getCurrent(); const config = linterConfig.getCurrent();
const cook = COOKS[linterConfig.getName()];
return linterConfig.invokeWorker({code, config}) return linterConfig.invokeWorker({code, config})
.then(cookResults[linterConfig.getName()]); .then(data => cook(data, cm));
} }
})(); })();

View File

@ -1,6 +1,7 @@
/* global CodeMirror messageBox */ /* global CodeMirror messageBox */
/* global editors makeSectionVisible showCodeMirrorPopup showHelp */ /* global editors makeSectionVisible showCodeMirrorPopup showHelp */
/* global loadScript require CSSLint stylelint */ /* global loadScript require CSSLint stylelint */
/* global clipString */
'use strict'; 'use strict';
onDOMready().then(loadLinterAssets); onDOMready().then(loadLinterAssets);
@ -150,18 +151,6 @@ var linterConfig = {
setupLinterPopup(linterConfig.stringify()); setupLinterPopup(linterConfig.stringify());
}, },
showSavedMessage() {
$('#help-popup .saved-message').classList.add('show');
clearTimeout($('#help-popup .contents').timer);
$('#help-popup .contents').timer = setTimeout(() => {
// popup may be closed at this point
const msg = $('#help-popup .saved-message');
if (msg) {
msg.classList.remove('show');
}
}, 2000);
},
init() { init() {
if (!this.init.pending) this.init.pending = this.loadAll(); if (!this.init.pending) this.init.pending = this.loadAll();
return this.init.pending; return this.init.pending;
@ -300,10 +289,6 @@ function updateLintReportInternal(scope, {postponeNewIssues} = {}) {
result.fixedSome |= lintState.reportDisplayed && oldMarkers.size; result.fixedSome |= lintState.reportDisplayed && oldMarkers.size;
return result; return result;
} }
function clipString(str, limit) {
return str.length <= limit ? str : str.substr(0, limit) + '...';
}
} }
function renderLintReport(someBlockChanged) { function renderLintReport(someBlockChanged) {
@ -448,10 +433,11 @@ function setupLinterPopup(config) {
t('linterRulesLink')), t('linterRulesLink')),
linter === 'csslint' ? ' ' + t('linterCSSLintSettings') : '', linter === 'csslint' ? ' ' + t('linterCSSLintSettings') : '',
]), ]),
$create('.buttons', [
$create('button.save', {onclick: save, title: 'Ctrl-Enter'}, t('styleSaveLabel')), $create('button.save', {onclick: save, title: 'Ctrl-Enter'}, t('styleSaveLabel')),
$create('button.cancel', {onclick: cancel}, t('confirmClose')), $create('button.cancel', {onclick: cancel}, t('confirmClose')),
$create('button.reset', {onclick: reset, title: t('linterResetMessage')}, t('genericResetLabel')), $create('button.reset', {onclick: reset, title: t('linterResetMessage')}, t('genericResetLabel')),
$create('span.saved-message', t('genericSavedMessage')), ]),
]); ]);
} }
@ -475,7 +461,6 @@ function setupLinterPopup(config) {
} }
linterConfig.setLinter(linter); linterConfig.setLinter(linter);
linterConfig.save(json); linterConfig.save(json);
linterConfig.showSavedMessage();
cm.markClean(); cm.markClean();
cm.focus(); cm.focus();
updateButtonState(); updateButtonState();

View File

@ -5,6 +5,7 @@ global onChange indicateCodeChange initHooks setCleanGlobal
global fromMozillaFormat maximizeCodeHeight toggleContextMenuDelete global fromMozillaFormat maximizeCodeHeight toggleContextMenuDelete
global setCleanItem updateTitle updateLintReportIfEnabled renderLintReport global setCleanItem updateTitle updateLintReportIfEnabled renderLintReport
global showAppliesToHelp beautify regExpTester setGlobalProgress setCleanSection global showAppliesToHelp beautify regExpTester setGlobalProgress setCleanSection
global clipString
*/ */
'use strict'; 'use strict';
@ -14,7 +15,7 @@ function initWithSectionStyle(style, codeIsUpdated) {
$('#url').href = style.url || ''; $('#url').href = style.url || '';
if (codeIsUpdated !== false) { if (codeIsUpdated !== false) {
editors.length = 0; editors.length = 0;
getSections().forEach(div => div.remove()); $('#sections').textContent = '';
addSections(style.sections.length ? style.sections : [{code: ''}]); addSections(style.sections.length ? style.sections : [{code: ''}]);
initHooks(); initHooks();
} }
@ -76,9 +77,12 @@ function addSections(sections, onAdded = () => {}) {
function addSection(event, section) { function addSection(event, section) {
const div = template.section.cloneNode(true); const div = template.section.cloneNode(true);
$('.applies-to-help', div).addEventListener('click', showAppliesToHelp, false); $('.applies-to-help', div).addEventListener('click', showAppliesToHelp);
$('.remove-section', div).addEventListener('click', removeSection, false); $('.remove-section', div).addEventListener('click', removeSection);
$('.add-section', div).addEventListener('click', addSection, false); $('.add-section', div).addEventListener('click', addSection);
$('.clone-section', div).addEventListener('click', cloneSection);
$('.move-section-up', div).addEventListener('click', moveSection);
$('.move-section-down', div).addEventListener('click', moveSection);
$('.beautify-section', div).addEventListener('click', beautify); $('.beautify-section', div).addEventListener('click', beautify);
const code = (section || {}).code || ''; const code = (section || {}).code || '';
@ -97,7 +101,7 @@ function addSection(event, section) {
} }
} }
if (!appliesToAdded) { if (!appliesToAdded) {
addAppliesTo(appliesTo); addAppliesTo(appliesTo, event && 'url-prefix', '');
} }
appliesTo.addEventListener('change', onChange); appliesTo.addEventListener('change', onChange);
@ -134,8 +138,11 @@ function addSection(event, section) {
const sections = $('#sections'); const sections = $('#sections');
let cm; let cm;
if (event) { if (event) {
const clickedSection = getSectionForChild(event.target); let clickedSection = event && getSectionForChild(event.target, {includeDeleted: true});
sections.insertBefore(div, clickedSection.nextElementSibling); clickedSection.insertAdjacentElement('afterend', div);
while (clickedSection && !clickedSection.matches('.section')) {
clickedSection = clickedSection.previousElementSibling;
}
const newIndex = getSections().indexOf(clickedSection) + 1; const newIndex = getSections().indexOf(clickedSection) + 1;
cm = setupCodeMirror(div, code, newIndex); cm = setupCodeMirror(div, code, newIndex);
makeSectionVisible(cm); makeSectionVisible(cm);
@ -192,7 +199,31 @@ function addAppliesTo(list, type, value) {
if (toFocus) toFocus.focus(); if (toFocus) toFocus.focus();
} }
function setupCodeMirror(sectionDiv, code, index) { function cloneSection(event) {
const section = getSectionForChild(event.target);
addSection(event, getSectionsHashes([section]).pop());
setCleanItem($('#sections'), false);
updateTitle();
}
function moveSection(event) {
const section = getSectionForChild(event.target);
const dir = event.target.closest('.move-section-up') ? -1 : 1;
const cm = section.CodeMirror;
const index = editors.indexOf(cm);
const newIndex = (index + dir + editors.length) % editors.length;
const currentNextEl = section.nextElementSibling;
const newSection = editors[newIndex].getSection();
newSection.insertAdjacentElement('afterend', section);
section.parentNode.insertBefore(newSection, currentNextEl || null);
cm.focus();
editors[index] = editors[newIndex];
editors[newIndex] = cm;
setCleanItem($('#sections'), false);
updateTitle();
}
function setupCodeMirror(sectionDiv, code, index = editors.length) {
const cm = CodeMirror(wrapper => { const cm = CodeMirror(wrapper => {
$('.code-label', sectionDiv).insertAdjacentElement('afterend', wrapper); $('.code-label', sectionDiv).insertAdjacentElement('afterend', wrapper);
}, { }, {
@ -269,7 +300,7 @@ function setupCodeMirror(sectionDiv, code, index) {
}); });
}; };
editors.splice(index || editors.length, 0, cm); editors.splice(index, 0, cm);
return cm; return cm;
} }
@ -385,17 +416,17 @@ function toggleSectionHeight(cm) {
} }
} }
function getSectionForChild(e) { function getSectionForChild(el, {includeDeleted} = {}) {
return e.closest('#sections > div'); return el.closest(`#sections > ${includeDeleted ? '*' : '.section'}`);
} }
function getSections() { function getSections() {
return $$('#sections > div'); return $$('#sections > .section');
} }
function getSectionsHashes() { function getSectionsHashes(elements = getSections()) {
const sections = []; const sections = [];
for (const div of getSections()) { for (const div of elements) {
const meta = {urls: [], urlPrefixes: [], domains: [], regexps: []}; const meta = {urls: [], urlPrefixes: [], domains: [], regexps: []};
for (const li of $('.applies-to-list', div).childNodes) { for (const li of $('.applies-to-list', div).childNodes) {
if (li.className === template.appliesToEverything.className) { if (li.className === template.appliesToEverything.className) {
@ -430,6 +461,29 @@ function removeAppliesTo(event) {
function removeSection(event) { function removeSection(event) {
const section = getSectionForChild(event.target); const section = getSectionForChild(event.target);
const cm = section.CodeMirror; const cm = section.CodeMirror;
if (event instanceof Event && (!cm.isClean() || !cm.isBlank())) {
const stub = template.deletedSection.cloneNode(true);
const MAX_LINES = 10;
const lines = [];
cm.doc.iter(0, MAX_LINES + 1, ({text}) => lines.push(text) && false);
stub.title = t('sectionCode') + '\n' +
'-'.repeat(20) + '\n' +
lines.slice(0, MAX_LINES).map(s => clipString(s, 100)).join('\n') +
(lines.length > MAX_LINES ? '\n...' : '');
$('.restore-section', stub).onclick = () => {
let el = stub;
while (el && !el.matches('.section')) {
el = el.previousElementSibling;
}
const index = el ? editors.indexOf(el) + 1 : 0;
editors.splice(index, 0, cm);
stub.parentNode.replaceChild(section, stub);
setCleanItem(section, false);
updateTitle();
cm.focus();
};
section.insertAdjacentElement('afterend', stub);
}
setCleanItem($('#sections'), false); setCleanItem($('#sections'), false);
removeAreaAndSetDirty(section); removeAreaAndSetDirty(section);
editors.splice(editors.indexOf(cm), 1); editors.splice(editors.indexOf(cm), 1);

View File

@ -4,6 +4,7 @@ global CodeMirror dirtyReporter
global updateLintReportIfEnabled initLint linterConfig updateLinter global updateLintReportIfEnabled initLint linterConfig updateLinter
global createAppliesToLineWidget messageBox global createAppliesToLineWidget messageBox
global sectionsToMozFormat global sectionsToMozFormat
global beforeUnload
*/ */
'use strict'; 'use strict';
@ -18,8 +19,10 @@ function createSourceEditor(style) {
const dirty = dirtyReporter(); const dirty = dirtyReporter();
dirty.onChange(() => { dirty.onChange(() => {
document.body.classList.toggle('dirty', dirty.isDirty()); const isDirty = dirty.isDirty();
$('#save-button').disabled = !dirty.isDirty(); window.onbeforeunload = isDirty ? beforeUnload : null;
document.body.classList.toggle('dirty', isDirty);
$('#save-button').disabled = !isDirty;
updateTitle(); updateTitle();
}); });
@ -107,12 +110,9 @@ function createSourceEditor(style) {
} }
const DEFAULT_CODE = ` const DEFAULT_CODE = `
/* ==UserStyle== /* ==UserStyle==
@name ${ @name ${''/* a trick to preserve the trailing spaces */}
style.name ||
t('usercssReplaceTemplateName') + ' - ' + new Date().toLocaleString()
}
@namespace github.com/openstyles/stylus @namespace github.com/openstyles/stylus
@version 0.1.0 @version 1.0.0
@description A new userstyle @description A new userstyle
@author Me @author Me
==/UserStyle== */ ==/UserStyle== */
@ -123,8 +123,12 @@ function createSourceEditor(style) {
chromeSync.getLZValue('usercssTemplate').then(code => { chromeSync.getLZValue('usercssTemplate').then(code => {
code = code || DEFAULT_CODE; code = code || DEFAULT_CODE;
code = code.replace(/@name(\s*)(?=[\r\n])/, (str, space) =>
`${str}${space ? '' : ' '}${
style.name ||
t('usercssReplaceTemplateName') + ' - ' + new Date().toLocaleString()}`);
// strip the last dummy section if any, add an empty line followed by the section // strip the last dummy section if any, add an empty line followed by the section
style.sourceCode = code.replace(/@-moz-document[^{]*\{[^}]*\}\s*$|\s+$/g, '') + '\n\n' + section; style.sourceCode = code.replace(/\s*@-moz-document[^{]*\{[^}]*\}\s*$|\s+$/g, '') + '\n\n' + section;
cm.startOperation(); cm.startOperation();
cm.setValue(style.sourceCode); cm.setValue(style.sourceCode);
cm.clearHistory(); cm.clearHistory();

View File

@ -116,3 +116,8 @@ function sectionsToMozFormat(style) {
section.code; section.code;
}).join('\n\n'); }).join('\n\n');
} }
function clipString(str, limit = 100) {
return str.length <= limit ? str : str.substr(0, limit) + '...';
}

View File

@ -16,7 +16,7 @@
<script src="js/script-loader.js"></script> <script src="js/script-loader.js"></script>
<script src="js/storage-util.js"></script> <script src="js/storage-util.js"></script>
<script src="content/apply.js"></script> <script src="content/apply.js"></script>
<script src="vendor/node-semver/semver.js"></script> <script src="vendor/semver-bundle/semver.js"></script>
<link href="msgbox/msgbox.css" rel="stylesheet"> <link href="msgbox/msgbox.css" rel="stylesheet">
<script src="msgbox/msgbox.js"></script> <script src="msgbox/msgbox.js"></script>

View File

@ -306,7 +306,7 @@ li {
user-select: auto; user-select: auto;
} }
label { label:not(.unavailable) {
padding-left: 16px; padding-left: 16px;
position: relative; position: relative;
} }

View File

@ -3,6 +3,8 @@
'use strict'; 'use strict';
(() => { (() => {
const DUMMY_URL = 'foo:';
// TODO: remove .replace(/^\?/, '') when minimum_chrome_version >= 52 (https://crbug.com/601425) // TODO: remove .replace(/^\?/, '') when minimum_chrome_version >= 52 (https://crbug.com/601425)
const params = new URLSearchParams(location.search.replace(/^\?/, '')); const params = new URLSearchParams(location.search.replace(/^\?/, ''));
let liveReload = false; let liveReload = false;
@ -14,7 +16,8 @@
let port; let port;
if (params.has('direct')) { if (params.has('direct')) {
$('.live-reload').remove(); $('.live-reload').textContent = t('liveReloadUnavailable');
$('.live-reload').classList.add('unavailable');
getCodeDirectly(); getCodeDirectly();
} else { } else {
port = chrome.tabs.connect(tabId); port = chrome.tabs.connect(tabId);
@ -40,10 +43,18 @@
port.onDisconnect.addListener(onPortDisconnected); port.onDisconnect.addListener(onPortDisconnected);
} }
const theme = prefs.get('editor.theme');
const cm = CodeMirror($('.main'), { const cm = CodeMirror($('.main'), {
readOnly: true, readOnly: true,
colorpicker: true, colorpicker: true,
theme,
}); });
if (theme !== 'default') {
document.head.appendChild($create('link', {
rel: 'stylesheet',
href: `vendor/codemirror/theme/${theme}.css`
}));
}
let liveReloadPending = Promise.resolve(); let liveReloadPending = Promise.resolve();
window.addEventListener('resize', adjustCodeHeight); window.addEventListener('resize', adjustCodeHeight);
@ -300,15 +311,17 @@
const checker = $('.set-update-url input[type=checkbox]'); const checker = $('.set-update-url input[type=checkbox]');
// prefer the installation URL unless drag'n'dropped on the manage page // prefer the installation URL unless drag'n'dropped on the manage page
const installationUrl = (params.get('updateUrl') || '').replace(/^blob.+/, ''); const installationUrl = (params.get('updateUrl') || '').replace(/^blob.+/, '');
const updateUrl = new URL(installationUrl || style.updateUrl || 'foo:bar'); const updateUrl = new URL(installationUrl || style.updateUrl || DUMMY_URL);
$('.set-update-url > span').textContent = t('installUpdateFromLabel'); $('.set-update-url > span').textContent = t('installUpdateFromLabel');
if (dup && dup.updateUrl === updateUrl.href) { if (dup && dup.updateUrl === updateUrl.href) {
checker.checked = true; checker.checked = true;
// there is no way to "unset" updateUrl, you can only overwrite it. // there is no way to "unset" updateUrl, you can only overwrite it.
checker.disabled = true; checker.disabled = true;
} else if (updateUrl.protocol === 'foo:') { } else if (updateUrl.href === DUMMY_URL) {
// drag'n'dropped on the manage page and the style doesn't have @updateURL // drag'n'dropped on the manage page and the style doesn't have @updateURL
checker.disabled = true; $('.set-update-url').textContent = t('installUpdateUnavailable');
$('.set-update-url').classList.add('unavailable');
return;
} else if (updateUrl.protocol !== 'file:') { } else if (updateUrl.protocol !== 'file:') {
checker.checked = true; checker.checked = true;
style.updateUrl = updateUrl.href; style.updateUrl = updateUrl.href;

View File

@ -355,3 +355,23 @@ function focusAccessibility() {
} }
} }
} }
/**
* Switches to the next/previous keyboard-focusable element
* @param {HTMLElement} rootElement
* @param {Number} step - for exmaple 1 or -1
*/
function moveFocus(rootElement, step) {
const elements = [...rootElement.getElementsByTagName('*')];
const activeIndex = Math.max(0, elements.indexOf(document.activeElement));
const num = elements.length;
for (let i = 1; i < num; i++) {
const elementIndex = (activeIndex + i * step + num) % num;
// we don't use positive tabindex so we stop at any valid value
const el = elements[elementIndex];
if (!el.disabled && el.tabIndex >= 0) {
el.focus();
return;
}
}
}

View File

@ -379,6 +379,8 @@ function onTabReady(tabOrId) {
* @returns {Promise<Tab>} Promise that resolves to the opened/activated tab * @returns {Promise<Tab>} Promise that resolves to the opened/activated tab
*/ */
function openURL({ function openURL({
// https://github.com/eslint/eslint/issues/10639
// eslint-disable-next-line no-undef
url = arguments[0], url = arguments[0],
index, index,
active, active,

View File

@ -54,6 +54,7 @@ var prefs = new function Prefs() {
newline_between_properties: true, newline_between_properties: true,
newline_before_close_brace: true, newline_before_close_brace: true,
newline_between_rules: false, newline_between_rules: false,
preserve_newlines: true,
end_with_newline: false, end_with_newline: false,
indent_conditional: true, indent_conditional: true,
}, },

View File

@ -69,7 +69,7 @@ var [chromeLocal, chromeSync] = (() => {
function loadLZStringScript() { function loadLZStringScript() {
return window.LZString ? return window.LZString ?
Promise.resolve(window.LZString) : Promise.resolve(window.LZString) :
loadScript('/vendor/lz-string/lz-string-unsafe.js').then(() => loadScript('/vendor/lz-string-unsafe/lz-string-unsafe.min.js').then(() =>
(window.LZString = window.LZString || window.LZStringUnsafe)); (window.LZString = window.LZString || window.LZStringUnsafe));
} }

View File

@ -47,7 +47,7 @@ var usercss = (() => {
}, },
stylus: { stylus: {
preprocess(source, vars) { preprocess(source, vars) {
return loadScript('/vendor/stylus-lang/stylus.min.js').then(() => ( return loadScript('/vendor/stylus-lang-bundle/stylus.min.js').then(() => (
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
const varDef = Object.keys(vars).map(key => `${key} = ${vars[key].value};\n`).join(''); const varDef = Object.keys(vars).map(key => `${key} = ${vars[key].value};\n`).join('');
if (!Error.captureStackTrace) Error.captureStackTrace = () => {}; if (!Error.captureStackTrace) Error.captureStackTrace = () => {};

View File

@ -380,6 +380,7 @@
<span><a href="https://userstyles.org" target="_blank" i18n-text="linkGetStyles"></a></span> <span><a href="https://userstyles.org" target="_blank" i18n-text="linkGetStyles"></a></span>
<span><a href="https://add0n.com/stylus.html#features" target="_blank" i18n-text="linkGetHelp"></a></span> <span><a href="https://add0n.com/stylus.html#features" target="_blank" i18n-text="linkGetHelp"></a></span>
<span><a href="https://github.com/openstyles/stylus/wiki" target="_blank" i18n-text="linkStylusWiki"></a></span> <span><a href="https://github.com/openstyles/stylus/wiki" target="_blank" i18n-text="linkStylusWiki"></a></span>
<span><a href="https://www.transifex.com/github-7/Stylus" target="_blank" i18n-text="linkTranslate"></a></span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -275,39 +275,37 @@ function importFromString(jsonString, oldStyles) {
$('#file-all-styles').onclick = () => { $('#file-all-styles').onclick = () => {
API.getStyles().then(styles => { API.getStyles().then(styles => {
const text = JSON.stringify(styles, null, '\t');
const blob = new Blob([text], {type: 'application/json'});
const url = URL.createObjectURL(blob);
let link = $create('a', {
href: url,
type: 'application/json',
download: generateFileName(),
});
// https://crbug.com/714373 // https://crbug.com/714373
if (!FIREFOX && !(CHROME > 3310 && CHROME < Infinity)) { document.documentElement.appendChild(
link.dispatchEvent(new MouseEvent('click')); $create('iframe', {
return doTimeout() onload() {
.then(() => URL.revokeObjectURL(url)); const text = JSON.stringify(styles, null, '\t');
} const type = 'application/json';
const iframe = document.body.appendChild($create('iframe', { this.onload = null;
style: 'width: 0; height: 0; position: fixed; opacity: 0;'.replace(/;/g, '!important;'), this.contentDocument.body.appendChild(
})); $create('a', {
return doTimeout() href: URL.createObjectURL(new Blob([text], {type})),
.then(() => { download: generateFileName(),
link = iframe.contentDocument.importNode(link, true); type,
iframe.contentDocument.body.appendChild(link);
}) })
.then(() => doTimeout()) ).dispatchEvent(new MouseEvent('click'));
.then(() => link.dispatchEvent(new MouseEvent('click'))) },
.then(() => doTimeout(1000)) // we can't use display:none as some browsers are ignoring such iframes
.then(() => URL.revokeObjectURL(url)) style: `
.then(() => iframe.remove()); all: unset;
width: 0;
height: 0;
position: fixed;
opacity: 0;
border: none;
`.replace(/;/g, '!important;'),
})
);
// we don't remove the iframe or the object URL because the browser may show
// a download dialog and we don't know how long it'll take until the user confirms it
// (some browsers like Vivaldi can't download if we revoke the URL)
}); });
function doTimeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function generateFileName() { function generateFileName() {
const today = new Date(); const today = new Date();
const dd = ('0' + today.getDate()).substr(-2); const dd = ('0' + today.getDate()).substr(-2);

View File

@ -240,6 +240,8 @@ select {
border-radius: 4px; border-radius: 4px;
margin-left: 1ex; margin-left: 1ex;
white-space: nowrap; white-space: nowrap;
position: relative;
top: 2px;
} }
.entry.usercss .style-name-link::after { .entry.usercss .style-name-link::after {
@ -445,6 +447,7 @@ select {
#manage-text { #manage-text {
display: flex; display: flex;
flex-wrap: wrap;
align-items: baseline; align-items: baseline;
padding-top: .35rem; padding-top: .35rem;
} }

View File

@ -73,8 +73,7 @@ function initGlobalEvents() {
installed.addEventListener('mouseover', handleEvent.lazyAddEntryTitle); installed.addEventListener('mouseover', handleEvent.lazyAddEntryTitle);
installed.addEventListener('mouseout', handleEvent.lazyAddEntryTitle); installed.addEventListener('mouseout', handleEvent.lazyAddEntryTitle);
// remember scroll position on normal history navigation document.addEventListener('visibilitychange', onVisibilityChange);
window.onbeforeunload = rememberScrollPosition;
$$('[data-toggle-on-click]').forEach(el => { $$('[data-toggle-on-click]').forEach(el => {
// dataset on SVG doesn't work in Chrome 49-??, works in 57+ // dataset on SVG doesn't work in Chrome 49-??, works in 57+
@ -116,7 +115,6 @@ function initGlobalEvents() {
`)); `));
} }
function showStyles(styles = [], matchUrlIds) { function showStyles(styles = [], matchUrlIds) {
const sorted = sorter.sort({ const sorted = sorter.sort({
styles: styles.map(style => ({ styles: styles.map(style => ({
@ -165,14 +163,7 @@ function showStyles(styles = [], matchUrlIds) {
if ('scrollY' in (history.state || {}) && !sessionStorage.justEditedStyleId) { if ('scrollY' in (history.state || {}) && !sessionStorage.justEditedStyleId) {
setTimeout(window.scrollTo, 0, 0, history.state.scrollY); setTimeout(window.scrollTo, 0, 0, history.state.scrollY);
} }
if (sessionStorage.justEditedStyleId) { highlightEditedStyle();
const entry = $(ENTRY_ID_PREFIX + sessionStorage.justEditedStyleId);
delete sessionStorage.justEditedStyleId;
if (entry) {
animateElement(entry);
requestAnimationFrame(() => scrollElementIntoView(entry));
}
}
} }
} }
@ -321,16 +312,15 @@ function recreateStyleTargets({styles, iconsOnly = false} = {}) {
} }
function getFaviconImgSrc(container = installed) { function getFaviconImgSrc(container = installed) {
const targets = $$('.target', container);
const regexpRemoveNegativeLookAhead = /(\?!([^)]+\))|\(\?![\w(]+[^)]+[\w|)]+)/g; const regexpRemoveNegativeLookAhead = /(\?!([^)]+\))|\(\?![\w(]+[^)]+[\w|)]+)/g;
// replace extra characters & all but the first group entry "(abc|def|ghi)xyz" => abcxyz // replace extra characters & all but the first group entry "(abc|def|ghi)xyz" => abcxyz
const regexpReplaceExtraCharacters = /[\\(]|((\|\w+)+\))/g; const regexpReplaceExtraCharacters = /[\\(]|((\|\w+)+\))/g;
const domainExt = 'com,org,co,net,im,io,edu,gov,biz,info,de,cn,uk,nl,eu,ru'.split(','); const regexpMatchRegExp = /[\w-]+[.(]+(com|org|co|net|im|io|edu|gov|biz|info|de|cn|uk|nl|eu|ru)\b/g;
const regexpMatchRegExp = new RegExp(`[\\w-]+[\\.(]+(${domainExt.join('|')})\\b`, 'g');
const regexpMatchDomain = /^.*?:\/\/([^/]+)/; const regexpMatchDomain = /^.*?:\/\/([^/]+)/;
for (const target of targets) { for (const target of $$('.target', container)) {
const type = target.dataset.type; const type = target.dataset.type;
const targetValue = target.textContent; const targetValue = target.textContent;
if (!targetValue) continue;
let favicon = ''; let favicon = '';
if (type === 'domains') { if (type === 'domains') {
favicon = GET_FAVICON_URL + targetValue; favicon = GET_FAVICON_URL + targetValue;
@ -418,7 +408,7 @@ Object.assign(handleEvent, {
}); });
} }
} else { } else {
rememberScrollPosition(); onVisibilityChange();
getActiveTab().then(tab => { getActiveTab().then(tab => {
sessionStorageHash('manageStylesHistory').set(tab.id, url); sessionStorageHash('manageStylesHistory').set(tab.id, url);
location.href = url; location.href = url;
@ -541,7 +531,7 @@ Object.assign(handleEvent, {
}); });
function handleUpdate(style, {reason, method, codeIsUpdated} = {}) { function handleUpdate(style, {reason, method} = {}) {
if (reason === 'editPreview') return; if (reason === 'editPreview') return;
// the style was toggled and refreshAllTabs() sent a mini-notification, // the style was toggled and refreshAllTabs() sent a mini-notification,
// but we've already processed 'styleUpdated' sent directly from notifyAllTabs() // but we've already processed 'styleUpdated' sent directly from notifyAllTabs()
@ -689,8 +679,28 @@ function switchUI({styleOnly} = {}) {
} }
function rememberScrollPosition() { function onVisibilityChange() {
switch (document.visibilityState) {
// page restored without reloading via history navigation (currently only in FF)
case 'visible':
highlightEditedStyle();
break;
// going away
case 'hidden':
history.replaceState({scrollY: window.scrollY}, document.title); history.replaceState({scrollY: window.scrollY}, document.title);
break;
}
}
function highlightEditedStyle() {
if (!sessionStorage.justEditedStyleId) return;
const entry = $(ENTRY_ID_PREFIX + sessionStorage.justEditedStyleId);
delete sessionStorage.justEditedStyleId;
if (entry) {
animateElement(entry);
requestAnimationFrame(() => scrollElementIntoView(entry));
}
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "Stylus", "name": "Stylus",
"version": "1.4.16", "version": "1.4.17",
"minimum_chrome_version": "49", "minimum_chrome_version": "49",
"description": "__MSG_description__", "description": "__MSG_description__",
"homepage_url": "https://add0n.com/stylus.html", "homepage_url": "https://add0n.com/stylus.html",
@ -39,7 +39,7 @@
"background/update.js", "background/update.js",
"background/refresh-all-tabs.js", "background/refresh-all-tabs.js",
"background/openusercss-api.js", "background/openusercss-api.js",
"vendor/node-semver/semver.js", "vendor/semver-bundle/semver.js",
"vendor-overwrites/colorpicker/colorconverter.js" "vendor-overwrites/colorpicker/colorconverter.js"
] ]
}, },

View File

@ -1,4 +1,5 @@
/* global focusAccessibility */ /* global focusAccessibility */
/* global moveFocus */
'use strict'; 'use strict';
/** /**
@ -33,7 +34,7 @@ function messageBox({
document.body.appendChild(messageBox.element); document.body.appendChild(messageBox.element);
messageBox.originalFocus = document.activeElement; messageBox.originalFocus = document.activeElement;
moveFocus(1); moveFocus(messageBox.element, 1);
if (typeof onshow === 'function') { if (typeof onshow === 'function') {
onshow(messageBox.element); onshow(messageBox.element);
@ -67,7 +68,7 @@ function messageBox({
event.stopPropagation(); event.stopPropagation();
break; break;
case 9: case 9:
moveFocus(shiftKey ? -1 : 1); moveFocus(messageBox.element, shiftKey ? -1 : 1);
event.preventDefault(); event.preventDefault();
return; return;
default: default:
@ -139,21 +140,6 @@ function messageBox({
messageBox.element = null; messageBox.element = null;
messageBox.resolve = null; messageBox.resolve = null;
} }
function moveFocus(dir) {
const elements = [...messageBox.element.getElementsByTagName('*')];
const activeIndex = Math.max(0, elements.indexOf(document.activeElement));
const num = elements.length;
for (let i = 1; i < num; i++) {
const elementIndex = (activeIndex + i * dir + num) % num;
// we don't use positive tabindex so we stop at any valid value
const el = elements[elementIndex];
if (!el.disabled && el.tabIndex >= 0) {
el.focus();
return;
}
}
}
} }
/** /**

29
package.json Normal file
View File

@ -0,0 +1,29 @@
{
"name": "Stylus",
"version": "1.4.17",
"description": "Redesign the web with Stylus, a user styles manager",
"license": "GPL-3.0-only",
"repository": "openstyles/stylus",
"author": "Stylus Team",
"devDependencies": {
"archiver": "^2.1.1",
"codemirror": "^5.39.2",
"eslint": "^5.2.0",
"fs-extra": "^7.0.0",
"jsonlint": "^1.6.3",
"less": "^3.8.0",
"lz-string-unsafe": "^1.4.4-beta",
"semver-bundle": "^0.1.1",
"stylelint-bundle": "^8.0.0",
"stylus-lang-bundle": "^0.54.5",
"updates": "^4.0.1"
},
"scripts": {
"lint": "eslint **/*.js || true",
"update": "npm run update-node && npm run update-versions && npm run update-codemirror",
"update-codemirror": "node tools/update-libraries.js && node tools/update-codemirror-themes.js",
"update-node": "updates -u && npm update",
"update-versions": "node tools/update-versions",
"zip": "npm run update-versions && node tools/zip.js"
}
}

9
tools/.eslintrc Normal file
View File

@ -0,0 +1,9 @@
# https://github.com/eslint/eslint/blob/master/docs/rules/README.md
parserOptions:
ecmaVersion: 2017
env:
browser: true
es6: true
node: true

View File

@ -0,0 +1,44 @@
#!/usr/bin/env node
'use strict';
const fs = require('fs-extra');
const path = require('path');
// Update theme names list in codemirror-editing-hook.js
async function getThemes() {
const p = path.join(__dirname, '..', 'vendor/codemirror/theme/');
const files = await fs.readdir(p);
return files
.filter(name => name.endsWith('.css'))
.map(name => name.replace('.css', ''))
.sort();
}
function replaceThemes(content, themes) {
const lineFeed = content.includes('\r\n') ? '\r\n' : '\n';
return content.replace(
/(\x20+)(\/\*\s*populate-theme-start\s*\*\/)[\s\S]+?(\/\*\s*populate-theme-end\s*\*\/)/,
(_, indent, intro, outro) =>
indent + intro + lineFeed +
themes.map(_ => `${indent}'${_}',`).join(lineFeed) + lineFeed +
indent + outro
);
}
async function updateHook(themes) {
const fileName = path.join(__dirname, '..', 'edit/codemirror-editing-hooks.js');
const content = await fs.readFile(fileName, 'utf-8');
fs.writeFile(fileName, replaceThemes(content, themes));
}
function exit(err) {
if (err) {
console.error(err);
}
process.exit(err ? 1 : 0);
}
getThemes()
.then(themes => updateHook(themes))
.then(() => console.log('\x1b[32m%s\x1b[0m', 'codemirror themes list updated'))
.catch(exit);

122
tools/update-libraries.js Normal file
View File

@ -0,0 +1,122 @@
#!/usr/bin/env node
'use strict';
const fs = require('fs-extra');
const path = require('path');
const root = path.join(__dirname, '..');
const files = {
'codemirror': [
'*', // only update existing vendor files
'theme' // update all theme files
],
'jsonlint': [
'lib/jsonlint.js → jsonlint.js'
],
'less': [
'dist/less.min.js → less.min.js'
],
'lz-string-unsafe': [
'lz-string-unsafe.min.js'
],
'semver-bundle': [
'dist/semver.js → semver.js'
],
'stylelint-bundle': [
'stylelint-bundle.min.js'
],
'stylus-lang-bundle': [
'stylus.min.js'
]
};
async function updateReadme(lib) {
const pkg = await fs.readJson(`${root}/node_modules/${lib}/package.json`);
const file = `${root}/vendor/${lib}/README.md`;
const txt = await fs.readFile(file, 'utf8');
return fs.writeFile(file, txt.replace(/\bv[\d.]+[-\w]*\b/g, `v${pkg.version}`));
}
function isFolder(fileOrFolder) {
const stat = fs.statSync(fileOrFolder);
return stat.isDirectory();
}
// Rename CodeMirror$1 -> CodeMirror for development purposes
function renameCodeMirrorVariable(filePath) {
const file = fs.readFileSync(filePath, 'utf8');
fs.writeFileSync(filePath, file.replace(/CodeMirror\$1/g, 'CodeMirror'));
}
function updateExisting(lib) {
const libRoot = `${root}/node_modules/`;
const vendorRoot = `${root}/vendor/`;
const folders = [lib];
const process = function () {
if (folders.length) {
const folder = folders.shift();
const folderRoot = `${vendorRoot}${folder}`;
const entries = fs.readdirSync(folderRoot);
entries.forEach(entry => {
// Remove $1 from "CodeMirror$1" in codemirror.js
if (entry === 'codemirror.js') {
renameCodeMirrorVariable(`${folderRoot}/${entry}`);
} else if (entry !== 'README.md' && entry !== 'LICENSE') {
// Ignore README.md & LICENSE files
const entryPath = `${folderRoot}/${entry}`;
try {
if (fs.existsSync(entryPath)) {
if (isFolder(entryPath)) {
folders.push(`${folder}/${entry}`);
} else {
fs.copySync(`${libRoot}${folder}/${entry}`, entryPath);
}
}
} catch (err) {
// Show error in case file exists in vendor, but not in node_modules
console.log('\x1b[36m%s\x1b[0m', `"${entryPath}" doesn't exist!`);
}
}
});
}
if (folders.length) {
process();
}
};
process();
}
async function copy(lib, folder) {
const [src, dest] = folder.split(/\s*→\s*/);
try {
if (folder === '*') {
updateExisting(lib);
} else {
await fs.copy(`${root}/node_modules/${lib}/${src}`, `${root}/vendor/${lib}/${dest || src}`);
}
} catch (err) {
exit(err);
}
}
function exit(err) {
if (err) {
console.error(err);
}
process.exit(err ? 1 : 0);
}
Object.keys(files).forEach(lib => {
updateReadme(lib);
files[lib].forEach(folder => {
if (folder === '*') {
updateExisting(lib);
} else {
copy(lib, folder);
}
});
console.log('\x1b[32m%s\x1b[0m', `${lib} files updated`);
});

70
tools/update-versions.js Normal file
View File

@ -0,0 +1,70 @@
#!/usr/bin/env node
'use strict';
const fs = require('fs-extra');
const path = require('path');
const root = path.join(__dirname, '..');
const good = '\x1b[32m%s\x1b[0m';
const warn = '\x1b[36m%s\x1b[0m';
function exit(err) {
if (err) {
console.error(err);
}
process.exit(err ? 1 : 0);
}
function verToArray(v) {
return v.replace('v', '').split('.').map(Number);
}
// Simple compare function since we can't require semverCompare here
function compare(v1, v2) {
if (v1 === v2) {
return 0;
}
const [maj1, min1, pat1] = verToArray(v1);
const [maj2, min2, pat2] = verToArray(v2);
const majMatch = maj1 === maj2;
const minMatch = min1 === min2;
if (
maj1 > maj2 ||
majMatch && min1 > min2 ||
majMatch && minMatch && pat1 > pat2
) {
return 1;
}
return -1;
}
async function updateVersions() {
const regexp = /"([v\d.]+)"/;
const manifest = await fs.readFile(`${root}/manifest.json`, 'utf8');
const pkg = await fs.readFile(`${root}/package.json`, 'utf8');
const manifestVersion = manifest.match(regexp);
const pkgVersion = pkg.match(regexp);
if (manifestVersion && pkgVersion) {
const result = compare(manifestVersion[1], pkgVersion[1]);
let match, version, file, str;
if (result === 0) {
return console.log(good, 'Manifest & package versions match');
} else if (result > 0) {
match = pkgVersion;
version = manifestVersion[1];
file = 'package.json';
str = pkg;
} else {
match = manifestVersion;
version = pkgVersion[1];
file = 'manifest.json';
str = manifest;
}
console.log(warn, `Updating ${file} to ${version}`);
str = str.slice(0, match.index + 1) + version + str.slice(match.index + match[1].length + 1);
return fs.writeFile(`${root}/${file}`, str);
}
throw Error(`Error reading ${manifestVersion ? '' : 'manifest.json'} ${pkgVersion ? '' : 'package.json'}`);
}
updateVersions().catch(err => exit(err));

51
tools/zip.js Normal file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env node
'use strict';
const fs = require('fs');
const archiver = require('archiver');
function createZip() {
const fileName = 'stylus.zip';
const exclude = [
'.*', // dot files/folders (glob, not regexp)
'vendor/codemirror/lib/**', // get unmodified copy from node_modules
'node_modules/**',
'tools/**',
'package.json',
'package-lock.json',
'yarn.lock',
'*.zip'
];
const file = fs.createWriteStream(fileName);
const archive = archiver('zip');
return new Promise((resolve, reject) => {
archive.on('finish', () => {
resolve();
});
archive.on('warning', err => {
if (err.code === 'ENOENT') {
console.log('\x1b[33m%s\x1b[0m', 'Warning', err.message);
} else {
reject();
throw err;
}
});
archive.on('error', err => {
reject();
throw err;
});
archive.pipe(file);
archive.glob('**', {ignore: exclude});
// Don't use modified codemirror.js (see "update-libraries.js")
archive.directory('node_modules/codemirror/lib', 'vendor/codemirror/lib');
archive.finalize();
});
}
createZip()
.then(() => console.log('\x1b[32m%s\x1b[0m', 'Stylus zip complete'))
.catch(err => {
throw err;
});

View File

@ -0,0 +1,9 @@
## beautify-css - modified from v1.6.12
Beautify-css was **heavily** modified from its source:
https://github.com/beautify-web/js-beautify/blob/v1.6.12/js/lib/beautify-css.js
After this version the source repo split the file and built it using webpack.
Our version has more options & modes. It should be considered a fork of the original.

View File

@ -508,15 +508,11 @@
// sass/less parent reference don't use a space // sass/less parent reference don't use a space
// sass nested pseudo-class don't use a space // sass nested pseudo-class don't use a space
/* Stylus override.
Disabling this block since we don't like the result.
// preserve space before pseudoclasses/pseudoelements, as it means "in any child" // preserve space before pseudoclasses/pseudoelements, as it means "in any child"
if (lookBack(" ") && output[output.length - 1] !== " ") { if (lookBack(" ") && outputPosCol && !/\s$/.test(output[output.length - 1])) {
output.push(" "); output.push(" ");
outputPosCol++; outputPosCol++;
} }
*/
if (peek() === ":") { if (peek() === ":") {
// pseudo-element // pseudo-element

View File

@ -0,0 +1,7 @@
## color-picker - forked from v1.0.9
codemirror-colorpicker was **heavily** modified from its source:
https://github.com/easylogic/codemirror-colorpicker/...
Shortly after this version the source repo split the file and built it using rollup. It should be considered a fork of the original.

View File

@ -169,6 +169,7 @@
state.line = viewFrom; state.line = viewFrom;
state.inComment = null; state.inComment = null;
state.now = performance.now();
state.stopAt = state.stopped = null; state.stopAt = state.stopped = null;
cm.doc.iter(viewFrom, viewTo, lineHandle => colorizeLine(state, lineHandle)); cm.doc.iter(viewFrom, viewTo, lineHandle => colorizeLine(state, lineHandle));
@ -188,7 +189,8 @@
const {curOp} = cm; const {curOp} = cm;
if (!curOp) cm.startOperation(); if (!curOp) cm.startOperation();
state.stopAt = performance.now() + TIME_BUDGET; state.now = performance.now();
state.stopAt = state.now + TIME_BUDGET;
state.stopped = null; state.stopped = null;
// before the visible range // before the visible range
@ -247,7 +249,8 @@
const {curOp} = cm; const {curOp} = cm;
if (!curOp) cm.startOperation(); if (!curOp) cm.startOperation();
const stopAt = canPostpone && performance.now() + TIME_BUDGET; state.now = performance.now();
const stopAt = canPostpone && state.now + TIME_BUDGET;
let stopped = null; let stopped = null;
let change, changeFromLine; let change, changeFromLine;
@ -271,7 +274,7 @@
if (!lineHandle.styles) state.cm.getTokenTypeAt({line, ch: 0}); if (!lineHandle.styles) state.cm.getTokenTypeAt({line, ch: 0});
colorizeLineViaStyles(state, lineHandle); colorizeLineViaStyles(state, lineHandle);
} }
if (canPostpone && performance.now() > stopAt) { if (canPostpone && (state.now = performance.now()) > stopAt) {
stopped = true; stopped = true;
return true; return true;
} }
@ -295,7 +298,7 @@
function colorizeLine(state, lineHandle) { function colorizeLine(state, lineHandle) {
if (state.stopAt && performance.now() > state.stopAt) { if (state.stopAt && (state.now = performance.now()) > state.stopAt) {
state.stopped = true; state.stopped = true;
return true; return true;
} }
@ -349,6 +352,8 @@
let {markedSpans} = lineHandle; let {markedSpans} = lineHandle;
let spansSorted = false; let spansSorted = false;
let spansZombies = markedSpans && markedSpans.length;
const spanGeneration = state.now;
for (let i = styleIndex; i + 1 < styles.length; i += 2) { for (let i = styleIndex; i + 1 < styles.length; i += 2) {
style = styles[i + 1]; style = styles[i + 1];
@ -432,6 +437,8 @@
break; break;
} }
if (span.from === start && span.marker.className === COLORVIEW_CLASS) { if (span.from === start && span.marker.className === COLORVIEW_CLASS) {
spansZombies--;
span.generation = spanGeneration;
const same = color === span.marker.color && const same = color === span.marker.color &&
(isFunc || /\W|^$/i.test(text.substr(start + color.length, 1))); (isFunc || /\W|^$/i.test(text.substr(start + color.length, 1)));
if (same) return 'same'; if (same) return 'same';
@ -442,6 +449,7 @@
} }
function redeem(colorValue) { function redeem(colorValue) {
spansZombies++;
state.markersToRemove.pop(); state.markersToRemove.pop();
state.markersToRepaint.push(span); state.markersToRepaint.push(span);
span.to = end; span.to = end;
@ -452,9 +460,10 @@
} }
function removeDeadSpans() { function removeDeadSpans() {
while (markedSpans && spanIndex < markedSpans.length) { if (!spansZombies) return;
span = markedSpans[spanIndex++]; for (const span of markedSpans) {
if (span.marker.className === COLORVIEW_CLASS) { if (span.generation !== spanGeneration &&
span.marker.className === COLORVIEW_CLASS) {
state.markersToRemove.push(span.marker); state.markersToRemove.push(span.marker);
} }
} }

View File

@ -0,0 +1,3 @@
## css-lint - modified from v0.10.0 (2013-08-15)
This version has been **heavily** modified since [it was originally added](https://github.com/openstyles/stylus/commit/b4173d68f6312300ab761f5454d7a8fb230d2bce#diff-4392791c2f6559cb1de01b0e1f3e1c08) in Stylish v1.3.0. It should be considered a fork of the [original](https://github.com/CSSLint/csslint).

26
vendor/README.md vendored Normal file
View File

@ -0,0 +1,26 @@
# Vendor files are populated by the build script:
## What the build script does
Using this repo, run `npm install`... the latest versions of:
* `CodeMirror` (https://github.com/codemirror/CodeMirror) is installed.
* `jsonlint` (https://github.com/zaach/jsonlint) is installed.
* `less` (https://github.com/less/less.js) is installed.
* `lz-string-unsafe` (https://github.com/openstyles/lz-string-unsafe) is installed.
* `semver-bundle` (https://github.com/openstyles/semver-bundle) is installed.
* `stylus-lang` (https://github.com/openstyles/stylus-lang-bundle) is installed.<br><br>
* The necessary build tools are installed; see `devDependencies` in the `package.json`.
## Running the build script
Use `npm run update` to first update the packages in the `node_modules` folder & then update the vendor folder.
The following changes are made:
* `CodeMirror`: Only existing files are updated directly from the `node_modules` folder; see the [CodeMirror readme](codemirror/README.md) for specifics.
* `jsonlint`: The uncompressed `lib/jsonlint.js` is copied directly to `vendor/jsonlint`.
* `less`: The compressed `dist/less.min.js` file is copied directly into `vendor/less`.
* `lz-string-unsafe`: The compressed `lz-string-unsafe.min.js` file is copied directly into `vendor/lz-string-unsafe`.
* `semver-bundle`: The `dist/semver.js` file is copied directly into `vendor/semver`.
* `stylus-lang-bundle`: The `stylus.min.js` file is copied directly into `vendor/stylus-lang-bundle`.

3
vendor/codemirror/README.md vendored Normal file
View File

@ -0,0 +1,3 @@
## CodeMirror v5.39.2
Only files & folders that exist in the `vendor/codemirror` folder are copied from the `node_modules/codemirror` folder. Except all theme files are copied, in case new themes have been added.

View File

@ -25,6 +25,7 @@
} else { // Assuming it's a detached DOM element. } else { // Assuming it's a detached DOM element.
dialog.appendChild(template); dialog.appendChild(template);
} }
CodeMirror.addClass(wrap, 'dialog-opened');
return dialog; return dialog;
} }
@ -47,6 +48,7 @@
} else { } else {
if (closed) return; if (closed) return;
closed = true; closed = true;
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
dialog.parentNode.removeChild(dialog); dialog.parentNode.removeChild(dialog);
me.focus(); me.focus();
@ -102,6 +104,7 @@
function close() { function close() {
if (closed) return; if (closed) return;
closed = true; closed = true;
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
dialog.parentNode.removeChild(dialog); dialog.parentNode.removeChild(dialog);
me.focus(); me.focus();
} }
@ -141,6 +144,7 @@
if (closed) return; if (closed) return;
closed = true; closed = true;
clearTimeout(doneTimer); clearTimeout(doneTimer);
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
dialog.parentNode.removeChild(dialog); dialog.parentNode.removeChild(dialog);
} }

View File

@ -98,7 +98,7 @@
var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line); var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch || if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
pos.ch < this.startPos.ch || this.cm.somethingSelected() || pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
(pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) { (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
this.close(); this.close();
} else { } else {
var self = this; var self = this;
@ -200,7 +200,8 @@
var widget = this, cm = completion.cm; var widget = this, cm = completion.cm;
var hints = this.hints = document.createElement("ul"); var hints = this.hints = document.createElement("ul");
hints.className = "CodeMirror-hints"; var theme = completion.cm.options.theme;
hints.className = "CodeMirror-hints " + theme;
this.selectedHint = data.selectedHint || 0; this.selectedHint = data.selectedHint || 0;
var completions = data.list; var completions = data.list;
@ -333,7 +334,7 @@
i = avoidWrap ? 0 : this.data.list.length - 1; i = avoidWrap ? 0 : this.data.list.length - 1;
if (this.selectedHint == i) return; if (this.selectedHint == i) return;
var node = this.hints.childNodes[this.selectedHint]; var node = this.hints.childNodes[this.selectedHint];
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); if (node) node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
node = this.hints.childNodes[this.selectedHint = i]; node = this.hints.childNodes[this.selectedHint = i];
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS; node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
if (node.offsetTop < this.hints.scrollTop) if (node.offsetTop < this.hints.scrollTop)
@ -397,12 +398,13 @@
}); });
CodeMirror.registerHelper("hint", "fromList", function(cm, options) { CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur); var cur = cm.getCursor(), token = cm.getTokenAt(cur)
var to = CodeMirror.Pos(cur.line, token.end); var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
if (token.string && /\w/.test(token.string[token.string.length - 1])) { if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
var term = token.string, from = CodeMirror.Pos(cur.line, token.start); term = token.string.substr(0, cur.ch - token.start)
} else { } else {
var term = "", from = to; term = ""
from = cur
} }
var found = []; var found = [];
for (var i = 0; i < options.words.length; i++) { for (var i = 0; i < options.words.length; i++) {

View File

@ -23,6 +23,9 @@ CodeMirror.registerHelper("lint", "json", function(text) {
} }
return found; return found;
} }
// for jsonlint's web dist jsonlint is exported as an object with a single property parser, of which parseError
// is a subproperty
var jsonlint = window.jsonlint.parser || window.jsonlint
jsonlint.parseError = function(str, hash) { jsonlint.parseError = function(str, hash) {
var loc = hash.loc; var loc = hash.loc;
found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column), found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),

View File

@ -307,6 +307,7 @@
"Backspace": function(cm) { killRegion(cm, false) || killTo(cm, byChar, -1, false); }, "Backspace": function(cm) { killRegion(cm, false) || killTo(cm, byChar, -1, false); },
"Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1), "Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1),
"Alt-Right": move(byWord, 1), "Alt-Left": move(byWord, -1),
"Alt-D": function(cm) { killTo(cm, byWord, 1, "grow"); }, "Alt-D": function(cm) { killTo(cm, byWord, 1, "grow"); },
"Alt-Backspace": function(cm) { killTo(cm, byWord, -1, "grow"); }, "Alt-Backspace": function(cm) { killTo(cm, byWord, -1, "grow"); },

View File

@ -93,6 +93,8 @@
{ keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }},
{ keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }},
{ keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }},
{ keys: '(', type: 'motion', motion: 'moveBySentence', motionArgs: { forward: false }},
{ keys: ')', type: 'motion', motion: 'moveBySentence', motionArgs: { forward: true }},
{ keys: '<C-f>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, { keys: '<C-f>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }},
{ keys: '<C-b>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, { keys: '<C-b>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }},
{ keys: '<C-d>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, { keys: '<C-d>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }},
@ -423,6 +425,9 @@
function isWhiteSpaceString(k) { function isWhiteSpaceString(k) {
return (/^\s*$/).test(k); return (/^\s*$/).test(k);
} }
function isEndOfSentenceSymbol(k) {
return '.?!'.indexOf(k) != -1;
}
function inArray(val, arr) { function inArray(val, arr) {
for (var i = 0; i < arr.length; i++) { for (var i = 0; i < arr.length; i++) {
if (arr[i] == val) { if (arr[i] == val) {
@ -866,7 +871,7 @@
if (vim.insertMode) { command = handleKeyInsertMode(); } if (vim.insertMode) { command = handleKeyInsertMode(); }
else { command = handleKeyNonInsertMode(); } else { command = handleKeyNonInsertMode(); }
if (command === false) { if (command === false) {
return undefined; return !vim.insertMode && key.length === 1 ? function() { return true; } : undefined;
} else if (command === true) { } else if (command === true) {
// TODO: Look into using CodeMirror's multi-key handling. // TODO: Look into using CodeMirror's multi-key handling.
// Return no-op since we are caching the key. Counts as handled, but // Return no-op since we are caching the key. Counts as handled, but
@ -1811,6 +1816,10 @@
var dir = motionArgs.forward ? 1 : -1; var dir = motionArgs.forward ? 1 : -1;
return findParagraph(cm, head, motionArgs.repeat, dir); return findParagraph(cm, head, motionArgs.repeat, dir);
}, },
moveBySentence: function(cm, head, motionArgs) {
var dir = motionArgs.forward ? 1 : -1;
return findSentence(cm, head, motionArgs.repeat, dir);
},
moveByScroll: function(cm, head, motionArgs, vim) { moveByScroll: function(cm, head, motionArgs, vim) {
var scrollbox = cm.getScrollInfo(); var scrollbox = cm.getScrollInfo();
var curEnd = null; var curEnd = null;
@ -3534,6 +3543,179 @@
return { start: start, end: end }; return { start: start, end: end };
} }
function findSentence(cm, cur, repeat, dir) {
/*
Takes an index object
{
line: the line string,
ln: line number,
pos: index in line,
dir: direction of traversal (-1 or 1)
}
and modifies the line, ln, and pos members to represent the
next valid position or sets them to null if there are
no more valid positions.
*/
function nextChar(cm, idx) {
if (idx.pos + idx.dir < 0 || idx.pos + idx.dir >= idx.line.length) {
idx.ln += idx.dir;
if (!isLine(cm, idx.ln)) {
idx.line = null;
idx.ln = null;
idx.pos = null;
return;
}
idx.line = cm.getLine(idx.ln);
idx.pos = (idx.dir > 0) ? 0 : idx.line.length - 1;
}
else {
idx.pos += idx.dir;
}
}
/*
Performs one iteration of traversal in forward direction
Returns an index object of the new location
*/
function forward(cm, ln, pos, dir) {
var line = cm.getLine(ln);
var stop = (line === "");
var curr = {
line: line,
ln: ln,
pos: pos,
dir: dir,
}
var last_valid = {
ln: curr.ln,
pos: curr.pos,
}
var skip_empty_lines = (curr.line === "");
// Move one step to skip character we start on
nextChar(cm, curr);
while (curr.line !== null) {
last_valid.ln = curr.ln;
last_valid.pos = curr.pos;
if (curr.line === "" && !skip_empty_lines) {
return { ln: curr.ln, pos: curr.pos, };
}
else if (stop && curr.line !== "" && !isWhiteSpaceString(curr.line[curr.pos])) {
return { ln: curr.ln, pos: curr.pos, };
}
else if (isEndOfSentenceSymbol(curr.line[curr.pos])
&& !stop
&& (curr.pos === curr.line.length - 1
|| isWhiteSpaceString(curr.line[curr.pos + 1]))) {
stop = true;
}
nextChar(cm, curr);
}
/*
Set the position to the last non whitespace character on the last
valid line in the case that we reach the end of the document.
*/
var line = cm.getLine(last_valid.ln);
last_valid.pos = 0;
for(var i = line.length - 1; i >= 0; --i) {
if (!isWhiteSpaceString(line[i])) {
last_valid.pos = i;
break;
}
}
return last_valid;
}
/*
Performs one iteration of traversal in reverse direction
Returns an index object of the new location
*/
function reverse(cm, ln, pos, dir) {
var line = cm.getLine(ln);
var curr = {
line: line,
ln: ln,
pos: pos,
dir: dir,
}
var last_valid = {
ln: curr.ln,
pos: null,
};
var skip_empty_lines = (curr.line === "");
// Move one step to skip character we start on
nextChar(cm, curr);
while (curr.line !== null) {
if (curr.line === "" && !skip_empty_lines) {
if (last_valid.pos !== null) {
return last_valid;
}
else {
return { ln: curr.ln, pos: curr.pos };
}
}
else if (isEndOfSentenceSymbol(curr.line[curr.pos])
&& last_valid.pos !== null
&& !(curr.ln === last_valid.ln && curr.pos + 1 === last_valid.pos)) {
return last_valid;
}
else if (curr.line !== "" && !isWhiteSpaceString(curr.line[curr.pos])) {
skip_empty_lines = false;
last_valid = { ln: curr.ln, pos: curr.pos }
}
nextChar(cm, curr);
}
/*
Set the position to the first non whitespace character on the last
valid line in the case that we reach the beginning of the document.
*/
var line = cm.getLine(last_valid.ln);
last_valid.pos = 0;
for(var i = 0; i < line.length; ++i) {
if (!isWhiteSpaceString(line[i])) {
last_valid.pos = i;
break;
}
}
return last_valid;
}
var curr_index = {
ln: cur.line,
pos: cur.ch,
};
while (repeat > 0) {
if (dir < 0) {
curr_index = reverse(cm, curr_index.ln, curr_index.pos, dir);
}
else {
curr_index = forward(cm, curr_index.ln, curr_index.pos, dir);
}
repeat--;
}
return Pos(curr_index.ln, curr_index.pos);
}
// TODO: perhaps this finagling of start and end positions belonds // TODO: perhaps this finagling of start and end positions belonds
// in codemirror/replaceRange? // in codemirror/replaceRange?
function selectCompanionObject(cm, head, symb, inclusive) { function selectCompanionObject(cm, head, symb, inclusive) {
@ -3552,8 +3734,8 @@
// cursor is on a matching open bracket. // cursor is on a matching open bracket.
var offset = curChar === openSym ? 1 : 0; var offset = curChar === openSym ? 1 : 0;
start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp}); start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, undefined, {'bracketRegex': bracketRegexp});
end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp}); end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, undefined, {'bracketRegex': bracketRegexp});
if (!start || !end) { if (!start || !end) {
return { start: cur, end: cur }; return { start: cur, end: cur };

File diff suppressed because it is too large Load Diff

View File

@ -75,17 +75,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return ret(ch); return ret(ch);
} else if (ch == "=" && stream.eat(">")) { } else if (ch == "=" && stream.eat(">")) {
return ret("=>", "operator"); return ret("=>", "operator");
} else if (ch == "0" && stream.eat(/x/i)) { } else if (ch == "0" && stream.match(/^(?:x[\da-f]+|o[0-7]+|b[01]+)n?/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
} else if (ch == "0" && stream.eat(/o/i)) {
stream.eatWhile(/[0-7]/i);
return ret("number", "number");
} else if (ch == "0" && stream.eat(/b/i)) {
stream.eatWhile(/[01]/i);
return ret("number", "number"); return ret("number", "number");
} else if (/\d/.test(ch)) { } else if (/\d/.test(ch)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); stream.match(/^\d*(?:n|(?:\.\d*)?(?:[eE][+\-]?\d+)?)?/);
return ret("number", "number"); return ret("number", "number");
} else if (ch == "/") { } else if (ch == "/") {
if (stream.eat("*")) { if (stream.eat("*")) {
@ -96,7 +89,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return ret("comment", "comment"); return ret("comment", "comment");
} else if (expressionAllowed(stream, state, 1)) { } else if (expressionAllowed(stream, state, 1)) {
readRegexp(stream); readRegexp(stream);
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
return ret("regexp", "string-2"); return ret("regexp", "string-2");
} else { } else {
stream.eat("="); stream.eat("=");
@ -126,7 +119,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var kw = keywords[word] var kw = keywords[word]
return ret(kw.type, kw.style, word) return ret(kw.type, kw.style, word)
} }
if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\(\w]/, false)) if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
return ret("async", "keyword", word) return ret("async", "keyword", word)
} }
return ret("variable", "variable", word) return ret("variable", "variable", word)
@ -265,21 +258,42 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
pass.apply(null, arguments); pass.apply(null, arguments);
return true; return true;
} }
function register(varname) { function inList(name, list) {
function inList(list) { for (var v = list; v; v = v.next) if (v.name == name) return true
for (var v = list; v; v = v.next)
if (v.name == varname) return true;
return false; return false;
} }
function register(varname) {
var state = cx.state; var state = cx.state;
cx.marked = "def"; cx.marked = "def";
if (state.context) { if (state.context) {
if (inList(state.localVars)) return; if (state.lexical.info == "var" && state.context && state.context.block) {
state.localVars = {name: varname, next: state.localVars}; // FIXME function decls are also not block scoped
var newContext = registerVarScoped(varname, state.context)
if (newContext != null) {
state.context = newContext
return
}
} else if (!inList(varname, state.localVars)) {
state.localVars = new Var(varname, state.localVars)
return
}
}
// Fall through means this is global
if (parserConfig.globalVars && !inList(varname, state.globalVars))
state.globalVars = new Var(varname, state.globalVars)
}
function registerVarScoped(varname, context) {
if (!context) {
return null
} else if (context.block) {
var inner = registerVarScoped(varname, context.prev)
if (!inner) return null
if (inner == context.prev) return context
return new Context(inner, context.vars, true)
} else if (inList(varname, context.vars)) {
return context
} else { } else {
if (inList(state.globalVars)) return; return new Context(context.prev, new Var(varname, context.vars), false)
if (parserConfig.globalVars)
state.globalVars = {name: varname, next: state.globalVars};
} }
} }
@ -289,15 +303,23 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
// Combinators // Combinators
var defaultVars = {name: "this", next: {name: "arguments"}}; function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }
function Var(name, next) { this.name = name; this.next = next }
var defaultVars = new Var("this", new Var("arguments", null))
function pushcontext() { function pushcontext() {
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; cx.state.context = new Context(cx.state.context, cx.state.localVars, false)
cx.state.localVars = defaultVars; cx.state.localVars = defaultVars
}
function pushblockcontext() {
cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
cx.state.localVars = null
} }
function popcontext() { function popcontext() {
cx.state.localVars = cx.state.context.vars; cx.state.localVars = cx.state.context.vars
cx.state.context = cx.state.context.prev; cx.state.context = cx.state.context.prev
} }
popcontext.lex = true
function pushlex(type, info) { function pushlex(type, info) {
var result = function() { var result = function() {
var state = cx.state, indent = state.indented; var state = cx.state, indent = state.indented;
@ -322,19 +344,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function expect(wanted) { function expect(wanted) {
function exp(type) { function exp(type) {
if (type == wanted) return cont(); if (type == wanted) return cont();
else if (wanted == ";") return pass(); else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
else return cont(exp); else return cont(exp);
}; };
return exp; return exp;
} }
function statement(type, value) { function statement(type, value) {
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
if (type == "keyword b") return cont(pushlex("form"), statement, poplex); if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex); if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
if (type == "debugger") return cont(expect(";")); if (type == "debugger") return cont(expect(";"));
if (type == "{") return cont(pushlex("}"), block, poplex); if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
if (type == ";") return cont(); if (type == ";") return cont();
if (type == "if") { if (type == "if") {
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
@ -356,22 +378,27 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
} else if (isTS && value == "namespace") { } else if (isTS && value == "namespace") {
cx.marked = "keyword" cx.marked = "keyword"
return cont(pushlex("form"), expression, block, poplex) return cont(pushlex("form"), expression, block, poplex)
} else if (isTS && value == "abstract") {
cx.marked = "keyword"
return cont(statement)
} else { } else {
return cont(pushlex("stat"), maybelabel); return cont(pushlex("stat"), maybelabel);
} }
} }
if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
block, poplex, poplex); block, poplex, poplex, popcontext);
if (type == "case") return cont(expression, expect(":")); if (type == "case") return cont(expression, expect(":"));
if (type == "default") return cont(expect(":")); if (type == "default") return cont(expect(":"));
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
statement, poplex, popcontext);
if (type == "export") return cont(pushlex("stat"), afterExport, poplex); if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
if (type == "import") return cont(pushlex("stat"), afterImport, poplex); if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
if (type == "async") return cont(statement) if (type == "async") return cont(statement)
if (value == "@") return cont(expression, statement) if (value == "@") return cont(expression, statement)
return pass(pushlex("stat"), expression, expect(";"), poplex); return pass(pushlex("stat"), expression, expect(";"), poplex);
} }
function maybeCatchBinding(type) {
if (type == "(") return cont(funarg, expect(")"))
}
function expression(type, value) { function expression(type, value) {
return expressionInner(type, value, false); return expressionInner(type, value, false);
} }
@ -562,7 +589,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function typeexpr(type, value) { function typeexpr(type, value) {
if (value == "keyof" || value == "typeof") { if (value == "keyof" || value == "typeof") {
cx.marked = "keyword" cx.marked = "keyword"
return cont(value == "keyof" ? typeexpr : expression) return cont(value == "keyof" ? typeexpr : expressionNoComma)
} }
if (type == "variable" || value == "void") { if (type == "variable" || value == "void") {
cx.marked = "type" cx.marked = "type"
@ -572,6 +599,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType) if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType) if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType) if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
} }
function maybeReturnType(type) { function maybeReturnType(type) {
if (type == "=>") return cont(typeexpr) if (type == "=>") return cont(typeexpr)
@ -588,9 +616,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return cont(expression, maybetype, expect("]"), typeprop) return cont(expression, maybetype, expect("]"), typeprop)
} }
} }
function typearg(type) { function typearg(type, value) {
if (type == "variable") return cont(typearg) if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
else if (type == ":") return cont(typeexpr) if (type == ":") return cont(typeexpr)
return pass(typeexpr)
} }
function afterType(type, value) { function afterType(type, value) {
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
@ -778,7 +807,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
cc: [], cc: [],
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: parserConfig.localVars, localVars: parserConfig.localVars,
context: parserConfig.localVars && {vars: parserConfig.localVars}, context: parserConfig.localVars && new Context(null, null, false),
indented: basecolumn || 0 indented: basecolumn || 0
}; };
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
@ -819,7 +848,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
lexical = lexical.prev; lexical = lexical.prev;
var type = lexical.type, closing = firstChar == type; var type = lexical.type, closing = firstChar == type;
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
else if (type == "form" && firstChar == "{") return lexical.indented; else if (type == "form" && firstChar == "{") return lexical.indented;
else if (type == "form") return lexical.indented + indentUnit; else if (type == "form") return lexical.indented + indentUnit;
else if (type == "stat") else if (type == "stat")

46
vendor/codemirror/theme/darcula.css vendored Normal file
View File

@ -0,0 +1,46 @@
/**
Name: IntelliJ IDEA darcula theme
From IntelliJ IDEA by JetBrains
*/
.cm-s-darcula span.cm-meta { color: #BBB529; }
.cm-s-darcula span.cm-number { color: #6897BB; }
.cm-s-darcula span.cm-keyword { line-height: 1em; font-weight: bold; color: #CC7832; }
.cm-s-darcula span.cm-def { color: #FFC66D; }
.cm-s-darcula span.cm-variable { color: #A9B7C6; }
.cm-s-darcula span.cm-variable-2 { color: #A9B7C6; }
.cm-s-darcula span.cm-variable-3, .cm-s-darcula span.cm-type { color: #A9B7C6; }
.cm-s-darcula span.cm-property { color: #A9B7C6; }
.cm-s-darcula span.cm-operator { color: #A9B7C6; }
.cm-s-darcula span.cm-string { color: #6A8759; }
.cm-s-darcula span.cm-string-2 { color: #6A8759; }
.cm-s-darcula span.cm-comment { color: #808080; }
.cm-s-darcula span.cm-link { color: #287BDE; }
.cm-s-darcula span.cm-atom { font-weight: bold; color: #CC7832; }
.cm-s-darcula span.cm-error { color: #BC3F3C; }
.cm-s-darcula span.cm-tag { color: #CC7832; }
.cm-s-darcula span.cm-attribute { color: #6A8759; }
.cm-s-darcula span.cm-qualifier { color: #6A8759; }
.cm-s-darcula span.cm-bracket { color: #A9B7C6; }
.cm-s-darcula.CodeMirror { background: #2B2B2B; color: #A9B7C6; }
.cm-s-darcula .CodeMirror-cursor { border-left: 1px solid #dddddd; }
.cm-s-darcula .CodeMirror-activeline-background { background: #3A3A3A; }
.cm-s-darcula div.CodeMirror-selected { background: #085a9c; }
.cm-s-darcula .CodeMirror-gutters { background: rgb(72, 72, 72); border-right: 1px solid grey; color: #606366 }
.cm-s-darcula span.cm-builtin { color: #A9B7C6; }
.cm-s-darcula { font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;}
.cm-s-darcula .CodeMirror-matchingbracket { background-color: #3b514d; color: yellow !important; }
.CodeMirror-hints.darcula {
font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
color: #9c9e9e;
background-color: #3b3e3f !important;
}
.CodeMirror-hints.darcula .CodeMirror-hint-active {
background-color: #494d4e !important;
color: #9c9e9e !important;
}

View File

@ -0,0 +1,34 @@
/*
Name: gruvbox-dark
Author: kRkk (https://github.com/krkk)
Original gruvbox color scheme by Pavel Pertsev (https://github.com/morhetz/gruvbox)
*/
.cm-s-gruvbox-dark.CodeMirror, .cm-s-gruvbox-dark .CodeMirror-gutters { background-color: #282828; color: #bdae93; }
.cm-s-gruvbox-dark .CodeMirror-gutters {background: #282828; border-right: 0px;}
.cm-s-gruvbox-dark .CodeMirror-linenumber {color: #7c6f64;}
.cm-s-gruvbox-dark .CodeMirror-cursor { border-left: 1px solid #ebdbb2; }
.cm-s-gruvbox-dark div.CodeMirror-selected { background: #928374; }
.cm-s-gruvbox-dark span.cm-meta { color: #808000; }
.cm-s-gruvbox-dark span.cm-comment { color: #928374; }
.cm-s-gruvbox-dark span.cm-number, span.cm-atom { color: #d3869b; }
.cm-s-gruvbox-dark span.cm-keyword { color: #f84934; }
.cm-s-gruvbox-dark span.cm-variable { color: #ebdbb2; }
.cm-s-gruvbox-dark span.cm-variable-2 { color: #ebdbb2; }
.cm-s-gruvbox-dark span.cm-variable-3, .cm-s-gruvbox-dark span.cm-type { color: black; }
.cm-s-gruvbox-dark span.cm-operator { color: #ebdbb2; }
.cm-s-gruvbox-dark span.cm-def { color: #ebdbb2; }
.cm-s-gruvbox-dark span.cm-string { color: #b8bb26; }
.cm-s-gruvbox-dark span.cm-string-2 { color: #8ec07c; }
.cm-s-gruvbox-dark span.cm-qualifier { color: #555; }
.cm-s-gruvbox-dark span.cm-attribute { color: #8ec07c; }
.cm-s-gruvbox-dark .CodeMirror-activeline-background { background: #3c3836; }
.cm-s-gruvbox-dark .CodeMirror-matchingbracket { background: #928374; color:#282828 !important; }
.cm-s-gruvbox-dark span.cm-builtin { color: #fe8019; }

42
vendor/codemirror/theme/idea.css vendored Normal file
View File

@ -0,0 +1,42 @@
/**
Name: IDEA default theme
From IntelliJ IDEA by JetBrains
*/
.cm-s-idea span.cm-meta { color: #808000; }
.cm-s-idea span.cm-number { color: #0000FF; }
.cm-s-idea span.cm-keyword { line-height: 1em; font-weight: bold; color: #000080; }
.cm-s-idea span.cm-atom { font-weight: bold; color: #000080; }
.cm-s-idea span.cm-def { color: #000000; }
.cm-s-idea span.cm-variable { color: black; }
.cm-s-idea span.cm-variable-2 { color: black; }
.cm-s-idea span.cm-variable-3, .cm-s-idea span.cm-type { color: black; }
.cm-s-idea span.cm-property { color: black; }
.cm-s-idea span.cm-operator { color: black; }
.cm-s-idea span.cm-comment { color: #808080; }
.cm-s-idea span.cm-string { color: #008000; }
.cm-s-idea span.cm-string-2 { color: #008000; }
.cm-s-idea span.cm-qualifier { color: #555; }
.cm-s-idea span.cm-error { color: #FF0000; }
.cm-s-idea span.cm-attribute { color: #0000FF; }
.cm-s-idea span.cm-tag { color: #000080; }
.cm-s-idea span.cm-link { color: #0000FF; }
.cm-s-idea .CodeMirror-activeline-background { background: #FFFAE3; }
.cm-s-idea span.cm-builtin { color: #30a; }
.cm-s-idea span.cm-bracket { color: #cc7; }
.cm-s-idea { font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;}
.cm-s-idea .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; }
.CodeMirror-hints.idea {
font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
color: #616569;
background-color: #ebf3fd !important;
}
.CodeMirror-hints.idea .CodeMirror-hint-active {
background-color: #a2b8c9 !important;
color: #5c6065 !important;
}

View File

@ -38,7 +38,7 @@ Ported to CodeMirror by Peter Kroon
.cm-s-lesser-dark span.cm-builtin { color: #ff9e59; } .cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }
.cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; } .cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }
.cm-s-lesser-dark span.cm-tag { color: #669199; } .cm-s-lesser-dark span.cm-tag { color: #669199; }
.cm-s-lesser-dark span.cm-attribute { color: #00c; } .cm-s-lesser-dark span.cm-attribute { color: #81a4d5; }
.cm-s-lesser-dark span.cm-hr { color: #999; } .cm-s-lesser-dark span.cm-hr { color: #999; }
.cm-s-lesser-dark span.cm-link { color: #00c; } .cm-s-lesser-dark span.cm-link { color: #00c; }
.cm-s-lesser-dark span.cm-error { color: #9d1e15; } .cm-s-lesser-dark span.cm-error { color: #9d1e15; }

37
vendor/codemirror/theme/lucario.css vendored Normal file
View File

@ -0,0 +1,37 @@
/*
Name: lucario
Author: Raphael Amorim
Original Lucario color scheme (https://github.com/raphamorim/lucario)
*/
.cm-s-lucario.CodeMirror, .cm-s-lucario .CodeMirror-gutters {
background-color: #2b3e50 !important;
color: #f8f8f2 !important;
border: none;
}
.cm-s-lucario .CodeMirror-gutters { color: #2b3e50; }
.cm-s-lucario .CodeMirror-cursor { border-left: solid thin #E6C845; }
.cm-s-lucario .CodeMirror-linenumber { color: #f8f8f2; }
.cm-s-lucario .CodeMirror-selected { background: #243443; }
.cm-s-lucario .CodeMirror-line::selection, .cm-s-lucario .CodeMirror-line > span::selection, .cm-s-lucario .CodeMirror-line > span > span::selection { background: #243443; }
.cm-s-lucario .CodeMirror-line::-moz-selection, .cm-s-lucario .CodeMirror-line > span::-moz-selection, .cm-s-lucario .CodeMirror-line > span > span::-moz-selection { background: #243443; }
.cm-s-lucario span.cm-comment { color: #5c98cd; }
.cm-s-lucario span.cm-string, .cm-s-lucario span.cm-string-2 { color: #E6DB74; }
.cm-s-lucario span.cm-number { color: #ca94ff; }
.cm-s-lucario span.cm-variable { color: #f8f8f2; }
.cm-s-lucario span.cm-variable-2 { color: #f8f8f2; }
.cm-s-lucario span.cm-def { color: #72C05D; }
.cm-s-lucario span.cm-operator { color: #66D9EF; }
.cm-s-lucario span.cm-keyword { color: #ff6541; }
.cm-s-lucario span.cm-atom { color: #bd93f9; }
.cm-s-lucario span.cm-meta { color: #f8f8f2; }
.cm-s-lucario span.cm-tag { color: #ff6541; }
.cm-s-lucario span.cm-attribute { color: #66D9EF; }
.cm-s-lucario span.cm-qualifier { color: #72C05D; }
.cm-s-lucario span.cm-property { color: #f8f8f2; }
.cm-s-lucario span.cm-builtin { color: #72C05D; }
.cm-s-lucario span.cm-variable-3, .cm-s-lucario span.cm-type { color: #ffb86c; }
.cm-s-lucario .CodeMirror-activeline-background { background: #243443; }
.cm-s-lucario .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }

View File

@ -14,6 +14,11 @@
.cm-s-monokai span.cm-atom { color: #ae81ff; } .cm-s-monokai span.cm-atom { color: #ae81ff; }
.cm-s-monokai span.cm-number { color: #ae81ff; } .cm-s-monokai span.cm-number { color: #ae81ff; }
.cm-s-monokai span.cm-comment.cm-attribute { color: #97b757; }
.cm-s-monokai span.cm-comment.cm-def { color: #bc9262; }
.cm-s-monokai span.cm-comment.cm-tag { color: #bc6283; }
.cm-s-monokai span.cm-comment.cm-type { color: #5998a6; }
.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute { color: #a6e22e; } .cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute { color: #a6e22e; }
.cm-s-monokai span.cm-keyword { color: #f92672; } .cm-s-monokai span.cm-keyword { color: #f92672; }
.cm-s-monokai span.cm-builtin { color: #66d9ef; } .cm-s-monokai span.cm-builtin { color: #66d9ef; }

16
vendor/codemirror/theme/ssms.css vendored Normal file
View File

@ -0,0 +1,16 @@
.cm-s-ssms span.cm-keyword { color: blue; }
.cm-s-ssms span.cm-comment { color: darkgreen; }
.cm-s-ssms span.cm-string { color: red; }
.cm-s-ssms span.cm-def { color: black; }
.cm-s-ssms span.cm-variable { color: black; }
.cm-s-ssms span.cm-variable-2 { color: black; }
.cm-s-ssms span.cm-atom { color: darkgray; }
.cm-s-ssms .CodeMirror-linenumber { color: teal; }
.cm-s-ssms .CodeMirror-activeline-background { background: #ffffff; }
.cm-s-ssms span.cm-string-2 { color: #FF00FF; }
.cm-s-ssms span.cm-operator,
.cm-s-ssms span.cm-bracket,
.cm-s-ssms span.cm-punctuation { color: darkgray; }
.cm-s-ssms .CodeMirror-gutters { border-right: 3px solid #ffee62; background-color: #ffffff; }
.cm-s-ssms div.CodeMirror-selected { background: #ADD6FF; }

10
vendor/jsonlint/README.md vendored Normal file
View File

@ -0,0 +1,10 @@
## Jsonlint v1.6.3
Jsonlint installed via npm - source repo:
https://github.com/zaach/jsonlint/blob/v1.6.3/lib/jsonlint.js
If the link doesn't work, it is likely that the npm version and the release versions don't match:
- https://www.npmjs.com/package/jsonlint
- https://github.com/zaach/jsonlint/releases

10
vendor/less/README.md vendored Normal file
View File

@ -0,0 +1,10 @@
## LESS v3.8.0
less.js installed via npm - source repo:
https://github.com/less/less.js/blob/v3.8.0/dist/less.min.js
If the link doesn't work, it is likely that the npm version and the release versions don't match:
- https://www.npmjs.com/package/less
- https://github.com/less/less.js/releases

File diff suppressed because one or more lines are too long

5
vendor/lz-string-unsafe/README.md vendored Normal file
View File

@ -0,0 +1,5 @@
## Lz-string-unsafe v1.4.4-beta
lz-string-unsafe installed via npm - source repo:
https://github.com/openstyles/lz-string-unsafe/blob/v1.4.4-beta/lz-string-unsafe.min.js

View File

@ -0,0 +1 @@
var LZStringUnsafe=function(){function b(z,A){for(var B=0;A>>=1;B++)r=1&z>>B|r<<1,++s===t&&(s=0,q.push(u(r)),r=0)}function d(z){return x[z]}function e(z){return y[z]}function f(z){return p(z+32)}function g(z,A,B){if(q=[],null!=z){r=0,s=0,t=A,u=B;var C=0,D=0,E=0,F=[3],G=[2,2,F],H=!0,I=0,J=3,K=4;if(z.length){I=z.charCodeAt(0),E=256>I?0:1,b(E,K),b(I,E?65536:256),G[1]=I;nextchar:for(C=1;C<z.length;C++){for(I=z.charCodeAt(C),D=1;D<F.length;D+=2)if(F[D]==I){F=F[D+1];continue nextchar}for(H?H=!1:b(F[0],K),D=1;G[D]!=I&&D<G.length;)D+=2;D==G.length&&(++J>=K&&(K<<=1),E=256>I?0:1,b(E,K),b(I,E?65536:256),G.push(I),G.push([J]),H=!0),F.push(I),F.push([++J]),J>=K&&(K<<=1),F=G[D+1]}for(H?H=!1:b(F[0],K),D=1;G[D]!=I&&D<G.length;)D+=2;D==G.length&&(++J>=K&&(K<<=1),E=256>I?0:1,b(E,K),b(I,E?65536:256)),++J>=K&&(K<<=1)}b(2,K),r<<=t-s,q.push(u(r))}return q}function h(z,A,B){for(var C=[0,1,2],D=4,E=4,F=3,G="",H=[],I="",J=0,K=2,L=0,M="",N=B(0),O=A,P=1;L!=K;)J+=(1&N>>--O)<<L++,0==O&&(O=A,N=B(P++));if(2==J)return"";for(K=8*J+8,J=L=0;L!=K;)J+=(1&N>>--O)<<L++,0==O&&(O=A,N=B(P++));for(M=p(J),C[3]=M,I=M,H.push(M);P<=z;){for(K=F,J=L=0;L!=K;)J+=(1&N>>--O)<<L++,0==O&&(O=A,N=B(P++));if(2>J){for(K=8+8*J,J=L=0;L!=K;)J+=(1&N>>--O)<<L++,0==O&&(O=A,N=B(P++));C[E]=p(J),J=E++,0==--D&&(D=1<<F++)}else if(2==J)return H.join("");if(J>C.length)return null;G=J<C.length?C[J]:I+I.charAt(0),H.push(G),C[E++]=I+G.charAt(0),I=G,0==--D&&(D=1<<F++)}return""}function l(z){return g(z,16,p)}function m(z){return null==z?"":0==z.length?null:h(z.length,16,function(A){return z[A].charCodeAt(0)})}for(var q,r,s,t,u,n=0,o={},p=String.fromCharCode,v="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+",x=(v+"/=").split(""),y=(v+"-$").split("");65>n;)62<n&&(o[y[n].charCodeAt(0)]=n),o[x[n].charCodeAt(0)]=n++;return{compressToBase64:function(z){if(null==z)return"";for(var A=g(z,6,d),B=A.length%4;B--;)A.push("=");return A.join("")},decompressFromBase64:function(z){return null==z?"":""==z?null:h(z.length,6,function(A){return o[z.charCodeAt(A)]})},compressToUTF16:function(z){if(null==z)return"";var A=g(z,15,f);return A.push(" "),A.join("")},decompressFromUTF16:function(z){return null==z?"":""==z?null:h(z.length,15,function(A){return z.charCodeAt(A)-32})},compressToUint8Array:function(z){for(var E,A=l(z),B=new Uint8Array(2*A.length),C=0,D=A.length;C<D;C++)E=A[C].charCodeAt(0),B[2*C]=E>>>8,B[2*C+1]=255&E;return B},decompressFromUint8Array:function(z){if(null===z||z===void 0)return m(z);return 0==z.length?null:h(z.length,8,function(A){return z[A]})},compressToEncodedURIComponent:function(z){return null==z?"":g(z,6,e).join("")},decompressFromEncodedURIComponent:function(z){return null==z?"":""==z?null:(z=z.replace(/ /g,"+"),h(z.length,6,function(A){return o[z.charCodeAt(A)]}))},compress:function(z){return l(z).join("")},compressToArray:l,decompress:function(z){return null==z?"":""==z?null:h(z.length,16,function(A){return z.charCodeAt(A)})},decompressFromArray:m}}();"function"==typeof define&&define.amd?define(function(){return LZStringUnsafe}):"undefined"!=typeof module&&null!=module?module.exports=LZStringUnsafe:"undefined"!=typeof angular&&null!=angular&&angular.module("LZStringUnsafe",[]).factory("LZStringUnsafe",function(){return LZStringUnsafe});

View File

@ -1,449 +0,0 @@
var LZStringUnsafe = (
function () {
// private property
var f = String.fromCharCode,
Base64CharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split(''),
UriSafeCharArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$".split(''),
Base64ReverseDic = {},
UriSafeReverseDic = {},
i = 65;
while (i--) {
Base64ReverseDic[Base64CharArray[i].charCodeAt(0)] = i;
UriSafeReverseDic[UriSafeCharArray[i].charCodeAt(0)] = i;
}
var getChar16Bits = function (a) { return f(a); },
getCharFromBase64 = function (a) { return Base64CharArray[a]; },
getCharFromURISafe = function (a) { return UriSafeCharArray[a]; },
getCharFromUTF16 = function (a) { return f(a + 32); };
var LZString = {
compressToBase64: function (input) {
if (input == null) return "";
var res = LZString._compressToArray(input, 6, getCharFromBase64);
// To produce valid Base64
var i = res.length % 4;
while (i--) {
res.push("=");
}
return res.join('');
},
decompressFromBase64: function (input) {
if (input == null) return "";
if (input == "") return null;
return LZString._decompress(input.length, 6, function (index) { return Base64ReverseDic[input.charCodeAt(index)]; });
},
compressToUTF16: function (input) {
if (input == null) return "";
var compressed = LZString._compressToArray(input, 15, getCharFromUTF16);
compressed.push(" ");
return compressed.join('');
},
decompressFromUTF16: function (compressed) {
if (compressed == null) return "";
if (compressed == "") return null;
return LZString._decompress(compressed.length, 15, function (index) { return compressed.charCodeAt(index) - 32; });
},
//compress into uint8array (UCS-2 big endian format)
compressToUint8Array: function (uncompressed) {
var compressed = LZString.compressToArray(uncompressed);
var buf = new Uint8Array(compressed.length * 2); // 2 bytes per character
for (var i = 0, TotalLen = compressed.length; i < TotalLen; i++) {
var current_value = compressed[i].charCodeAt(0);
buf[i * 2] = current_value >>> 8;
buf[i * 2 + 1] = current_value & 0xFF;
}
return buf;
},
//decompress from uint8array (UCS-2 big endian format)
decompressFromUint8Array: function (compressed) {
if (compressed === null || compressed === undefined) {
return LZString.decompressFromArray(compressed);
} else if (compressed.length == 0) {
return null;
}
return LZString._decompress(compressed.length, 8, function (index) { return compressed[index]; });
},
//compress into a string that is already URI encoded
compressToEncodedURIComponent: function (input) {
if (input == null) return "";
return LZString._compressToArray(input, 6, getCharFromURISafe).join('');
},
//decompress from an output of compressToEncodedURIComponent
decompressFromEncodedURIComponent: function (input) {
if (input == null) return "";
if (input == "") return null;
input = input.replace(/ /g, "+");
return LZString._decompress(input.length, 6, function (index) { return UriSafeReverseDic[input.charCodeAt(index)]; });
},
compress: function (uncompressed) {
return LZString.compressToArray(uncompressed).join('');
},
compressToArray: function (uncompressed) {
return LZString._compressToArray(uncompressed, 16, getChar16Bits);
},
_compressToArray: function (uncompressed, bitsPerChar, getCharFromInt) {
if (uncompressed == null) return [];
var i = 0, j = 0, k = 0, value = 0,
node = [3], // first node will always be initialised like this.
// we should never output the root anyway,
// so we initiate with terminating token
// Also, dictionary[1] will be overwritten
// by the firs charCode
dictionary = [2, 2, node],
freshNode = true,
c = 0,
nextNode,
enlargeIn = 1,
dictSize = 4,
numBits = 2,
data = [],
data_val = 0,
data_position = 0;
if (uncompressed.length) {
// If there is a string, the first charCode is guaranteed to
// be new, so we write it to output stream, and add it to the
// dictionary. For the same reason we can initialize freshNode
// as true, and new_node, node and dictSize as if
// it was already added to the dictionary (see above).
c = uncompressed.charCodeAt(0);
// == Write first charCode token to output ==
// 8 or 16 bit?
value = c < 256 ? 0 : 1
// insert "new 8/16 bit charCode" token
// into bitstream (value 1)
for (i = 0; i < numBits; i++) {
// Value is 0 (8 bit) or 1 (16 bit).
// We shift it into the bitstream in reverse
// (shifting has precedence over bitmasking)
data_val = value >> i | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
// insert charCode bits into bitstream
// Nasty but effective hack:
// loop 8 or 16 times based on token value
value = 8 + 8 * value;
for (i = 0; i < value; i++) {
// shifting has precedence over bitmasking
data_val = c >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
// Add charCode to the dictionary.
dictionary[1] = c;
nextchar:
for (j = 1; j < uncompressed.length; j++) {
c = uncompressed.charCodeAt(j);
// does the new charCode match an existing prefix?
for (k = 1; k < node.length; k += 2) {
if (node[k] == c) {
node = node[k + 1];
continue nextchar;
}
}
// we only end up here if there is no matching char
// Prefix+charCode does not exist in trie yet.
// We write the prefix to the bitstream, and add
// the new charCode to the dictionary if it's new
// Then we set `node` to the root node matching
// the charCode.
if (freshNode) {
// Prefix is a freshly added character token,
// which was already written to the bitstream
freshNode = false;
} else {
// write out the current prefix token
value = node[0];
for (i = 0; i < numBits; i++) {
// shifting has precedence over bitmasking
data_val = value >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
}
// Is the new charCode a new character
// that needs to be stored at the root?
k = 1;
while (dictionary[k] != c && k < dictionary.length) {
k += 2;
}
if (k == dictionary.length) {
// increase token bitlength if necessary
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
// insert "new 8/16 bit charCode" token,
// see comments above for explanation
value = c < 256 ? 0 : 1
for (i = 0; i < numBits; i++) {
data_val = value >> i | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
value = 8 + 8 * value;
for (i = 0; i < value; i++) {
data_val = c >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
dictionary.push(c);
dictionary.push([dictSize++]);
// Note of that we already wrote
// the charCode token to the bitstream
freshNode = true;
}
// add node representing prefix + new charCode to trie
node.push(c);
node.push([dictSize++]);
// increase token bitlength if necessary
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
// set node to first charCode of new prefix
// k is guaranteed to be at the current charCode,
// since we either broke out of the while loop
// when it matched, or just added the new charCode
node = dictionary[k + 1];
}
// === Write last prefix to output ===
if (freshNode) {
// character token already written to output
freshNode = false;
} else {
// write out the prefix token
value = node[0];
for (i = 0; i < numBits; i++) {
// shifting has precedence over bitmasking
data_val = value >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
}
// Is c a new character?
k = 1;
while (dictionary[k] != c && k < dictionary.length) {
k += 2;
}
if (k == dictionary.length) {
// increase token bitlength if necessary
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
// insert "new 8/16 bit charCode" token,
// see comments above for explanation
value = c < 256 ? 0 : 1
for (i = 0; i < numBits; i++) {
data_val = value >> i | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
value = 8 + 8 * value;
for (i = 0; i < value; i++) {
data_val = c >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
}
// increase token bitlength if necessary
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
}
// Mark the end of the stream
for (i = 0; i < numBits; i++) {
// shifting has precedence over bitmasking
data_val = 2 >> i & 1 | data_val << 1;
if (++data_position == bitsPerChar) {
data_position = 0;
data.push(getCharFromInt(data_val));
data_val = 0;
}
}
// Flush the last char
data_val <<= bitsPerChar - data_position;
data.push(getCharFromInt(data_val));
return data;
},
decompress: function (compressed) {
if (compressed == null) return "";
if (compressed == "") return null;
return LZString._decompress(compressed.length, 16, function (index) { return compressed.charCodeAt(index); });
},
decompressFromArray: function (compressed) {
if (compressed == null) return "";
if (compressed.length == 0) return null;
return LZString._decompress(compressed.length, 16, function (index) { return compressed[index].charCodeAt(0); });
},
_decompress: function (length, resetBits, getNextValue) {
var dictionary = [0, 1, 2],
enlargeIn = 4,
dictSize = 4,
numBits = 3,
entry = "",
result = [],
w = "",
bits = 0,
maxpower = 2,
power = 0,
c = "",
data_val = getNextValue(0),
data_position = resetBits,
data_index = 1;
// Get first token, guaranteed to be either
// a new character token (8 or 16 bits)
// or end of stream token.
while (power != maxpower) {
// shifting has precedence over bitmasking
bits += (data_val >> --data_position & 1) << power++;
if (data_position == 0) {
data_position = resetBits;
data_val = getNextValue(data_index++);
}
}
// if end of stream token, return empty string
if (bits == 2) {
return "";
}
// else, get character
maxpower = bits * 8 + 8;
bits = power = 0;
while (power != maxpower) {
// shifting has precedence over bitmasking
bits += (data_val >> --data_position & 1) << power++;
if (data_position == 0) {
data_position = resetBits;
data_val = getNextValue(data_index++);
}
}
c = f(bits);
dictionary[3] = c;
w = c;
result.push(c);
// read rest of string
while (data_index <= length) {
// read out next token
maxpower = numBits;
bits = power = 0;
while (power != maxpower) {
// shifting has precedence over bitmasking
bits += (data_val >> --data_position & 1) << power++;
if (data_position == 0) {
data_position = resetBits;
data_val = getNextValue(data_index++);
}
}
// 0 or 1 implies new character token
if (bits < 2) {
maxpower = (8 + 8 * bits);
bits = power = 0;
while (power != maxpower) {
// shifting has precedence over bitmasking
bits += (data_val >> --data_position & 1) << power++;
if (data_position == 0) {
data_position = resetBits;
data_val = getNextValue(data_index++);
}
}
dictionary[dictSize] = f(bits);
bits = dictSize++;
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
} else if (bits == 2) {
// end of stream token
return result.join('');
}
if (bits > dictionary.length) {
return null;
}
entry = bits < dictionary.length ? dictionary[bits] : w + w.charAt(0);
result.push(entry);
// Add w+entry[0] to the dictionary.
dictionary[dictSize++] = w + entry.charAt(0);
w = entry;
if (--enlargeIn == 0) {
enlargeIn = 1 << numBits++;
}
}
return "";
}
};
return LZString;
}
)();
if (typeof define === 'function' && define.amd) {
define(function () { return LZStringUnsafe; });
} else if (typeof module !== 'undefined' && module != null) {
module.exports = LZStringUnsafe
} else if (typeof angular !== 'undefined' && angular != null) {
angular.module('LZStringUnsafe', [])
.factory('LZStringUnsafe', function () {
return LZStringUnsafe;
});
}

View File

@ -1 +0,0 @@
See https://github.com/eight04/node-semver-bundle.

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
https://github.com/eight04/node-semver-bundle https://github.com/openstyles/semver-bundle
https://github.com/eight04/node-semver-bundle/blob/master/LICENSE https://github.com/openstyles/semver-bundle/blob/master/LICENSE
The ISC License The ISC License

5
vendor/semver-bundle/README.md vendored Normal file
View File

@ -0,0 +1,5 @@
## Semver-bundle v0.1.0
semver-bundle installed via npm - source repo:
https://github.com/openstyles/semver-bundle/blob/v0.1.0/dist/semver.js

1
vendor/semver-bundle/semver.js vendored Normal file
View File

@ -0,0 +1 @@
var semverCompare=function(){"use strict";var s=256,i=Number.MAX_SAFE_INTEGER||9007199254740991,a=[],e=[],r=0,t=r++;e[t]="0|[1-9]\\d*";var n=r++;e[n]="[0-9]+";var h=r++;e[h]="\\d*[a-zA-Z-][a-zA-Z0-9-]*";var o=r++;e[o]="("+e[t]+")\\.("+e[t]+")\\.("+e[t]+")";var p=r++;e[p]="("+e[n]+")\\.("+e[n]+")\\.("+e[n]+")";var l=r++;e[l]="(?:"+e[t]+"|"+e[h]+")";var c=r++;e[c]="(?:"+e[n]+"|"+e[h]+")";var v=r++;e[v]="(?:-("+e[l]+"(?:\\."+e[l]+")*))";var f=r++;e[f]="(?:-?("+e[c]+"(?:\\."+e[c]+")*))";var m=r++;e[m]="[0-9A-Za-z-]+";var u=r++;e[u]="(?:\\+("+e[m]+"(?:\\."+e[m]+")*))";var g=r++,w="v?"+e[o]+e[v]+"?"+e[u]+"?";e[g]="^"+w+"$";var d="[v=\\s]*"+e[p]+e[f]+"?"+e[u]+"?",$=r++;e[$]="^"+d+"$";var y=r++;e[y]="((?:<|>)?=?)";var E=r++;e[E]=e[n]+"|x|X|\\*";var j=r++;e[j]=e[t]+"|x|X|\\*";var b=r++;e[b]="[v=\\s]*("+e[j]+")(?:\\.("+e[j]+")(?:\\.("+e[j]+")(?:"+e[v]+")?"+e[u]+"?)?)?";var k=r++;e[k]="[v=\\s]*("+e[E]+")(?:\\.("+e[E]+")(?:\\.("+e[E]+")(?:"+e[f]+")?"+e[u]+"?)?)?",e[r++]="^"+e[y]+"\\s*"+e[b]+"$",e[r++]="^"+e[y]+"\\s*"+e[k]+"$",e[r++]="(?:^|[^\\d])(\\d{1,16})(?:\\.(\\d{1,16}))?(?:\\.(\\d{1,16}))?(?:$|[^\\d])";var T=r++;e[T]="(?:~>?)";var x=r++;e[x]="(\\s*)"+e[T]+"\\s+",a[x]=new RegExp(e[x],"g"),e[r++]="^"+e[T]+e[b]+"$",e[r++]="^"+e[T]+e[k]+"$";var I=r++;e[I]="(?:\\^)";var A=r++;e[A]="(\\s*)"+e[I]+"\\s+",a[A]=new RegExp(e[A],"g"),e[r++]="^"+e[I]+e[b]+"$",e[r++]="^"+e[I]+e[k]+"$",e[r++]="^"+e[y]+"\\s*("+d+")$|^$",e[r++]="^"+e[y]+"\\s*("+w+")$|^$";var R=r++;e[R]="(\\s*)"+e[y]+"\\s*("+d+"|"+e[b]+")",a[R]=new RegExp(e[R],"g"),e[r++]="^\\s*("+e[b]+")\\s+-\\s+("+e[b]+")\\s*$",e[r++]="^\\s*("+e[k]+")\\s+-\\s+("+e[k]+")\\s*$",e[r++]="(<|>)?=?\\s*\\*";for(var N=0;N<35;N++)a[N]||(a[N]=new RegExp(e[N]));function z(e,r){if(e instanceof z){if(e.loose===r)return e;e=e.version}else if("string"!=typeof e)throw new TypeError("Invalid Version: "+e);if(e.length>s)throw new TypeError("version is longer than "+s+" characters");if(!(this instanceof z))return new z(e,r);this.loose=r;var t=e.trim().match(r?a[$]:a[g]);if(!t)throw new TypeError("Invalid Version: "+e);if(this.raw=e,this.major=+t[1],this.minor=+t[2],this.patch=+t[3],this.major>i||this.major<0)throw new TypeError("Invalid major version");if(this.minor>i||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>i||this.patch<0)throw new TypeError("Invalid patch version");t[4]?this.prerelease=t[4].split(".").map(function(e){if(/^[0-9]+$/.test(e)){var r=+e;if(0<=r&&r<i)return r}return e}):this.prerelease=[],this.build=t[5]?t[5].split("."):[],this.format()}z.prototype.format=function(){return this.version=this.major+"."+this.minor+"."+this.patch,this.prerelease.length&&(this.version+="-"+this.prerelease.join(".")),this.version},z.prototype.toString=function(){return this.version},z.prototype.compare=function(e){return e instanceof z||(e=new z(e,this.loose)),this.compareMain(e)||this.comparePre(e)},z.prototype.compareMain=function(e){return e instanceof z||(e=new z(e,this.loose)),X(this.major,e.major)||X(this.minor,e.minor)||X(this.patch,e.patch)},z.prototype.comparePre=function(e){if(e instanceof z||(e=new z(e,this.loose)),this.prerelease.length&&!e.prerelease.length)return-1;if(!this.prerelease.length&&e.prerelease.length)return 1;if(!this.prerelease.length&&!e.prerelease.length)return 0;var r=0;do{var t=this.prerelease[r],s=e.prerelease[r];if(void 0===t&&void 0===s)return 0;if(void 0===s)return 1;if(void 0===t)return-1;if(t!==s)return X(t,s)}while(++r)},z.prototype.inc=function(e,r){switch(e){case"premajor":this.prerelease.length=0,this.patch=0,this.minor=0,this.major++,this.inc("pre",r);break;case"preminor":this.prerelease.length=0,this.patch=0,this.minor++,this.inc("pre",r);break;case"prepatch":this.prerelease.length=0,this.inc("patch",r),this.inc("pre",r);break;case"prerelease":0===this.prerelease.length&&this.inc("patch",r),this.inc("pre",r);break;case"major":0===this.minor&&0===this.patch&&0!==this.prerelease.length||this.major++,this.minor=0,this.patch=0,this.prerelease=[];break;case"minor":0===this.patch&&0!==this.prerelease.length||this.minor++,this.patch=0,this.prerelease=[];break;case"patch":0===this.prerelease.length&&this.patch++,this.prerelease=[];break;case"pre":if(0===this.prerelease.length)this.prerelease=[0];else{for(var t=this.prerelease.length;0<=--t;)"number"==typeof this.prerelease[t]&&(this.prerelease[t]++,t=-2);-1===t&&this.prerelease.push(0)}r&&(this.prerelease[0]===r?isNaN(this.prerelease[1])&&(this.prerelease=[r,0]):this.prerelease=[r,0]);break;default:throw new Error("invalid increment argument: "+e)}return this.format(),this.raw=this.version,this};var M=/^[0-9]+$/;function X(e,r){var t=M.test(e),s=M.test(r);return t&&s&&(e=+e,r=+r),t&&!s?-1:s&&!t?1:e<r?-1:r<e?1:0}return function(e,r,t){return new z(e,t).compare(new z(r,t))}}();

5
vendor/stylelint-bundle/README.md vendored Normal file
View File

@ -0,0 +1,5 @@
## Stylelint-bundle v8.0.0
stylelint-bundle installed via npm - source repo:
https://github.com/openstyles/stylelint-bundle/blob/v8.0.0/stylelint-bundle.min.js

View File

@ -1,7 +1,8 @@
http://stylus-lang.com/ http://stylus-lang.com/
https://github.com/stylus/stylus/ https://github.com/stylus/stylus/
https://github.com/openstyles/stylus-lang-bundle
https://github.com/stylus/stylus/blob/dev/LICENSE https://github.com/openstyles/stylus-lang-bundle/blob/master/LICENSE
The MIT License The MIT License

5
vendor/stylus-lang-bundle/README.md vendored Normal file
View File

@ -0,0 +1,5 @@
## Stylus-lang-bundle v0.54.5
stylus-lang-bundle installed via npm - source repo:
https://github.com/openstyles/stylus-lang-bundle/blob/v0.54.5/stylus.min.js