Merge branch 'master' of https://github.com/openstyles/stylus into dev-exclusions
This commit is contained in:
commit
24b1eea8a4
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
|
@ -21,7 +21,7 @@ If not, then provide details describing which page the feature will effect, e.g.
|
|||
|
||||
## Adding translations
|
||||
|
||||
You can help us translate the extension on [Transifex](https://www.transifex.com/github-7/Stylus). When `messages.json` file is ready to be merged, please open a new bug report in [stylus/issues](https://github.com/openstyles/stylus/issues).
|
||||
You can help us translate the extension on [Transifex](https://www.transifex.com/github-7/Stylus).
|
||||
|
||||
## Pull requests
|
||||
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@ node_modules/
|
|||
package-lock.json
|
||||
yarn.lock
|
||||
*.zip
|
||||
.eslintcache
|
||||
|
|
|
@ -39,7 +39,7 @@ Stylus is a fork of Stylish for Chrome, also compatible with Firefox as a WebExt
|
|||
|
||||
The source is hosted on [GitHub](https://github.com/openstyles/stylus) and pull requests are welcome.
|
||||
|
||||
You can help us translate the extension on [Transifex](https://www.transifex.com/github-7/Stylus). When `messages.json` file is ready to be merged, please open a new bug report in [stylus/issues](https://github.com/openstyles/stylus/issues).
|
||||
You can help us translate the extension on [Transifex](https://www.transifex.com/github-7/Stylus).
|
||||
|
||||
See our [contributing](./.github/CONTRIBUTING.md) page for more details.
|
||||
|
||||
|
|
|
@ -1,210 +1,163 @@
|
|||
{
|
||||
"appliesToEverything": {
|
||||
"message": "كل شيء",
|
||||
"description": "Text displayed for styles that apply to all sites"
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "تمكين",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "أدخل اسمًا",
|
||||
"description": "Error displayed when user saves without providing a name"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "عناوين URL في النطاق",
|
||||
"description": "Option to make the style apply to the entered string as a domain"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "البحث عن تحديث",
|
||||
"description": "Label for the button to check a single style for an update"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "مساعدة",
|
||||
"description": "Alternate text for help buttons"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "البحث عن المزيد من الأنماط لموقع الويب هذا",
|
||||
"description": "Text for a link that gets a list of styles for the current site"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "الأنماط المثبتة",
|
||||
"description": "Heading for the manage page"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "ممكّن",
|
||||
"description": "Label for the enabled state of styles"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "يمكن استخدام تنسيق موزيلا للرمز باستخدام Stylus للمتصفح فايرفوكس ويمكن إرساله إلى userstyles.org.",
|
||||
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "إضافة قسم آخر",
|
||||
"description": "Label for the button to add a section"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "حفظ",
|
||||
"description": "Label for save button for style editing"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "إضافة",
|
||||
"description": "Label for the button to add an 'applies' entry"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "عناوين URL التي تطابق regexp",
|
||||
"description": "Option to make the style apply to the entered string as a regular expression"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "هل تريد تثبيت '$stylename$' في Stylus؟",
|
||||
"description": "Confirmation when installing a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "تعطيل",
|
||||
"description": "Label for the button to disable a style"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "رجوع للإدارة",
|
||||
"description": "Label for cancel button for style editing"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "لقد أجريت تغييرات على هذا النمط بدون حفظها.",
|
||||
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "أخفق التحديث - الخادم يتعذر الوصول إليه.",
|
||||
"description": "Text that displays when an update check failed because the update server is unreachable"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "هل تريد بالتأكيد حذف هذا النمط؟",
|
||||
"description": "Confirmation before deleting a style"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "ينطبق على: $applies$",
|
||||
"description": "Text on the manage screen to describe what the style applies to",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "الأقسام",
|
||||
"description": "Title for the style sections section"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "تعديل النمط $stylename$",
|
||||
"description": "Title of the page for editing styles",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "النمط محدّث.",
|
||||
"description": "Text that displays when an update check completed and no update is available"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "عناوين URL البادئة بـ",
|
||||
"description": "Option to make the style apply to the entered string as a URL prefix"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "تتيح لك الأقسام تحديد أجزاء مختلفة من الرمز لتطبيقها على مجموعات مختلفة من عناوين URL بالنمط نفسه. فعلى سبيل المثال، يمكن لنمط مفرد تغيير الصفحة الرئيسية لموقع ويب بطريقة، مع تغيير بقية أجزاء موقع الويب بطريقة أخرى.",
|
||||
"description": "Help text for sections"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "لم يتم تثبيت أي أنماط لموقع الويب هذا.",
|
||||
"description": "Text displayed when no styles are installed for the current site"
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "والمزيد",
|
||||
"description": "Text added to appliesDisplay when there are more sites for the style than are displayed"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "إزالة",
|
||||
"description": "Label for the button to remove an 'applies' entry"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "ينطبق على",
|
||||
"description": "Label for 'applies to' fields on the edit/add screen"
|
||||
},
|
||||
"openManage": {
|
||||
"message": "إدارة الأنماط المثبتة",
|
||||
"description": "Link to open the manage page."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "أخفق التحديث - استجاب الخادم بالرمز $code$",
|
||||
"description": "Text that displays when an update check failed because the response code indicates an error",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "تحديد",
|
||||
"description": "Label for the button to make a style apply only to specific sites"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "تثبيت التحديث",
|
||||
"description": "Label for the button to install an update for a single style"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "إزالة القسم",
|
||||
"description": "Label for the button to remove a section"
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "اكتمل التحديث.",
|
||||
"description": "Text that displays when an update completed"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "جارٍ البحث...",
|
||||
"description": "Text to display when checking a style for an update"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "الرمز",
|
||||
"description": "Label for the code for a section"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "استخدم عناصر تحكم 'ينطبق على' لتقييد عناوين URL التي ينطبق عليها الرمز في هذا القسم.",
|
||||
"description": "Help text for 'applies to' section"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "تعديل النمط",
|
||||
"description": "Title of the page for editing styles"
|
||||
},
|
||||
"appliesUrlOption": {
|
||||
"message": "عنوان URL",
|
||||
"description": "Option to make the style apply to the entered string as a URL"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "إضافة نمط",
|
||||
"description": "Title of the page for adding styles"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "البحث عن تحديثات لكل الأنماط",
|
||||
"description": "Label for the button to check all styles for updates"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "حذف",
|
||||
"description": "Label for the button to delete a style"
|
||||
},
|
||||
"addStyleLabel": {
|
||||
"message": "كتابة نمط جديد",
|
||||
"description": "Label for the button to go to the add style page"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "تعديل",
|
||||
"description": "Label for the button to go to the edit style page"
|
||||
},
|
||||
"description": {
|
||||
"message": "يمكنك تغيير نمط الويب باستخدام Stylus، وهي أداة لإدارة أنماط المستخدم. وتتيح Stylus لك بسهولة تثبيت المظاهر والأشكال الخارجية لكل من Google، وFacebook وYouTube وOrkut فضلاً عن الكثير جدًا من مواقع الويب الأخرى.",
|
||||
"description": "Extension description"
|
||||
}
|
||||
"addStyleLabel": {
|
||||
"message": "كتابة نمط جديد"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "إضافة نمط"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "إضافة"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "ينطبق على: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "والمزيد"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "عناوين URL في النطاق"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "استخدم عناصر تحكم 'ينطبق على' لتقييد عناوين URL التي ينطبق عليها الرمز في هذا القسم."
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "ينطبق على"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "عناوين URL التي تطابق regexp"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "إزالة"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "تحديد"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "كل شيء"
|
||||
},
|
||||
"appliesUrlOption": {
|
||||
"message": "عنوان URL"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "عناوين URL البادئة بـ"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "البحث عن تحديثات لكل الأنماط"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "البحث عن تحديث"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "جارٍ البحث..."
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "هل تريد بالتأكيد حذف هذا النمط؟"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "حذف"
|
||||
},
|
||||
"description": {
|
||||
"message": "يمكنك تغيير نمط الويب باستخدام Stylus، وهي أداة لإدارة أنماط المستخدم. وتتيح Stylus لك بسهولة تثبيت المظاهر والأشكال الخارجية لكل من Google، وFacebook وYouTube وOrkut فضلاً عن الكثير جدًا من مواقع الويب الأخرى."
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "تعطيل"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "تعديل النمط"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "تعديل"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "تعديل النمط $stylename$",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "تمكين"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "البحث عن المزيد من الأنماط لموقع الويب هذا"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "مساعدة"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "تثبيت التحديث"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "الأنماط المثبتة"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "لم يتم تثبيت أي أنماط لموقع الويب هذا."
|
||||
},
|
||||
"openManage": {
|
||||
"message": "إدارة الأنماط المثبتة"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "إضافة قسم آخر"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "الرمز"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "تتيح لك الأقسام تحديد أجزاء مختلفة من الرمز لتطبيقها على مجموعات مختلفة من عناوين URL بالنمط نفسه. فعلى سبيل المثال، يمكن لنمط مفرد تغيير الصفحة الرئيسية لموقع ويب بطريقة، مع تغيير بقية أجزاء موقع الويب بطريقة أخرى."
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "إزالة القسم"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "رجوع للإدارة"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "لقد أجريت تغييرات على هذا النمط بدون حفظها."
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "ممكّن"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "هل تريد تثبيت '$stylename$' في Stylus؟",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "أدخل اسمًا"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "حفظ"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "الأقسام"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "يمكن استخدام تنسيق موزيلا للرمز باستخدام Stylus للمتصفح فايرفوكس ويمكن إرساله إلى userstyles.org."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "أخفق التحديث - استجاب الخادم بالرمز $code$",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "أخفق التحديث - الخادم يتعذر الوصول إليه."
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "النمط محدّث."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "اكتمل التحديث."
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
287
_locales/bg_BG/messages.json
Normal file
287
_locales/bg_BG/messages.json
Normal file
|
@ -0,0 +1,287 @@
|
|||
{
|
||||
"addStyleLabel": {
|
||||
"message": "Напиши нов стил"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Добави стил"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Добави"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Прилага се към: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "и още"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URLи на домейна"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Използвайте \"Прилага се към\", за да ограничете адресите, за които ще работи кодът в тази секция."
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Прилага се към"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "Адреси, съвпадащи с regexp"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Премахни"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Уточни"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "Всички"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "URL започващи с"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Приложи всички промени"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Провери всички стилове за обновления"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Провери за обновление"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Проверявам..."
|
||||
},
|
||||
"cm_indentWithTabs": {
|
||||
"message": "Използвай табулация с умно отместване"
|
||||
},
|
||||
"cm_keyMap": {
|
||||
"message": "Клавишни комбинации"
|
||||
},
|
||||
"cm_lineWrapping": {
|
||||
"message": "Автоматично пренасяне"
|
||||
},
|
||||
"cm_smartIndent": {
|
||||
"message": "Използвай умно отместване"
|
||||
},
|
||||
"cm_tabSize": {
|
||||
"message": "Размер на табулацията"
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "Тема"
|
||||
},
|
||||
"confirmNo": {
|
||||
"message": "Не"
|
||||
},
|
||||
"confirmStop": {
|
||||
"message": "Спри"
|
||||
},
|
||||
"confirmYes": {
|
||||
"message": "Да"
|
||||
},
|
||||
"dbError": {
|
||||
"message": "Грешка в базата данни на Stylus. Желаеш ли да посетиш уебстраницата с възможни решения?"
|
||||
},
|
||||
"defaultTheme": {
|
||||
"message": "по подразбиране"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Наистина ли искаш да изтриеш този стил?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Изтрий"
|
||||
},
|
||||
"description": {
|
||||
"message": "Промени уеба със Stylus, мениджър на потребителски стилове. Stylus ти позволява лесно да инсталираш теми и скинове за много популярни сайтове."
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "Изключи всички стилове"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Забрани"
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Иди на ред (или ред:кол)"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Промени стила"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Редактирай"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Редактирай стил $stylename$",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Разреши"
|
||||
},
|
||||
"exportLabel": {
|
||||
"message": "Експорт"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Помощ"
|
||||
},
|
||||
"helpKeyMapCommand": {
|
||||
"message": "Напиши име на команда"
|
||||
},
|
||||
"helpKeyMapHotkey": {
|
||||
"message": "Натисни клавишна комбинация"
|
||||
},
|
||||
"importAppendLabel": {
|
||||
"message": "Добави към стил"
|
||||
},
|
||||
"importAppendTooltip": {
|
||||
"message": "Добави импортирания стил към текущия"
|
||||
},
|
||||
"importLabel": {
|
||||
"message": "Импорт"
|
||||
},
|
||||
"importReplaceLabel": {
|
||||
"message": "Презапиши стила"
|
||||
},
|
||||
"importReplaceTooltip": {
|
||||
"message": "Презапишете съдържанието на текущия стил с импортирания"
|
||||
},
|
||||
"installButton": {
|
||||
"message": "Инсталирай стил"
|
||||
},
|
||||
"installButtonInstalled": {
|
||||
"message": "Стилът е инсталиран"
|
||||
},
|
||||
"installButtonReinstall": {
|
||||
"message": "Преинсталирай стила"
|
||||
},
|
||||
"installButtonUpdate": {
|
||||
"message": "Обнови стила"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Инсталирай обновление"
|
||||
},
|
||||
"installUpdateFrom": {
|
||||
"message": "В момента стилът се обновява от $url$",
|
||||
"placeholders": {
|
||||
"url": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"installUpdateFromLabel": {
|
||||
"message": "Провери за обновления"
|
||||
},
|
||||
"installUpdateUnavailable": {
|
||||
"message": "За да разрешите проверка за обновления, пуснете файла върху лентата с табове, или в метаданните на стила укажете @updateURL."
|
||||
},
|
||||
"license": {
|
||||
"message": "Лиценз"
|
||||
},
|
||||
"linkGetHelp": {
|
||||
"message": "Получете помощ"
|
||||
},
|
||||
"linkGetStyles": {
|
||||
"message": "Вземете стилове"
|
||||
},
|
||||
"linkTranslate": {
|
||||
"message": "Преведете"
|
||||
},
|
||||
"linterCSSLintIncompatible": {
|
||||
"message": "CSSLint не поддържа $preprocessorname$ preprocessor",
|
||||
"placeholders": {
|
||||
"preprocessorname": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linterCSSLintSettings": {
|
||||
"message": "(Укажете правилата: 0 = забранен; 1 = предупреждения; 2 = грешки)"
|
||||
},
|
||||
"linterConfigPopupTitle": {
|
||||
"message": "Настройте конфигурация за $linter$ правила",
|
||||
"placeholders": {
|
||||
"linter": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linterConfigTooltip": {
|
||||
"message": "Щракнете, за да конфигурирате този linter"
|
||||
},
|
||||
"linterInvalidConfigError": {
|
||||
"message": "Не е записано заради тези неправилни настройки"
|
||||
},
|
||||
"linterIssues": {
|
||||
"message": "Проблеми"
|
||||
},
|
||||
"linterIssuesHelp": {
|
||||
"message": "Тези проблеми бяха намерени от $link$:",
|
||||
"placeholders": {
|
||||
"link": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linterJSONError": {
|
||||
"message": "Невалиден JSON формат"
|
||||
},
|
||||
"linterResetMessage": {
|
||||
"message": "За да върнете погрешно нулиране, натиснете Ctrl-Z (или Cmd-Z) в текстовия прозорец"
|
||||
},
|
||||
"linterRulesLink": {
|
||||
"message": "Вижте пълния списък с правила"
|
||||
},
|
||||
"liveReloadError": {
|
||||
"message": "Получи се грешка докато наблюдавахме файла"
|
||||
},
|
||||
"liveReloadInstallHint": {
|
||||
"message": "Преглед на живо е разрешен, така че инсталирания стил ще бъде обновен автоматично при външни промени докато двата прозореца с кода и оригинала са отворени."
|
||||
},
|
||||
"liveReloadLabel": {
|
||||
"message": "Преглед на живо"
|
||||
},
|
||||
"liveReloadUnavailable": {
|
||||
"message": "За да разрешите презареждане в реално време, пуснете файла върху лентата с табове (областта, където са показани заглавията на табовете)."
|
||||
},
|
||||
"manageFilters": {
|
||||
"message": "Филтри"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Инсталирани стилове"
|
||||
},
|
||||
"manageNewStyleAsUsercss": {
|
||||
"message": "като Потребителскиcss"
|
||||
},
|
||||
"manageNewUI": {
|
||||
"message": "Нова подредба на UI"
|
||||
},
|
||||
"manageOnlyDisabled": {
|
||||
"message": "Само забранените стилове"
|
||||
},
|
||||
"manageOnlyEnabled": {
|
||||
"message": "Само разрешените стилове"
|
||||
},
|
||||
"manageOnlyExternal": {
|
||||
"message": "Само външните стилове"
|
||||
},
|
||||
"manageOnlyLocal": {
|
||||
"message": "Само локалните стилове"
|
||||
},
|
||||
"manageOnlyLocalTooltip": {
|
||||
"message": "(стиловете не инсталирани чрез страницата на userstyles.org)"
|
||||
},
|
||||
"manageOnlyNonUsercss": {
|
||||
"message": "Само не-Потребителскитеcss стилове"
|
||||
},
|
||||
"manageOnlyUpdates": {
|
||||
"message": "Само с обновления или проблеми"
|
||||
},
|
||||
"manageOnlyUsercss": {
|
||||
"message": "Само Потребителскиcss стилове"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,295 +1,228 @@
|
|||
{
|
||||
"appliesToEverything": {
|
||||
"message": "Τα πάντα",
|
||||
"description": "Text displayed for styles that apply to all sites"
|
||||
},
|
||||
"cm_tabSize": {
|
||||
"message": "Μέγεθος καρτέλας",
|
||||
"description": "Label for the text box controlling tab size option for the style editor."
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Ενεργοποίηση",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Εισάγετε ένα όνομα",
|
||||
"description": "Error displayed when user saves without providing a name"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URL στον τομέα",
|
||||
"description": "Option to make the style apply to the entered string as a domain"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Έλεγχος για ενημερώσεις",
|
||||
"description": "Label for the button to check a single style for an update"
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "Όλα τα στυλ είναι ενημερωμένα.",
|
||||
"description": "Text that displays when an update all check completed and no updates are available"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Βοήθεια",
|
||||
"description": "Alternate text for help buttons"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Αναζήτηση περισσότερων στυλ για αυτή την ιστοσελίδα",
|
||||
"description": "Text for a link that gets a list of styles for the current site"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Εγκατεστημένα Στυλ",
|
||||
"description": "Heading for the manage page"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Ενεργοποιημένη",
|
||||
"description": "Label for the enabled state of styles"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Η μορφή του Mozilla κώδικα μπορεί να χρησιμοποιηθεί με το Stylish για το Firefox και μπορεί να υποβληθεί στο userstyles.org.",
|
||||
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Προσθήκη ένος άλλου τμήματος",
|
||||
"description": "Label for the button to add a section"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Αποθήκευση",
|
||||
"description": "Label for save button for style editing"
|
||||
},
|
||||
"writeStyleForURL": {
|
||||
"message": "αυτή την διεύθυνση URL",
|
||||
"description": "Text for link in toolbar pop-up to write a new style for the current URL"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Προσθήκη",
|
||||
"description": "Label for the button to add an 'applies' entry"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "Διευθύνσεις URL που ταιριάζουν με την κανονική έκφραση",
|
||||
"description": "Option to make the style apply to the entered string as a regular expression"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Εγκατάσταση του '$stylename$' στο Stylus;",
|
||||
"description": "Confirmation when installing a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Απενεργοποίηση",
|
||||
"description": "Label for the button to disable a style"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Εμφάνιση αριθμού των στυλ που δραστηριοποιούνται για την τρέχουσα τοποθεσία στην μπάρα εργαλείων",
|
||||
"description": "Label for the checkbox controlling toolbar badge text."
|
||||
},
|
||||
"menuShowBadge": {
|
||||
"message": "Εμφάνιση ενεργους καταμέτρησης στυλ",
|
||||
"description": "Label (must be very short) for the checkbox in the toolbar button context menu controlling toolbar badge text."
|
||||
},
|
||||
"cm_lineWrapping": {
|
||||
"message": "Αναδίπλωση λέξεων",
|
||||
"description": "Label for the checkbox controlling word wrap option for the style editor."
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Πίσω στη διαχείριση",
|
||||
"description": "Label for cancel button for style editing"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Έχετε κάνει αλλαγές σε αυτό το ύφος χωρίς αποθήκευση.",
|
||||
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Αποτυχία ενημέρωσης: απρόσιτος διακομιστής.",
|
||||
"description": "Text that displays when an update check failed because the update server is unreachable"
|
||||
},
|
||||
"manageFilters": {
|
||||
"message": "Φίλτρα",
|
||||
"description": "Label for filters container"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Εφαρμογή όλων των ενημερώσεων",
|
||||
"description": "Label for the button to apply all detected updates"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το στυλ;",
|
||||
"description": "Confirmation before deleting a style"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Το Regexp δεν είναι έγκυρο.",
|
||||
"description": "Validation message for a bad regexp in a style"
|
||||
},
|
||||
"optionsHeading": {
|
||||
"message": "Επιλογές",
|
||||
"description": "Heading for options section on manage page."
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Ισχύει για: $applies$",
|
||||
"description": "Text on the manage screen to describe what the style applies to",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleUpdate": {
|
||||
"message": "Είστε σίγουροι ότι θέλετε να ενημερώσετε το '$stylename$';",
|
||||
"description": "Confirmation when updating a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Ενότητες",
|
||||
"description": "Title for the style sections section"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Επεξεργασία του στυλ $stylename$",
|
||||
"description": "Title of the page for editing styles",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Το στυλ είναι ενημερωμένο.",
|
||||
"description": "Text that displays when an update check completed and no update is available"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "Διευθύνσεις URL που αρχίζουν με",
|
||||
"description": "Option to make the style apply to the entered string as a URL prefix"
|
||||
},
|
||||
"popupStylesFirst": {
|
||||
"message": "Στυλ λίστας πριν των εντολών στο μενού του κουμπιού γραμμής εργαλείων",
|
||||
"description": "Label for the checkbox controlling section order in the popup."
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Ενότητες σας επιτρέπουν να ορίσετε διαφορετικά κομμάτια του κώδικα για να εφαρμόζονται σε διαφορετικά σύνολα των διευθύνσεων URL στο ίδιο στυλ. Για παράδειγμα, ένα ενιαίο ύφος θα μπορούσε να αλλάξει την αρχική σελίδα ενός ιστότοπου με έναν τρόπο, ενώ αλλάζει το υπόλοιπο μιας τοποθεσίας ένας άλλος τρόπος.",
|
||||
"description": "Help text for sections"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Δεν υπάρχουν εγκατεστημένα στυλ για αυτή την ιστοσελίδα.",
|
||||
"description": "Text displayed when no styles are installed for the current site"
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "και πολλά άλλα",
|
||||
"description": "Text added to appliesDisplay when there are more sites for the style than are displayed"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Αφαίρεση",
|
||||
"description": "Label for the button to remove an 'applies' entry"
|
||||
},
|
||||
"manageTitle": {
|
||||
"message": "Κομψή",
|
||||
"description": "Title for the manage page"
|
||||
},
|
||||
"writeStyleFor": {
|
||||
"message": "Γράψτε νέο στυλ για:",
|
||||
"description": "Label for toolbar pop-up that precedes the links to write a new style"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Ισχύει για",
|
||||
"description": "Label for 'applies to' fields on the edit/add screen"
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Διαχείριση εγκατεστημένων στυλ",
|
||||
"description": "Link to open the manage page."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Αποτυχία ενημέρωσης: ο διακομιστής ανταποκρίθηκε με κωδικό $code$.",
|
||||
"description": "Text that displays when an update check failed because the response code indicates an error",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Καθορισμός",
|
||||
"description": "Label for the button to make a style apply only to specific sites"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Εγκατάσταση ενημέρωσης",
|
||||
"description": "Label for the button to install an update for a single style"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Αφαίρεση ενότητας",
|
||||
"description": "Label for the button to remove a section"
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "Απενεργοποιηση ολων των στυλ",
|
||||
"description": "Label for the checkbox that turns all enabled styles off."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Η ενημέρωση ολοκληρώθηκε.",
|
||||
"description": "Text that displays when an update completed"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Έλεγχος...",
|
||||
"description": "Text to display when checking a style for an update"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Κώδικας",
|
||||
"description": "Label for the code for a section"
|
||||
},
|
||||
"cm_smartIndent": {
|
||||
"message": "Χρήση έξυπνης εσοχής",
|
||||
"description": "Label for the checkbox controlling smart indentation option for the style editor."
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Χρησιμοποιήστε το \"Ισχύει για\" έλεγχοι ώστε να περιοριστουν ποιες διευθύνσεις τον κώδικα σε αυτό το τμήμα να εφαρμόζονται.",
|
||||
"description": "Help text for 'applies to' section"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Επεξεργασία Στυλ",
|
||||
"description": "Title of the page for editing styles"
|
||||
},
|
||||
"stylusUnavailableForURL": {
|
||||
"message": "To Stylus δεν λειτουργεί σε σελίδες όπως αυτή.",
|
||||
"description": "Note in the toolbar pop-up when on a URL Stylus can't affect"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Προσθήκη στυλ",
|
||||
"description": "Title of the page for adding styles"
|
||||
},
|
||||
"dbError": {
|
||||
"message": "Παρουσιάστηκε σφάλμα χρησιμοποιώντας την κομψή βάση δεδομένων. Θα θέλατε να επισκεφθείτε μια ιστοσελίδα με πιθανές λύσεις;",
|
||||
"description": "Prompt when a DB error is encountered"
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Μετάβαση στη γραμμή (ή line:col)",
|
||||
"description": "Go to line or line:column on Ctrl-G in style code editor"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Έλεγχος όλων των στυλ για ενημερώσεις",
|
||||
"description": "Label for the button to check all styles for updates"
|
||||
},
|
||||
"cm_indentWithTabs": {
|
||||
"message": "Χρήση καρτελών με έξυπνη εσοχή",
|
||||
"description": "Label for the checkbox controlling tabs with smart indentation option for the style editor."
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Διαγραφή",
|
||||
"description": "Label for the button to delete a style"
|
||||
},
|
||||
"addStyleLabel": {
|
||||
"message": "Γράψτε νέο στυλ",
|
||||
"description": "Label for the button to go to the add style page"
|
||||
},
|
||||
"manageOnlyEnabled": {
|
||||
"message": "Μόνο ενεργοποιημένα στυλ",
|
||||
"description": "Checkbox to show only enabled styles"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Επεξεργασία",
|
||||
"description": "Label for the button to go to the edit style page"
|
||||
},
|
||||
"description": {
|
||||
"message": "Επαναπροσδιορίση του διαδίκτυου με το Stylus, έναν διαχειριστή στυλ. Το Stylus σας επιτρέπει να εγκαταστήσετε εύκολα themes και skins για πολλές δημοφιλείς ιστοσελίδες.",
|
||||
"description": "Extension description"
|
||||
}
|
||||
"addStyleLabel": {
|
||||
"message": "Γράψτε νέο στυλ"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Προσθήκη στυλ"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Προσθήκη"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Ισχύει για: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "και πολλά άλλα"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URL στον τομέα"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Χρησιμοποιήστε το \"Ισχύει για\" έλεγχοι ώστε να περιοριστουν ποιες διευθύνσεις τον κώδικα σε αυτό το τμήμα να εφαρμόζονται."
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Ισχύει για"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "Διευθύνσεις URL που ταιριάζουν με την κανονική έκφραση"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Αφαίρεση"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Καθορισμός"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "Τα πάντα"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "Διευθύνσεις URL που αρχίζουν με"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Εφαρμογή όλων των ενημερώσεων"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Έλεγχος όλων των στυλ για ενημερώσεις"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Έλεγχος για ενημερώσεις"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Έλεγχος..."
|
||||
},
|
||||
"cm_indentWithTabs": {
|
||||
"message": "Χρήση καρτελών με έξυπνη εσοχή"
|
||||
},
|
||||
"cm_lineWrapping": {
|
||||
"message": "Αναδίπλωση λέξεων"
|
||||
},
|
||||
"cm_smartIndent": {
|
||||
"message": "Χρήση έξυπνης εσοχής"
|
||||
},
|
||||
"cm_tabSize": {
|
||||
"message": "Μέγεθος καρτέλας"
|
||||
},
|
||||
"dbError": {
|
||||
"message": "Παρουσιάστηκε σφάλμα χρησιμοποιώντας την κομψή βάση δεδομένων. Θα θέλατε να επισκεφθείτε μια ιστοσελίδα με πιθανές λύσεις;"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το στυλ;"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Διαγραφή"
|
||||
},
|
||||
"description": {
|
||||
"message": "Επαναπροσδιορίση του διαδίκτυου με το Stylus, έναν διαχειριστή στυλ. Το Stylus σας επιτρέπει να εγκαταστήσετε εύκολα themes και skins για πολλές δημοφιλείς ιστοσελίδες."
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "Απενεργοποιηση ολων των στυλ"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Απενεργοποίηση"
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Μετάβαση στη γραμμή (ή line:col)"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Επεξεργασία Στυλ"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Επεξεργασία"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Επεξεργασία του στυλ $stylename$",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Ενεργοποίηση"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Αναζήτηση περισσότερων στυλ για αυτή την ιστοσελίδα"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Βοήθεια"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Εγκατάσταση ενημέρωσης"
|
||||
},
|
||||
"manageFilters": {
|
||||
"message": "Φίλτρα"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Εγκατεστημένα Στυλ"
|
||||
},
|
||||
"manageOnlyEnabled": {
|
||||
"message": "Μόνο ενεργοποιημένα στυλ"
|
||||
},
|
||||
"manageTitle": {
|
||||
"message": "Κομψή"
|
||||
},
|
||||
"menuShowBadge": {
|
||||
"message": "Εμφάνιση ενεργους καταμέτρησης στυλ"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Δεν υπάρχουν εγκατεστημένα στυλ για αυτή την ιστοσελίδα."
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Διαχείριση εγκατεστημένων στυλ"
|
||||
},
|
||||
"optionsHeading": {
|
||||
"message": "Επιλογές"
|
||||
},
|
||||
"popupStylesFirst": {
|
||||
"message": "Στυλ λίστας πριν των εντολών στο μενού του κουμπιού γραμμής εργαλείων"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Εμφάνιση αριθμού των στυλ που δραστηριοποιούνται για την τρέχουσα τοποθεσία στην μπάρα εργαλείων"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Προσθήκη ένος άλλου τμήματος"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Κώδικας"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Ενότητες σας επιτρέπουν να ορίσετε διαφορετικά κομμάτια του κώδικα για να εφαρμόζονται σε διαφορετικά σύνολα των διευθύνσεων URL στο ίδιο στυλ. Για παράδειγμα, ένα ενιαίο ύφος θα μπορούσε να αλλάξει την αρχική σελίδα ενός ιστότοπου με έναν τρόπο, ενώ αλλάζει το υπόλοιπο μιας τοποθεσίας ένας άλλος τρόπος."
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Αφαίρεση ενότητας"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Το Regexp δεν είναι έγκυρο."
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Πίσω στη διαχείριση"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Έχετε κάνει αλλαγές σε αυτό το ύφος χωρίς αποθήκευση."
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Ενεργοποιημένη"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Εγκατάσταση του '$stylename$' στο Stylus;",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Εισάγετε ένα όνομα"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Αποθήκευση"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Ενότητες"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Η μορφή του Mozilla κώδικα μπορεί να χρησιμοποιηθεί με το Stylish για το Firefox και μπορεί να υποβληθεί στο userstyles.org."
|
||||
},
|
||||
"styleUpdate": {
|
||||
"message": "Είστε σίγουροι ότι θέλετε να ενημερώσετε το '$stylename$';",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"stylusUnavailableForURL": {
|
||||
"message": "To Stylus δεν λειτουργεί σε σελίδες όπως αυτή."
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "Όλα τα στυλ είναι ενημερωμένα."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Αποτυχία ενημέρωσης: ο διακομιστής ανταποκρίθηκε με κωδικό $code$.",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Αποτυχία ενημέρωσης: απρόσιτος διακομιστής."
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Το στυλ είναι ενημερωμένο."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Η ενημέρωση ολοκληρώθηκε."
|
||||
},
|
||||
"writeStyleFor": {
|
||||
"message": "Γράψτε νέο στυλ για:"
|
||||
},
|
||||
"writeStyleForURL": {
|
||||
"message": "αυτή την διεύθυνση URL"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
75
_locales/en_GB/messages.json
Normal file
75
_locales/en_GB/messages.json
Normal file
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"appliesRemoveError": {
|
||||
"message": "Cannot remove last 'applies to' entry"
|
||||
},
|
||||
"checkAllUpdatesForce": {
|
||||
"message": "Check again—I didn't edit any styles!"
|
||||
},
|
||||
"cm_autoCloseBrackets": {
|
||||
"message": "Auto-close brackets and quotes"
|
||||
},
|
||||
"cm_colorpicker": {
|
||||
"message": "Colour pickers for CSS colours"
|
||||
},
|
||||
"cm_resizeGripHint": {
|
||||
"message": "Double-click to maximise/restore the height"
|
||||
},
|
||||
"colorpickerTooltip": {
|
||||
"message": "Open colour picker"
|
||||
},
|
||||
"description": {
|
||||
"message": "Redesign the web with Stylus, a user-style manager. Stylus allows you to easily install themes and skins for many popular sites."
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Go to line (or line:col)"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Edit style"
|
||||
},
|
||||
"installUpdateUnavailable": {
|
||||
"message": "To enable checking for updates, drop the file on the tab strip or specify @updateURL in the style metadata."
|
||||
},
|
||||
"license": {
|
||||
"message": "Licence"
|
||||
},
|
||||
"manageFaviconsGray": {
|
||||
"message": "Greyed out"
|
||||
},
|
||||
"optionsBadgeDisabled": {
|
||||
"message": "Background colour when disabled"
|
||||
},
|
||||
"optionsBadgeNormal": {
|
||||
"message": "Background colour"
|
||||
},
|
||||
"optionsUpdateImportNote": {
|
||||
"message": "When importing style backups from an old version or from Stylish, do a one-time check for updates manually in the styles manager to ensure all styles are updated."
|
||||
},
|
||||
"optionsUpdateInterval": {
|
||||
"message": "Userstyle auto-update interval in hours (specify 0 to disable)"
|
||||
},
|
||||
"styleInstallFailed": {
|
||||
"message": "Failed to install userstyle\n$error$",
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMetaErrorColor": {
|
||||
"message": "$color$ is not a valid colour",
|
||||
"placeholders": {
|
||||
"color": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleRegexpPartialExplanation": {
|
||||
"message": "This style uses partially matching regexps in violation of <a href='https://developer.mozilla.org/docs/Web/CSS/@document'>CSS4 @document specification</a> which requires a full URL match. The affected CSS sections were not applied to the page. This style was probably created in Stylish-for-Chrome, which incorrectly checks 'regexp()' rules since the very first version (known bug)."
|
||||
},
|
||||
"styleUpdateDiscardChanges": {
|
||||
"message": "The style has been changed outside the editor. Would you like to reload the style?"
|
||||
},
|
||||
"usercssConfigIncomplete": {
|
||||
"message": "The style was updated or deleted after the configuration dialogue was shown. These variables were not saved to avoid corrupting the style's metadata:"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,226 +1,175 @@
|
|||
{
|
||||
"appliesToEverything": {
|
||||
"message": "Kaikki",
|
||||
"description": "Text displayed for styles that apply to all sites"
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Aktivoi",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Syötä nimi",
|
||||
"description": "Error displayed when user saves without providing a name"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URL ositteita domainilla",
|
||||
"description": "Option to make the style apply to the entered string as a domain"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Hae päivityksiä",
|
||||
"description": "Label for the button to check a single style for an update"
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "All styles are up to date.",
|
||||
"description": "Text that displays when an update all check completed and no updates are available"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Apu",
|
||||
"description": "Alternate text for help buttons"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Hae lisää tyylejä tälle sivustolle",
|
||||
"description": "Text for a link that gets a list of styles for the current site"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Asennetut Tyylit",
|
||||
"description": "Heading for the manage page"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Aktivoitu",
|
||||
"description": "Label for the enabled state of styles"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Mozilla formaattia koodista voidaan käyttää Stylish Firefoxille ohjelmassa ja voidaan lähettää userstyles.orgiin.",
|
||||
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Lisää uusi osio",
|
||||
"description": "Label for the button to add a section"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Tallenna",
|
||||
"description": "Label for save button for style editing"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Lisää",
|
||||
"description": "Label for the button to add an 'applies' entry"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "URL ositteet jotka vastaavat regexpiä",
|
||||
"description": "Option to make the style apply to the entered string as a regular expression"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Asennetaanko '$stylename$' Stylusiin?",
|
||||
"description": "Confirmation when installing a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Poista Käytöstä",
|
||||
"description": "Label for the button to disable a style"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Show number of styles active for the current site on the toolbar button",
|
||||
"description": "Label for the checkbox controlling toolbar badge text."
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Takaisin hallintapaneeliin",
|
||||
"description": "Label for cancel button for style editing"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Olet tehnyt muutoksia tähän tyyliin tallentamatta.",
|
||||
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Päivitys epäonnistui: ei voitu yhdistää palvelimeen.",
|
||||
"description": "Text that displays when an update check failed because the update server is unreachable"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Oletko varma että haluat poistaa tämän tyylin?",
|
||||
"description": "Confirmation before deleting a style"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Regexp ei kelpaa.",
|
||||
"description": "Validation message for a bad regexp in a style"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Kooskee: $applies$",
|
||||
"description": "Text on the manage screen to describe what the style applies to",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Osiot",
|
||||
"description": "Title for the style sections section"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Muokkaa Tyyliä $stylename$",
|
||||
"description": "Title of the page for editing styles",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Tyyli on ajan tasalla.",
|
||||
"description": "Text that displays when an update check completed and no update is available"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "URL osoitteet jotka alkavat",
|
||||
"description": "Option to make the style apply to the entered string as a URL prefix"
|
||||
},
|
||||
"popupStylesFirst": {
|
||||
"message": "List styles before commands in the toolbar button menu",
|
||||
"description": "Label for the checkbox controlling section order in the popup."
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Osiot antavat sinun tarkentaa koodin eri osia niin että ne koskevat eri URL osoitteita samassa tyylissä. Esimerkiksi, yksi tyyli voi muokata kotisivua yhdellä tavalla kun se muokkaa koko muuta sivustoa toisella tavalla.",
|
||||
"description": "Help text for sections"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Ei asennettuja tyylejä tällä sivustolla.",
|
||||
"description": "Text displayed when no styles are installed for the current site"
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "ja lisää",
|
||||
"description": "Text added to appliesDisplay when there are more sites for the style than are displayed"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Poista",
|
||||
"description": "Label for the button to remove an 'applies' entry"
|
||||
},
|
||||
"manageTitle": {
|
||||
"message": "Tyylikäs",
|
||||
"description": "Title for the manage page"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Koskee",
|
||||
"description": "Label for 'applies to' fields on the edit/add screen"
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Hallitse asennettuja tyylejä",
|
||||
"description": "Link to open the manage page."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Päivitys epäonnistui: palvelin vastasi koodilla $code$.",
|
||||
"description": "Text that displays when an update check failed because the response code indicates an error",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Tarkenna",
|
||||
"description": "Label for the button to make a style apply only to specific sites"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Asenna päivitys",
|
||||
"description": "Label for the button to install an update for a single style"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Poista osio",
|
||||
"description": "Label for the button to remove a section"
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Päivitys suoritettu.",
|
||||
"description": "Text that displays when an update completed"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Tarkistetaan...",
|
||||
"description": "Text to display when checking a style for an update"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Koodi",
|
||||
"description": "Label for the code for a section"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Käytä 'Koskee' kontrolleja rajoittaaksesi mitä URL osoitteisiin tämä osio koodista koskee.",
|
||||
"description": "Help text for 'applies to' section"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Muokkaa Tyyliä",
|
||||
"description": "Title of the page for editing styles"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Lisää Tyyli",
|
||||
"description": "Title of the page for adding styles"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Tarkista kaikki tyylit päivityksien varalta",
|
||||
"description": "Label for the button to check all styles for updates"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Poista",
|
||||
"description": "Label for the button to delete a style"
|
||||
},
|
||||
"addStyleLabel": {
|
||||
"message": "Uusi Tyyli",
|
||||
"description": "Label for the button to go to the add style page"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Muokkaa",
|
||||
"description": "Label for the button to go to the edit style page"
|
||||
},
|
||||
"description": {
|
||||
"message": "Uudelleen stailaa netti Stylusillä, käyttäjän tyyli hallintapaneelilla. Stylus antaa sinun helposti asentaa teemoja ja skinejä palvelluille kuten Google, Facebook, YouTube, Orkut, ja monelle, monelle muulle sivustolle.",
|
||||
"description": "Extension description"
|
||||
}
|
||||
"addStyleLabel": {
|
||||
"message": "Uusi Tyyli"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Lisää Tyyli"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Lisää"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Kooskee: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "ja lisää"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URL ositteita domainilla"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Käytä 'Koskee' kontrolleja rajoittaaksesi mitä URL osoitteisiin tämä osio koodista koskee."
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Koskee"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "URL ositteet jotka vastaavat regexpiä"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Poista"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Tarkenna"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "Kaikki"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "URL osoitteet jotka alkavat"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Tarkista kaikki tyylit päivityksien varalta"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Hae päivityksiä"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Tarkistetaan..."
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Oletko varma että haluat poistaa tämän tyylin?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Poista"
|
||||
},
|
||||
"description": {
|
||||
"message": "Uudelleen stailaa netti Stylusillä, käyttäjän tyyli hallintapaneelilla. Stylus antaa sinun helposti asentaa teemoja ja skinejä palvelluille kuten Google, Facebook, YouTube, Orkut, ja monelle, monelle muulle sivustolle."
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Poista Käytöstä"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Muokkaa Tyyliä"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Muokkaa"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Muokkaa Tyyliä $stylename$",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Aktivoi"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Hae lisää tyylejä tälle sivustolle"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Apu"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Asenna päivitys"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Asennetut Tyylit"
|
||||
},
|
||||
"manageTitle": {
|
||||
"message": "Tyylikäs"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Ei asennettuja tyylejä tällä sivustolla."
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Hallitse asennettuja tyylejä"
|
||||
},
|
||||
"popupStylesFirst": {
|
||||
"message": "List styles before commands in the toolbar button menu"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Show number of styles active for the current site on the toolbar button"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Lisää uusi osio"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Koodi"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Osiot antavat sinun tarkentaa koodin eri osia niin että ne koskevat eri URL osoitteita samassa tyylissä. Esimerkiksi, yksi tyyli voi muokata kotisivua yhdellä tavalla kun se muokkaa koko muuta sivustoa toisella tavalla."
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Poista osio"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Regexp ei kelpaa."
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Takaisin hallintapaneeliin"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Olet tehnyt muutoksia tähän tyyliin tallentamatta."
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Aktivoitu"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Asennetaanko '$stylename$' Stylusiin?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Syötä nimi"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Tallenna"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Osiot"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Mozilla formaattia koodista voidaan käyttää Stylish Firefoxille ohjelmassa ja voidaan lähettää userstyles.orgiin."
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "All styles are up to date."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Päivitys epäonnistui: palvelin vastasi koodilla $code$.",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Päivitys epäonnistui: ei voitu yhdistää palvelimeen."
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Tyyli on ajan tasalla."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Päivitys suoritettu."
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
97
_locales/fy/messages.json
Normal file
97
_locales/fy/messages.json
Normal file
|
@ -0,0 +1,97 @@
|
|||
{
|
||||
"addStyleLabel": {
|
||||
"message": "Nije styl skriuwe"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Styl tafoegje"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Tafoegje"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Fan tapassing op: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "en mear"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URL’s op it domein"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Brûk de ‘Fan tapassing op’-funksjes om de URL’s foar de koade yn dizze seksje te beheinen."
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Fan tapassing op"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "URL’s oerienkommend mei de regexp"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Fuortsmite"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Spesifisearje"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "Alles"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "URL’s begjinnend mei"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Alle fernijingen tapasse"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Alle stilen kontrolearje op fernijingen"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Kontrolearje op fernijing"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Kontrolearje..."
|
||||
},
|
||||
"cm_indentWithTabs": {
|
||||
"message": "Ljepblêden mei tûke ynspringing brûke"
|
||||
},
|
||||
"cm_keyMap": {
|
||||
"message": "Toetseboerdyndieling"
|
||||
},
|
||||
"cm_lineWrapping": {
|
||||
"message": "Teksttebekrin"
|
||||
},
|
||||
"cm_smartIndent": {
|
||||
"message": "Tûke ynspringing brûke"
|
||||
},
|
||||
"cm_tabSize": {
|
||||
"message": "Ljepblêdgrutte"
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "Tema"
|
||||
},
|
||||
"confirmNo": {
|
||||
"message": "Nee"
|
||||
},
|
||||
"confirmStop": {
|
||||
"message": "Stoppe"
|
||||
},
|
||||
"confirmYes": {
|
||||
"message": "Ja"
|
||||
},
|
||||
"dbError": {
|
||||
"message": "Der is in flater bard by it brûken fan de Stylus-database. Wolle jo in webside mei mooglike oplossingen besykje?"
|
||||
},
|
||||
"defaultTheme": {
|
||||
"message": "standert"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Binne jo wis dat jo dizze styl fuortsmite wolle?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Fuortsmite"
|
||||
}
|
||||
}
|
767
_locales/he/messages.json
Normal file
767
_locales/he/messages.json
Normal file
|
@ -0,0 +1,767 @@
|
|||
{
|
||||
"addStyleLabel": {
|
||||
"message": "כתוב עיצוב חדש"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "הוספת עיצוב"
|
||||
},
|
||||
"alphaChannel": {
|
||||
"message": "שקיפות"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "הוספה"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "מוחל על: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "עוד"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "קישורים תחת הדומיין"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "מוחל על"
|
||||
},
|
||||
"appliesLineWidgetLabel": {
|
||||
"message": "הצג אינפורמציית 'חל על'"
|
||||
},
|
||||
"appliesLineWidgetWarning": {
|
||||
"message": "לא עובד עם CSS מוקטן (minified)"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "קישורים התואמים regexp"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "הסרה"
|
||||
},
|
||||
"appliesRemoveError": {
|
||||
"message": "לא ניתן להסיר את הערך 'חל על' האחרון"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "פרט"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "כל האתרים"
|
||||
},
|
||||
"appliesUrlOption": {
|
||||
"message": "קישור (URL)"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "קישורים המתחילים ב"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "החל את כל העדכונים"
|
||||
},
|
||||
"author": {
|
||||
"message": "כותב"
|
||||
},
|
||||
"backupButtons": {
|
||||
"message": "גיבוי"
|
||||
},
|
||||
"backupMessage": {
|
||||
"message": "בחר קובץ או גרור ושחרר אותו בדף זה."
|
||||
},
|
||||
"bckpInstStyles": {
|
||||
"message": "ייצא עיצובים"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "בדוקים עדכונים עבור כל העיצובים"
|
||||
},
|
||||
"checkAllUpdatesForce": {
|
||||
"message": "בדוק שוב, לא ערכתי אף עיצוב!"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "בדוק עדכונים"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "בודק..."
|
||||
},
|
||||
"clickToUninstall": {
|
||||
"message": "הקלק להסרה"
|
||||
},
|
||||
"cm_autoCloseBrackets": {
|
||||
"message": "סגור באופן אוטומטי סוגריים וגרשיים"
|
||||
},
|
||||
"cm_autoCloseBracketsTooltip": {
|
||||
"message": "הוסף סוגר באופן אוטומטי כשמקלידים את אחת מהפותחים של ()[]{}''\"\""
|
||||
},
|
||||
"cm_autocompleteOnTyping": {
|
||||
"message": "השלמה אוטומטית בזמן הכתיבה"
|
||||
},
|
||||
"cm_colorpicker": {
|
||||
"message": "פלטות בחירת צבעים עבור צבעי CSS"
|
||||
},
|
||||
"cm_indentWithTabs": {
|
||||
"message": "השתמש בטאבים יחד עם הזחה חכמה"
|
||||
},
|
||||
"cm_keyMap": {
|
||||
"message": "מפת מקשים"
|
||||
},
|
||||
"cm_lineWrapping": {
|
||||
"message": "עטיפת מילים"
|
||||
},
|
||||
"cm_matchHighlight": {
|
||||
"message": "הדגש"
|
||||
},
|
||||
"cm_matchHighlightSelection": {
|
||||
"message": "בחירה בלבד"
|
||||
},
|
||||
"cm_resizeGripHint": {
|
||||
"message": "דאבל קליק להגדלה מירבית/איפוס הגובה"
|
||||
},
|
||||
"cm_selectByTokens": {
|
||||
"message": "דאבל קליק בוחר tokens"
|
||||
},
|
||||
"cm_smartIndent": {
|
||||
"message": "השתמש בהזחה חכמה"
|
||||
},
|
||||
"cm_tabSize": {
|
||||
"message": "גודל הכרטיסייה"
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "ערכת נושא"
|
||||
},
|
||||
"colorpickerTooltip": {
|
||||
"message": "פתח את פלטת בחירת הצבעים"
|
||||
},
|
||||
"configOnChange": {
|
||||
"message": "בעת שינוי"
|
||||
},
|
||||
"configOnChangeTooltip": {
|
||||
"message": "שמור והחל שינויים באופן אוטומטי"
|
||||
},
|
||||
"configureStyle": {
|
||||
"message": "הגדר"
|
||||
},
|
||||
"configureStyleOnHomepage": {
|
||||
"message": "הגדר בדף הבית"
|
||||
},
|
||||
"confirmCancel": {
|
||||
"message": "ביטול"
|
||||
},
|
||||
"confirmClose": {
|
||||
"message": "סגור"
|
||||
},
|
||||
"confirmDefault": {
|
||||
"message": "השתמש בברירת מחדל"
|
||||
},
|
||||
"confirmDelete": {
|
||||
"message": "מחיקה"
|
||||
},
|
||||
"confirmDiscardChanges": {
|
||||
"message": "למחוק את השינויים?"
|
||||
},
|
||||
"confirmNo": {
|
||||
"message": "לא"
|
||||
},
|
||||
"confirmOK": {
|
||||
"message": "אוקיי"
|
||||
},
|
||||
"confirmSave": {
|
||||
"message": "שמור"
|
||||
},
|
||||
"confirmStop": {
|
||||
"message": "עצור"
|
||||
},
|
||||
"confirmYes": {
|
||||
"message": "כן"
|
||||
},
|
||||
"dateInstalled": {
|
||||
"message": "תאריך התקנה"
|
||||
},
|
||||
"dateUpdated": {
|
||||
"message": "תאריך עדכון"
|
||||
},
|
||||
"defaultTheme": {
|
||||
"message": "ברירת מחדל"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "האם אתה בטוח שברצונך למחוק עיצוב זה?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "מחק"
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "השבת את כל העיצובים"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "השבת"
|
||||
},
|
||||
"dragDropMessage": {
|
||||
"message": "שחרר את קובץ הגיבוי שלך בכל מקום בדף זה על־מנת לייבא אותו."
|
||||
},
|
||||
"editDeleteText": {
|
||||
"message": "מחק"
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Goto לשורה (או line:col)"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "עריכת עיצוב"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "עריכה"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "עריכת העיצוב $stylename$",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"editorStylesButton": {
|
||||
"message": "מצא עיצובים לעורך"
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "אפשר"
|
||||
},
|
||||
"exportLabel": {
|
||||
"message": "ייצא"
|
||||
},
|
||||
"externalFeedback": {
|
||||
"message": "חוות דעת"
|
||||
},
|
||||
"externalHomepage": {
|
||||
"message": "דף הבית"
|
||||
},
|
||||
"externalLink": {
|
||||
"message": "קישור חיצוני"
|
||||
},
|
||||
"externalSupport": {
|
||||
"message": "תמיכה"
|
||||
},
|
||||
"findStyles": {
|
||||
"message": "מצא עיצובים"
|
||||
},
|
||||
"findStylesInline": {
|
||||
"message": "מוטבע"
|
||||
},
|
||||
"genericAdd": {
|
||||
"message": "הוספה"
|
||||
},
|
||||
"genericClone": {
|
||||
"message": "שכפול"
|
||||
},
|
||||
"genericDisabledLabel": {
|
||||
"message": "מושבת"
|
||||
},
|
||||
"genericEnabledLabel": {
|
||||
"message": "מאופשר"
|
||||
},
|
||||
"genericError": {
|
||||
"message": "שגיאה"
|
||||
},
|
||||
"genericHistoryLabel": {
|
||||
"message": "היסטוריה"
|
||||
},
|
||||
"genericNext": {
|
||||
"message": "הבא"
|
||||
},
|
||||
"genericPrevious": {
|
||||
"message": "הקודם"
|
||||
},
|
||||
"genericResetLabel": {
|
||||
"message": "איפוס"
|
||||
},
|
||||
"genericSavedMessage": {
|
||||
"message": "נשמר"
|
||||
},
|
||||
"genericTitle": {
|
||||
"message": "כותרת"
|
||||
},
|
||||
"genericUnknown": {
|
||||
"message": "לא ידוע"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "עזרה"
|
||||
},
|
||||
"helpKeyMapCommand": {
|
||||
"message": "הקלד שם פקודה"
|
||||
},
|
||||
"helpKeyMapHotkey": {
|
||||
"message": "לחץ על המקש החם"
|
||||
},
|
||||
"importAppendLabel": {
|
||||
"message": "צרף לעיצוב"
|
||||
},
|
||||
"importAppendTooltip": {
|
||||
"message": "צרף את העיצוב המיובא לעיצוב הנוכחי"
|
||||
},
|
||||
"importLabel": {
|
||||
"message": "ייבא"
|
||||
},
|
||||
"importReplaceLabel": {
|
||||
"message": "דרוס עיצוב"
|
||||
},
|
||||
"importReportLegendAdded": {
|
||||
"message": "נוספו"
|
||||
},
|
||||
"importReportLegendUpdatedCode": {
|
||||
"message": "קודים עודכנו"
|
||||
},
|
||||
"importReportLegendUpdatedMeta": {
|
||||
"message": "מידע meta עודכנו"
|
||||
},
|
||||
"importReportTitle": {
|
||||
"message": "סיום ייבוא עיצובים"
|
||||
},
|
||||
"importReportUnchanged": {
|
||||
"message": "שום דבר לא השתנה."
|
||||
},
|
||||
"importReportUndone": {
|
||||
"message": "עיצובים הוחזרו"
|
||||
},
|
||||
"importReportUndoneTitle": {
|
||||
"message": "הייבוא בוטל"
|
||||
},
|
||||
"installButton": {
|
||||
"message": "התקן עיצוב"
|
||||
},
|
||||
"installButtonInstalled": {
|
||||
"message": "העיצוב הותקן בהצלחה"
|
||||
},
|
||||
"installButtonReinstall": {
|
||||
"message": "התקן עיצוב מחדש"
|
||||
},
|
||||
"installButtonUpdate": {
|
||||
"message": "עדכן עיצוב"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "התקן עדכון"
|
||||
},
|
||||
"installUpdateFromLabel": {
|
||||
"message": "בדוק עדכונים"
|
||||
},
|
||||
"installUpdateUnavailable": {
|
||||
"message": "על־מנת לאפשר בדיקת עדכונים, אנא שחרר את הקובץ על רצועת הכרטיסיות או ציין @updateURL ב־metadata של העיצוב."
|
||||
},
|
||||
"license": {
|
||||
"message": "רישיון"
|
||||
},
|
||||
"linkGetHelp": {
|
||||
"message": "קבל עזרה"
|
||||
},
|
||||
"linkGetStyles": {
|
||||
"message": "מצא עיצובים"
|
||||
},
|
||||
"linkTranslate": {
|
||||
"message": "תרגום"
|
||||
},
|
||||
"linterCSSLintSettings": {
|
||||
"message": "(הגדר כלל כ: 0 = מושבת; 1 = אזהרה; 2 = שגיאה)"
|
||||
},
|
||||
"linterConfigPopupTitle": {
|
||||
"message": "הגדר $linter$ כללי תצורה",
|
||||
"placeholders": {
|
||||
"linter": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linterConfigTooltip": {
|
||||
"message": "לחץ להגדרת linter זה"
|
||||
},
|
||||
"linterIssues": {
|
||||
"message": "תקלות"
|
||||
},
|
||||
"linterIssuesHelp": {
|
||||
"message": "התקלות האלו נמצאו על־ידי $link$:",
|
||||
"placeholders": {
|
||||
"link": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linterJSONError": {
|
||||
"message": "פורמט JSON לא תקין"
|
||||
},
|
||||
"linterResetMessage": {
|
||||
"message": "על־מנת לבטל איפוסים לא רצוניים, לחץ Ctrl-Z (או Cmd-Z) בתיבת הטקסט"
|
||||
},
|
||||
"linterRulesLink": {
|
||||
"message": "ראה רשימת חוקים מלאה"
|
||||
},
|
||||
"liveReloadError": {
|
||||
"message": "התרחשה שגיאה בזמן הצפייה בקובץ"
|
||||
},
|
||||
"liveReloadLabel": {
|
||||
"message": "רענון לייב (live)"
|
||||
},
|
||||
"liveReloadUnavailable": {
|
||||
"message": "על־מנת לאפשר רענון לייב (live), אנא שחרר את הקובץ על רצועת הכרטיסיות (האזור בו כותרות הכרטיסיות מוצגות)."
|
||||
},
|
||||
"manageFavicons": {
|
||||
"message": "הצגת אייקונים בעמודת 'חל על'"
|
||||
},
|
||||
"manageFaviconsGray": {
|
||||
"message": "האפרת האייקונים"
|
||||
},
|
||||
"manageFaviconsHelp": {
|
||||
"message": "Stylus משתמש בשירות חיצוני https://www.google.com/s2/favicons"
|
||||
},
|
||||
"manageFilters": {
|
||||
"message": "מסננים"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "עיצובים מותקנים"
|
||||
},
|
||||
"manageMaxTargets": {
|
||||
"message": "מספר הפריטים ה־'מוחלים על'"
|
||||
},
|
||||
"manageNewStyleAsUsercss": {
|
||||
"message": "כ־Usercss"
|
||||
},
|
||||
"manageOnlyDisabled": {
|
||||
"message": "רק עיצובים מושבתים"
|
||||
},
|
||||
"manageOnlyEnabled": {
|
||||
"message": "רק עיצובים מאופשרים"
|
||||
},
|
||||
"manageOnlyExternal": {
|
||||
"message": "רק עיצובים חיצוניים"
|
||||
},
|
||||
"manageOnlyLocal": {
|
||||
"message": "רק עיצובים שנוצרו באופן מקומי"
|
||||
},
|
||||
"manageOnlyNonUsercss": {
|
||||
"message": "רק לא עיצובי Usercss"
|
||||
},
|
||||
"manageOnlyUpdates": {
|
||||
"message": "רק עם עדכונים או תקלות"
|
||||
},
|
||||
"manageOnlyUsercss": {
|
||||
"message": "רק עיצובי Usercss"
|
||||
},
|
||||
"menuShowBadge": {
|
||||
"message": "הצג כמות עיצובים מאופשרים"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "לא הותקנו עיצובים עבור אתר זה."
|
||||
},
|
||||
"openManage": {
|
||||
"message": "ניהול"
|
||||
},
|
||||
"openOptionsManage": {
|
||||
"message": "אפשרויות UI"
|
||||
},
|
||||
"openOptionsPopup": {
|
||||
"message": "אפשרויות"
|
||||
},
|
||||
"openStylesManager": {
|
||||
"message": "פתח את מנהל העיצובים"
|
||||
},
|
||||
"optionsActions": {
|
||||
"message": "פעולות"
|
||||
},
|
||||
"optionsAdvanced": {
|
||||
"message": "מתקדם"
|
||||
},
|
||||
"optionsAdvancedContextDelete": {
|
||||
"message": "הוספת 'מחיקה' בתפריט העורך"
|
||||
},
|
||||
"optionsBadgeDisabled": {
|
||||
"message": "צבע רקע בעת השבתה"
|
||||
},
|
||||
"optionsBadgeNormal": {
|
||||
"message": "צבע רקע"
|
||||
},
|
||||
"optionsCheck": {
|
||||
"message": "עדכן עיצובים"
|
||||
},
|
||||
"optionsCheckUpdate": {
|
||||
"message": "בדוק והתקן את כל העדכונים הזמינים"
|
||||
},
|
||||
"optionsCustomizeBadge": {
|
||||
"message": "תג על האייקון בסרגל הכלים"
|
||||
},
|
||||
"optionsCustomizeIcon": {
|
||||
"message": "אייקון בסרגל הכלים"
|
||||
},
|
||||
"optionsCustomizePopup": {
|
||||
"message": "חלון קופץ"
|
||||
},
|
||||
"optionsCustomizeUpdate": {
|
||||
"message": "עדכונים"
|
||||
},
|
||||
"optionsHeading": {
|
||||
"message": "אפשרויות"
|
||||
},
|
||||
"optionsIconDark": {
|
||||
"message": "ערכות נושא כהות לדפדפן"
|
||||
},
|
||||
"optionsIconLight": {
|
||||
"message": "ערכות נושא בהירות לדפדפן"
|
||||
},
|
||||
"optionsOpen": {
|
||||
"message": "פתח"
|
||||
},
|
||||
"optionsOpenManager": {
|
||||
"message": "נהל עיצובים"
|
||||
},
|
||||
"optionsPopupWidth": {
|
||||
"message": "רוחב החלון הקופץ (בפיקסלים)"
|
||||
},
|
||||
"optionsReset": {
|
||||
"message": "איפוס האפשרויות לערכי ברירת המחדל"
|
||||
},
|
||||
"optionsResetButton": {
|
||||
"message": "איפוס האפשרויות"
|
||||
},
|
||||
"optionsSubheading": {
|
||||
"message": "אפשרויות נוספות"
|
||||
},
|
||||
"optionsUpdateInterval": {
|
||||
"message": "עדכון אוטומטי של Userstyle בשעות (הגדר 0 להשבתה)"
|
||||
},
|
||||
"paginationCurrent": {
|
||||
"message": "הדף הנוכחי"
|
||||
},
|
||||
"paginationEstimated": {
|
||||
"message": "מספר דפים משוער"
|
||||
},
|
||||
"paginationNext": {
|
||||
"message": "הדף הבא"
|
||||
},
|
||||
"paginationPrevious": {
|
||||
"message": "הדף הקודם"
|
||||
},
|
||||
"paginationTotal": {
|
||||
"message": "סה״כ דפים"
|
||||
},
|
||||
"popupBorders": {
|
||||
"message": "הוספת שוליים לבנים בצדדים"
|
||||
},
|
||||
"popupHotkeysTooltip": {
|
||||
"message": "לחץ על־מנת לצפות במקשים החמים הזמינים"
|
||||
},
|
||||
"popupOpenEditInWindow": {
|
||||
"message": "פתח את העורך בחלון חדש"
|
||||
},
|
||||
"popupStylesFirst": {
|
||||
"message": "עיצובים לפני הפקודות"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "מֿמספר העיצובים המאופשרים באתר הנוכחי"
|
||||
},
|
||||
"previewLabel": {
|
||||
"message": "תצוגת לייב (live)"
|
||||
},
|
||||
"previewTooltip": {
|
||||
"message": "החלת השינויים באופן זמני ללא שמירה.\nשמור את העיצוב על־מנת להפוך את השינויים לקבועים."
|
||||
},
|
||||
"replace": {
|
||||
"message": "החלף"
|
||||
},
|
||||
"replaceAll": {
|
||||
"message": "החלף הכל"
|
||||
},
|
||||
"replaceWith": {
|
||||
"message": "החלף עם"
|
||||
},
|
||||
"retrieveBckp": {
|
||||
"message": "ייבוא עיצובים"
|
||||
},
|
||||
"search": {
|
||||
"message": "חיפוש"
|
||||
},
|
||||
"searchCaseSensitive": {
|
||||
"message": "רגיש לאותיות גדולות/קטנות"
|
||||
},
|
||||
"searchNumberOfResults": {
|
||||
"message": "מספר ההתאמות"
|
||||
},
|
||||
"searchNumberOfResults2": {
|
||||
"message": "מספר ההתאמות בקוד ובערכים ה'מוחלים על'"
|
||||
},
|
||||
"searchRegexp": {
|
||||
"message": "השתמש ב־/re/ לחיפוש באמצעות ביטוי regexp"
|
||||
},
|
||||
"searchResultInstallCount": {
|
||||
"message": "סה״כ התקנות"
|
||||
},
|
||||
"searchResultNoneFound": {
|
||||
"message": "לא נמצאו עיצובים לאתר זה."
|
||||
},
|
||||
"searchResultRating": {
|
||||
"message": "דירוג"
|
||||
},
|
||||
"searchResultUpdated": {
|
||||
"message": "עודכן"
|
||||
},
|
||||
"searchResultWeeklyCount": {
|
||||
"message": "התקנות שבועיות"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "הסר סעיף"
|
||||
},
|
||||
"sectionRestore": {
|
||||
"message": "שחזר סעיף שהוסר"
|
||||
},
|
||||
"shortcuts": {
|
||||
"message": "קיצורי מקשים"
|
||||
},
|
||||
"shortcutsNote": {
|
||||
"message": "הגדר קיצורי מקשים"
|
||||
},
|
||||
"sortDateNewestFirst": {
|
||||
"message": "החדש ביותר ראשון"
|
||||
},
|
||||
"sortDateOldestFirst": {
|
||||
"message": "הישן ביותר ראשון"
|
||||
},
|
||||
"sortLabel": {
|
||||
"message": "בחר שיטת מיון להחלה על העיצובים המותקנים"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "ביטוי ה־Regexp לא תקין."
|
||||
},
|
||||
"styleBeautify": {
|
||||
"message": "ייפה CSS"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "חזרה לניהול"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "מאופשר"
|
||||
},
|
||||
"styleFromMozillaFormatPrompt": {
|
||||
"message": "הדבק את הקוד ב־Mozilla-format"
|
||||
},
|
||||
"styleMetaErrorColor": {
|
||||
"message": "$color$ הוא צבע לא תקין",
|
||||
"placeholders": {
|
||||
"color": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMetaErrorPreprocessor": {
|
||||
"message": "@preprocessor לא נתמך: $preprocessor$",
|
||||
"placeholders": {
|
||||
"preprocessor": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMetaErrorSelectValueMismatch": {
|
||||
"message": "הערך @select: לא קיים ברשימה"
|
||||
},
|
||||
"styleMissingMeta": {
|
||||
"message": "@$key$ metadata חסרים",
|
||||
"placeholders": {
|
||||
"key": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "אנא הזן שם"
|
||||
},
|
||||
"styleRegexpTestButton": {
|
||||
"message": "בדוק RegExp"
|
||||
},
|
||||
"styleRegexpTestFull": {
|
||||
"message": "כרטיסיות תואמות"
|
||||
},
|
||||
"styleRegexpTestInvalid": {
|
||||
"message": "ביטוי regrxp לא תקין"
|
||||
},
|
||||
"styleRegexpTestNone": {
|
||||
"message": "לא תואם אף כרטיסייה"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "שמור"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "סעיפים"
|
||||
},
|
||||
"styleToMozillaFormatTitle": {
|
||||
"message": "עיצוב ב־Mozilla format"
|
||||
},
|
||||
"styleUpdate": {
|
||||
"message": "האם אתה בטוח שברצונך לעדכן את '$stylename$'?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"stylusUnavailableForURL": {
|
||||
"message": "Stylus לא עובד על דפים כמו זה."
|
||||
},
|
||||
"syncStorageErrorSaving": {
|
||||
"message": "הערך לא יכול להשמר. אנא נסה להקטין את גודל הטקסט."
|
||||
},
|
||||
"toggleStyle": {
|
||||
"message": "אפשר או השבת עיצוב"
|
||||
},
|
||||
"undo": {
|
||||
"message": "בטל"
|
||||
},
|
||||
"undoGlobal": {
|
||||
"message": "בטל בכל הסעיפים"
|
||||
},
|
||||
"unreachableAMO": {
|
||||
"message": "Firefox לא מאפשרת גישה לאתר זה."
|
||||
},
|
||||
"unreachableContentScript": {
|
||||
"message": "לא ניתן לתקשר עם הדף. אנא טען מחדש את הכרטיסייה."
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "לא נמצאו עדכונים."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "העדכון נכשל: השרת החזיר תגובה עם הקוד $code$.",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "העדכון נכשל: השרת לא זמין."
|
||||
},
|
||||
"updateCheckHistory": {
|
||||
"message": "היסטוריה של בדיקת עדכונים"
|
||||
},
|
||||
"updateCheckSkippedLocallyEdited": {
|
||||
"message": "עיצוב זה נערך באופן מקומי."
|
||||
},
|
||||
"updateCheckSkippedMaybeLocallyEdited": {
|
||||
"message": "ייתכן כי עיצוב זה נערך באופן מקומי."
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "העיצוב מעודכן."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "העדכון הושלם."
|
||||
},
|
||||
"updatesCurrentlyInstalled": {
|
||||
"message": "העדכונים הותקנו."
|
||||
},
|
||||
"usercssAvoidOverwriting": {
|
||||
"message": "אנא שנה את הערך של @name or @namespace על־מנת להמנע מדריסה של עיצוב קיים."
|
||||
},
|
||||
"usercssEditorNamePlaceholder": {
|
||||
"message": "ציין @name בקוד"
|
||||
},
|
||||
"usercssReplaceTemplateSectionBody": {
|
||||
"message": "הכנס כאן קוד..."
|
||||
},
|
||||
"versionInvalidOlder": {
|
||||
"message": "הגרסה ישנה יותר מהעיצוב המותקן."
|
||||
},
|
||||
"writeStyleFor": {
|
||||
"message": "כתוב עיצוב עבור: "
|
||||
},
|
||||
"writeStyleForURL": {
|
||||
"message": "הקישור הנוכחי"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,358 +1,274 @@
|
|||
{
|
||||
"appliesToEverything": {
|
||||
"message": "Tudo",
|
||||
"description": "Text displayed for styles that apply to all sites"
|
||||
},
|
||||
"defaultTheme": {
|
||||
"message": "padrão",
|
||||
"description": "Default CodeMirror CSS theme option on the edit style page"
|
||||
},
|
||||
"bckpInstStyles": {
|
||||
"message": "Exportar estilos",
|
||||
"description": ""
|
||||
},
|
||||
"exportLabel": {
|
||||
"message": "Exportar ",
|
||||
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
|
||||
},
|
||||
"optionsBadgeNormal": {
|
||||
"message": "Cor de fundo",
|
||||
"description": ""
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Ativar",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Insira um nome",
|
||||
"description": "Error displayed when user saves without providing a name"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URLs no domínio",
|
||||
"description": "Option to make the style apply to the entered string as a domain"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Verificar atualizações",
|
||||
"description": "Label for the button to check a single style for an update"
|
||||
},
|
||||
"importAppendLabel": {
|
||||
"message": "Anexar ao estilo",
|
||||
"description": "Label for the button to import a style and append to the existing sections"
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "Nenhuma atualização encontrada.",
|
||||
"description": "Text that displays when an update all check completed and no updates are available"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Ajuda",
|
||||
"description": "Alternate text for help buttons"
|
||||
},
|
||||
"search": {
|
||||
"message": "Buscar",
|
||||
"description": "Label before the search input field in the editor shown on Ctrl-F"
|
||||
},
|
||||
"confirmYes": {
|
||||
"message": "Sim",
|
||||
"description": "'Yes' button in a confirm dialog"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Procurar mais estilos para este site",
|
||||
"description": "Text for a link that gets a list of styles for the current site"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Estilos instalados",
|
||||
"description": "Heading for the manage page"
|
||||
},
|
||||
"styleBeautify": {
|
||||
"message": "Embelezar",
|
||||
"description": "Label for the CSS-beautifier button on the edit style page"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Ativado",
|
||||
"description": "Label for the enabled state of styles"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "O formato Mozilla do código pode ser usado com o Stylish para Firefox e pode ser enviado para userstyles.org.",
|
||||
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Adicionar outra seção",
|
||||
"description": "Label for the button to add a section"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Salvar",
|
||||
"description": "Label for save button for style editing"
|
||||
},
|
||||
"confirmDelete": {
|
||||
"message": "Deletar",
|
||||
"description": ""
|
||||
},
|
||||
"confirmCancel": {
|
||||
"message": "Cancelar",
|
||||
"description": ""
|
||||
},
|
||||
"retrieveBckp": {
|
||||
"message": "Importar estilos",
|
||||
"description": ""
|
||||
},
|
||||
"confirmStop": {
|
||||
"message": "Parar",
|
||||
"description": "'Stop' button in a confirm dialog"
|
||||
},
|
||||
"writeStyleForURL": {
|
||||
"message": "esse URL",
|
||||
"description": "Text for link in toolbar pop-up to write a new style for the current URL"
|
||||
},
|
||||
"optionsSubheading": {
|
||||
"message": "Mais Opções",
|
||||
"description": "Subheading for options section on manage page."
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Adicionar",
|
||||
"description": "Label for the button to add an 'applies' entry"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "URLs que correspondem a regexp",
|
||||
"description": "Option to make the style apply to the entered string as a regular expression"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Instalar \"$stylename$\" no Stylus?",
|
||||
"description": "Confirmation when installing a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"optionsBadgeDisabled": {
|
||||
"message": "Cor de fundo quando desativado",
|
||||
"description": ""
|
||||
},
|
||||
"optionsCheck": {
|
||||
"message": "Atualizar estilos",
|
||||
"description": ""
|
||||
},
|
||||
"searchStyles": {
|
||||
"message": "Buscar conteúdos",
|
||||
"description": "Label for the search filter textbox on the Manage styles page"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Desativar",
|
||||
"description": "Label for the button to disable a style"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Show number of styles active for the current site on the toolbar button",
|
||||
"description": "Label for the checkbox controlling toolbar badge text."
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Voltar ao gerenciamento",
|
||||
"description": "Label for cancel button for style editing"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Você fez alterações neste estilo sem salvar.",
|
||||
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
|
||||
},
|
||||
"importLabel": {
|
||||
"message": "Importar",
|
||||
"description": "Label for the button to import a style ('edit' page) or all styles ('manage' page)"
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "A atualização falhou: servidor inacessível.",
|
||||
"description": "Text that displays when an update check failed because the update server is unreachable"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Aplicar todas as atualizações",
|
||||
"description": "Label for the button to apply all detected updates"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Tem certeza de que deseja excluir este estilo?",
|
||||
"description": "Confirmation before deleting a style"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Expressão regular é inválida",
|
||||
"description": "Validation message for a bad regexp in a style"
|
||||
},
|
||||
"optionsHeading": {
|
||||
"message": "Opções",
|
||||
"description": "Heading for options section on manage page."
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Aplica-se a: $applies$",
|
||||
"description": "Text on the manage screen to describe what the style applies to",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Seções",
|
||||
"description": "Title for the style sections section"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Editar estilo $stylename$",
|
||||
"description": "Title of the page for editing styles",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "O estilo está atualizado.",
|
||||
"description": "Text that displays when an update check completed and no update is available"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "URLs que começam com",
|
||||
"description": "Option to make the style apply to the entered string as a URL prefix"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "As seções permitem definir diferentes partes de código para aplicar a diferentes conjuntos de URLs no mesmo estilo. Por exemplo, um único estilo poderia alterar a página inicial de um site de uma forma, enquanto alteraria o resto do site de outra forma.",
|
||||
"description": "Help text for sections"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Nenhum estilo instalado para este site.",
|
||||
"description": "Text displayed when no styles are installed for the current site"
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "e mais",
|
||||
"description": "Text added to appliesDisplay when there are more sites for the style than are displayed"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Remover",
|
||||
"description": "Label for the button to remove an 'applies' entry"
|
||||
},
|
||||
"replace": {
|
||||
"message": "Substituir",
|
||||
"description": "Label before the replace input field in the editor shown on Ctrl-H"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Aplica-se a",
|
||||
"description": "Label for 'applies to' fields on the edit/add screen"
|
||||
},
|
||||
"openOptionsPopup": {
|
||||
"message": "Opções",
|
||||
"description": "Go to Options UI"
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Gerenciar estilos instalados",
|
||||
"description": "Link to open the manage page."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "A atualização falhou: o servidor respondeu com código $code$.",
|
||||
"description": "Text that displays when an update check failed because the response code indicates an error",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Especificar",
|
||||
"description": "Label for the button to make a style apply only to specific sites"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Instalar atualização",
|
||||
"description": "Label for the button to install an update for a single style"
|
||||
},
|
||||
"styleMozillaFormatHeading": {
|
||||
"message": "Formato Mozilla",
|
||||
"description": "Heading for the section with buttons to import/export Mozilla format of the style"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Remover seção",
|
||||
"description": "Label for the button to remove a section"
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "Desativar todos os estilos",
|
||||
"description": "Label for the checkbox that turns all enabled styles off."
|
||||
},
|
||||
"undoGlobal": {
|
||||
"message": "Desfazer todas as seções",
|
||||
"description": "CSS-beautify global Undo button label"
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Atualização concluída.",
|
||||
"description": "Text that displays when an update completed"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Verificando...",
|
||||
"description": "Text to display when checking a style for an update"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Código",
|
||||
"description": "Label for the code for a section"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Use os controles \"Aplica-se a\" para limitar a quais URLs o código desta seção se aplica.",
|
||||
"description": "Help text for 'applies to' section"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Editar estilo",
|
||||
"description": "Title of the page for editing styles"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Adicionar estilo",
|
||||
"description": "Title of the page for adding styles"
|
||||
},
|
||||
"importReplaceLabel": {
|
||||
"message": "Sobrescrever estilo",
|
||||
"description": "Label for the button to import and overwrite current style"
|
||||
},
|
||||
"importAppendTooltip": {
|
||||
"message": "Anexar o estilo importado ao atual",
|
||||
"description": "Tooltip for the button to import a style and append to the existing sections"
|
||||
},
|
||||
"optionsOpen": {
|
||||
"message": "Abrir",
|
||||
"description": ""
|
||||
},
|
||||
"replaceAll": {
|
||||
"message": "Substituir todos",
|
||||
"description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey"
|
||||
},
|
||||
"optionsActions": {
|
||||
"message": "Ações",
|
||||
"description": ""
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Ir para linha (ou linha:coluna)",
|
||||
"description": "Go to line or line:column on Ctrl-G in style code editor"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Verificar atualizações para todos os estilos",
|
||||
"description": "Label for the button to check all styles for updates"
|
||||
},
|
||||
"confirmNo": {
|
||||
"message": "Não",
|
||||
"description": "'No' button in a confirm dialog"
|
||||
},
|
||||
"undo": {
|
||||
"message": "Desfazer",
|
||||
"description": "Button label"
|
||||
},
|
||||
"replaceWith": {
|
||||
"message": "Substituir com",
|
||||
"description": "Label before the replace-with input field in the editor shown on Ctrl-H etc."
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Excluir",
|
||||
"description": "Label for the button to delete a style"
|
||||
},
|
||||
"addStyleLabel": {
|
||||
"message": "Gravar novo estilo",
|
||||
"description": "Label for the button to go to the add style page"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Editar",
|
||||
"description": "Label for the button to go to the edit style page"
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "Tema",
|
||||
"description": "Label for the style editor's CSS theme."
|
||||
},
|
||||
"description": {
|
||||
"message": "Mude o estilo da web com o Stylus, um gerenciador de estilos do usuário. O Stylus permite instalar facilmente temas e skins para Google, Facebook, YouTube, Orkut e muitos, muitos outros sites.",
|
||||
"description": "Extension description"
|
||||
}
|
||||
"addStyleLabel": {
|
||||
"message": "Gravar novo estilo"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Adicionar estilo"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Adicionar"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Aplica-se a: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "e mais"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URLs no domínio"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Use os controles \"Aplica-se a\" para limitar a quais URLs o código desta seção se aplica."
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Aplica-se a"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "URLs que correspondem a regexp"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Remover"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Especificar"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "Tudo"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "URLs que começam com"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Aplicar todas as atualizações"
|
||||
},
|
||||
"bckpInstStyles": {
|
||||
"message": "Exportar estilos"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Verificar atualizações para todos os estilos"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Verificar atualizações"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Verificando..."
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "Tema"
|
||||
},
|
||||
"confirmCancel": {
|
||||
"message": "Cancelar"
|
||||
},
|
||||
"confirmDelete": {
|
||||
"message": "Deletar"
|
||||
},
|
||||
"confirmNo": {
|
||||
"message": "Não"
|
||||
},
|
||||
"confirmStop": {
|
||||
"message": "Parar"
|
||||
},
|
||||
"confirmYes": {
|
||||
"message": "Sim"
|
||||
},
|
||||
"defaultTheme": {
|
||||
"message": "padrão"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Tem certeza de que deseja excluir este estilo?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Excluir"
|
||||
},
|
||||
"description": {
|
||||
"message": "Mude o estilo da web com o Stylus, um gerenciador de estilos do usuário. O Stylus permite instalar facilmente temas e skins para Google, Facebook, YouTube, Orkut e muitos, muitos outros sites."
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "Desativar todos os estilos"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Desativar"
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Ir para linha (ou linha:coluna)"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Editar estilo"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Editar"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Editar estilo $stylename$",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Ativar"
|
||||
},
|
||||
"exportLabel": {
|
||||
"message": "Exportar "
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Procurar mais estilos para este site"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Ajuda"
|
||||
},
|
||||
"importAppendLabel": {
|
||||
"message": "Anexar ao estilo"
|
||||
},
|
||||
"importAppendTooltip": {
|
||||
"message": "Anexar o estilo importado ao atual"
|
||||
},
|
||||
"importLabel": {
|
||||
"message": "Importar"
|
||||
},
|
||||
"importReplaceLabel": {
|
||||
"message": "Sobrescrever estilo"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Instalar atualização"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Estilos instalados"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Nenhum estilo instalado para este site."
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Gerenciar estilos instalados"
|
||||
},
|
||||
"openOptionsPopup": {
|
||||
"message": "Opções"
|
||||
},
|
||||
"optionsActions": {
|
||||
"message": "Ações"
|
||||
},
|
||||
"optionsBadgeDisabled": {
|
||||
"message": "Cor de fundo quando desativado"
|
||||
},
|
||||
"optionsBadgeNormal": {
|
||||
"message": "Cor de fundo"
|
||||
},
|
||||
"optionsCheck": {
|
||||
"message": "Atualizar estilos"
|
||||
},
|
||||
"optionsHeading": {
|
||||
"message": "Opções"
|
||||
},
|
||||
"optionsOpen": {
|
||||
"message": "Abrir"
|
||||
},
|
||||
"optionsSubheading": {
|
||||
"message": "Mais Opções"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Show number of styles active for the current site on the toolbar button"
|
||||
},
|
||||
"replace": {
|
||||
"message": "Substituir"
|
||||
},
|
||||
"replaceAll": {
|
||||
"message": "Substituir todos"
|
||||
},
|
||||
"replaceWith": {
|
||||
"message": "Substituir com"
|
||||
},
|
||||
"retrieveBckp": {
|
||||
"message": "Importar estilos"
|
||||
},
|
||||
"search": {
|
||||
"message": "Buscar"
|
||||
},
|
||||
"searchStyles": {
|
||||
"message": "Buscar conteúdos"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Adicionar outra seção"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Código"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "As seções permitem definir diferentes partes de código para aplicar a diferentes conjuntos de URLs no mesmo estilo. Por exemplo, um único estilo poderia alterar a página inicial de um site de uma forma, enquanto alteraria o resto do site de outra forma."
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Remover seção"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Expressão regular é inválida"
|
||||
},
|
||||
"styleBeautify": {
|
||||
"message": "Embelezar"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Voltar ao gerenciamento"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Você fez alterações neste estilo sem salvar."
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Ativado"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Instalar \"$stylename$\" no Stylus?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Insira um nome"
|
||||
},
|
||||
"styleMozillaFormatHeading": {
|
||||
"message": "Formato Mozilla"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Salvar"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Seções"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "O formato Mozilla do código pode ser usado com o Stylish para Firefox e pode ser enviado para userstyles.org."
|
||||
},
|
||||
"undo": {
|
||||
"message": "Desfazer"
|
||||
},
|
||||
"undoGlobal": {
|
||||
"message": "Desfazer todas as seções"
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "Nenhuma atualização encontrada."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "A atualização falhou: o servidor respondeu com código $code$.",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "A atualização falhou: servidor inacessível."
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "O estilo está atualizado."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Atualização concluída."
|
||||
},
|
||||
"writeStyleForURL": {
|
||||
"message": "esse URL"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,420 +1,323 @@
|
|||
{
|
||||
"appliesToEverything": {
|
||||
"message": "Све",
|
||||
"description": "Text displayed for styles that apply to all sites"
|
||||
},
|
||||
"linterIssues": {
|
||||
"message": "Проблеми",
|
||||
"description": "Label for the CSS linter issues block on the style edit page"
|
||||
},
|
||||
"defaultTheme": {
|
||||
"message": "подразумевано",
|
||||
"description": "Default CodeMirror CSS theme option on the edit style page"
|
||||
},
|
||||
"exportLabel": {
|
||||
"message": "Извези",
|
||||
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
|
||||
},
|
||||
"cm_tabSize": {
|
||||
"message": "Величина картице",
|
||||
"description": "Label for the text box controlling tab size option for the style editor."
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Омогући",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Унесите назив",
|
||||
"description": "Error displayed when user saves without providing a name"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "УРЛ адресе на домену",
|
||||
"description": "Option to make the style apply to the entered string as a domain"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Проверите ажурирање",
|
||||
"description": "Label for the button to check a single style for an update"
|
||||
},
|
||||
"importAppendLabel": {
|
||||
"message": "Додај стилу",
|
||||
"description": "Label for the button to import a style and append to the existing sections"
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "Сви стилови су ажурирани.",
|
||||
"description": "Text that displays when an update all check completed and no updates are available"
|
||||
},
|
||||
"styleFromMozillaFormatPrompt": {
|
||||
"message": "Налепи код у Mozilla формату",
|
||||
"description": "Prompt in the dialog displayed after clicking 'Import from Mozilla format' button"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Помоћ",
|
||||
"description": "Alternate text for help buttons"
|
||||
},
|
||||
"search": {
|
||||
"message": "Претражи",
|
||||
"description": "Label before the search input field in the editor shown on Ctrl-F"
|
||||
},
|
||||
"confirmYes": {
|
||||
"message": "Да",
|
||||
"description": "'Yes' button in a confirm dialog"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Пронађи још стилова за овај сајт",
|
||||
"description": "Text for a link that gets a list of styles for the current site"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Инсталирани стилови",
|
||||
"description": "Heading for the manage page"
|
||||
},
|
||||
"styleBeautify": {
|
||||
"message": "Улепшај",
|
||||
"description": "Label for the CSS-beautifier button on the edit style page"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Омогућено",
|
||||
"description": "Label for the enabled state of styles"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Mozilla формат кода се може користити у Stylish за Firefox и може се послати на userstyles.org.",
|
||||
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Додај нови одељак",
|
||||
"description": "Label for the button to add a section"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Сачувај",
|
||||
"description": "Label for save button for style editing"
|
||||
},
|
||||
"confirmStop": {
|
||||
"message": "Заустави",
|
||||
"description": "'Stop' button in a confirm dialog"
|
||||
},
|
||||
"writeStyleForURL": {
|
||||
"message": "ову УРЛ адресу",
|
||||
"description": "Text for link in toolbar pop-up to write a new style for the current URL"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Додај",
|
||||
"description": "Label for the button to add an 'applies' entry"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "УРЛ адресе које одговарају регуларном изразу",
|
||||
"description": "Option to make the style apply to the entered string as a regular expression"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Инсталирати '$stylename$' у Stylus?",
|
||||
"description": "Confirmation when installing a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linterIssuesHelp": {
|
||||
"message": "Проблем пронађен од стране $link$:",
|
||||
"description": "Help popup message for the selected CSS linter issues block on the style edit page",
|
||||
"placeholders": {
|
||||
"link": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"searchStyles": {
|
||||
"message": "Претражи садржај",
|
||||
"description": "Label for the search filter textbox on the Manage styles page"
|
||||
},
|
||||
"linkGetStyles": {
|
||||
"message": "Преузмите стилове",
|
||||
"description": "Help link text on the manage page e.g. https://userstyles.org"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Онемогући",
|
||||
"description": "Label for the button to disable a style"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Прикажи број активних стилова за тренутни сајт на дугмету на алатној траци",
|
||||
"description": "Label for the checkbox controlling toolbar badge text."
|
||||
},
|
||||
"menuShowBadge": {
|
||||
"message": "Прикажи број активних стилова",
|
||||
"description": "Label (must be very short) for the checkbox in the toolbar button context menu controlling toolbar badge text."
|
||||
},
|
||||
"cm_lineWrapping": {
|
||||
"message": "Преламање текста",
|
||||
"description": "Label for the checkbox controlling word wrap option for the style editor."
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Назад на управљање",
|
||||
"description": "Label for cancel button for style editing"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Направили сте измене овог стила које нисте сачували.",
|
||||
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
|
||||
},
|
||||
"importLabel": {
|
||||
"message": "Увези",
|
||||
"description": "Label for the button to import a style ('edit' page) or all styles ('manage' page)"
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Ажурирање није успело: сервер није доступан.",
|
||||
"description": "Text that displays when an update check failed because the update server is unreachable"
|
||||
},
|
||||
"manageFilters": {
|
||||
"message": "Филтери",
|
||||
"description": "Label for filters container"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Примени сва ажурирања",
|
||||
"description": "Label for the button to apply all detected updates"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Да ли сте сигурни да желите да избришете овај стил?",
|
||||
"description": "Confirmation before deleting a style"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Регуларни израз је неисправан.",
|
||||
"description": "Validation message for a bad regexp in a style"
|
||||
},
|
||||
"optionsHeading": {
|
||||
"message": "Опције",
|
||||
"description": "Heading for options section on manage page."
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Примењује се на: $applies$",
|
||||
"description": "Text on the manage screen to describe what the style applies to",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleUpdate": {
|
||||
"message": "Да ли сте сигурни да желите да ажурирате '$stylename$'?",
|
||||
"description": "Confirmation when updating a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Одељци",
|
||||
"description": "Title for the style sections section"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Уреди стил $stylename$",
|
||||
"description": "Title of the page for editing styles",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Стил је ажуриран.",
|
||||
"description": "Text that displays when an update check completed and no update is available"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "УРЛ адресе које почињу са",
|
||||
"description": "Option to make the style apply to the entered string as a URL prefix"
|
||||
},
|
||||
"searchRegexp": {
|
||||
"message": "Користи /re/ синтаксу за претрагу регуларним изразом",
|
||||
"description": "Label after the search input field in the editor shown on Ctrl-F"
|
||||
},
|
||||
"importReplaceTooltip": {
|
||||
"message": "Одбаци садржај тренутног стила и упиши преко њега увезени стил",
|
||||
"description": "Label for the button to import and overwrite current style"
|
||||
},
|
||||
"popupStylesFirst": {
|
||||
"message": "Излистај стилове пре команди у менију дугмета на алатној траци",
|
||||
"description": "Label for the checkbox controlling section order in the popup."
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Одељци вам омогућавају да дефинишете различите делове кода који се примењују на раличите скупове УРЛ-ова у истом стилу. На пример, један исти стил може променити почетну страницу једног сајта на један начин а остатак сајта на други начин.",
|
||||
"description": "Help text for sections"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Нема инсталираних стилова за овај сајт.",
|
||||
"description": "Text displayed when no styles are installed for the current site"
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "и још",
|
||||
"description": "Text added to appliesDisplay when there are more sites for the style than are displayed"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Уклони",
|
||||
"description": "Label for the button to remove an 'applies' entry"
|
||||
},
|
||||
"styleToMozillaFormatTitle": {
|
||||
"message": "Стил у Mozilla формату",
|
||||
"description": "Title of the popup with the style code in Mozilla format, shown after pressing the Export button on Edit style page"
|
||||
},
|
||||
"writeStyleFor": {
|
||||
"message": "Упиши стил за:",
|
||||
"description": "Label for toolbar pop-up that precedes the links to write a new style"
|
||||
},
|
||||
"replace": {
|
||||
"message": "Замени",
|
||||
"description": "Label before the replace input field in the editor shown on Ctrl-H"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Примењује се на",
|
||||
"description": "Label for 'applies to' fields on the edit/add screen"
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Управљај инсталираним стиловима",
|
||||
"description": "Link to open the manage page."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Ажурирање није успело: сервер је одговорио кодом $code$.",
|
||||
"description": "Text that displays when an update check failed because the response code indicates an error",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Детаљније",
|
||||
"description": "Label for the button to make a style apply only to specific sites"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Инсталирај ажурирање",
|
||||
"description": "Label for the button to install an update for a single style"
|
||||
},
|
||||
"styleMozillaFormatHeading": {
|
||||
"message": "Mozilla формат",
|
||||
"description": "Heading for the section with buttons to import/export Mozilla format of the style"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Уклони одељак",
|
||||
"description": "Label for the button to remove a section"
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "Искључи све стилове",
|
||||
"description": "Label for the checkbox that turns all enabled styles off."
|
||||
},
|
||||
"undoGlobal": {
|
||||
"message": "Опозови (свеобухватно)",
|
||||
"description": "CSS-beautify global Undo button label"
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Ажурирање је комплетирано.",
|
||||
"description": "Text that displays when an update completed"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Проверавање...",
|
||||
"description": "Text to display when checking a style for an update"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Код",
|
||||
"description": "Label for the code for a section"
|
||||
},
|
||||
"cm_smartIndent": {
|
||||
"message": "Користи паметно увлачење редова",
|
||||
"description": "Label for the checkbox controlling smart indentation option for the style editor."
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Употреба 'Примењује се на' одређује опсег УРЛ адреса на које се код у овом одељку примењује.",
|
||||
"description": "Help text for 'applies to' section"
|
||||
},
|
||||
"linkGetHelp": {
|
||||
"message": "Помоћ",
|
||||
"description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Уреди стил",
|
||||
"description": "Title of the page for editing styles"
|
||||
},
|
||||
"appliesUrlOption": {
|
||||
"message": "УРЛ",
|
||||
"description": "Option to make the style apply to the entered string as a URL"
|
||||
},
|
||||
"stylusUnavailableForURL": {
|
||||
"message": "Stylus не ради на страницама као што је ова.",
|
||||
"description": "Note in the toolbar pop-up when on a URL Stylus can't affect"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Додај стил",
|
||||
"description": "Title of the page for adding styles"
|
||||
},
|
||||
"importReplaceLabel": {
|
||||
"message": "Упиши преко стила",
|
||||
"description": "Label for the button to import and overwrite current style"
|
||||
},
|
||||
"dbError": {
|
||||
"message": "Дошло је до грешке користећи Stylus базу података. Да ли желите да посетите веб страницу са могућим решењима?",
|
||||
"description": "Prompt when a DB error is encountered"
|
||||
},
|
||||
"importAppendTooltip": {
|
||||
"message": "Додај увезени стил тренутном стилу",
|
||||
"description": "Tooltip for the button to import a style and append to the existing sections"
|
||||
},
|
||||
"helpKeyMapHotkey": {
|
||||
"message": "Притисни пречицу",
|
||||
"description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short"
|
||||
},
|
||||
"replaceAll": {
|
||||
"message": "Замени све",
|
||||
"description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey"
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Иди на ред (или line:col)",
|
||||
"description": "Go to line or line:column on Ctrl-G in style code editor"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Проверите ажурирања за све стилове",
|
||||
"description": "Label for the button to check all styles for updates"
|
||||
},
|
||||
"confirmNo": {
|
||||
"message": "Не",
|
||||
"description": "'No' button in a confirm dialog"
|
||||
},
|
||||
"undo": {
|
||||
"message": "Опозови",
|
||||
"description": "Button label"
|
||||
},
|
||||
"cm_keyMap": {
|
||||
"message": "Мапа тастера",
|
||||
"description": "Label for the drop-down list controlling the keymap for the style editor."
|
||||
},
|
||||
"cm_indentWithTabs": {
|
||||
"message": "Користи картице са паметним увлачењем редова",
|
||||
"description": "Label for the checkbox controlling tabs with smart indentation option for the style editor."
|
||||
},
|
||||
"replaceWith": {
|
||||
"message": "Замени са",
|
||||
"description": "Label before the replace-with input field in the editor shown on Ctrl-H etc."
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Избриши",
|
||||
"description": "Label for the button to delete a style"
|
||||
},
|
||||
"addStyleLabel": {
|
||||
"message": "Упиши нови стил",
|
||||
"description": "Label for the button to go to the add style page"
|
||||
},
|
||||
"manageOnlyEnabled": {
|
||||
"message": "Само омогућени стилови",
|
||||
"description": "Checkbox to show only enabled styles"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Уреди",
|
||||
"description": "Label for the button to go to the edit style page"
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "Тема",
|
||||
"description": "Label for the style editor's CSS theme."
|
||||
},
|
||||
"helpKeyMapCommand": {
|
||||
"message": "Укуцај име команде",
|
||||
"description": "Placeholder text of inputbox in keymap help popup on the edit style page. Must be very short"
|
||||
},
|
||||
"description": {
|
||||
"message": "Измените стил интернет мреже управљачем корисничких стилова. Stylus вам омогућава да лако инсталирате теме и скинове за многе популарне сајтове.",
|
||||
"description": "Extension description"
|
||||
}
|
||||
"addStyleLabel": {
|
||||
"message": "Упиши нови стил"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Додај стил"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Додај"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Примењује се на: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "и још"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "УРЛ адресе на домену"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Употреба 'Примењује се на' одређује опсег УРЛ адреса на које се код у овом одељку примењује."
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Примењује се на"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "УРЛ адресе које одговарају регуларном изразу"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Уклони"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Детаљније"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "Све"
|
||||
},
|
||||
"appliesUrlOption": {
|
||||
"message": "УРЛ"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "УРЛ адресе које почињу са"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Примени сва ажурирања"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Проверите ажурирања за све стилове"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Проверите ажурирање"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Проверавање..."
|
||||
},
|
||||
"cm_indentWithTabs": {
|
||||
"message": "Користи картице са паметним увлачењем редова"
|
||||
},
|
||||
"cm_keyMap": {
|
||||
"message": "Мапа тастера"
|
||||
},
|
||||
"cm_lineWrapping": {
|
||||
"message": "Преламање текста"
|
||||
},
|
||||
"cm_smartIndent": {
|
||||
"message": "Користи паметно увлачење редова"
|
||||
},
|
||||
"cm_tabSize": {
|
||||
"message": "Величина картице"
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "Тема"
|
||||
},
|
||||
"confirmNo": {
|
||||
"message": "Не"
|
||||
},
|
||||
"confirmStop": {
|
||||
"message": "Заустави"
|
||||
},
|
||||
"confirmYes": {
|
||||
"message": "Да"
|
||||
},
|
||||
"dbError": {
|
||||
"message": "Дошло је до грешке користећи Stylus базу података. Да ли желите да посетите веб страницу са могућим решењима?"
|
||||
},
|
||||
"defaultTheme": {
|
||||
"message": "подразумевано"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Да ли сте сигурни да желите да избришете овај стил?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Избриши"
|
||||
},
|
||||
"description": {
|
||||
"message": "Измените стил интернет мреже управљачем корисничких стилова. Stylus вам омогућава да лако инсталирате теме и скинове за многе популарне сајтове."
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "Искључи све стилове"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Онемогући"
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Иди на ред (или line:col)"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Уреди стил"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Уреди"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Уреди стил $stylename$",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Омогући"
|
||||
},
|
||||
"exportLabel": {
|
||||
"message": "Извези"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Пронађи још стилова за овај сајт"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Помоћ"
|
||||
},
|
||||
"helpKeyMapCommand": {
|
||||
"message": "Укуцај име команде"
|
||||
},
|
||||
"helpKeyMapHotkey": {
|
||||
"message": "Притисни пречицу"
|
||||
},
|
||||
"importAppendLabel": {
|
||||
"message": "Додај стилу"
|
||||
},
|
||||
"importAppendTooltip": {
|
||||
"message": "Додај увезени стил тренутном стилу"
|
||||
},
|
||||
"importLabel": {
|
||||
"message": "Увези"
|
||||
},
|
||||
"importReplaceLabel": {
|
||||
"message": "Упиши преко стила"
|
||||
},
|
||||
"importReplaceTooltip": {
|
||||
"message": "Одбаци садржај тренутног стила и упиши преко њега увезени стил"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Инсталирај ажурирање"
|
||||
},
|
||||
"linkGetHelp": {
|
||||
"message": "Помоћ"
|
||||
},
|
||||
"linkGetStyles": {
|
||||
"message": "Преузмите стилове"
|
||||
},
|
||||
"linterIssues": {
|
||||
"message": "Проблеми"
|
||||
},
|
||||
"linterIssuesHelp": {
|
||||
"message": "Проблем пронађен од стране $link$:",
|
||||
"placeholders": {
|
||||
"link": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"manageFilters": {
|
||||
"message": "Филтери"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Инсталирани стилови"
|
||||
},
|
||||
"manageOnlyEnabled": {
|
||||
"message": "Само омогућени стилови"
|
||||
},
|
||||
"menuShowBadge": {
|
||||
"message": "Прикажи број активних стилова"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Нема инсталираних стилова за овај сајт."
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Управљај инсталираним стиловима"
|
||||
},
|
||||
"optionsHeading": {
|
||||
"message": "Опције"
|
||||
},
|
||||
"popupStylesFirst": {
|
||||
"message": "Излистај стилове пре команди у менију дугмета на алатној траци"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Прикажи број активних стилова за тренутни сајт на дугмету на алатној траци"
|
||||
},
|
||||
"replace": {
|
||||
"message": "Замени"
|
||||
},
|
||||
"replaceAll": {
|
||||
"message": "Замени све"
|
||||
},
|
||||
"replaceWith": {
|
||||
"message": "Замени са"
|
||||
},
|
||||
"search": {
|
||||
"message": "Претражи"
|
||||
},
|
||||
"searchRegexp": {
|
||||
"message": "Користи /re/ синтаксу за претрагу регуларним изразом"
|
||||
},
|
||||
"searchStyles": {
|
||||
"message": "Претражи садржај"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Додај нови одељак"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Код"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Одељци вам омогућавају да дефинишете различите делове кода који се примењују на раличите скупове УРЛ-ова у истом стилу. На пример, један исти стил може променити почетну страницу једног сајта на један начин а остатак сајта на други начин."
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Уклони одељак"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Регуларни израз је неисправан."
|
||||
},
|
||||
"styleBeautify": {
|
||||
"message": "Улепшај"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Назад на управљање"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Направили сте измене овог стила које нисте сачували."
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Омогућено"
|
||||
},
|
||||
"styleFromMozillaFormatPrompt": {
|
||||
"message": "Налепи код у Mozilla формату"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Инсталирати '$stylename$' у Stylus?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Унесите назив"
|
||||
},
|
||||
"styleMozillaFormatHeading": {
|
||||
"message": "Mozilla формат"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Сачувај"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Одељци"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Mozilla формат кода се може користити у Stylish за Firefox и може се послати на userstyles.org."
|
||||
},
|
||||
"styleToMozillaFormatTitle": {
|
||||
"message": "Стил у Mozilla формату"
|
||||
},
|
||||
"styleUpdate": {
|
||||
"message": "Да ли сте сигурни да желите да ажурирате '$stylename$'?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"stylusUnavailableForURL": {
|
||||
"message": "Stylus не ради на страницама као што је ова."
|
||||
},
|
||||
"undo": {
|
||||
"message": "Опозови"
|
||||
},
|
||||
"undoGlobal": {
|
||||
"message": "Опозови (свеобухватно)"
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "Сви стилови су ажурирани."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Ажурирање није успело: сервер је одговорио кодом $code$.",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Ажурирање није успело: сервер није доступан."
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Стил је ажуриран."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Ажурирање је комплетирано."
|
||||
},
|
||||
"writeStyleFor": {
|
||||
"message": "Упиши стил за:"
|
||||
},
|
||||
"writeStyleForURL": {
|
||||
"message": "ову УРЛ адресу"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,435 +1,405 @@
|
|||
{
|
||||
"appliesToEverything": {
|
||||
"message": "Allt",
|
||||
"description": "Text displayed for styles that apply to all sites"
|
||||
},
|
||||
"manageOnlyUsercss": {
|
||||
"message": "Endast Usercss stilar",
|
||||
"description": "Checkbox to show only Usercss styles"
|
||||
},
|
||||
"exportLabel": {
|
||||
"message": "Exportera",
|
||||
"description": "Label for the button to export a style ('edit' page) or all styles ('manage' page)"
|
||||
},
|
||||
"cm_tabSize": {
|
||||
"message": "Tabbstorlek",
|
||||
"description": "Label for the text box controlling tab size option for the style editor."
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Aktivera",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Ange ett namn",
|
||||
"description": "Error displayed when user saves without providing a name"
|
||||
},
|
||||
"genericHistoryLabel": {
|
||||
"message": "Historik",
|
||||
"description": "Used in various places to show a history log of something"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URL:er på domänen",
|
||||
"description": "Option to make the style apply to the entered string as a domain"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Leta efter uppdatering",
|
||||
"description": "Label for the button to check a single style for an update"
|
||||
},
|
||||
"styleFromMozillaFormatError": {
|
||||
"message": "Import av Mozilla-format misslyckades",
|
||||
"description": "Label for the import error"
|
||||
},
|
||||
"importAppendLabel": {
|
||||
"message": "Lägg till i stil",
|
||||
"description": "Label for the button to import a style and append to the existing sections"
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "Alla stilar är fullt uppdaterade.",
|
||||
"description": "Text that displays when an update all check completed and no updates are available"
|
||||
},
|
||||
"styleFromMozillaFormatPrompt": {
|
||||
"message": "Klistra in koden i Mozilla-formatet",
|
||||
"description": "Prompt in the dialog displayed after clicking 'Import from Mozilla format' button"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Hjälp",
|
||||
"description": "Alternate text for help buttons"
|
||||
},
|
||||
"search": {
|
||||
"message": "Sök",
|
||||
"description": "Label before the search input field in the editor shown on Ctrl-F"
|
||||
},
|
||||
"genericEnabledLabel": {
|
||||
"message": "Aktiverad",
|
||||
"description": "Used in various lists/options to indicate that something is enabled"
|
||||
},
|
||||
"confirmYes": {
|
||||
"message": "Ja",
|
||||
"description": "'Yes' button in a confirm dialog"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Hitta fler stilar för denna sida",
|
||||
"description": "Text for a link that gets a list of styles for the current site"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Installerade Stilar",
|
||||
"description": "Heading for the manage page"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Aktiverad",
|
||||
"description": "Label for the enabled state of styles"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Mozilla-formatet av koden fungerar i Stylish till Firefox samt vid uppladdandet till userstyles.org.",
|
||||
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Lägg till ytterligare en sektion",
|
||||
"description": "Label for the button to add a section"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Spara",
|
||||
"description": "Label for save button for style editing"
|
||||
},
|
||||
"writeStyleForURL": {
|
||||
"message": "denna URL",
|
||||
"description": "Text for link in toolbar pop-up to write a new style for the current URL"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Lägg till",
|
||||
"description": "Label for the button to add an 'applies' entry"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "URL:er som matchar regexp:en",
|
||||
"description": "Option to make the style apply to the entered string as a regular expression"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Installera '$stylename$' in i Stylus?",
|
||||
"description": "Confirmation when installing a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"manageOnlyLocal": {
|
||||
"message": "Endast lokalt skapade stilar",
|
||||
"description": "Checkbox to show only locally created styles i.e. non-updatable"
|
||||
},
|
||||
"searchStyles": {
|
||||
"message": "Sök innehåll",
|
||||
"description": "Label for the search filter textbox on the Manage styles page"
|
||||
},
|
||||
"manageOnlyNonUsercss": {
|
||||
"message": "Endast icke-Usercss stilar",
|
||||
"description": "Checkbox to show only non-Usercss (standard) styles"
|
||||
},
|
||||
"linkGetStyles": {
|
||||
"message": "Skaffa stilar",
|
||||
"description": "Help link text on the manage page e.g. https://userstyles.org"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Inaktivera",
|
||||
"description": "Label for the button to disable a style"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Visa antalet aktiva stilar för den nuvarande sidan på verktygsfältsikonen",
|
||||
"description": "Label for the checkbox controlling toolbar badge text."
|
||||
},
|
||||
"menuShowBadge": {
|
||||
"message": "Visa antalet aktiva stilar",
|
||||
"description": "Label (must be very short) for the checkbox in the toolbar button context menu controlling toolbar badge text."
|
||||
},
|
||||
"cm_lineWrapping": {
|
||||
"message": "Radbrytning",
|
||||
"description": "Label for the checkbox controlling word wrap option for the style editor."
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Återgå till hantera",
|
||||
"description": "Label for cancel button for style editing"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Du har gjort ändringar i denna stil utan att spara.",
|
||||
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
|
||||
},
|
||||
"importLabel": {
|
||||
"message": "Importera",
|
||||
"description": "Label for the button to import a style ('edit' page) or all styles ('manage' page)"
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Uppdateringen misslyckades: server onåbar.",
|
||||
"description": "Text that displays when an update check failed because the update server is unreachable"
|
||||
},
|
||||
"manageFilters": {
|
||||
"message": "Filter",
|
||||
"description": "Label for filters container"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Verkställ alla uppdateringar",
|
||||
"description": "Label for the button to apply all detected updates"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Är du säker på att du vill ta bort denna stil?",
|
||||
"description": "Confirmation before deleting a style"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Regexp:en är ogiltig",
|
||||
"description": "Validation message for a bad regexp in a style"
|
||||
},
|
||||
"optionsHeading": {
|
||||
"message": "Alternativ",
|
||||
"description": "Heading for options section on manage page."
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Gäller för: $applies$",
|
||||
"description": "Text on the manage screen to describe what the style applies to",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleUpdate": {
|
||||
"message": "Är du säker på att du vill uppdatera '$stylename$'?",
|
||||
"description": "Confirmation when updating a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Sektioner",
|
||||
"description": "Title for the style sections section"
|
||||
},
|
||||
"optionsAdvancedNewStyleAsUsercss": {
|
||||
"message": "Skriv ny stil som Usercss",
|
||||
"description": ""
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Ändra i Stil $stylename$",
|
||||
"description": "Title of the page for editing styles",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Stilen är fullt uppdaterad.",
|
||||
"description": "Text that displays when an update check completed and no update is available"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "URL:er som börjar på",
|
||||
"description": "Option to make the style apply to the entered string as a URL prefix"
|
||||
},
|
||||
"searchRegexp": {
|
||||
"message": "Använd /re/ för regexp-sökning",
|
||||
"description": "Label after the search input field in the editor shown on Ctrl-F"
|
||||
},
|
||||
"popupStylesFirst": {
|
||||
"message": "Lista stilar före kommandon i verktygsfältets knappmeny",
|
||||
"description": "Label for the checkbox controlling section order in the popup."
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Sektioner låter dig definiera olika sorters kod som påverkar olika URL:er i samma stil. Till exempel, en stil kan ändra en viss hemsida på ett sätt, samtidigt som den ändrar andra delar på en helt annan sida.",
|
||||
"description": "Help text for sections"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Inga stilar installerade för denna sida.",
|
||||
"description": "Text displayed when no styles are installed for the current site"
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "och mer",
|
||||
"description": "Text added to appliesDisplay when there are more sites for the style than are displayed"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Ta bort",
|
||||
"description": "Label for the button to remove an 'applies' entry"
|
||||
},
|
||||
"styleToMozillaFormatTitle": {
|
||||
"message": "Stil i Mozilla-format",
|
||||
"description": "Title of the popup with the style code in Mozilla format, shown after pressing the Export button on Edit style page"
|
||||
},
|
||||
"writeStyleFor": {
|
||||
"message": "Skriv stil för:",
|
||||
"description": "Label for toolbar pop-up that precedes the links to write a new style"
|
||||
},
|
||||
"replace": {
|
||||
"message": "Ersätt",
|
||||
"description": "Label before the replace input field in the editor shown on Ctrl-H"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Gäller för",
|
||||
"description": "Label for 'applies to' fields on the edit/add screen"
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Hantera installerade stilar",
|
||||
"description": "Link to open the manage page."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Uppdateringen misslyckades: servern svarade med kod $code$.",
|
||||
"description": "Text that displays when an update check failed because the response code indicates an error",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Specificera",
|
||||
"description": "Label for the button to make a style apply only to specific sites"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Installera uppdatering",
|
||||
"description": "Label for the button to install an update for a single style"
|
||||
},
|
||||
"styleMozillaFormatHeading": {
|
||||
"message": "Mozilla-format",
|
||||
"description": "Heading for the section with buttons to import/export Mozilla format of the style"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Ta bort sektion",
|
||||
"description": "Label for the button to remove a section"
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "Stäng av alla stilar",
|
||||
"description": "Label for the checkbox that turns all enabled styles off."
|
||||
},
|
||||
"undoGlobal": {
|
||||
"message": "Ångra i alla sektioner",
|
||||
"description": "CSS-beautify global Undo button label"
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Uppdatering slutförd.",
|
||||
"description": "Text that displays when an update completed"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Letar...",
|
||||
"description": "Text to display when checking a style for an update"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Kod",
|
||||
"description": "Label for the code for a section"
|
||||
},
|
||||
"externalUsercssDocument": {
|
||||
"message": "Dokumentation för Usercss",
|
||||
"description": "Label for the external link to usercss documentation"
|
||||
},
|
||||
"cm_smartIndent": {
|
||||
"message": "Använd smart indrag",
|
||||
"description": "Label for the checkbox controlling smart indentation option for the style editor."
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Använd 'Gäller för' alternativet för att begränsa vilka URL:er koden i denna sektion gäller för.",
|
||||
"description": "Help text for 'applies to' section"
|
||||
},
|
||||
"linkGetHelp": {
|
||||
"message": "Hjälp",
|
||||
"description": "Homepage link text on the manage page e.g. https://add0n.com/stylus.html#features with chat/FAQ/intro/info"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Ändra i Stil",
|
||||
"description": "Title of the page for editing styles"
|
||||
},
|
||||
"manageOnlyDisabled": {
|
||||
"message": "Endast inaktiverade stilar",
|
||||
"description": "Checkbox to show only disabled styles"
|
||||
},
|
||||
"stylusUnavailableForURL": {
|
||||
"message": "Stylus fungerar inte på sidor som denna.",
|
||||
"description": "Note in the toolbar pop-up when on a URL Stylus can't affect"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Lägg till stil",
|
||||
"description": "Title of the page for adding styles"
|
||||
},
|
||||
"importReplaceLabel": {
|
||||
"message": "Ersätt stil",
|
||||
"description": "Label for the button to import and overwrite current style"
|
||||
},
|
||||
"dbError": {
|
||||
"message": "Ett fel inträffades vid hanteringen av Stylus-databasen. Skulle du vilja besöka en sida med eventuella lösningar?",
|
||||
"description": "Prompt when a DB error is encountered"
|
||||
},
|
||||
"importAppendTooltip": {
|
||||
"message": "Lägg till den importerad stilen i aktuell stil",
|
||||
"description": "Tooltip for the button to import a style and append to the existing sections"
|
||||
},
|
||||
"manageOnlyExternal": {
|
||||
"message": "Endast externa stilar",
|
||||
"description": "Checkbox to show only externally installed styles i.e. updatable"
|
||||
},
|
||||
"replaceAll": {
|
||||
"message": "Ersätt alla",
|
||||
"description": "Label before the replace input field in the editor shown on 'replaceAll' hotkey"
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Gå till rad (eller rad:kol)",
|
||||
"description": "Go to line or line:column on Ctrl-G in style code editor"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Sök efter uppdateringar",
|
||||
"description": "Label for the button to check all styles for updates"
|
||||
},
|
||||
"manageNewStyleAsUsercss": {
|
||||
"message": "som Usercss",
|
||||
"description": "VERY SHORT label for the checkbox next to the 'Write new style' button in the style manager"
|
||||
},
|
||||
"confirmNo": {
|
||||
"message": "Nej",
|
||||
"description": "'No' button in a confirm dialog"
|
||||
},
|
||||
"undo": {
|
||||
"message": "Ångra",
|
||||
"description": "Button label"
|
||||
},
|
||||
"cm_keyMap": {
|
||||
"message": "Nyckelkarta",
|
||||
"description": "Label for the drop-down list controlling the keymap for the style editor."
|
||||
},
|
||||
"confirmSave": {
|
||||
"message": "Spara",
|
||||
"description": "'Save' button in a confirm dialog"
|
||||
},
|
||||
"genericDisabledLabel": {
|
||||
"message": "Inaktiverad",
|
||||
"description": "Used in various lists/options to indicate that something is disabled"
|
||||
},
|
||||
"cm_indentWithTabs": {
|
||||
"message": "Använd tabbar med smart indrag",
|
||||
"description": "Label for the checkbox controlling tabs with smart indentation option for the style editor."
|
||||
},
|
||||
"replaceWith": {
|
||||
"message": "Ersätt med",
|
||||
"description": "Label before the replace-with input field in the editor shown on Ctrl-H etc."
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Ta bort",
|
||||
"description": "Label for the button to delete a style"
|
||||
},
|
||||
"addStyleLabel": {
|
||||
"message": "Skriv ny stil",
|
||||
"description": "Label for the button to go to the add style page"
|
||||
},
|
||||
"manageOnlyEnabled": {
|
||||
"message": "Endast aktiverade stilar",
|
||||
"description": "Checkbox to show only enabled styles"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Ändra",
|
||||
"description": "Label for the button to go to the edit style page"
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "Tema",
|
||||
"description": "Label for the style editor's CSS theme."
|
||||
},
|
||||
"description": {
|
||||
"message": "Style:a om webben med Stylus, en användarstils-hanterare. Stylus låter dig enkelt installera teman och skal för många populära sidor.",
|
||||
"description": "Extension description"
|
||||
},
|
||||
"confirmClose": {
|
||||
"message": "Stäng",
|
||||
"description": "'Close' button in a confirm dialog"
|
||||
}
|
||||
"addStyleLabel": {
|
||||
"message": "Skriv ny stil"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Lägg till stil"
|
||||
},
|
||||
"alphaChannel": {
|
||||
"message": "Opacitet"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Lägg till"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Gäller för: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "och mer"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "URL:er på domänen"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Använd 'Gäller för' alternativet för att begränsa vilka URL:er koden i denna sektion gäller för."
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Gäller för"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "URL:er som matchar regexp:en"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Ta bort"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Specificera"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "Allt"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "URL:er som börjar på"
|
||||
},
|
||||
"applyAllUpdates": {
|
||||
"message": "Verkställ alla uppdateringar"
|
||||
},
|
||||
"bckpInstStyles": {
|
||||
"message": "Exportera stilar"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Sök efter uppdateringar"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Leta efter uppdatering"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Letar..."
|
||||
},
|
||||
"cm_indentWithTabs": {
|
||||
"message": "Använd tabbar med smart indrag"
|
||||
},
|
||||
"cm_keyMap": {
|
||||
"message": "Nyckelkarta"
|
||||
},
|
||||
"cm_lineWrapping": {
|
||||
"message": "Radbrytning"
|
||||
},
|
||||
"cm_smartIndent": {
|
||||
"message": "Använd smart indrag"
|
||||
},
|
||||
"cm_tabSize": {
|
||||
"message": "Tabbstorlek"
|
||||
},
|
||||
"cm_theme": {
|
||||
"message": "Tema"
|
||||
},
|
||||
"confirmClose": {
|
||||
"message": "Stäng"
|
||||
},
|
||||
"confirmNo": {
|
||||
"message": "Nej"
|
||||
},
|
||||
"confirmSave": {
|
||||
"message": "Spara"
|
||||
},
|
||||
"confirmYes": {
|
||||
"message": "Ja"
|
||||
},
|
||||
"dbError": {
|
||||
"message": "Ett fel inträffades vid hanteringen av Stylus-databasen. Skulle du vilja besöka en sida med eventuella lösningar?"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Är du säker på att du vill ta bort denna stil?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Ta bort"
|
||||
},
|
||||
"description": {
|
||||
"message": "Style:a om webben med Stylus, en användarstils-hanterare. Stylus låter dig enkelt installera teman och skal för många populära sidor."
|
||||
},
|
||||
"disableAllStyles": {
|
||||
"message": "Stäng av alla stilar"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Inaktivera"
|
||||
},
|
||||
"editGotoLine": {
|
||||
"message": "Gå till rad (eller rad:kol)"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Ändra i Stil"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Ändra"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "Ändra i Stil $stylename$",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Aktivera"
|
||||
},
|
||||
"exportLabel": {
|
||||
"message": "Exportera"
|
||||
},
|
||||
"externalUsercssDocument": {
|
||||
"message": "Dokumentation för Usercss"
|
||||
},
|
||||
"findStyles": {
|
||||
"message": "Hitta stilar"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Hitta fler stilar för denna sida"
|
||||
},
|
||||
"genericAdd": {
|
||||
"message": "Lägg till"
|
||||
},
|
||||
"genericDisabledLabel": {
|
||||
"message": "Inaktiverad"
|
||||
},
|
||||
"genericEnabledLabel": {
|
||||
"message": "Aktiverad"
|
||||
},
|
||||
"genericHistoryLabel": {
|
||||
"message": "Historik"
|
||||
},
|
||||
"genericNext": {
|
||||
"message": "Nästa"
|
||||
},
|
||||
"genericPrevious": {
|
||||
"message": "Föregående"
|
||||
},
|
||||
"genericResetLabel": {
|
||||
"message": "Återställ"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Hjälp"
|
||||
},
|
||||
"importAppendLabel": {
|
||||
"message": "Lägg till i stil"
|
||||
},
|
||||
"importAppendTooltip": {
|
||||
"message": "Lägg till den importerad stilen i aktuell stil"
|
||||
},
|
||||
"importLabel": {
|
||||
"message": "Importera"
|
||||
},
|
||||
"importReplaceLabel": {
|
||||
"message": "Ersätt stil"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Installera uppdatering"
|
||||
},
|
||||
"linkGetHelp": {
|
||||
"message": "Hjälp"
|
||||
},
|
||||
"linkGetStyles": {
|
||||
"message": "Skaffa stilar"
|
||||
},
|
||||
"linkTranslate": {
|
||||
"message": "Översätt"
|
||||
},
|
||||
"manageFavicons": {
|
||||
"message": "Ikoner i 'Gäller för' kolumnen"
|
||||
},
|
||||
"manageFaviconsGray": {
|
||||
"message": "Nedtonade"
|
||||
},
|
||||
"manageFaviconsHelp": {
|
||||
"message": "Stylus använder en extern tjänst https://www.google.com/s2/favicons"
|
||||
},
|
||||
"manageFilters": {
|
||||
"message": "Filter"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Installerade Stilar"
|
||||
},
|
||||
"manageNewStyleAsUsercss": {
|
||||
"message": "som Usercss"
|
||||
},
|
||||
"manageOnlyDisabled": {
|
||||
"message": "Endast inaktiverade stilar"
|
||||
},
|
||||
"manageOnlyEnabled": {
|
||||
"message": "Endast aktiverade stilar"
|
||||
},
|
||||
"manageOnlyExternal": {
|
||||
"message": "Endast externa stilar"
|
||||
},
|
||||
"manageOnlyLocal": {
|
||||
"message": "Endast lokalt skapade stilar"
|
||||
},
|
||||
"manageOnlyNonUsercss": {
|
||||
"message": "Endast icke-Usercss stilar"
|
||||
},
|
||||
"manageOnlyUsercss": {
|
||||
"message": "Endast Usercss stilar"
|
||||
},
|
||||
"menuShowBadge": {
|
||||
"message": "Visa antalet aktiva stilar"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Inga stilar installerade för denna sida."
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Hantera installerade stilar"
|
||||
},
|
||||
"openOptionsPopup": {
|
||||
"message": "Alternativ"
|
||||
},
|
||||
"openStylesManager": {
|
||||
"message": "Öppna stilhanteraren"
|
||||
},
|
||||
"optionsAdvancedNewStyleAsUsercss": {
|
||||
"message": "Skriv ny stil som Usercss"
|
||||
},
|
||||
"optionsCheck": {
|
||||
"message": "Uppdatera stilar"
|
||||
},
|
||||
"optionsCheckUpdate": {
|
||||
"message": "Leta efter och installera alla tillgängliga uppdateringar"
|
||||
},
|
||||
"optionsHeading": {
|
||||
"message": "Alternativ"
|
||||
},
|
||||
"optionsOpenManager": {
|
||||
"message": "Hantera stilar"
|
||||
},
|
||||
"optionsReset": {
|
||||
"message": "Återställ alternativen till standard"
|
||||
},
|
||||
"optionsResetButton": {
|
||||
"message": "Återställ alternativ"
|
||||
},
|
||||
"paginationNext": {
|
||||
"message": "Nästa sida"
|
||||
},
|
||||
"paginationPrevious": {
|
||||
"message": "Föregående sida"
|
||||
},
|
||||
"popupStylesFirst": {
|
||||
"message": "Lista stilar före kommandon i verktygsfältets knappmeny"
|
||||
},
|
||||
"prefShowBadge": {
|
||||
"message": "Visa antalet aktiva stilar för den nuvarande sidan på verktygsfältsikonen"
|
||||
},
|
||||
"replace": {
|
||||
"message": "Ersätt"
|
||||
},
|
||||
"replaceAll": {
|
||||
"message": "Ersätt alla"
|
||||
},
|
||||
"replaceWith": {
|
||||
"message": "Ersätt med"
|
||||
},
|
||||
"retrieveBckp": {
|
||||
"message": "Importera stilar"
|
||||
},
|
||||
"search": {
|
||||
"message": "Sök"
|
||||
},
|
||||
"searchRegexp": {
|
||||
"message": "Använd /re/ för regexp-sökning"
|
||||
},
|
||||
"searchStyles": {
|
||||
"message": "Sök innehåll"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Lägg till ytterligare en sektion"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Kod"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Sektioner låter dig definiera olika sorters kod som påverkar olika URL:er i samma stil. Till exempel, en stil kan ändra en viss hemsida på ett sätt, samtidigt som den ändrar andra delar på en helt annan sida."
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Ta bort sektion"
|
||||
},
|
||||
"sectionRestore": {
|
||||
"message": "Återställ borttagen sektion"
|
||||
},
|
||||
"shortcuts": {
|
||||
"message": "Genvägar"
|
||||
},
|
||||
"shortcutsNote": {
|
||||
"message": "Ställ in tangentbordsgenvägar"
|
||||
},
|
||||
"styleBadRegexp": {
|
||||
"message": "Regexp:en är ogiltig"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Återgå till hantera"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Du har gjort ändringar i denna stil utan att spara."
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Aktiverad"
|
||||
},
|
||||
"styleFromMozillaFormatError": {
|
||||
"message": "Import av Mozilla-format misslyckades"
|
||||
},
|
||||
"styleFromMozillaFormatPrompt": {
|
||||
"message": "Klistra in koden i Mozilla-formatet"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "Installera '$stylename$' in i Stylus?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Ange ett namn"
|
||||
},
|
||||
"styleMozillaFormatHeading": {
|
||||
"message": "Mozilla-format"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Spara"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Sektioner"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Mozilla-formatet av koden fungerar i Stylish till Firefox samt vid uppladdandet till userstyles.org."
|
||||
},
|
||||
"styleToMozillaFormatTitle": {
|
||||
"message": "Stil i Mozilla-format"
|
||||
},
|
||||
"styleUpdate": {
|
||||
"message": "Är du säker på att du vill uppdatera '$stylename$'?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"stylusUnavailableForURL": {
|
||||
"message": "Stylus fungerar inte på sidor som denna."
|
||||
},
|
||||
"undo": {
|
||||
"message": "Ångra"
|
||||
},
|
||||
"undoGlobal": {
|
||||
"message": "Ångra i alla sektioner"
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "Alla stilar är fullt uppdaterade."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Uppdateringen misslyckades: servern svarade med kod $code$.",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Uppdateringen misslyckades: server onåbar."
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Stilen är fullt uppdaterad."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Uppdatering slutförd."
|
||||
},
|
||||
"writeStyleFor": {
|
||||
"message": "Skriv stil för:"
|
||||
},
|
||||
"writeStyleForURL": {
|
||||
"message": "denna URL"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,71 +1,55 @@
|
|||
{
|
||||
"appliesToEverything": {
|
||||
"message": "అన్నిటికీ",
|
||||
"description": "Text displayed for styles that apply to all sites"
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "చేతనించు",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "సహాయం",
|
||||
"description": "Alternate text for help buttons"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "స్థాపిత శైలులు",
|
||||
"description": "Heading for the manage page"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "భద్రపరచు",
|
||||
"description": "Label for save button for style editing"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "చేర్చు",
|
||||
"description": "Label for the button to add an 'applies' entry"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "అచేతనించు",
|
||||
"description": "Label for the button to disable a style"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "మీరు నజంగానే ఈ శైలిని తొలగించాలనుకుంటున్నారా?",
|
||||
"description": "Confirmation before deleting a style"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "వేటికి వర్తిస్తుంది; $applies$",
|
||||
"description": "Text on the manage screen to describe what the style applies to",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "విభాగాలు",
|
||||
"description": "Title for the style sections section"
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "ఇంకా మరిన్ని",
|
||||
"description": "Text added to appliesDisplay when there are more sites for the style than are displayed"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "తొలగించు",
|
||||
"description": "Label for the button to remove an 'applies' entry"
|
||||
},
|
||||
"manageTitle": {
|
||||
"message": "స్టైలిష్",
|
||||
"description": "Title for the manage page"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "తొలగించు",
|
||||
"description": "Label for the button to delete a style"
|
||||
},
|
||||
"addStyleLabel": {
|
||||
"message": "క్రొత్త స్టైల్ వ్రాయండి",
|
||||
"description": "Label for the button to go to the add style page"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "మార్చు",
|
||||
"description": "Label for the button to go to the edit style page"
|
||||
}
|
||||
"addStyleLabel": {
|
||||
"message": "క్రొత్త స్టైల్ వ్రాయండి"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "చేర్చు"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "వేటికి వర్తిస్తుంది; $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "ఇంకా మరిన్ని"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "తొలగించు"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "అన్నిటికీ"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "మీరు నజంగానే ఈ శైలిని తొలగించాలనుకుంటున్నారా?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "తొలగించు"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "అచేతనించు"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "మార్చు"
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "చేతనించు"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "సహాయం"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "స్థాపిత శైలులు"
|
||||
},
|
||||
"manageTitle": {
|
||||
"message": "స్టైలిష్"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "భద్రపరచు"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "విభాగాలు"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,206 +1,160 @@
|
|||
{
|
||||
"appliesToEverything": {
|
||||
"message": "Her şey",
|
||||
"description": "Text displayed for styles that apply to all sites"
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Etkinleştir",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Bir ad girin",
|
||||
"description": "Error displayed when user saves without providing a name"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "Alan adındaki URLler",
|
||||
"description": "Option to make the style apply to the entered string as a domain"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Güncellemeleri denetle",
|
||||
"description": "Label for the button to check a single style for an update"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Yardım",
|
||||
"description": "Alternate text for help buttons"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Bu site için başka stiller bul",
|
||||
"description": "Text for a link that gets a list of styles for the current site"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Yüklü Stiller",
|
||||
"description": "Heading for the manage page"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Etkin",
|
||||
"description": "Label for the enabled state of styles"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Kodun Mozilla biçimi, Firefox için Stylish ile kullanılabilir ve userstyles.org sitesine gönderilebilir.",
|
||||
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Başka bölüm ekle",
|
||||
"description": "Label for the button to add a section"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Kaydet",
|
||||
"description": "Label for save button for style editing"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Ekleyin",
|
||||
"description": "Label for the button to add an 'applies' entry"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "regexp ile eşleşen URL'ler",
|
||||
"description": "Option to make the style apply to the entered string as a regular expression"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "'$stylename$' Stylus'e yüklensin mi?",
|
||||
"description": "Confirmation when installing a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Devre dışı bırak",
|
||||
"description": "Label for the button to disable a style"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Yönetim sayfasına dön",
|
||||
"description": "Label for cancel button for style editing"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Bu stilde yaptığınız, kaydedilmemiş değişiklikler var.",
|
||||
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Güncellenemedi: sunucuya erişilemiyor.",
|
||||
"description": "Text that displays when an update check failed because the update server is unreachable"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Bu stili silmek istediğinizden emin misiniz?",
|
||||
"description": "Confirmation before deleting a style"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Şuraya uygulanır: $applies$",
|
||||
"description": "Text on the manage screen to describe what the style applies to",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Bölümler",
|
||||
"description": "Title for the style sections section"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "$stylename$ Stilini Düzenleyin",
|
||||
"description": "Title of the page for editing styles",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Stil güncel.",
|
||||
"description": "Text that displays when an update check completed and no update is available"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "Şununla başlayan URL'ler:",
|
||||
"description": "Option to make the style apply to the entered string as a URL prefix"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Bölümler, aynı stil içindeki farklı URL kümelerine uygulanacak farklı kod parçaları tanımlamanıza olanak sağlar. Örneğin, tek bir stil bir sitenin ana sayfasını belirli bir şekilde değiştirirken, sayfanın kalan kısmını farklı bir şekilde değiştirebilir.",
|
||||
"description": "Help text for sections"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Bu site için hiçbir stil yüklenmedi.",
|
||||
"description": "Text displayed when no styles are installed for the current site"
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "ve diğerleri",
|
||||
"description": "Text added to appliesDisplay when there are more sites for the style than are displayed"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Kaldır",
|
||||
"description": "Label for the button to remove an 'applies' entry"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Şuraya uygulanır",
|
||||
"description": "Label for 'applies to' fields on the edit/add screen"
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Yüklü stilleri yönet",
|
||||
"description": "Link to open the manage page."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Güncellenemedi: sunucu yanıt olarak $code$ kodunu gönderdi.",
|
||||
"description": "Text that displays when an update check failed because the response code indicates an error",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Belirt",
|
||||
"description": "Label for the button to make a style apply only to specific sites"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Güncellemeyi yükle",
|
||||
"description": "Label for the button to install an update for a single style"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Bölümü kaldır",
|
||||
"description": "Label for the button to remove a section"
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Güncelleme tamamlandı.",
|
||||
"description": "Text that displays when an update completed"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Kontrol ediliyor...",
|
||||
"description": "Text to display when checking a style for an update"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Kod",
|
||||
"description": "Label for the code for a section"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Bu bölümdeki kodun hangi URLlere uygulanacağını sınırlamak için 'Şuraya uygulanır' denetimlerini kullanın.",
|
||||
"description": "Help text for 'applies to' section"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Stili Düzenle",
|
||||
"description": "Title of the page for editing styles"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Stil Ekleyin",
|
||||
"description": "Title of the page for adding styles"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Tüm stiller için güncellemeleri denetle",
|
||||
"description": "Label for the button to check all styles for updates"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Sil",
|
||||
"description": "Label for the button to delete a style"
|
||||
},
|
||||
"addStyleLabel": {
|
||||
"message": "Yeni stil oluşturun",
|
||||
"description": "Label for the button to go to the add style page"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Düzenle",
|
||||
"description": "Label for the button to go to the edit style page"
|
||||
},
|
||||
"description": {
|
||||
"message": "Kullanıcı stil yöneticisi Stylus ile Web'in stilini yenileyin. Stylus Google, Facebook, YouTube, Orkut ve diğer pek çok site için temalar ve görünüm yüklemenize imkân tanır.",
|
||||
"description": "Extension description"
|
||||
}
|
||||
"addStyleLabel": {
|
||||
"message": "Yeni stil oluşturun"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "Stil Ekleyin"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "Ekleyin"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "Şuraya uygulanır: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "ve diğerleri"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "Alan adındaki URLler"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "Bu bölümdeki kodun hangi URLlere uygulanacağını sınırlamak için 'Şuraya uygulanır' denetimlerini kullanın."
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "Şuraya uygulanır"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "regexp ile eşleşen URL'ler"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "Kaldır"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "Belirt"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "Her şey"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "Şununla başlayan URL'ler:"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "Tüm stiller için güncellemeleri denetle"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "Güncellemeleri denetle"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "Kontrol ediliyor..."
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "Bu stili silmek istediğinizden emin misiniz?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "Sil"
|
||||
},
|
||||
"description": {
|
||||
"message": "Kullanıcı stil yöneticisi Stylus ile Web'in stilini yenileyin. Stylus Google, Facebook, YouTube, Orkut ve diğer pek çok site için temalar ve görünüm yüklemenize imkân tanır."
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "Devre dışı bırak"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "Stili Düzenle"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "Düzenle"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "$stylename$ Stilini Düzenleyin",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "Etkinleştir"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "Bu site için başka stiller bul"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "Yardım"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "Güncellemeyi yükle"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "Yüklü Stiller"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "Bu site için hiçbir stil yüklenmedi."
|
||||
},
|
||||
"openManage": {
|
||||
"message": "Yüklü stilleri yönet"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Başka bölüm ekle"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "Kod"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "Bölümler, aynı stil içindeki farklı URL kümelerine uygulanacak farklı kod parçaları tanımlamanıza olanak sağlar. Örneğin, tek bir stil bir sitenin ana sayfasını belirli bir şekilde değiştirirken, sayfanın kalan kısmını farklı bir şekilde değiştirebilir."
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "Bölümü kaldır"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "Yönetim sayfasına dön"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "Bu stilde yaptığınız, kaydedilmemiş değişiklikler var."
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "Etkin"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "'$stylename$' Stylus'e yüklensin mi?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "Bir ad girin"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "Kaydet"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "Bölümler"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "Kodun Mozilla biçimi, Firefox için Stylish ile kullanılabilir ve userstyles.org sitesine gönderilebilir."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "Güncellenemedi: sunucu yanıt olarak $code$ kodunu gönderdi.",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "Güncellenemedi: sunucuya erişilemiyor."
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "Stil güncel."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "Güncelleme tamamlandı."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,219 +1,171 @@
|
|||
{
|
||||
"appliesToEverything": {
|
||||
"message": "所有站点",
|
||||
"description": "Text displayed for styles that apply to all sites"
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "启用",
|
||||
"description": "Label for the button to enable a style"
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "请输入名称",
|
||||
"description": "Error displayed when user saves without providing a name"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "指定域上的URL",
|
||||
"description": "Option to make the style apply to the entered string as a domain"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "检查更新",
|
||||
"description": "Label for the button to check a single style for an update"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "帮助",
|
||||
"description": "Alternate text for help buttons"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "查找更多适合此站点的样式",
|
||||
"description": "Text for a link that gets a list of styles for the current site"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "已安装的样式",
|
||||
"description": "Heading for the manage page"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "已启用",
|
||||
"description": "Label for the enabled state of styles"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "用于Firefox上的Stylish的Mozilla格式样式代码可以在 userstyles.org 上提交",
|
||||
"description": "Help info for the Mozilla format header section that converts the code to/from Mozilla format"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "添加新节",
|
||||
"description": "Label for the button to add a section"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "保存",
|
||||
"description": "Label for save button for style editing"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "添加",
|
||||
"description": "Label for the button to add an 'applies' entry"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "匹配正则的URL",
|
||||
"description": "Option to make the style apply to the entered string as a regular expression"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "安装 '$stylename$' 到 Stylus?",
|
||||
"description": "Confirmation when installing a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "禁用",
|
||||
"description": "Label for the button to disable a style"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "返回到管理",
|
||||
"description": "Label for cancel button for style editing"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "您已经修改了此样式,但尚未保存",
|
||||
"description": "Text for the prompt when changes are made to a style and the user tries to leave without saving"
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "更新失败: 服务器无法访问.",
|
||||
"description": "Text that displays when an update check failed because the update server is unreachable"
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "确定要删除这个样式吗?",
|
||||
"description": "Confirmation before deleting a style"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "应用到: $applies$",
|
||||
"description": "Text on the manage screen to describe what the style applies to",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleUpdate": {
|
||||
"message": "你確定要更新 '$stylename$' 嗎?",
|
||||
"description": "Confirmation when updating a style",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "样式节",
|
||||
"description": "Title for the style sections section"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "编辑样式 $stylename$",
|
||||
"description": "Title of the page for editing styles",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "已经是最新的.",
|
||||
"description": "Text that displays when an update check completed and no update is available"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "以指定地址开始",
|
||||
"description": "Option to make the style apply to the entered string as a URL prefix"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "样式节允许你定义多个样式段落并将它们应用于不同的站点匹配规则上。例如,一个样式可以更改使用一个方式来更改主页,而此时其它的样式段可以更改站点的其它部分。",
|
||||
"description": "Help text for sections"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "当前站点上没有已安装的样式",
|
||||
"description": "Text displayed when no styles are installed for the current site"
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "以及更多",
|
||||
"description": "Text added to appliesDisplay when there are more sites for the style than are displayed"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "移除",
|
||||
"description": "Label for the button to remove an 'applies' entry"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "应用到",
|
||||
"description": "Label for 'applies to' fields on the edit/add screen"
|
||||
},
|
||||
"openManage": {
|
||||
"message": "管理已安装样式",
|
||||
"description": "Link to open the manage page."
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "更新失败: 服务器了返回代码 $code$。",
|
||||
"description": "Text that displays when an update check failed because the response code indicates an error",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "指定站点",
|
||||
"description": "Label for the button to make a style apply only to specific sites"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "安装更新",
|
||||
"description": "Label for the button to install an update for a single style"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "移除节",
|
||||
"description": "Label for the button to remove a section"
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "更新完成.",
|
||||
"description": "Text that displays when an update completed"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "检查中...",
|
||||
"description": "Text to display when checking a style for an update"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "代码",
|
||||
"description": "Label for the code for a section"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "使用“应用到”来控制这个样式应用到哪些地址上。",
|
||||
"description": "Help text for 'applies to' section"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "编辑样式",
|
||||
"description": "Title of the page for editing styles"
|
||||
},
|
||||
"appliesUrlOption": {
|
||||
"message": "地址",
|
||||
"description": "Option to make the style apply to the entered string as a URL"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "添加样式",
|
||||
"description": "Title of the page for adding styles"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "检查所有样式的更新",
|
||||
"description": "Label for the button to check all styles for updates"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "删除",
|
||||
"description": "Label for the button to delete a style"
|
||||
},
|
||||
"addStyleLabel": {
|
||||
"message": "编写新的样式",
|
||||
"description": "Label for the button to go to the add style page"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "编辑",
|
||||
"description": "Label for the button to go to the edit style page"
|
||||
},
|
||||
"description": {
|
||||
"message": "Stylus,一个用户样式管理器,帮助您重新定义网页样式。Stylus易于为Google,Facebook,Youtube,Orkut以及其它各类型网站安装样式和主题。",
|
||||
"description": "Extension description"
|
||||
}
|
||||
"addStyleLabel": {
|
||||
"message": "编写新的样式"
|
||||
},
|
||||
"addStyleTitle": {
|
||||
"message": "添加样式"
|
||||
},
|
||||
"appliesAdd": {
|
||||
"message": "添加"
|
||||
},
|
||||
"appliesDisplay": {
|
||||
"message": "应用到: $applies$",
|
||||
"placeholders": {
|
||||
"applies": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"appliesDisplayTruncatedSuffix": {
|
||||
"message": "以及更多"
|
||||
},
|
||||
"appliesDomainOption": {
|
||||
"message": "指定域上的URL"
|
||||
},
|
||||
"appliesHelp": {
|
||||
"message": "使用“应用到”来控制这个样式应用到哪些地址上。"
|
||||
},
|
||||
"appliesLabel": {
|
||||
"message": "应用到"
|
||||
},
|
||||
"appliesRegexpOption": {
|
||||
"message": "匹配正则的URL"
|
||||
},
|
||||
"appliesRemove": {
|
||||
"message": "移除"
|
||||
},
|
||||
"appliesSpecify": {
|
||||
"message": "指定站点"
|
||||
},
|
||||
"appliesToEverything": {
|
||||
"message": "所有站点"
|
||||
},
|
||||
"appliesUrlOption": {
|
||||
"message": "地址"
|
||||
},
|
||||
"appliesUrlPrefixOption": {
|
||||
"message": "以指定地址开始"
|
||||
},
|
||||
"checkAllUpdates": {
|
||||
"message": "检查所有样式的更新"
|
||||
},
|
||||
"checkForUpdate": {
|
||||
"message": "检查更新"
|
||||
},
|
||||
"checkingForUpdate": {
|
||||
"message": "检查中..."
|
||||
},
|
||||
"deleteStyleConfirm": {
|
||||
"message": "确定要删除这个样式吗?"
|
||||
},
|
||||
"deleteStyleLabel": {
|
||||
"message": "删除"
|
||||
},
|
||||
"description": {
|
||||
"message": "Stylus,一个用户样式管理器,帮助您重新定义网页样式。Stylus易于为Google,Facebook,Youtube,Orkut以及其它各类型网站安装样式和主题。"
|
||||
},
|
||||
"disableStyleLabel": {
|
||||
"message": "禁用"
|
||||
},
|
||||
"editStyleHeading": {
|
||||
"message": "编辑样式"
|
||||
},
|
||||
"editStyleLabel": {
|
||||
"message": "编辑"
|
||||
},
|
||||
"editStyleTitle": {
|
||||
"message": "编辑样式 $stylename$",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableStyleLabel": {
|
||||
"message": "启用"
|
||||
},
|
||||
"findStylesForSite": {
|
||||
"message": "查找更多适合此站点的样式"
|
||||
},
|
||||
"helpAlt": {
|
||||
"message": "帮助"
|
||||
},
|
||||
"installUpdate": {
|
||||
"message": "安装更新"
|
||||
},
|
||||
"manageHeading": {
|
||||
"message": "已安装的样式"
|
||||
},
|
||||
"noStylesForSite": {
|
||||
"message": "当前站点上没有已安装的样式"
|
||||
},
|
||||
"openManage": {
|
||||
"message": "管理已安装样式"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "添加新节"
|
||||
},
|
||||
"sectionCode": {
|
||||
"message": "代码"
|
||||
},
|
||||
"sectionHelp": {
|
||||
"message": "样式节允许你定义多个样式段落并将它们应用于不同的站点匹配规则上。例如,一个样式可以更改使用一个方式来更改主页,而此时其它的样式段可以更改站点的其它部分。"
|
||||
},
|
||||
"sectionRemove": {
|
||||
"message": "移除节"
|
||||
},
|
||||
"styleCancelEditLabel": {
|
||||
"message": "返回到管理"
|
||||
},
|
||||
"styleChangesNotSaved": {
|
||||
"message": "您已经修改了此样式,但尚未保存"
|
||||
},
|
||||
"styleEnabledLabel": {
|
||||
"message": "已启用"
|
||||
},
|
||||
"styleInstall": {
|
||||
"message": "安装 '$stylename$' 到 Stylus?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"styleMissingName": {
|
||||
"message": "请输入名称"
|
||||
},
|
||||
"styleSaveLabel": {
|
||||
"message": "保存"
|
||||
},
|
||||
"styleSectionsTitle": {
|
||||
"message": "样式节"
|
||||
},
|
||||
"styleToMozillaFormatHelp": {
|
||||
"message": "用于Firefox上的Stylish的Mozilla格式样式代码可以在 userstyles.org 上提交"
|
||||
},
|
||||
"styleUpdate": {
|
||||
"message": "你確定要更新 '$stylename$' 嗎?",
|
||||
"placeholders": {
|
||||
"stylename": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailBadResponseCode": {
|
||||
"message": "更新失败: 服务器了返回代码 $code$。",
|
||||
"placeholders": {
|
||||
"code": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updateCheckFailServerUnreachable": {
|
||||
"message": "更新失败: 服务器无法访问."
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
"message": "已经是最新的."
|
||||
},
|
||||
"updateCompleted": {
|
||||
"message": "更新完成."
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -14,6 +14,9 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
|
|||
saveStyle,
|
||||
deleteStyle,
|
||||
|
||||
getStyleFromDB: id =>
|
||||
dbExec('get', id).then(event => event.target.result),
|
||||
|
||||
download(msg) {
|
||||
delete msg.method;
|
||||
return download(msg.url, msg);
|
||||
|
@ -56,6 +59,32 @@ var browserCommands, contextMenus;
|
|||
// register all listeners
|
||||
chrome.runtime.onMessage.addListener(onRuntimeMessage);
|
||||
|
||||
if (FIREFOX) {
|
||||
// see notes in apply.js for getStylesFallback
|
||||
const MSG_GET_STYLES = 'getStyles:';
|
||||
const MSG_GET_STYLES_LEN = MSG_GET_STYLES.length;
|
||||
chrome.runtime.onConnect.addListener(port => {
|
||||
if (!port.name.startsWith(MSG_GET_STYLES)) return;
|
||||
const tabId = port.sender.tab.id;
|
||||
const frameId = port.sender.frameId;
|
||||
const options = tryJSONparse(port.name.slice(MSG_GET_STYLES_LEN));
|
||||
port.disconnect();
|
||||
getStyles(options).then(styles => {
|
||||
if (!styles.length) return;
|
||||
chrome.tabs.executeScript(tabId, {
|
||||
code: `
|
||||
applyOnMessage({
|
||||
method: 'styleApply',
|
||||
styles: ${JSON.stringify(styles)},
|
||||
})
|
||||
`,
|
||||
runAt: 'document_start',
|
||||
frameId,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const listener =
|
||||
URLS.chromeProtectsNTP
|
||||
|
@ -119,22 +148,15 @@ prefs.subscribe(['iconset'], () =>
|
|||
}));
|
||||
|
||||
// *************************************************************************
|
||||
{
|
||||
const onInstall = ({reason}) => {
|
||||
chrome.runtime.onInstalled.removeListener(onInstall);
|
||||
if (reason === 'update') {
|
||||
// translations may change
|
||||
localStorage.L10N = JSON.stringify({
|
||||
browserUIlanguage: chrome.i18n.getUILanguage(),
|
||||
});
|
||||
// themes may change
|
||||
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'});
|
||||
}
|
||||
chrome.runtime.onInstalled.addListener(({reason}) => {
|
||||
if (reason !== 'update') return;
|
||||
// translations may change
|
||||
localStorage.L10N = JSON.stringify({
|
||||
browserUIlanguage: chrome.i18n.getUILanguage(),
|
||||
});
|
||||
// themes may change
|
||||
delete localStorage.codeMirrorThemes;
|
||||
});
|
||||
|
||||
// *************************************************************************
|
||||
// browser commands
|
||||
|
|
9
background/parserlib-loader.js
Normal file
9
background/parserlib-loader.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* global importScripts parserlib CSSLint parseMozFormat */
|
||||
'use strict';
|
||||
|
||||
importScripts('/vendor-overwrites/csslint/parserlib.js', '/js/moz-parser.js');
|
||||
parserlib.css.Tokens[parserlib.css.Tokens.COMMENT].hide = false;
|
||||
|
||||
self.onmessage = ({data}) => {
|
||||
self.postMessage(parseMozFormat(data));
|
||||
};
|
|
@ -153,9 +153,8 @@ global API_METHODS
|
|||
case 0:
|
||||
// re-install is invalid in a soft upgrade
|
||||
if (!ignoreDigest) {
|
||||
return Promise.reject(STATES.SAME_VERSION);
|
||||
} else if (text === style.sourceCode) {
|
||||
return Promise.reject(STATES.SAME_CODE);
|
||||
const sameCode = text === style.sourceCode;
|
||||
return Promise.reject(sameCode ? STATES.SAME_CODE : STATES.SAME_VERSION);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
|
@ -186,10 +185,14 @@ global API_METHODS
|
|||
json.originalName = json.name;
|
||||
}
|
||||
|
||||
if (styleSectionsEqual(json, style)) {
|
||||
if (styleSectionsEqual(json, style, {checkSource: true})) {
|
||||
// update digest even if save === false as there might be just a space added etc.
|
||||
saveStyle(Object.assign(json, {reason: 'update-digest'}));
|
||||
return Promise.reject(STATES.SAME_CODE);
|
||||
json.reason = 'update-digest';
|
||||
return saveStyle(json)
|
||||
.then(saved => {
|
||||
style.originalDigest = saved.originalDigest;
|
||||
return Promise.reject(STATES.SAME_CODE);
|
||||
});
|
||||
}
|
||||
|
||||
if (!style.originalDigest && !ignoreDigest) {
|
||||
|
|
|
@ -65,10 +65,21 @@
|
|||
return style;
|
||||
}
|
||||
|
||||
// Parse the source and find the duplication
|
||||
function build({sourceCode, checkDup = false}) {
|
||||
return buildMeta({sourceCode})
|
||||
.then(usercss.buildCode)
|
||||
/**
|
||||
* Parse the source and find the duplication
|
||||
* @param _
|
||||
* @param {String} _.sourceCode
|
||||
* @param {Boolean=} _.checkDup
|
||||
* @param {Boolean=} _.metaOnly
|
||||
* @returns {Promise<{style, dup:Boolean?}>}
|
||||
*/
|
||||
function build({
|
||||
sourceCode,
|
||||
checkDup,
|
||||
metaOnly,
|
||||
}) {
|
||||
const task = buildMeta({sourceCode});
|
||||
return (metaOnly ? task : task.then(usercss.buildCode))
|
||||
.then(style => ({
|
||||
style,
|
||||
dup: checkDup && find(style),
|
||||
|
|
|
@ -18,6 +18,13 @@
|
|||
var docRewriteObserver;
|
||||
var docRootObserver;
|
||||
|
||||
// FF59+ bug workaround
|
||||
// See https://github.com/openstyles/stylus/issues/461
|
||||
// Since it's easy to spoof the browser version in pre-Quantum FF we're checking
|
||||
// for getPreventDefault which got removed in FF59 https://bugzil.la/691151
|
||||
const FF_BUG461 = !CHROME && !isOwnPage && !Event.prototype.getPreventDefault;
|
||||
const pageContextQueue = [];
|
||||
|
||||
requestStyles();
|
||||
chrome.runtime.onMessage.addListener(applyOnMessage);
|
||||
window.applyOnMessage = applyOnMessage;
|
||||
|
@ -50,11 +57,35 @@
|
|||
// On own pages we request the styles directly to minimize delay and flicker
|
||||
if (typeof API === 'function') {
|
||||
API.getStyles(request).then(callback);
|
||||
} else if (!CHROME && getStylesFallback(request)) {
|
||||
// NOP
|
||||
} else {
|
||||
chrome.runtime.sendMessage(request, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: remove when FF fixes the bug.
|
||||
* Firefox borks sendMessage in same-origin iframes that have 'src' with a real path on the site.
|
||||
* We implement a workaround for the initial styleApply case only.
|
||||
* Everything else (like toggling of styles) is still buggy.
|
||||
* @param {Object} msg
|
||||
* @param {Function} callback
|
||||
* @returns {Boolean|undefined}
|
||||
*/
|
||||
function getStylesFallback(msg) {
|
||||
if (window !== parent &&
|
||||
location.href !== 'about:blank') {
|
||||
try {
|
||||
if (parent.location.origin === location.origin &&
|
||||
parent.location.href !== location.href) {
|
||||
chrome.runtime.connect({name: 'getStyles:' + JSON.stringify(msg)});
|
||||
return true;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
function applyOnMessage(request, sender, sendResponse) {
|
||||
if (request.styles === 'DIY') {
|
||||
// Do-It-Yourself tells our built-in pages to fetch the styles directly
|
||||
|
@ -235,7 +266,11 @@
|
|||
if (!Array.isArray(sections)) continue;
|
||||
applySections(id, sections.map(({code}) => code).join('\n'));
|
||||
}
|
||||
docRootObserver.start({sort: true});
|
||||
docRootObserver.firstStart();
|
||||
}
|
||||
|
||||
if (FF_BUG461 && (gotNewStyles || styles.needTransitionPatch)) {
|
||||
setContentsInPageContext();
|
||||
}
|
||||
|
||||
if (!isOwnPage && !docRewriteObserver && styleElements.size) {
|
||||
|
@ -260,6 +295,8 @@
|
|||
// workaround for Chrome devtools bug fixed in v65
|
||||
el.remove();
|
||||
el = null;
|
||||
} else if (FF_BUG461) {
|
||||
pageContextQueue.push({id: el.id, el, code});
|
||||
} else {
|
||||
el.textContent = code;
|
||||
}
|
||||
|
@ -275,13 +312,15 @@
|
|||
// HTML document style; also works on HTML-embedded SVG
|
||||
el = document.createElement('style');
|
||||
}
|
||||
Object.assign(el, {
|
||||
id,
|
||||
type: 'text/css',
|
||||
textContent: code,
|
||||
});
|
||||
el.id = id;
|
||||
el.type = 'text/css';
|
||||
// SVG className is not a string, but an instance of SVGAnimatedString
|
||||
el.classList.add('stylus');
|
||||
if (FF_BUG461) {
|
||||
pageContextQueue.push({id: el.id, el, code});
|
||||
} else {
|
||||
el.textContent = code;
|
||||
}
|
||||
addStyleElement(el);
|
||||
}
|
||||
styleElements.set(id, el);
|
||||
|
@ -289,6 +328,34 @@
|
|||
return el;
|
||||
}
|
||||
|
||||
function setContentsInPageContext() {
|
||||
try {
|
||||
(document.head || ROOT).appendChild(document.createElement('script')).text = `(${queue => {
|
||||
document.currentScript.remove();
|
||||
for (const {id, code} of queue) {
|
||||
const el = document.getElementById(id) ||
|
||||
document.querySelector('style.stylus[id="' + id + '"]');
|
||||
if (!el) continue;
|
||||
const {disabled} = el.sheet;
|
||||
el.textContent = code;
|
||||
el.sheet.disabled = disabled;
|
||||
}
|
||||
}})(${JSON.stringify(pageContextQueue)})`;
|
||||
} catch (e) {}
|
||||
let failedSome;
|
||||
for (const {el, code} of pageContextQueue) {
|
||||
if (el.textContent !== code) {
|
||||
el.textContent = code;
|
||||
failedSome = true;
|
||||
}
|
||||
}
|
||||
if (failedSome) {
|
||||
console.debug('Could not set code of some styles in page context, ' +
|
||||
'see https://github.com/openstyles/stylus/issues/461');
|
||||
}
|
||||
pageContextQueue.length = 0;
|
||||
}
|
||||
|
||||
function addStyleElement(newElement) {
|
||||
if (!ROOT) {
|
||||
return;
|
||||
|
@ -430,13 +497,16 @@
|
|||
|
||||
function init() {
|
||||
observer = new MutationObserver(sortStyleElements);
|
||||
docRootObserver = {start, stop, evade, disconnect: stop};
|
||||
docRootObserver = {firstStart, start, stop, evade, disconnect: stop};
|
||||
setTimeout(sortStyleElements);
|
||||
}
|
||||
function start({sort = false} = {}) {
|
||||
if (sort && sortStyleMap()) {
|
||||
function firstStart() {
|
||||
if (sortStyleMap()) {
|
||||
sortStyleElements();
|
||||
}
|
||||
start();
|
||||
}
|
||||
function start() {
|
||||
if (!observing && ROOT && observer) {
|
||||
observer.observe(ROOT, {childList: true});
|
||||
observing = true;
|
||||
|
@ -477,16 +547,12 @@
|
|||
}
|
||||
}
|
||||
function sortStyleElements() {
|
||||
if (!observing) {
|
||||
return;
|
||||
}
|
||||
if (!observing) return;
|
||||
let prevExpected = document.documentElement.lastElementChild;
|
||||
while (prevExpected && isSkippable(prevExpected, true)) {
|
||||
prevExpected = prevExpected.previousElementSibling;
|
||||
}
|
||||
if (!prevExpected) {
|
||||
return;
|
||||
}
|
||||
if (!prevExpected) return;
|
||||
for (const el of styleElements.values()) {
|
||||
if (!isMovable(el)) {
|
||||
continue;
|
||||
|
|
29
edit.html
29
edit.html
|
@ -26,7 +26,6 @@
|
|||
<script src="js/storage-util.js"></script>
|
||||
<script src="js/exclusions.js"></script>
|
||||
<script src="content/apply.js"></script>
|
||||
<script src="edit/lint.js"></script>
|
||||
<script src="edit/util.js"></script>
|
||||
<script src="edit/regexp-tester.js"></script>
|
||||
<script src="edit/applies-to-line-widget.js"></script>
|
||||
|
@ -66,6 +65,8 @@
|
|||
<script src="vendor/codemirror/addon/fold/comment-fold.js"></script>
|
||||
|
||||
<link href="vendor/codemirror/addon/lint/lint.css" rel="stylesheet" />
|
||||
<script src="vendor/codemirror/addon/lint/lint.js"></script>
|
||||
|
||||
|
||||
<link href="vendor/codemirror/addon/hint/show-hint.css" rel="stylesheet" />
|
||||
<script src="vendor/codemirror/addon/hint/show-hint.js"></script>
|
||||
|
@ -88,6 +89,16 @@
|
|||
<link href="edit/codemirror-default.css" rel="stylesheet">
|
||||
<script src="edit/codemirror-default.js"></script>
|
||||
|
||||
<script src="edit/linter.js"></script>
|
||||
<script src="edit/linter-defaults.js"></script>
|
||||
<script src="edit/linter-engines.js"></script>
|
||||
<script src="edit/linter-meta.js"></script>
|
||||
<script src="edit/linter-help-dialog.js"></script>
|
||||
<script src="edit/linter-report.js"></script>
|
||||
<script src="edit/linter-config-dialog.js"></script>
|
||||
|
||||
<script src="edit/editor-worker.js"></script>
|
||||
|
||||
<link id="cm-theme" rel="stylesheet">
|
||||
|
||||
<template data-id="appliesTo">
|
||||
|
@ -122,7 +133,7 @@
|
|||
</template>
|
||||
|
||||
<template data-id="section">
|
||||
<div>
|
||||
<div class="section">
|
||||
<label i18n-text="sectionCode" class="code-label"></label>
|
||||
<br>
|
||||
<div class="applies-to">
|
||||
|
@ -135,13 +146,23 @@
|
|||
</div>
|
||||
<div class="edit-actions">
|
||||
<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="test-regexp" i18n-text="styleRegexpTestButton"></button>
|
||||
</div>
|
||||
</div>
|
||||
</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">
|
||||
<div id="search-replace-dialog">
|
||||
<div data-type="main">
|
||||
|
@ -428,7 +449,7 @@
|
|||
</a>
|
||||
</h2>
|
||||
</summary>
|
||||
<div></div>
|
||||
<div class="lint-report-container"></div>
|
||||
</details>
|
||||
<div id="footer" class="hidden">
|
||||
<a href="https://github.com/openstyles/stylus/wiki/Usercss"
|
||||
|
|
123
edit/beautify.js
123
edit/beautify.js
|
@ -16,46 +16,55 @@ function beautify(event) {
|
|||
function doBeautify() {
|
||||
const tabs = prefs.get('editor.indentWithTabs');
|
||||
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_char = tabs ? '\t' : ' ';
|
||||
|
||||
const section = getSectionForChild(event.target);
|
||||
const scope = section ? [section.CodeMirror] : editors;
|
||||
|
||||
showHelp(t('styleBeautify'), '<div class="beautify-options">' +
|
||||
optionHtml('.selector1,', 'selector_separator_newline') +
|
||||
optionHtml('.selector2', 'newline_before_open_brace') +
|
||||
optionHtml('{', 'newline_after_open_brace') +
|
||||
optionHtml('border: none;', 'newline_between_properties', true) +
|
||||
optionHtml('display: block;', 'newline_before_close_brace', true) +
|
||||
optionHtml('}', 'newline_between_rules') +
|
||||
`<label style="display: block; clear: both;">
|
||||
<input data-option="indent_conditional" type="checkbox"
|
||||
${options.indent_conditional !== false ? 'checked' : ''}>
|
||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>` +
|
||||
t('styleBeautifyIndentConditional') + '</label>' +
|
||||
'</div>' +
|
||||
'<div><button role="undo"></button></div>');
|
||||
showHelp(t('styleBeautify'),
|
||||
$create([
|
||||
$create('.beautify-options', [
|
||||
$createOption('.selector1,', 'selector_separator_newline'),
|
||||
$createOption('.selector2', 'newline_before_open_brace'),
|
||||
$createOption('{', 'newline_after_open_brace'),
|
||||
$createOption('border: none;', 'newline_between_properties', true),
|
||||
$createOption('display: block;', 'newline_before_close_brace', true),
|
||||
$createOption('}', 'newline_between_rules'),
|
||||
$createLabeledCheckbox('preserve_newlines', 'styleBeautifyPreserveNewlines'),
|
||||
$createLabeledCheckbox('indent_conditional', 'styleBeautifyIndentConditional'),
|
||||
]),
|
||||
$create('.buttons', [
|
||||
$create('button', {
|
||||
attributes: {role: 'close'},
|
||||
// showHelp.close will be defined after showHelp() is invoked
|
||||
onclick: () => showHelp.close(),
|
||||
}, t('confirmClose')),
|
||||
$create('button', {
|
||||
attributes: {role: 'undo'},
|
||||
onclick() {
|
||||
let undoable = false;
|
||||
for (const cm of scope) {
|
||||
const data = cm.beautifyChange;
|
||||
if (!data || !data[cm.changeGeneration()]) continue;
|
||||
delete data[cm.changeGeneration()];
|
||||
const {scrollX, scrollY} = window;
|
||||
cm.undo();
|
||||
cm.scrollIntoView(cm.getCursor());
|
||||
window.scrollTo(scrollX, scrollY);
|
||||
undoable |= data[cm.changeGeneration()];
|
||||
}
|
||||
this.disabled = !undoable;
|
||||
},
|
||||
}, t(scope.length === 1 ? 'undo' : 'undoGlobal')),
|
||||
]),
|
||||
]));
|
||||
|
||||
$('#help-popup').className = 'wide';
|
||||
|
||||
const undoButton = $('#help-popup button[role="undo"]');
|
||||
undoButton.textContent = t(scope.length === 1 ? 'undo' : 'undoGlobal');
|
||||
undoButton.addEventListener('click', () => {
|
||||
let undoable = false;
|
||||
scope.forEach(cm => {
|
||||
if (cm.beautifyChange && cm.beautifyChange[cm.changeGeneration()]) {
|
||||
delete cm.beautifyChange[cm.changeGeneration()];
|
||||
const {scrollX, scrollY} = window;
|
||||
cm.undo();
|
||||
cm.scrollIntoView(cm.getCursor());
|
||||
window.scrollTo(scrollX, scrollY);
|
||||
undoable |= cm.beautifyChange[cm.changeGeneration()];
|
||||
}
|
||||
});
|
||||
undoButton.disabled = !undoable;
|
||||
});
|
||||
|
||||
scope.forEach(cm => {
|
||||
setTimeout(() => {
|
||||
const pos = options.translate_positions =
|
||||
|
@ -77,9 +86,9 @@ function beautify(event) {
|
|||
cm.setSelections(selections);
|
||||
window.scrollTo(scrollX, scrollY);
|
||||
cm.beautifyChange[cm.changeGeneration()] = true;
|
||||
undoButton.disabled = false;
|
||||
$('#help-popup button[role="close"]').disabled = false;
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
$('.beautify-options').onchange = ({target}) => {
|
||||
|
@ -91,21 +100,41 @@ function beautify(event) {
|
|||
doBeautify();
|
||||
};
|
||||
|
||||
function optionHtml(label, optionName, indent) {
|
||||
function $createOption(label, optionName, indent) {
|
||||
const value = options[optionName];
|
||||
return '<div newline="' + value.toString() + '">' +
|
||||
'<span' + (indent ? ' indent' : '') + '>' + label + '</span>' +
|
||||
'<div class="select-resizer">' +
|
||||
'<select data-option="' + optionName + '">' +
|
||||
'<option' + (value ? '' : ' selected') + '> </option>' +
|
||||
'<option' + (value ? ' selected' : '') + '>\\n</option>' +
|
||||
'</select>' +
|
||||
'<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 ' +
|
||||
'19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>' +
|
||||
'</svg>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
return (
|
||||
$create('div', {attributes: {newline: value}}, [
|
||||
$create('span', indent ? {attributes: {indent: ''}} : {}, label),
|
||||
$create('div.select-resizer', [
|
||||
$create('select', {dataset: {option: optionName}}, [
|
||||
$create('option', {selected: !value}, '\xA0'),
|
||||
$create('option', {selected: value}, '\\n'),
|
||||
]),
|
||||
$create('SVG:svg.svg-icon.select-arrow', {viewBox: '0 0 1792 1792'}, [
|
||||
$create('SVG:path', {
|
||||
'fill-rule': 'evenodd',
|
||||
'd': 'M1408 704q0 26-19 45l-448 448q-19 19-45 ' +
|
||||
'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),
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
global CodeMirror linterConfig loadScript
|
||||
global CodeMirror loadScript
|
||||
global editors editor styleId ownTabId
|
||||
global save toggleStyle setupAutocomplete makeSectionVisible getSectionForChild
|
||||
global getSectionsHashes
|
||||
|
@ -8,9 +8,6 @@ global messageBox
|
|||
'use strict';
|
||||
|
||||
onDOMscriptReady('/codemirror.js').then(() => {
|
||||
|
||||
CodeMirror.defaults.lint = linterConfig.getForCodeMirror();
|
||||
|
||||
const COMMANDS = {
|
||||
save,
|
||||
toggleStyle,
|
||||
|
@ -43,6 +40,9 @@ onDOMscriptReady('/codemirror.js').then(() => {
|
|||
});
|
||||
|
||||
CodeMirror.defineInitHook(cm => {
|
||||
if (!cm.display.wrapper.closest('#sections')) {
|
||||
return;
|
||||
}
|
||||
if (prefs.get('editor.livePreview') && styleId) {
|
||||
cm.on('changes', updatePreview);
|
||||
}
|
||||
|
@ -618,14 +618,56 @@ onDOMscriptReady('/codemirror.js').then(() => {
|
|||
const me = this instanceof Node ? this : $('#editor.livePreview');
|
||||
const previewing = me.checked;
|
||||
editors.forEach(cm => cm[previewing ? 'on' : 'off']('changes', updatePreview));
|
||||
const addRemove = previewing ? 'addEventListener' : 'removeEventListener';
|
||||
$('#enabled')[addRemove]('change', updatePreview);
|
||||
$('#sections')[addRemove]('change', updatePreview);
|
||||
const addRemove = EventTarget.prototype[previewing ? 'addEventListener' : 'removeEventListener'];
|
||||
addRemove.call($('#enabled'), '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')) {
|
||||
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) {
|
||||
if (previewing !== true && previewing !== false) {
|
||||
if (data instanceof Event && !data.target.matches('.style-contributor')) return;
|
||||
|
@ -644,7 +686,8 @@ onDOMscriptReady('/codemirror.js').then(() => {
|
|||
}).then(() => {
|
||||
errors.classList.add('hidden');
|
||||
}).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);
|
||||
err = `${pos.line}:${pos.ch} ${err}`;
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/* global importScripts parserlib CSSLint parseMozFormat */
|
||||
'use strict';
|
||||
|
||||
const CSSLINT_PATH = '/vendor-overwrites/csslint/';
|
||||
importScripts(CSSLINT_PATH + 'parserlib.js');
|
||||
|
||||
parserlib.css.Tokens[parserlib.css.Tokens.COMMENT].hide = false;
|
||||
|
||||
self.onmessage = ({data}) => {
|
||||
|
||||
const {action = 'run'} = data;
|
||||
|
||||
if (action === 'parse') {
|
||||
if (!self.parseMozFormat) self.importScripts('/js/moz-parser.js');
|
||||
self.postMessage(parseMozFormat(data));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.CSSLint) self.importScripts(CSSLINT_PATH + 'csslint.js');
|
||||
|
||||
switch (action) {
|
||||
case 'getAllRuleIds':
|
||||
// the functions are non-tranferable and we need only an id
|
||||
self.postMessage(CSSLint.getRules().map(rule => rule.id));
|
||||
return;
|
||||
|
||||
case 'getAllRuleInfos':
|
||||
// the functions are non-tranferable
|
||||
self.postMessage(CSSLint.getRules().map(rule => JSON.parse(JSON.stringify(rule))));
|
||||
return;
|
||||
|
||||
case 'run': {
|
||||
const {code, config} = data;
|
||||
const results = CSSLint.verify(code, config).messages
|
||||
//.filter(m => !m.message.includes('/*[[') && !m.message.includes(']]*/'))
|
||||
.map(m => Object.assign(m, {rule: {id: m.rule.id}}));
|
||||
self.postMessage(results);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -301,16 +301,22 @@ input:invalid {
|
|||
margin-top: 4em;
|
||||
}
|
||||
/************ content ***********/
|
||||
#sections > div {
|
||||
#sections > * {
|
||||
margin: 0.7rem;
|
||||
padding: 1rem 1rem .3rem;
|
||||
}
|
||||
#sections > div:first-of-type {
|
||||
#sections > *:first-child {
|
||||
padding: 0 1rem .3rem;
|
||||
}
|
||||
#sections > div:not(:first-of-type) {
|
||||
#sections > *:not(:first-child) {
|
||||
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 {
|
||||
display: none;
|
||||
}
|
||||
|
@ -328,17 +334,35 @@ input:invalid {
|
|||
#sections {
|
||||
counter-reset: codebox;
|
||||
}
|
||||
#sections > div > label {
|
||||
#sections > .section > label {
|
||||
animation: 2s highlight;
|
||||
animation-play-state: paused;
|
||||
animation-direction: reverse;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
#sections > div > label::after {
|
||||
#sections > .section > label::after {
|
||||
counter-increment: codebox;
|
||||
content: counter(codebox);
|
||||
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 {
|
||||
height: 10rem;
|
||||
|
@ -600,15 +624,6 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
|||
right: 4px;
|
||||
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 {
|
||||
font-size: 12px;
|
||||
|
@ -627,13 +642,19 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
|||
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"] {
|
||||
line-height: 1.5rem;
|
||||
padding: 0 0.5rem;
|
||||
margin: 0.5rem 0 0 0.5rem;
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
float: right;
|
||||
}
|
||||
#help-popup.ready button[name^="import"] {
|
||||
pointer-events: all;
|
||||
|
@ -667,6 +688,9 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
|||
#lint table:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#lint table.empty {
|
||||
display: none;
|
||||
}
|
||||
#lint caption {
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
|
@ -769,7 +793,7 @@ html:not(.usercss) .usercss-only,
|
|||
}
|
||||
|
||||
#sections .single-editor,
|
||||
#sections > div.single-editor:first-of-type {
|
||||
#sections > .single-editor:first-child {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
|
@ -948,11 +972,11 @@ html:not(.usercss) .usercss-only,
|
|||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
#sections > div {
|
||||
#sections > * {
|
||||
margin: 0 .5rem .5rem;
|
||||
padding: .5rem 0 0;
|
||||
}
|
||||
#sections > div:first-of-type {
|
||||
#sections > *:first-child {
|
||||
margin: .5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
|
137
edit/edit.js
137
edit/edit.js
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
global CodeMirror parserlib loadScript
|
||||
global CSSLint initLint linterConfig updateLintReport renderLintReport updateLinter
|
||||
global CodeMirror loadScript
|
||||
global createSourceEditor
|
||||
global closeCurrentTab regExpTester messageBox
|
||||
global setupCodeMirror
|
||||
|
@ -8,6 +7,7 @@ global beautify
|
|||
global initWithSectionStyle addSections removeSection getSectionsHashes
|
||||
global sectionsToMozFormat
|
||||
global exclusions
|
||||
global moveFocus editorWorker
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
|
@ -25,7 +25,8 @@ const CssToProperty = {'url': 'urls', 'url-prefix': 'urlPrefixes', 'domain': 'do
|
|||
|
||||
let editor;
|
||||
|
||||
window.onbeforeunload = beforeUnload;
|
||||
|
||||
document.addEventListener('visibilitychange', beforeUnload);
|
||||
chrome.runtime.onMessage.addListener(onRuntimeMessage);
|
||||
|
||||
preinit();
|
||||
|
@ -177,7 +178,8 @@ function onRuntimeMessage(request) {
|
|||
break;
|
||||
case 'styleDeleted':
|
||||
if (styleId === request.id || editor && editor.getStyle().id === request.id) {
|
||||
window.onbeforeunload = () => {};
|
||||
document.removeEventListener('visibilitychange', beforeUnload);
|
||||
window.onbeforeunload = null;
|
||||
closeCurrentTab();
|
||||
break;
|
||||
}
|
||||
|
@ -199,24 +201,26 @@ 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() {
|
||||
if (saveSizeOnClose) {
|
||||
rememberWindowSize();
|
||||
if (saveSizeOnClose) rememberWindowSize();
|
||||
const activeElement = document.activeElement;
|
||||
if (activeElement) {
|
||||
// blurring triggers 'change' or 'input' event if needed
|
||||
activeElement.blur();
|
||||
// refocus if unloading was canceled
|
||||
setTimeout(() => activeElement.focus());
|
||||
}
|
||||
document.activeElement.blur();
|
||||
if (isClean()) {
|
||||
return;
|
||||
}
|
||||
updateLintReportIfEnabled(null, 0);
|
||||
// neither confirm() nor custom messages work in modern browsers but just in case
|
||||
return t('styleChangesNotSaved');
|
||||
|
||||
function isClean() {
|
||||
if (editor) {
|
||||
return !editor.isDirty();
|
||||
} else {
|
||||
return isCleanGlobal();
|
||||
}
|
||||
const isDirty = editor ? editor.isDirty() : !isCleanGlobal();
|
||||
if (isDirty) {
|
||||
// neither confirm() nor custom messages work in modern browsers but just in case
|
||||
return t('styleChangesNotSaved');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,7 +234,7 @@ function isUsercss(style) {
|
|||
function initStyleData() {
|
||||
// TODO: remove .replace(/^\?/, '') when minimum_chrome_version >= 52 (https://crbug.com/601425)
|
||||
const params = new URLSearchParams(location.search.replace(/^\?/, ''));
|
||||
const id = params.get('id');
|
||||
const id = Number(params.get('id'));
|
||||
const createEmptyStyle = () => ({
|
||||
id: null,
|
||||
name: params.get('domain') ||
|
||||
|
@ -246,8 +250,8 @@ function initStyleData() {
|
|||
)
|
||||
],
|
||||
});
|
||||
return API.getStyles({id: id || -1})
|
||||
.then(([style = createEmptyStyle()]) => {
|
||||
return fetchStyle()
|
||||
.then(style => {
|
||||
styleId = style.id;
|
||||
if (styleId) sessionStorage.justEditedStyleId = styleId;
|
||||
// we set "usercss" class on <html> when <body> is empty
|
||||
|
@ -261,6 +265,13 @@ function initStyleData() {
|
|||
}
|
||||
return style;
|
||||
});
|
||||
|
||||
function fetchStyle() {
|
||||
if (id) {
|
||||
return API.getStyleFromDB(id);
|
||||
}
|
||||
return Promise.resolve(createEmptyStyle());
|
||||
}
|
||||
}
|
||||
|
||||
function initHooks() {
|
||||
|
@ -278,9 +289,6 @@ function initHooks() {
|
|||
$('#save-button').addEventListener('click', save, false);
|
||||
$('#sections-help').addEventListener('click', showSectionHelp, false);
|
||||
|
||||
// TODO: investigate why FF needs this delay
|
||||
debounce(initLint, FIREFOX ? 100 : 0);
|
||||
|
||||
if (!FIREFOX) {
|
||||
$$([
|
||||
'input:not([type])',
|
||||
|
@ -344,7 +352,7 @@ function isCleanGlobal() {
|
|||
|
||||
function setCleanGlobal() {
|
||||
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
|
||||
dirty = {};
|
||||
}
|
||||
|
@ -360,7 +368,6 @@ function toggleStyle() {
|
|||
}
|
||||
|
||||
function save() {
|
||||
updateLintReportIfEnabled(null, 0);
|
||||
if (!validate()) {
|
||||
return;
|
||||
}
|
||||
|
@ -414,20 +421,14 @@ function validate() {
|
|||
}
|
||||
|
||||
function updateTitle() {
|
||||
const DIRTY_TITLE = '* $';
|
||||
const name = $('#name').savedValue;
|
||||
const clean = isCleanGlobal();
|
||||
const title = styleId === null ? t('addStyleTitle') : t('editStyleTitle', [name]);
|
||||
document.title = clean ? title : DIRTY_TITLE.replace('$', title);
|
||||
const title = styleId === null ? t('addStyleTitle') : name;
|
||||
document.title = (clean ? '' : '* ') + title;
|
||||
window.onbeforeunload = clean ? null : beforeUnload;
|
||||
$('#save-button').disabled = clean;
|
||||
}
|
||||
|
||||
function updateLintReportIfEnabled(...args) {
|
||||
if (CodeMirror.defaults.lint) {
|
||||
updateLintReport(...args);
|
||||
}
|
||||
}
|
||||
|
||||
function showMozillaFormat() {
|
||||
const popup = showCodeMirrorPopup(t('styleToMozillaFormatTitle'), '', {readOnly: true});
|
||||
popup.codebox.setValue(toMozillaFormat());
|
||||
|
@ -440,19 +441,19 @@ function toMozillaFormat() {
|
|||
|
||||
function fromMozillaFormat() {
|
||||
const popup = showCodeMirrorPopup(t('styleFromMozillaFormatPrompt'),
|
||||
$create([
|
||||
$create('button', {
|
||||
name: 'import-append',
|
||||
textContent: t('importAppendLabel'),
|
||||
title: 'Ctrl-Enter:\n' + t('importAppendTooltip'),
|
||||
onclick: doImport,
|
||||
}),
|
||||
$create('.buttons', [
|
||||
$create('button', {
|
||||
name: 'import-replace',
|
||||
textContent: t('importReplaceLabel'),
|
||||
title: 'Ctrl-Shift-Enter:\n' + t('importReplaceTooltip'),
|
||||
onclick: () => doImport({replaceOldStyle: true}),
|
||||
}),
|
||||
$create('button', {
|
||||
name: 'import-append',
|
||||
textContent: t('importAppendLabel'),
|
||||
title: 'Ctrl-Enter:\n' + t('importAppendTooltip'),
|
||||
onclick: doImport,
|
||||
}),
|
||||
]));
|
||||
const contents = $('.contents', popup);
|
||||
contents.insertBefore(popup.codebox.display.wrapper, contents.firstElementChild);
|
||||
|
@ -469,16 +470,7 @@ function fromMozillaFormat() {
|
|||
|
||||
function doImport({replaceOldStyle = false}) {
|
||||
lockPageUI(true);
|
||||
new Promise(setTimeout)
|
||||
.then(() => {
|
||||
const worker = linterConfig.worker.csslint;
|
||||
if (!worker.instance) worker.instance = new Worker(worker.path);
|
||||
})
|
||||
.then(() => linterConfig.invokeWorker({
|
||||
linter: 'csslint',
|
||||
action: 'parse',
|
||||
code: popup.codebox.getValue().trim(),
|
||||
}))
|
||||
editorWorker.parseMozFormat({code: popup.codebox.getValue().trim()})
|
||||
.then(({sections, errors}) => {
|
||||
// shouldn't happen but just in case
|
||||
if (!sections.length && errors.length) {
|
||||
|
@ -491,8 +483,7 @@ function fromMozillaFormat() {
|
|||
removeOldSections(replaceOldStyle);
|
||||
return addSections(sections, div => setCleanItem(div, false));
|
||||
})
|
||||
.then(sectionDivs => {
|
||||
sectionDivs.forEach(div => updateLintReportIfEnabled(div.CodeMirror, 1));
|
||||
.then(() => {
|
||||
$('.dismiss').dispatchEvent(new Event('click'));
|
||||
})
|
||||
.catch(showError)
|
||||
|
@ -591,10 +582,8 @@ function showHelp(title = '', body) {
|
|||
window.dispatchEvent(new Event('closeHelp'));
|
||||
});
|
||||
|
||||
if (getComputedStyle(div).display === 'none') {
|
||||
window.addEventListener('keydown', showHelp.close, true);
|
||||
$('.dismiss', div).onclick = showHelp.close;
|
||||
}
|
||||
window.addEventListener('keydown', showHelp.close, true);
|
||||
$('.dismiss', div).onclick = showHelp.close;
|
||||
|
||||
// reset any inline styles
|
||||
div.style = 'display: block';
|
||||
|
@ -610,26 +599,38 @@ function showCodeMirrorPopup(title, html, options) {
|
|||
let cm = popup.codebox = CodeMirror($('.contents', popup), Object.assign({
|
||||
mode: 'css',
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
lineWrapping: prefs.get('editor.lineWrapping'),
|
||||
foldGutter: true,
|
||||
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
|
||||
matchBrackets: true,
|
||||
lint: linterConfig.getForCodeMirror(),
|
||||
styleActiveLine: true,
|
||||
theme: prefs.get('editor.theme'),
|
||||
keyMap: prefs.get('editor.keyMap')
|
||||
}, options));
|
||||
cm.focus();
|
||||
const rerouteOn = () => cm.rerouteHotkeys(false);
|
||||
const rerouteOff = () => cm.rerouteHotkeys(true);
|
||||
cm.on('focus', rerouteOn);
|
||||
cm.on('blur', rerouteOff);
|
||||
cm.rerouteHotkeys(false);
|
||||
|
||||
document.documentElement.style.pointerEvents = 'none';
|
||||
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.removeEventListener('closeHelp', _);
|
||||
cm.off('focus', rerouteOn);
|
||||
cm.off('blur', rerouteOff);
|
||||
window.removeEventListener('keydown', onKeyDown, true);
|
||||
document.documentElement.style.removeProperty('pointer-events');
|
||||
cm.rerouteHotkeys(true);
|
||||
cm = popup.codebox = null;
|
||||
});
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
|
|
118
edit/editor-worker-body.js
Normal file
118
edit/editor-worker-body.js
Normal file
|
@ -0,0 +1,118 @@
|
|||
/* global importScripts parseMozFormat parserlib CSSLint require */
|
||||
'use strict';
|
||||
|
||||
createAPI({
|
||||
csslint: (code, config) => {
|
||||
loadParserLib();
|
||||
loadScript(['/vendor-overwrites/csslint/csslint.js']);
|
||||
return CSSLint.verify(code, config).messages
|
||||
.map(m => Object.assign(m, {rule: {id: m.rule.id}}));
|
||||
},
|
||||
stylelint: (code, config) => {
|
||||
loadScript(['/vendor/stylelint-bundle/stylelint-bundle.min.js']);
|
||||
return require('stylelint').lint({code, config});
|
||||
},
|
||||
parseMozFormat: data => {
|
||||
loadParserLib();
|
||||
loadScript(['/js/moz-parser.js']);
|
||||
return parseMozFormat(data);
|
||||
},
|
||||
getStylelintRules,
|
||||
getCsslintRules
|
||||
});
|
||||
|
||||
function getCsslintRules() {
|
||||
loadScript(['/vendor-overwrites/csslint/csslint.js']);
|
||||
return CSSLint.getRules().map(rule => {
|
||||
const output = {};
|
||||
for (const [key, value] of Object.entries(rule)) {
|
||||
if (typeof value !== 'function') {
|
||||
output[key] = value;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
});
|
||||
}
|
||||
|
||||
function getStylelintRules() {
|
||||
loadScript(['/vendor/stylelint-bundle/stylelint-bundle.min.js']);
|
||||
const stylelint = require('stylelint');
|
||||
const options = {};
|
||||
const rxPossible = /\bpossible:("(?:[^"]*?)"|\[(?:[^\]]*?)\]|\{(?:[^}]*?)\})/g;
|
||||
const rxString = /"([-\w\s]{3,}?)"/g;
|
||||
for (const id of Object.keys(stylelint.rules)) {
|
||||
const ruleCode = String(stylelint.rules[id]);
|
||||
const sets = [];
|
||||
let m, mStr;
|
||||
while ((m = rxPossible.exec(ruleCode))) {
|
||||
const possible = m[1];
|
||||
const set = [];
|
||||
while ((mStr = rxString.exec(possible))) {
|
||||
const s = mStr[1];
|
||||
if (s.includes(' ')) {
|
||||
set.push(...s.split(/\s+/));
|
||||
} else {
|
||||
set.push(s);
|
||||
}
|
||||
}
|
||||
if (possible.includes('ignoreAtRules')) {
|
||||
set.push('ignoreAtRules');
|
||||
}
|
||||
if (possible.includes('ignoreShorthands')) {
|
||||
set.push('ignoreShorthands');
|
||||
}
|
||||
if (set.length) {
|
||||
sets.push(set);
|
||||
}
|
||||
}
|
||||
if (sets.length) {
|
||||
options[id] = sets;
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
function loadParserLib() {
|
||||
if (typeof parserlib !== 'undefined') {
|
||||
return;
|
||||
}
|
||||
importScripts('/vendor-overwrites/csslint/parserlib.js');
|
||||
parserlib.css.Tokens[parserlib.css.Tokens.COMMENT].hide = false;
|
||||
}
|
||||
|
||||
const loadedUrls = new Set();
|
||||
function loadScript(urls) {
|
||||
urls = urls.filter(u => !loadedUrls.has(u));
|
||||
importScripts(...urls);
|
||||
urls.forEach(u => loadedUrls.add(u));
|
||||
}
|
||||
|
||||
function createAPI(methods) {
|
||||
self.onmessage = e => {
|
||||
const message = e.data;
|
||||
Promise.resolve()
|
||||
.then(() => methods[message.action](...message.args))
|
||||
.then(result => ({
|
||||
id: message.id,
|
||||
error: false,
|
||||
data: result
|
||||
}))
|
||||
.catch(err => ({
|
||||
id: message.id,
|
||||
error: true,
|
||||
data: cloneError(err)
|
||||
}))
|
||||
.then(data => self.postMessage(data));
|
||||
};
|
||||
}
|
||||
|
||||
function cloneError(err) {
|
||||
return Object.assign({
|
||||
name: err.name,
|
||||
stack: err.stack,
|
||||
message: err.message,
|
||||
lineNumber: err.lineNumber,
|
||||
columnNumber: err.columnNumber,
|
||||
fileName: err.fileName
|
||||
}, err);
|
||||
}
|
39
edit/editor-worker.js
Normal file
39
edit/editor-worker.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
'use strict';
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
var editorWorker = (() => {
|
||||
let worker;
|
||||
return new Proxy({}, {
|
||||
get: (target, prop) =>
|
||||
(...args) => {
|
||||
if (!worker) {
|
||||
worker = createWorker();
|
||||
}
|
||||
return worker.invoke(prop, args);
|
||||
}
|
||||
});
|
||||
|
||||
function createWorker() {
|
||||
let id = 0;
|
||||
const pendingResponse = new Map();
|
||||
const worker = new Worker('/edit/editor-worker-body.js');
|
||||
worker.onmessage = e => {
|
||||
const message = e.data;
|
||||
pendingResponse.get(message.id)[message.error ? 'reject' : 'resolve'](message.data);
|
||||
pendingResponse.delete(message.id);
|
||||
};
|
||||
return {invoke};
|
||||
|
||||
function invoke(action, args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
pendingResponse.set(id, {resolve, reject});
|
||||
worker.postMessage({
|
||||
id,
|
||||
action,
|
||||
args
|
||||
});
|
||||
id++;
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -565,6 +565,7 @@ onDOMready().then(() => {
|
|||
Object.assign(dialog, DIALOG_PROPS.dialog);
|
||||
dialog.addEventListener('focusout', EVENTS.onfocusout);
|
||||
dialog.dataset.type = type;
|
||||
dialog.style.pointerEvents = 'auto';
|
||||
|
||||
const content = $('[data-type="content"]', dialog);
|
||||
content.parentNode.replaceChild(template[type].cloneNode(true), content);
|
||||
|
@ -881,7 +882,7 @@ onDOMready().then(() => {
|
|||
function restoreWindowScrollPos({immediately = true} = {}) {
|
||||
if (!immediately) {
|
||||
// run in the next microtask cycle
|
||||
new Promise(() => restoreWindowScrollPos({immediately: true}));
|
||||
Promise.resolve().then(restoreWindowScrollPos);
|
||||
return;
|
||||
}
|
||||
if (window.scrollX !== state.scrollX || window.scrollY !== state.scrollY) {
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/* global CodeMirror linterConfig */
|
||||
'use strict';
|
||||
|
||||
(() => {
|
||||
CodeMirror.registerHelper('lint', 'csslint', invokeHelper);
|
||||
CodeMirror.registerHelper('lint', 'stylelint', invokeHelper);
|
||||
|
||||
const cookResults = {
|
||||
csslint: results =>
|
||||
results.map(({line, col: ch, message, rule, type: severity}) => line && {
|
||||
message,
|
||||
from: {line: line - 1, ch: ch - 1},
|
||||
to: {line: line - 1, ch},
|
||||
rule: rule.id,
|
||||
severity,
|
||||
}).filter(Boolean),
|
||||
|
||||
stylelint: ({results}) =>
|
||||
!results[0] && [] ||
|
||||
results[0].warnings.map(({line, column: ch, text, severity}) => ({
|
||||
from: {line: line - 1, ch: ch - 1},
|
||||
to: {line: line - 1, ch},
|
||||
message: text
|
||||
.replace('Unexpected ', '')
|
||||
.replace(/^./, firstLetter => firstLetter.toUpperCase())
|
||||
.replace(/\s*\([^(]+\)$/, ''), // strip the rule,
|
||||
rule: text.replace(/^.*?\s*\(([^(]+)\)$/, '$1'),
|
||||
severity,
|
||||
})),
|
||||
};
|
||||
|
||||
function invokeHelper(code) {
|
||||
const config = linterConfig.getCurrent();
|
||||
return linterConfig.invokeWorker({code, config})
|
||||
.then(cookResults[linterConfig.getName()]);
|
||||
}
|
||||
})();
|
|
@ -1,50 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* CSSLint Config values
|
||||
* 0 = disabled; 1 = warning; 2 = error
|
||||
*/
|
||||
window.linterConfig.defaults.csslint = {
|
||||
// Default warnings
|
||||
'display-property-grouping': 1,
|
||||
'duplicate-properties': 1,
|
||||
'empty-rules': 1,
|
||||
'errors': 1,
|
||||
'warnings': 1,
|
||||
'known-properties': 1,
|
||||
|
||||
// Default disabled
|
||||
'adjoining-classes': 0,
|
||||
'box-model': 0,
|
||||
'box-sizing': 0,
|
||||
'bulletproof-font-face': 0,
|
||||
'compatible-vendor-prefixes': 0,
|
||||
'duplicate-background-images': 0,
|
||||
'fallback-colors': 0,
|
||||
'floats': 0,
|
||||
'font-faces': 0,
|
||||
'font-sizes': 0,
|
||||
'gradients': 0,
|
||||
'ids': 0,
|
||||
'import': 0,
|
||||
'import-ie-limit': 0,
|
||||
'important': 0,
|
||||
'order-alphabetical': 0,
|
||||
'outline-none': 0,
|
||||
'overqualified-elements': 0,
|
||||
'qualified-headings': 0,
|
||||
'regex-selectors': 0,
|
||||
'rules-count': 0,
|
||||
'selector-max': 0,
|
||||
'selector-max-approaching': 0,
|
||||
'selector-newline': 0,
|
||||
'shorthand': 0,
|
||||
'star-property-hack': 0,
|
||||
'text-indent': 0,
|
||||
'underscore-property-hack': 0,
|
||||
'unique-headings': 0,
|
||||
'universal-selector': 0,
|
||||
'unqualified-attributes': 0,
|
||||
'vendor-prefix': 0,
|
||||
'zero-units': 0
|
||||
};
|
|
@ -1,170 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
window.linterConfig.defaults.stylelint = (defaultSeverity => ({
|
||||
// 'sugarss' is a indent-based syntax like Sass or Stylus
|
||||
// ref: https://github.com/postcss/postcss#syntaxes
|
||||
syntax: 'sugarss',
|
||||
// ** recommended rules **
|
||||
// ref: https://github.com/stylelint/stylelint-config-recommended/blob/master/index.js
|
||||
rules: {
|
||||
'at-rule-no-unknown': [true, defaultSeverity],
|
||||
'block-no-empty': [true, defaultSeverity],
|
||||
'color-no-invalid-hex': [true, defaultSeverity],
|
||||
'declaration-block-no-duplicate-properties': [true, {
|
||||
'ignore': ['consecutive-duplicates-with-different-values'],
|
||||
'severity': 'warning'
|
||||
}],
|
||||
'declaration-block-no-shorthand-property-overrides': [true, defaultSeverity],
|
||||
'font-family-no-duplicate-names': [true, defaultSeverity],
|
||||
'function-calc-no-unspaced-operator': [true, defaultSeverity],
|
||||
'function-linear-gradient-no-nonstandard-direction': [true, defaultSeverity],
|
||||
'keyframe-declaration-no-important': [true, defaultSeverity],
|
||||
'media-feature-name-no-unknown': [true, defaultSeverity],
|
||||
/* recommended true */
|
||||
'no-empty-source': false,
|
||||
'no-extra-semicolons': [true, defaultSeverity],
|
||||
'no-invalid-double-slash-comments': [true, defaultSeverity],
|
||||
'property-no-unknown': [true, defaultSeverity],
|
||||
'selector-pseudo-class-no-unknown': [true, defaultSeverity],
|
||||
'selector-pseudo-element-no-unknown': [true, defaultSeverity],
|
||||
'selector-type-no-unknown': false, // for scss/less/stylus-lang
|
||||
'string-no-newline': [true, defaultSeverity],
|
||||
'unit-no-unknown': [true, defaultSeverity],
|
||||
|
||||
// ** non-essential rules
|
||||
'comment-no-empty': false,
|
||||
'declaration-block-no-redundant-longhand-properties': false,
|
||||
'shorthand-property-no-redundant-values': false,
|
||||
|
||||
// ** stylistic rules **
|
||||
/*
|
||||
'at-rule-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
'except': [
|
||||
'blockless-after-same-name-blockless',
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'after-comment'
|
||||
]
|
||||
}
|
||||
],
|
||||
'at-rule-name-case': 'lower',
|
||||
'at-rule-name-space-after': 'always-single-line',
|
||||
'at-rule-semicolon-newline-after': 'always',
|
||||
'block-closing-brace-empty-line-before': 'never',
|
||||
'block-closing-brace-newline-after': 'always',
|
||||
'block-closing-brace-newline-before': 'always-multi-line',
|
||||
'block-closing-brace-space-before': 'always-single-line',
|
||||
'block-opening-brace-newline-after': 'always-multi-line',
|
||||
'block-opening-brace-space-after': 'always-single-line',
|
||||
'block-opening-brace-space-before': 'always',
|
||||
'color-hex-case': 'lower',
|
||||
'color-hex-length': 'short',
|
||||
'comment-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
'except': [
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'stylelint-commands'
|
||||
]
|
||||
}
|
||||
],
|
||||
'comment-whitespace-inside': 'always',
|
||||
'custom-property-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
'except': [
|
||||
'after-custom-property',
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'after-comment',
|
||||
'inside-single-line-block'
|
||||
]
|
||||
}
|
||||
],
|
||||
'declaration-bang-space-after': 'never',
|
||||
'declaration-bang-space-before': 'always',
|
||||
'declaration-block-semicolon-newline-after': 'always-multi-line',
|
||||
'declaration-block-semicolon-space-after': 'always-single-line',
|
||||
'declaration-block-semicolon-space-before': 'never',
|
||||
'declaration-block-single-line-max-declarations': 1,
|
||||
'declaration-block-trailing-semicolon': 'always',
|
||||
'declaration-colon-newline-after': 'always-multi-line',
|
||||
'declaration-colon-space-after': 'always-single-line',
|
||||
'declaration-colon-space-before': 'never',
|
||||
'declaration-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
'except': [
|
||||
'after-declaration',
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'after-comment',
|
||||
'inside-single-line-block'
|
||||
]
|
||||
}
|
||||
],
|
||||
'function-comma-newline-after': 'always-multi-line',
|
||||
'function-comma-space-after': 'always-single-line',
|
||||
'function-comma-space-before': 'never',
|
||||
'function-max-empty-lines': 0,
|
||||
'function-name-case': 'lower',
|
||||
'function-parentheses-newline-inside': 'always-multi-line',
|
||||
'function-parentheses-space-inside': 'never-single-line',
|
||||
'function-whitespace-after': 'always',
|
||||
'indentation': 2,
|
||||
'length-zero-no-unit': true,
|
||||
'max-empty-lines': 1,
|
||||
'media-feature-colon-space-after': 'always',
|
||||
'media-feature-colon-space-before': 'never',
|
||||
'media-feature-name-case': 'lower',
|
||||
'media-feature-parentheses-space-inside': 'never',
|
||||
'media-feature-range-operator-space-after': 'always',
|
||||
'media-feature-range-operator-space-before': 'always',
|
||||
'media-query-list-comma-newline-after': 'always-multi-line',
|
||||
'media-query-list-comma-space-after': 'always-single-line',
|
||||
'media-query-list-comma-space-before': 'never',
|
||||
'no-eol-whitespace': true,
|
||||
'no-missing-end-of-source-newline': true,
|
||||
'number-leading-zero': 'always',
|
||||
'number-no-trailing-zeros': true,
|
||||
'property-case': 'lower',
|
||||
'rule-empty-line-before': [
|
||||
'always-multi-line',
|
||||
{
|
||||
'except': [
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'after-comment'
|
||||
]
|
||||
}
|
||||
],
|
||||
'selector-attribute-brackets-space-inside': 'never',
|
||||
'selector-attribute-operator-space-after': 'never',
|
||||
'selector-attribute-operator-space-before': 'never',
|
||||
'selector-combinator-space-after': 'always',
|
||||
'selector-combinator-space-before': 'always',
|
||||
'selector-descendant-combinator-no-non-space': true,
|
||||
'selector-list-comma-newline-after': 'always',
|
||||
'selector-list-comma-space-before': 'never',
|
||||
'selector-max-empty-lines': 0,
|
||||
'selector-pseudo-class-case': 'lower',
|
||||
'selector-pseudo-class-parentheses-space-inside': 'never',
|
||||
'selector-pseudo-element-case': 'lower',
|
||||
'selector-pseudo-element-colon-notation': 'double',
|
||||
'selector-type-case': 'lower',
|
||||
'unit-case': 'lower',
|
||||
'value-list-comma-newline-after': 'always-multi-line',
|
||||
'value-list-comma-space-after': 'always-single-line',
|
||||
'value-list-comma-space-before': 'never',
|
||||
'value-list-max-empty-lines': 0
|
||||
*/
|
||||
}
|
||||
}))({severity: 'warning'});
|
573
edit/lint.js
573
edit/lint.js
|
@ -1,573 +0,0 @@
|
|||
/* global CodeMirror messageBox */
|
||||
/* global editors makeSectionVisible showCodeMirrorPopup showHelp */
|
||||
/* global loadScript require CSSLint stylelint */
|
||||
'use strict';
|
||||
|
||||
onDOMready().then(loadLinterAssets);
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
var linterConfig = {
|
||||
csslint: {},
|
||||
stylelint: {},
|
||||
defaults: {
|
||||
// set in lint-defaults-csslint.js
|
||||
csslint: {},
|
||||
// set in lint-defaults-stylelint.js
|
||||
stylelint: {},
|
||||
},
|
||||
storageName: {
|
||||
csslint: 'editorCSSLintConfig',
|
||||
stylelint: 'editorStylelintConfig',
|
||||
},
|
||||
worker: {
|
||||
csslint: {path: '/edit/csslint-loader.js'},
|
||||
stylelint: {path: '/edit/stylelint-loader.js'},
|
||||
},
|
||||
allRuleIds: {
|
||||
csslint: null,
|
||||
stylelint: null,
|
||||
},
|
||||
|
||||
getName() {
|
||||
// some dirty hacks to override editor.linter getting from prefs
|
||||
const linter = prefs.get('editor.linter');
|
||||
const mode = linter && editors[0] && editors[0].doc.mode;
|
||||
return mode && ((mode.name || mode) !== 'css' || mode.helperType) ? 'stylelint' : linter;
|
||||
},
|
||||
|
||||
getCurrent(linter = linterConfig.getName()) {
|
||||
return this.fallbackToDefaults(this[linter] || {});
|
||||
},
|
||||
|
||||
getForCodeMirror(linter = linterConfig.getName()) {
|
||||
return CodeMirror.lint && CodeMirror.lint[linter] ? {
|
||||
getAnnotations: CodeMirror.lint[linter],
|
||||
delay: prefs.get('editor.lintDelay'),
|
||||
onUpdateLinting(annotationsNotSorted, annotations, cm) {
|
||||
updateLintReport(cm);
|
||||
},
|
||||
} : false;
|
||||
},
|
||||
|
||||
fallbackToDefaults(config, linter = linterConfig.getName()) {
|
||||
if (config && Object.keys(config).length) {
|
||||
if (linter === 'stylelint') {
|
||||
// always use default syntax because we don't expose it in config UI
|
||||
config.syntax = this.defaults.stylelint.syntax;
|
||||
}
|
||||
return Object.assign({}, this.defaults[linter] || {}, config);
|
||||
} else {
|
||||
return deepCopy(this.defaults[linter] || {});
|
||||
}
|
||||
},
|
||||
|
||||
setLinter(linter = linterConfig.getName()) {
|
||||
linter = linter.toLowerCase();
|
||||
linter = linter === 'csslint' || linter === 'stylelint' ? linter : '';
|
||||
if (linterConfig.getName() !== linter) {
|
||||
prefs.set('editor.linter', linter);
|
||||
}
|
||||
return linter;
|
||||
},
|
||||
|
||||
invokeWorker(message) {
|
||||
const worker = linterConfig.worker[message.linter || linterConfig.getName()];
|
||||
if (!worker.queue) {
|
||||
worker.queue = [];
|
||||
worker.instance.onmessage = ({data}) => {
|
||||
worker.queue.shift().resolve(data);
|
||||
if (worker.queue.length) {
|
||||
worker.instance.postMessage(worker.queue[0].message);
|
||||
}
|
||||
};
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
worker.queue.push({message, resolve});
|
||||
if (worker.queue.length === 1) {
|
||||
worker.instance.postMessage(message);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getAllRuleIds(linter = linterConfig.getName()) {
|
||||
return Promise.resolve(
|
||||
this.allRuleIds[linter] ||
|
||||
this.invokeWorker({linter, action: 'getAllRuleIds'})
|
||||
.then(ids => (this.allRuleIds[linter] = ids.sort()))
|
||||
);
|
||||
},
|
||||
|
||||
findInvalidRules(config, linter = linterConfig.getName()) {
|
||||
return this.getAllRuleIds(linter).then(allRuleIds => {
|
||||
const allRuleIdsSet = new Set(allRuleIds);
|
||||
const rules = linter === 'stylelint' ? config.rules : config;
|
||||
return Object.keys(rules).filter(rule => !allRuleIdsSet.has(rule));
|
||||
});
|
||||
},
|
||||
|
||||
stringify(config = this.getCurrent()) {
|
||||
if (linterConfig.getName() === 'stylelint') {
|
||||
config.syntax = undefined;
|
||||
}
|
||||
return JSON.stringify(config, null, 2)
|
||||
.replace(/,\n\s+\{\n\s+("severity":\s"\w+")\n\s+\}/g, ', {$1}');
|
||||
},
|
||||
|
||||
save(config) {
|
||||
config = this.fallbackToDefaults(config);
|
||||
const linter = linterConfig.getName();
|
||||
this[linter] = config;
|
||||
chromeSync.setLZValue(this.storageName[linter], config);
|
||||
return config;
|
||||
},
|
||||
|
||||
loadAll() {
|
||||
return chromeSync.getLZValues([
|
||||
'editorCSSLintConfig',
|
||||
'editorStylelintConfig',
|
||||
]).then(data => {
|
||||
this.csslint = this.fallbackToDefaults(data.editorCSSLintConfig, 'csslint');
|
||||
this.stylelint = this.fallbackToDefaults(data.editorStylelintConfig, 'stylelint');
|
||||
});
|
||||
},
|
||||
|
||||
watchStorage() {
|
||||
chrome.storage.onChanged.addListener((changes, area) => {
|
||||
if (area === 'sync') {
|
||||
for (const name of ['editorCSSLintConfig', 'editorStylelintConfig']) {
|
||||
if (name in changes && changes[name].newValue !== changes[name].oldValue) {
|
||||
this.loadAll().then(updateLinter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// this is an event listener so it can't refer to self via 'this'
|
||||
openOnClick(event) {
|
||||
event.preventDefault();
|
||||
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() {
|
||||
if (!this.init.pending) this.init.pending = this.loadAll();
|
||||
return this.init.pending;
|
||||
}
|
||||
};
|
||||
|
||||
function initLint() {
|
||||
$('#lint-help').addEventListener('click', showLintHelp);
|
||||
$('#lint').addEventListener('click', gotoLintIssue);
|
||||
$('#linter-settings').addEventListener('click', linterConfig.openOnClick);
|
||||
|
||||
updateLinter();
|
||||
linterConfig.watchStorage();
|
||||
prefs.subscribe(['editor.linter'], updateLinter);
|
||||
}
|
||||
|
||||
function updateLinter({immediately, linter = linterConfig.getName()} = {}) {
|
||||
if (!immediately) {
|
||||
debounce(updateLinter, 0, {immediately: true, linter});
|
||||
return;
|
||||
}
|
||||
const GUTTERS_CLASS = 'CodeMirror-lint-markers';
|
||||
|
||||
Promise.all([
|
||||
linterConfig.init(),
|
||||
loadLinterAssets(linter)
|
||||
]).then(updateEditors);
|
||||
$('#linter-settings').style.display = !linter ? 'none' : 'inline-block';
|
||||
$('#lint').classList.add('hidden');
|
||||
|
||||
function updateEditors() {
|
||||
CodeMirror.defaults.lint = linterConfig.getForCodeMirror(linter);
|
||||
const guttersOption = prepareGuttersOption();
|
||||
editors.forEach(cm => {
|
||||
if (cm.options.lint !== CodeMirror.defaults.lint) {
|
||||
cm.setOption('lint', CodeMirror.defaults.lint);
|
||||
}
|
||||
if (guttersOption) {
|
||||
cm.setOption('guttersOption', guttersOption);
|
||||
updateGutters(cm, guttersOption);
|
||||
cm.refresh();
|
||||
}
|
||||
setTimeout(updateLintReport, 0, cm);
|
||||
});
|
||||
}
|
||||
|
||||
function prepareGuttersOption() {
|
||||
const gutters = CodeMirror.defaults.gutters;
|
||||
const needRefresh = Boolean(linter) !== gutters.includes(GUTTERS_CLASS);
|
||||
if (needRefresh) {
|
||||
if (linter) {
|
||||
gutters.push(GUTTERS_CLASS);
|
||||
} else {
|
||||
gutters.splice(gutters.indexOf(GUTTERS_CLASS), 1);
|
||||
}
|
||||
}
|
||||
return needRefresh && gutters;
|
||||
}
|
||||
|
||||
function updateGutters(cm, guttersOption) {
|
||||
cm.options.gutters = guttersOption;
|
||||
const el = $('.' + GUTTERS_CLASS, cm.display.gutters);
|
||||
if (linter && !el) {
|
||||
cm.display.gutters.appendChild($create('.CodeMirror-gutter ' + GUTTERS_CLASS));
|
||||
} else if (!linter && el) {
|
||||
el.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateLintReport(cm, delay) {
|
||||
const state = cm && cm.state && cm.state.lint || {};
|
||||
if (delay === 0) {
|
||||
// immediately show pending csslint/stylelint messages in onbeforeunload and save
|
||||
clearTimeout(state.lintTimeout);
|
||||
updateLintReportInternal(cm);
|
||||
return;
|
||||
}
|
||||
if (delay > 0) {
|
||||
clearTimeout(state.lintTimeout);
|
||||
state.lintTimeout = setTimeout(cm => {
|
||||
if (cm.performLint) {
|
||||
cm.performLint();
|
||||
updateLintReportInternal(cm);
|
||||
}
|
||||
}, delay, cm);
|
||||
return;
|
||||
}
|
||||
if (state.options) {
|
||||
clearTimeout(state.reportTimeout);
|
||||
const delay = cm && cm.state.renderLintReportNow ? 0 : state.options.delay + 100;
|
||||
state.reportTimeout = setTimeout(updateLintReportInternal, delay, cm, {
|
||||
postponeNewIssues: delay === undefined || delay === null
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateLintReportInternal(scope, {postponeNewIssues} = {}) {
|
||||
const {changed, fixedSome} = (scope ? [scope] : editors).reduce(process, {});
|
||||
if (changed) {
|
||||
const renderNow = editors.last.state.renderLintReportNow =
|
||||
!postponeNewIssues || fixedSome || editors.last.state.renderLintReportNow;
|
||||
debounce(renderLintReport, renderNow ? 0 : CodeMirror.defaults.lintReportDelay, true);
|
||||
}
|
||||
|
||||
function process(result, cm) {
|
||||
const lintState = cm.state.lint || {};
|
||||
const oldMarkers = lintState.stylusMarkers || new Map();
|
||||
const newMarkers = lintState.stylusMarkers = new Map();
|
||||
const oldText = (lintState.body || {}).textContentCached || '';
|
||||
const activeLine = cm.getCursor().line;
|
||||
const body = !(lintState.marked || {}).length ? {} :
|
||||
$create('tbody', lintState.marked.map(mark => {
|
||||
const info = mark.__annotation;
|
||||
const {line, ch} = info.from;
|
||||
const isActiveLine = line === activeLine;
|
||||
const pos = isActiveLine ? 'cursor' : (line + ',' + ch);
|
||||
const title = clipString(info.message, 1000) + `\n(${info.rule})`;
|
||||
const message = clipString(info.message, 100);
|
||||
if (isActiveLine || oldMarkers[pos] === message) {
|
||||
oldMarkers.delete(pos);
|
||||
}
|
||||
newMarkers.set(pos, message);
|
||||
return $create(`tr.${info.severity}`, [
|
||||
$create('td', {attributes: {role: 'severity'}, dataset: {rule: info.rule}},
|
||||
$create('.CodeMirror-lint-marker-' + info.severity, info.severity)),
|
||||
$create('td', {attributes: {role: 'line'}}, line + 1),
|
||||
$create('td', {attributes: {role: 'sep'}}, ':'),
|
||||
$create('td', {attributes: {role: 'col'}}, ch + 1),
|
||||
$create('td', {attributes: {role: 'message'}, title}, message),
|
||||
]);
|
||||
}));
|
||||
body.textContentCached = body.textContent || '';
|
||||
lintState.body = body.textContentCached && body;
|
||||
result.changed |= oldText !== body.textContentCached;
|
||||
result.fixedSome |= lintState.reportDisplayed && oldMarkers.size;
|
||||
return result;
|
||||
}
|
||||
|
||||
function clipString(str, limit) {
|
||||
return str.length <= limit ? str : str.substr(0, limit) + '...';
|
||||
}
|
||||
}
|
||||
|
||||
function renderLintReport(someBlockChanged) {
|
||||
const container = $('#lint');
|
||||
const content = container.children[1];
|
||||
const label = t('sectionCode');
|
||||
const newContent = content.cloneNode(false);
|
||||
let issueCount = 0;
|
||||
editors.forEach((cm, index) => {
|
||||
cm.state.renderLintReportNow = false;
|
||||
const lintState = cm.state.lint || {};
|
||||
const body = lintState.body;
|
||||
if (!body) {
|
||||
return;
|
||||
}
|
||||
const newBlock = $create('table', {cm}, [
|
||||
$create('caption', label + ' ' + (index + 1)),
|
||||
body,
|
||||
]);
|
||||
newContent.appendChild(newBlock);
|
||||
issueCount += newBlock.rows.length;
|
||||
|
||||
const block = content.children[newContent.children.length - 1];
|
||||
const blockChanged =
|
||||
!block ||
|
||||
block.cm !== cm ||
|
||||
body.textContentCached !== block.textContentCached;
|
||||
someBlockChanged |= blockChanged;
|
||||
lintState.reportDisplayed = blockChanged;
|
||||
});
|
||||
if (someBlockChanged || newContent.children.length !== content.children.length) {
|
||||
$('#issue-count').textContent = issueCount;
|
||||
container.replaceChild(newContent, content);
|
||||
container.classList.toggle('hidden', !newContent.children.length);
|
||||
}
|
||||
}
|
||||
|
||||
function gotoLintIssue(event) {
|
||||
const issue = event.target.closest('tr');
|
||||
if (!issue) {
|
||||
return;
|
||||
}
|
||||
const block = issue.closest('table');
|
||||
makeSectionVisible(block.cm);
|
||||
block.cm.focus();
|
||||
block.cm.setSelection({
|
||||
line: parseInt($('td[role="line"]', issue).textContent) - 1,
|
||||
ch: parseInt($('td[role="col"]', issue).textContent) - 1
|
||||
});
|
||||
}
|
||||
|
||||
function showLintHelp() {
|
||||
const linter = linterConfig.getName();
|
||||
const baseUrl = linter === 'stylelint'
|
||||
? 'https://stylelint.io/user-guide/rules/'
|
||||
// some CSSLint rules do not have a url
|
||||
: 'https://github.com/CSSLint/csslint/issues/535';
|
||||
let headerLink, template, csslintRules;
|
||||
if (linter === 'csslint') {
|
||||
headerLink = $createLink('https://github.com/CSSLint/csslint/wiki/Rules', 'CSSLint');
|
||||
template = ruleID => {
|
||||
const rule = csslintRules.find(rule => rule.id === ruleID);
|
||||
return rule &&
|
||||
$create('li', [
|
||||
$create('b', $createLink(rule.url || baseUrl, rule.name)),
|
||||
$create('br'),
|
||||
rule.desc,
|
||||
]);
|
||||
};
|
||||
} else {
|
||||
headerLink = $createLink(baseUrl, 'stylelint');
|
||||
template = rule =>
|
||||
$create('li',
|
||||
rule === 'CssSyntaxError' ? rule : $createLink(baseUrl + rule, rule));
|
||||
}
|
||||
const header = t('linterIssuesHelp', '\x01').split('\x01');
|
||||
const activeRules = new Set($$('#lint td[role="severity"]').map(el => el.dataset.rule));
|
||||
Promise.resolve(linter !== 'csslint' || linterConfig.invokeWorker({action: 'getAllRuleInfos'}))
|
||||
.then(data => {
|
||||
csslintRules = data;
|
||||
showHelp(t('linterIssues'),
|
||||
$create([
|
||||
header[0], headerLink, header[1],
|
||||
$create('ul.rules', [...activeRules.values()].map(template)),
|
||||
])
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function showLinterErrorMessage(title, contents, popup) {
|
||||
messageBox({
|
||||
title,
|
||||
contents,
|
||||
className: 'danger center lint-config',
|
||||
buttons: [t('confirmOK')],
|
||||
}).then(() => popup && popup.codebox && popup.codebox.focus());
|
||||
}
|
||||
|
||||
function setupLinterPopup(config) {
|
||||
const linter = linterConfig.getName();
|
||||
const linterTitle = linter === 'stylelint' ? 'Stylelint' : 'CSSLint';
|
||||
const defaultConfig = linterConfig.stringify(linterConfig.defaults[linter] || {});
|
||||
const title = t('linterConfigPopupTitle', linterTitle);
|
||||
const popup = showCodeMirrorPopup(title, null, {
|
||||
lint: false,
|
||||
extraKeys: {'Ctrl-Enter': save},
|
||||
hintOptions: {hint},
|
||||
});
|
||||
$('.contents', popup).appendChild(makeFooter());
|
||||
|
||||
let cm = popup.codebox;
|
||||
cm.focus();
|
||||
cm.setValue(config);
|
||||
cm.clearHistory();
|
||||
cm.markClean();
|
||||
cm.on('changes', updateButtonState);
|
||||
updateButtonState();
|
||||
|
||||
cm.rerouteHotkeys(false);
|
||||
window.addEventListener('closeHelp', function _() {
|
||||
window.removeEventListener('closeHelp', _);
|
||||
cm.rerouteHotkeys(true);
|
||||
cm = null;
|
||||
});
|
||||
|
||||
loadScript([
|
||||
'/vendor/codemirror/mode/javascript/javascript.js',
|
||||
'/vendor/codemirror/addon/lint/json-lint.js',
|
||||
'/vendor/jsonlint/jsonlint.js'
|
||||
]).then(() => {
|
||||
cm.setOption('mode', 'application/json');
|
||||
cm.setOption('lint', 'json');
|
||||
});
|
||||
|
||||
function makeFooter() {
|
||||
return $create('div', [
|
||||
$create('p', [
|
||||
$createLink(
|
||||
linter === 'stylelint'
|
||||
? 'https://stylelint.io/user-guide/rules/'
|
||||
: 'https://github.com/CSSLint/csslint/wiki/Rules-by-ID',
|
||||
t('linterRulesLink')),
|
||||
linter === 'csslint' ? ' ' + t('linterCSSLintSettings') : '',
|
||||
]),
|
||||
$create('button.save', {onclick: save, title: 'Ctrl-Enter'}, t('styleSaveLabel')),
|
||||
$create('button.cancel', {onclick: cancel}, t('confirmClose')),
|
||||
$create('button.reset', {onclick: reset, title: t('linterResetMessage')}, t('genericResetLabel')),
|
||||
$create('span.saved-message', t('genericSavedMessage')),
|
||||
]);
|
||||
}
|
||||
|
||||
function save(event) {
|
||||
if (event instanceof Event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
const json = tryJSONparse(cm.getValue());
|
||||
if (!json) {
|
||||
showLinterErrorMessage(linter, t('linterJSONError'), popup);
|
||||
cm.focus();
|
||||
return;
|
||||
}
|
||||
linterConfig.findInvalidRules(json, linter).then(invalid => {
|
||||
if (invalid.length) {
|
||||
showLinterErrorMessage(linter, [
|
||||
t('linterInvalidConfigError'),
|
||||
$create('ul', invalid.map(name => $create('li', name))),
|
||||
], popup);
|
||||
return;
|
||||
}
|
||||
linterConfig.setLinter(linter);
|
||||
linterConfig.save(json);
|
||||
linterConfig.showSavedMessage();
|
||||
cm.markClean();
|
||||
cm.focus();
|
||||
updateButtonState();
|
||||
});
|
||||
}
|
||||
|
||||
function reset(event) {
|
||||
event.preventDefault();
|
||||
linterConfig.setLinter(linter);
|
||||
cm.setValue(defaultConfig);
|
||||
cm.focus();
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
function cancel(event) {
|
||||
event.preventDefault();
|
||||
$('.dismiss').dispatchEvent(new Event('click'));
|
||||
}
|
||||
|
||||
function updateButtonState() {
|
||||
$('.save', popup).disabled = cm.isClean();
|
||||
$('.reset', popup).disabled = cm.getValue() === defaultConfig;
|
||||
$('.cancel', popup).textContent = t(cm.isClean() ? 'confirmClose' : 'confirmCancel');
|
||||
}
|
||||
|
||||
function hint(cm) {
|
||||
return Promise.all([
|
||||
linterConfig.getAllRuleIds(linter),
|
||||
linter !== 'stylelint' || hint.allOptions ||
|
||||
linterConfig.invokeWorker({action: 'getAllRuleOptions', linter})
|
||||
.then(options => (hint.allOptions = options)),
|
||||
])
|
||||
.then(([ruleIds, options]) => {
|
||||
const cursor = cm.getCursor();
|
||||
const {start, end, string, type, state: {lexical}} = cm.getTokenAt(cursor);
|
||||
const {line, ch} = cursor;
|
||||
|
||||
const quoted = string.startsWith('"');
|
||||
const leftPart = string.slice(quoted ? 1 : 0, ch - start).trim();
|
||||
const depth = getLexicalDepth(lexical);
|
||||
|
||||
const search = cm.getSearchCursor(/"([-\w]+)"/, {line, ch: start - 1});
|
||||
let [, prevWord] = search.find(true) || [];
|
||||
let words = [];
|
||||
|
||||
if (depth === 1 && linter === 'stylelint') {
|
||||
words = quoted ? ['rules'] : [];
|
||||
} else if ((depth === 1 || depth === 2) && type && type.includes('property')) {
|
||||
words = ruleIds;
|
||||
} else if (depth === 2 || depth === 3 && lexical.type === ']') {
|
||||
words = !quoted ? ['true', 'false', 'null'] :
|
||||
ruleIds.includes(prevWord) && (options[prevWord] || [])[0] || [];
|
||||
} else if (depth === 4 && prevWord === 'severity') {
|
||||
words = ['error', 'warning'];
|
||||
} else if (depth === 4) {
|
||||
words = ['ignore', 'ignoreAtRules', 'except', 'severity'];
|
||||
} else if (depth === 5 && lexical.type === ']' && quoted) {
|
||||
while (prevWord && !ruleIds.includes(prevWord)) {
|
||||
prevWord = (search.find(true) || [])[1];
|
||||
}
|
||||
words = (options[prevWord] || []).slice(-1)[0] || ruleIds;
|
||||
}
|
||||
return {
|
||||
list: words.filter(word => word.startsWith(leftPart)),
|
||||
from: {line, ch: start + (quoted ? 1 : 0)},
|
||||
to: {line, ch: string.endsWith('"') ? end - 1 : end},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getLexicalDepth(lexicalState) {
|
||||
let depth = 0;
|
||||
while ((lexicalState = lexicalState.prev)) {
|
||||
depth++;
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
}
|
||||
|
||||
function loadLinterAssets(name = linterConfig.getName()) {
|
||||
const worker = linterConfig.worker[name];
|
||||
if (!name || !worker) return Promise.resolve();
|
||||
const scripts = [];
|
||||
if (!worker.instance) {
|
||||
worker.instance = new Worker(worker.path);
|
||||
scripts.push(`/edit/lint-defaults-${name}.js`);
|
||||
}
|
||||
if (!CodeMirror.lint) {
|
||||
scripts.push(
|
||||
'/vendor/codemirror/addon/lint/lint.css',
|
||||
'/vendor/codemirror/addon/lint/lint.js',
|
||||
'/edit/lint-codemirror-helper.js');
|
||||
}
|
||||
return scripts.length ? loadScript(scripts) : Promise.resolve();
|
||||
}
|
196
edit/linter-config-dialog.js
Normal file
196
edit/linter-config-dialog.js
Normal file
|
@ -0,0 +1,196 @@
|
|||
/* global memoize editorWorker showCodeMirrorPopup loadScript messageBox LINTER_DEFAULTS*/
|
||||
'use strict';
|
||||
|
||||
(() => {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
$('#linter-settings').addEventListener('click', showLintConfig);
|
||||
}, {once: true});
|
||||
|
||||
function stringifyConfig(config) {
|
||||
return JSON.stringify(config, null, 2)
|
||||
.replace(/,\n\s+\{\n\s+("severity":\s"\w+")\n\s+\}/g, ', {$1}');
|
||||
}
|
||||
|
||||
function showLinterErrorMessage(title, contents, popup) {
|
||||
messageBox({
|
||||
title,
|
||||
contents,
|
||||
className: 'danger center lint-config',
|
||||
buttons: [t('confirmOK')],
|
||||
}).then(() => popup && popup.codebox && popup.codebox.focus());
|
||||
}
|
||||
|
||||
function showLintConfig() {
|
||||
const linter = $('#editor.linter').value;
|
||||
if (!linter) {
|
||||
return;
|
||||
}
|
||||
const storageName = linter === 'styleint' ? 'editorStylelintConfig' : 'editorCSSLintConfig';
|
||||
const getRules = memoize(linter === 'stylelint' ?
|
||||
editorWorker.getStylelintRules : editorWorker.getCsslintRules);
|
||||
const linterTitle = linter === 'stylelint' ? 'Stylelint' : 'CSSLint';
|
||||
const defaultConfig = stringifyConfig(
|
||||
linter === 'stylelint' ? LINTER_DEFAULTS.STYLELINT : LINTER_DEFAULTS.CSSLINT
|
||||
);
|
||||
const title = t('linterConfigPopupTitle', linterTitle);
|
||||
const popup = showCodeMirrorPopup(title, null, {
|
||||
lint: false,
|
||||
extraKeys: {'Ctrl-Enter': save},
|
||||
hintOptions: {hint},
|
||||
});
|
||||
$('.contents', popup).appendChild(makeFooter());
|
||||
|
||||
let cm = popup.codebox;
|
||||
cm.focus();
|
||||
chromeSync.getLZValue(storageName).then(config => {
|
||||
cm.setValue(config ? stringifyConfig(config) : defaultConfig);
|
||||
cm.clearHistory();
|
||||
cm.markClean();
|
||||
updateButtonState();
|
||||
});
|
||||
cm.on('changes', updateButtonState);
|
||||
|
||||
cm.rerouteHotkeys(false);
|
||||
window.addEventListener('closeHelp', function _() {
|
||||
window.removeEventListener('closeHelp', _);
|
||||
cm.rerouteHotkeys(true);
|
||||
cm = null;
|
||||
});
|
||||
|
||||
loadScript([
|
||||
'/vendor/codemirror/mode/javascript/javascript.js',
|
||||
'/vendor/codemirror/addon/lint/json-lint.js',
|
||||
'/vendor/jsonlint/jsonlint.js'
|
||||
]).then(() => {
|
||||
cm.setOption('mode', 'application/json');
|
||||
cm.setOption('lint', true);
|
||||
});
|
||||
|
||||
function findInvalidRules(config, linter) {
|
||||
return getRules()
|
||||
.then(rules => {
|
||||
if (linter === 'stylelint') {
|
||||
return Object.keys(config.rules).filter(k => !rules.hasOwnProperty(k));
|
||||
}
|
||||
const ruleSet = new Set(rules.map(r => r.id));
|
||||
return Object.keys(config).filter(k => !ruleSet.has(k));
|
||||
});
|
||||
}
|
||||
|
||||
function makeFooter() {
|
||||
return $create('div', [
|
||||
$create('p', [
|
||||
$createLink(
|
||||
linter === 'stylelint'
|
||||
? 'https://stylelint.io/user-guide/rules/'
|
||||
: 'https://github.com/CSSLint/csslint/wiki/Rules-by-ID',
|
||||
t('linterRulesLink')),
|
||||
linter === 'csslint' ? ' ' + t('linterCSSLintSettings') : '',
|
||||
]),
|
||||
$create('.buttons', [
|
||||
$create('button.save', {onclick: save, title: 'Ctrl-Enter'}, t('styleSaveLabel')),
|
||||
$create('button.cancel', {onclick: cancel}, t('confirmClose')),
|
||||
$create('button.reset', {onclick: reset, title: t('linterResetMessage')}, t('genericResetLabel')),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
function save(event) {
|
||||
if (event instanceof Event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
const json = tryJSONparse(cm.getValue());
|
||||
if (!json) {
|
||||
showLinterErrorMessage(linter, t('linterJSONError'), popup);
|
||||
cm.focus();
|
||||
return;
|
||||
}
|
||||
findInvalidRules(json, linter).then(invalid => {
|
||||
if (invalid.length) {
|
||||
showLinterErrorMessage(linter, [
|
||||
t('linterInvalidConfigError'),
|
||||
$create('ul', invalid.map(name => $create('li', name))),
|
||||
], popup);
|
||||
return;
|
||||
}
|
||||
chromeSync.setLZValue(storageName, json);
|
||||
cm.markClean();
|
||||
cm.focus();
|
||||
updateButtonState();
|
||||
});
|
||||
}
|
||||
|
||||
function reset(event) {
|
||||
event.preventDefault();
|
||||
cm.setValue(defaultConfig);
|
||||
cm.focus();
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
function cancel(event) {
|
||||
event.preventDefault();
|
||||
$('.dismiss').dispatchEvent(new Event('click'));
|
||||
}
|
||||
|
||||
function updateButtonState() {
|
||||
$('.save', popup).disabled = cm.isClean();
|
||||
$('.reset', popup).disabled = cm.getValue() === defaultConfig;
|
||||
$('.cancel', popup).textContent = t(cm.isClean() ? 'confirmClose' : 'confirmCancel');
|
||||
}
|
||||
|
||||
function hint(cm) {
|
||||
return getRules().then(rules => {
|
||||
let ruleIds, options;
|
||||
if (linter === 'stylelint') {
|
||||
ruleIds = Object.keys(rules);
|
||||
options = rules;
|
||||
} else {
|
||||
ruleIds = rules.map(r => r.id);
|
||||
options = {};
|
||||
}
|
||||
const cursor = cm.getCursor();
|
||||
const {start, end, string, type, state: {lexical}} = cm.getTokenAt(cursor);
|
||||
const {line, ch} = cursor;
|
||||
|
||||
const quoted = string.startsWith('"');
|
||||
const leftPart = string.slice(quoted ? 1 : 0, ch - start).trim();
|
||||
const depth = getLexicalDepth(lexical);
|
||||
|
||||
const search = cm.getSearchCursor(/"([-\w]+)"/, {line, ch: start - 1});
|
||||
let [, prevWord] = search.find(true) || [];
|
||||
let words = [];
|
||||
|
||||
if (depth === 1 && linter === 'stylelint') {
|
||||
words = quoted ? ['rules'] : [];
|
||||
} else if ((depth === 1 || depth === 2) && type && type.includes('property')) {
|
||||
words = ruleIds;
|
||||
} else if (depth === 2 || depth === 3 && lexical.type === ']') {
|
||||
words = !quoted ? ['true', 'false', 'null'] :
|
||||
ruleIds.includes(prevWord) && (options[prevWord] || [])[0] || [];
|
||||
} else if (depth === 4 && prevWord === 'severity') {
|
||||
words = ['error', 'warning'];
|
||||
} else if (depth === 4) {
|
||||
words = ['ignore', 'ignoreAtRules', 'except', 'severity'];
|
||||
} else if (depth === 5 && lexical.type === ']' && quoted) {
|
||||
while (prevWord && !ruleIds.includes(prevWord)) {
|
||||
prevWord = (search.find(true) || [])[1];
|
||||
}
|
||||
words = (options[prevWord] || []).slice(-1)[0] || ruleIds;
|
||||
}
|
||||
return {
|
||||
list: words.filter(word => word.startsWith(leftPart)),
|
||||
from: {line, ch: start + (quoted ? 1 : 0)},
|
||||
to: {line, ch: string.endsWith('"') ? end - 1 : end},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getLexicalDepth(lexicalState) {
|
||||
let depth = 0;
|
||||
while ((lexicalState = lexicalState.prev)) {
|
||||
depth++;
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
}
|
||||
})();
|
219
edit/linter-defaults.js
Normal file
219
edit/linter-defaults.js
Normal file
|
@ -0,0 +1,219 @@
|
|||
'use strict';
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
var LINTER_DEFAULTS = (() => {
|
||||
const SEVERITY = {severity: 'warning'};
|
||||
const STYLELINT = {
|
||||
// 'sugarss' is a indent-based syntax like Sass or Stylus
|
||||
// ref: https://github.com/postcss/postcss#syntaxes
|
||||
// syntax: 'sugarss',
|
||||
// ** recommended rules **
|
||||
// ref: https://github.com/stylelint/stylelint-config-recommended/blob/master/index.js
|
||||
rules: {
|
||||
'at-rule-no-unknown': [true, SEVERITY],
|
||||
'block-no-empty': [true, SEVERITY],
|
||||
'color-no-invalid-hex': [true, SEVERITY],
|
||||
'declaration-block-no-duplicate-properties': [true, {
|
||||
'ignore': ['consecutive-duplicates-with-different-values'],
|
||||
'severity': 'warning'
|
||||
}],
|
||||
'declaration-block-no-shorthand-property-overrides': [true, SEVERITY],
|
||||
'font-family-no-duplicate-names': [true, SEVERITY],
|
||||
'function-calc-no-unspaced-operator': [true, SEVERITY],
|
||||
'function-linear-gradient-no-nonstandard-direction': [true, SEVERITY],
|
||||
'keyframe-declaration-no-important': [true, SEVERITY],
|
||||
'media-feature-name-no-unknown': [true, SEVERITY],
|
||||
/* recommended true */
|
||||
'no-empty-source': false,
|
||||
'no-extra-semicolons': [true, SEVERITY],
|
||||
'no-invalid-double-slash-comments': [true, SEVERITY],
|
||||
'property-no-unknown': [true, SEVERITY],
|
||||
'selector-pseudo-class-no-unknown': [true, SEVERITY],
|
||||
'selector-pseudo-element-no-unknown': [true, SEVERITY],
|
||||
'selector-type-no-unknown': false, // for scss/less/stylus-lang
|
||||
'string-no-newline': [true, SEVERITY],
|
||||
'unit-no-unknown': [true, SEVERITY],
|
||||
|
||||
// ** non-essential rules
|
||||
'comment-no-empty': false,
|
||||
'declaration-block-no-redundant-longhand-properties': false,
|
||||
'shorthand-property-no-redundant-values': false,
|
||||
|
||||
// ** stylistic rules **
|
||||
/*
|
||||
'at-rule-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
'except': [
|
||||
'blockless-after-same-name-blockless',
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'after-comment'
|
||||
]
|
||||
}
|
||||
],
|
||||
'at-rule-name-case': 'lower',
|
||||
'at-rule-name-space-after': 'always-single-line',
|
||||
'at-rule-semicolon-newline-after': 'always',
|
||||
'block-closing-brace-empty-line-before': 'never',
|
||||
'block-closing-brace-newline-after': 'always',
|
||||
'block-closing-brace-newline-before': 'always-multi-line',
|
||||
'block-closing-brace-space-before': 'always-single-line',
|
||||
'block-opening-brace-newline-after': 'always-multi-line',
|
||||
'block-opening-brace-space-after': 'always-single-line',
|
||||
'block-opening-brace-space-before': 'always',
|
||||
'color-hex-case': 'lower',
|
||||
'color-hex-length': 'short',
|
||||
'comment-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
'except': [
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'stylelint-commands'
|
||||
]
|
||||
}
|
||||
],
|
||||
'comment-whitespace-inside': 'always',
|
||||
'custom-property-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
'except': [
|
||||
'after-custom-property',
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'after-comment',
|
||||
'inside-single-line-block'
|
||||
]
|
||||
}
|
||||
],
|
||||
'declaration-bang-space-after': 'never',
|
||||
'declaration-bang-space-before': 'always',
|
||||
'declaration-block-semicolon-newline-after': 'always-multi-line',
|
||||
'declaration-block-semicolon-space-after': 'always-single-line',
|
||||
'declaration-block-semicolon-space-before': 'never',
|
||||
'declaration-block-single-line-max-declarations': 1,
|
||||
'declaration-block-trailing-semicolon': 'always',
|
||||
'declaration-colon-newline-after': 'always-multi-line',
|
||||
'declaration-colon-space-after': 'always-single-line',
|
||||
'declaration-colon-space-before': 'never',
|
||||
'declaration-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
'except': [
|
||||
'after-declaration',
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'after-comment',
|
||||
'inside-single-line-block'
|
||||
]
|
||||
}
|
||||
],
|
||||
'function-comma-newline-after': 'always-multi-line',
|
||||
'function-comma-space-after': 'always-single-line',
|
||||
'function-comma-space-before': 'never',
|
||||
'function-max-empty-lines': 0,
|
||||
'function-name-case': 'lower',
|
||||
'function-parentheses-newline-inside': 'always-multi-line',
|
||||
'function-parentheses-space-inside': 'never-single-line',
|
||||
'function-whitespace-after': 'always',
|
||||
'indentation': 2,
|
||||
'length-zero-no-unit': true,
|
||||
'max-empty-lines': 1,
|
||||
'media-feature-colon-space-after': 'always',
|
||||
'media-feature-colon-space-before': 'never',
|
||||
'media-feature-name-case': 'lower',
|
||||
'media-feature-parentheses-space-inside': 'never',
|
||||
'media-feature-range-operator-space-after': 'always',
|
||||
'media-feature-range-operator-space-before': 'always',
|
||||
'media-query-list-comma-newline-after': 'always-multi-line',
|
||||
'media-query-list-comma-space-after': 'always-single-line',
|
||||
'media-query-list-comma-space-before': 'never',
|
||||
'no-eol-whitespace': true,
|
||||
'no-missing-end-of-source-newline': true,
|
||||
'number-leading-zero': 'always',
|
||||
'number-no-trailing-zeros': true,
|
||||
'property-case': 'lower',
|
||||
'rule-empty-line-before': [
|
||||
'always-multi-line',
|
||||
{
|
||||
'except': [
|
||||
'first-nested'
|
||||
],
|
||||
'ignore': [
|
||||
'after-comment'
|
||||
]
|
||||
}
|
||||
],
|
||||
'selector-attribute-brackets-space-inside': 'never',
|
||||
'selector-attribute-operator-space-after': 'never',
|
||||
'selector-attribute-operator-space-before': 'never',
|
||||
'selector-combinator-space-after': 'always',
|
||||
'selector-combinator-space-before': 'always',
|
||||
'selector-descendant-combinator-no-non-space': true,
|
||||
'selector-list-comma-newline-after': 'always',
|
||||
'selector-list-comma-space-before': 'never',
|
||||
'selector-max-empty-lines': 0,
|
||||
'selector-pseudo-class-case': 'lower',
|
||||
'selector-pseudo-class-parentheses-space-inside': 'never',
|
||||
'selector-pseudo-element-case': 'lower',
|
||||
'selector-pseudo-element-colon-notation': 'double',
|
||||
'selector-type-case': 'lower',
|
||||
'unit-case': 'lower',
|
||||
'value-list-comma-newline-after': 'always-multi-line',
|
||||
'value-list-comma-space-after': 'always-single-line',
|
||||
'value-list-comma-space-before': 'never',
|
||||
'value-list-max-empty-lines': 0
|
||||
*/
|
||||
}
|
||||
};
|
||||
const CSSLINT = {
|
||||
// Default warnings
|
||||
'display-property-grouping': 1,
|
||||
'duplicate-properties': 1,
|
||||
'empty-rules': 1,
|
||||
'errors': 1,
|
||||
'warnings': 1,
|
||||
'known-properties': 1,
|
||||
|
||||
// Default disabled
|
||||
'adjoining-classes': 0,
|
||||
'box-model': 0,
|
||||
'box-sizing': 0,
|
||||
'bulletproof-font-face': 0,
|
||||
'compatible-vendor-prefixes': 0,
|
||||
'duplicate-background-images': 0,
|
||||
'fallback-colors': 0,
|
||||
'floats': 0,
|
||||
'font-faces': 0,
|
||||
'font-sizes': 0,
|
||||
'gradients': 0,
|
||||
'ids': 0,
|
||||
'import': 0,
|
||||
'import-ie-limit': 0,
|
||||
'important': 0,
|
||||
'order-alphabetical': 0,
|
||||
'outline-none': 0,
|
||||
'overqualified-elements': 0,
|
||||
'qualified-headings': 0,
|
||||
'regex-selectors': 0,
|
||||
'rules-count': 0,
|
||||
'selector-max': 0,
|
||||
'selector-max-approaching': 0,
|
||||
'selector-newline': 0,
|
||||
'shorthand': 0,
|
||||
'star-property-hack': 0,
|
||||
'text-indent': 0,
|
||||
'underscore-property-hack': 0,
|
||||
'unique-headings': 0,
|
||||
'universal-selector': 0,
|
||||
'unqualified-attributes': 0,
|
||||
'vendor-prefix': 0,
|
||||
'zero-units': 0
|
||||
};
|
||||
return {STYLELINT, CSSLINT, SEVERITY};
|
||||
})();
|
113
edit/linter-engines.js
Normal file
113
edit/linter-engines.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
/* global LINTER_DEFAULTS linter editorWorker */
|
||||
'use strict';
|
||||
|
||||
(() => {
|
||||
registerLinters({
|
||||
csslint: {
|
||||
storageName: 'editorCSSLintConfig',
|
||||
lint: csslint,
|
||||
validMode: mode => mode === 'css',
|
||||
getConfig: config => Object.assign({}, LINTER_DEFAULTS.CSSLINT, config)
|
||||
},
|
||||
stylelint: {
|
||||
storageName: 'editorStylelintConfig',
|
||||
lint: stylelint,
|
||||
validMode: () => true,
|
||||
getConfig: config => ({
|
||||
syntax: 'sugarss',
|
||||
rules: Object.assign({}, LINTER_DEFAULTS.STYLELINT.rules, config && config.rules)
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
function stylelint(text, config, mode) {
|
||||
return editorWorker.stylelint(text, config)
|
||||
.then(({results}) => {
|
||||
if (!results[0]) {
|
||||
return [];
|
||||
}
|
||||
const output = results[0].warnings.map(({line, column: ch, text, severity}) =>
|
||||
({
|
||||
from: {line: line - 1, ch: ch - 1},
|
||||
to: {line: line - 1, ch},
|
||||
message: text
|
||||
.replace('Unexpected ', '')
|
||||
.replace(/^./, firstLetter => firstLetter.toUpperCase())
|
||||
.replace(/\s*\([^(]+\)$/, ''), // strip the rule,
|
||||
rule: text.replace(/^.*?\s*\(([^(]+)\)$/, '$1'),
|
||||
severity,
|
||||
})
|
||||
);
|
||||
return mode !== 'stylus' ?
|
||||
output :
|
||||
output.filter(({message}) =>
|
||||
!message.includes('"@css"') || !message.includes('(at-rule-no-unknown)'));
|
||||
});
|
||||
}
|
||||
|
||||
function csslint(text, config) {
|
||||
return editorWorker.csslint(text, config)
|
||||
.then(results =>
|
||||
results
|
||||
.map(({line, col: ch, message, rule, type: severity}) => line && {
|
||||
message,
|
||||
from: {line: line - 1, ch: ch - 1},
|
||||
to: {line: line - 1, ch},
|
||||
rule: rule.id,
|
||||
severity,
|
||||
})
|
||||
.filter(Boolean)
|
||||
);
|
||||
}
|
||||
|
||||
function registerLinters(engines) {
|
||||
const configs = new Map();
|
||||
|
||||
chrome.storage.onChanged.addListener((changes, area) => {
|
||||
if (area !== 'sync') {
|
||||
return;
|
||||
}
|
||||
for (const [name, engine] of Object.entries(engines)) {
|
||||
if (changes.hasOwnProperty(engine.storageName)) {
|
||||
chromeSync.getLZValue(engine.storageName)
|
||||
.then(config => {
|
||||
configs.set(name, engine.getConfig(config));
|
||||
linter.run();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
linter.register((text, options, cm) => {
|
||||
const selectedLinter = prefs.get('editor.linter');
|
||||
if (!selectedLinter) {
|
||||
return;
|
||||
}
|
||||
const mode = cm.getOption('mode');
|
||||
if (engines[selectedLinter].validMode(mode)) {
|
||||
return runLint(selectedLinter);
|
||||
}
|
||||
for (const [name, engine] of Object.entries(engines)) {
|
||||
if (engine.validMode(mode)) {
|
||||
return runLint(name);
|
||||
}
|
||||
}
|
||||
|
||||
function runLint(name) {
|
||||
return getConfig(name)
|
||||
.then(config => engines[name].lint(text, config, mode));
|
||||
}
|
||||
});
|
||||
|
||||
function getConfig(name) {
|
||||
if (configs.has(name)) {
|
||||
return Promise.resolve(configs.get(name));
|
||||
}
|
||||
return chromeSync.getLZValue(engines[name].storageName)
|
||||
.then(config => {
|
||||
configs.set(name, engines[name].getConfig(config));
|
||||
return configs.get(name);
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
51
edit/linter-help-dialog.js
Normal file
51
edit/linter-help-dialog.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* global showHelp editorWorker memoize */
|
||||
'use strict';
|
||||
|
||||
function createLinterHelpDialog(getIssues) {
|
||||
let csslintRules;
|
||||
const prepareCsslintRules = memoize(() =>
|
||||
editorWorker.getCsslintRules()
|
||||
.then(rules => {
|
||||
csslintRules = rules;
|
||||
})
|
||||
);
|
||||
return {show};
|
||||
|
||||
function show() {
|
||||
// FIXME: implement a linterChooser?
|
||||
const linter = $('#editor.linter').value;
|
||||
const baseUrl = linter === 'stylelint'
|
||||
? 'https://stylelint.io/user-guide/rules/'
|
||||
// some CSSLint rules do not have a url
|
||||
: 'https://github.com/CSSLint/csslint/issues/535';
|
||||
let headerLink, template;
|
||||
if (linter === 'csslint') {
|
||||
headerLink = $createLink('https://github.com/CSSLint/csslint/wiki/Rules', 'CSSLint');
|
||||
template = ({rule: ruleID}) => {
|
||||
const rule = csslintRules.find(rule => rule.id === ruleID);
|
||||
return rule &&
|
||||
$create('li', [
|
||||
$create('b', $createLink(rule.url || baseUrl, rule.name)),
|
||||
$create('br'),
|
||||
rule.desc,
|
||||
]);
|
||||
};
|
||||
} else {
|
||||
headerLink = $createLink(baseUrl, 'stylelint');
|
||||
template = ({rule}) =>
|
||||
$create('li',
|
||||
rule === 'CssSyntaxError' ? rule : $createLink(baseUrl + rule, rule));
|
||||
}
|
||||
const header = t('linterIssuesHelp', '\x01').split('\x01');
|
||||
const activeRules = getIssues();
|
||||
Promise.resolve(linter === 'csslint' && prepareCsslintRules())
|
||||
.then(() =>
|
||||
showHelp(t('linterIssues'),
|
||||
$create([
|
||||
header[0], headerLink, header[1],
|
||||
$create('ul.rules', [...activeRules.values()].map(template)),
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
47
edit/linter-meta.js
Normal file
47
edit/linter-meta.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* global linter */
|
||||
'use strict';
|
||||
|
||||
function createMetaCompiler(cm) {
|
||||
const updateListeners = [];
|
||||
let meta = null;
|
||||
let metaIndex = null;
|
||||
let cache = [];
|
||||
|
||||
linter.register((text, options, _cm) => {
|
||||
if (_cm !== cm) {
|
||||
return;
|
||||
}
|
||||
const match = text.match(/\/\*\s*==userstyle==[\s\S]*?==\/userstyle==\s*\*\//i);
|
||||
if (!match) {
|
||||
return [];
|
||||
}
|
||||
if (match[0] === meta && match.index === metaIndex) {
|
||||
return cache;
|
||||
}
|
||||
return API.parseUsercss({sourceCode: match[0], metaOnly: true})
|
||||
.then(result => result.usercssData)
|
||||
.then(result => {
|
||||
for (const cb of updateListeners) {
|
||||
cb(result);
|
||||
}
|
||||
meta = match[0];
|
||||
metaIndex = match.index;
|
||||
cache = [];
|
||||
return cache;
|
||||
}, err => {
|
||||
meta = match[0];
|
||||
metaIndex = match.index;
|
||||
cache = [{
|
||||
from: cm.posFromIndex((err.index || 0) + match.index),
|
||||
to: cm.posFromIndex((err.index || 0) + match.index),
|
||||
message: err.message,
|
||||
severity: 'error'
|
||||
}];
|
||||
return cache;
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
onUpdated: cb => updateListeners.push(cb)
|
||||
};
|
||||
}
|
165
edit/linter-report.js
Normal file
165
edit/linter-report.js
Normal file
|
@ -0,0 +1,165 @@
|
|||
/* global linter editors clipString createLinterHelpDialog makeSectionVisible */
|
||||
'use strict';
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
Object.assign(linter, (() => {
|
||||
const tables = new Map();
|
||||
const helpDialog = createLinterHelpDialog(getIssues);
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
$('#lint-help').addEventListener('click', helpDialog.show);
|
||||
}, {once: true});
|
||||
|
||||
linter.onLintingUpdated((annotationsNotSorted, annotations, cm) => {
|
||||
let table = tables.get(cm);
|
||||
if (!table) {
|
||||
table = createTable(cm);
|
||||
tables.set(cm, table);
|
||||
const container = $('.lint-report-container');
|
||||
if (typeof editor === 'object') {
|
||||
container.append(table.element);
|
||||
} else {
|
||||
const nextSibling = findNextSibling(tables, cm);
|
||||
container.insertBefore(table.element, nextSibling && tables.get(nextSibling).element);
|
||||
}
|
||||
}
|
||||
table.updateCaption();
|
||||
table.updateAnnotations(annotations);
|
||||
updateCount();
|
||||
});
|
||||
|
||||
linter.onUnhook(cm => {
|
||||
const table = tables.get(cm);
|
||||
if (table) {
|
||||
table.element.remove();
|
||||
tables.delete(cm);
|
||||
}
|
||||
updateCount();
|
||||
});
|
||||
|
||||
return {refreshReport};
|
||||
|
||||
function updateCount() {
|
||||
const issueCount = Array.from(tables.values())
|
||||
.reduce((sum, table) => sum + table.trs.length, 0);
|
||||
$('#lint').classList.toggle('hidden', issueCount === 0);
|
||||
$('#issue-count').textContent = issueCount;
|
||||
}
|
||||
|
||||
function getIssues() {
|
||||
const issues = new Set();
|
||||
for (const table of tables.values()) {
|
||||
for (const tr of table.trs) {
|
||||
issues.add(tr.getAnnotation());
|
||||
}
|
||||
}
|
||||
return issues;
|
||||
}
|
||||
|
||||
function findNextSibling(tables, cm) {
|
||||
let i = editors.indexOf(cm) + 1;
|
||||
while (i < editors.length) {
|
||||
if (tables.has(editors[i])) {
|
||||
return editors[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
function refreshReport() {
|
||||
for (const table of tables.values()) {
|
||||
table.updateCaption();
|
||||
}
|
||||
}
|
||||
|
||||
function createTable(cm) {
|
||||
const caption = $create('caption');
|
||||
const tbody = $create('tbody');
|
||||
const table = $create('table', [caption, tbody]);
|
||||
const trs = [];
|
||||
return {
|
||||
element: table,
|
||||
trs,
|
||||
updateAnnotations,
|
||||
updateCaption
|
||||
};
|
||||
|
||||
function updateCaption() {
|
||||
caption.textContent = typeof editor === 'object' ?
|
||||
'' : `${t('sectionCode')} ${editors.indexOf(cm) + 1}`;
|
||||
}
|
||||
|
||||
function updateAnnotations(lines) {
|
||||
let i = 0;
|
||||
for (const anno of getAnnotations()) {
|
||||
let tr;
|
||||
if (i < trs.length) {
|
||||
tr = trs[i];
|
||||
} else {
|
||||
tr = createTr();
|
||||
trs.push(tr);
|
||||
tbody.append(tr.element);
|
||||
}
|
||||
tr.update(anno);
|
||||
i++;
|
||||
}
|
||||
if (i === 0) {
|
||||
trs.length = 0;
|
||||
tbody.textContent = '';
|
||||
} else {
|
||||
while (trs.length > i) {
|
||||
trs.pop().element.remove();
|
||||
}
|
||||
}
|
||||
table.classList.toggle('empty', trs.length === 0);
|
||||
|
||||
function *getAnnotations() {
|
||||
for (const line of lines.filter(Boolean)) {
|
||||
yield *line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createTr() {
|
||||
let anno;
|
||||
const severityIcon = $create('div');
|
||||
const severity = $create('td', {attributes: {role: 'severity'}}, severityIcon);
|
||||
const line = $create('td', {attributes: {role: 'line'}});
|
||||
const col = $create('td', {attributes: {role: 'col'}});
|
||||
const message = $create('td', {attributes: {role: 'message'}});
|
||||
|
||||
const trElement = $create('tr', {
|
||||
onclick: () => gotoLintIssue(cm, anno)
|
||||
}, [
|
||||
severity,
|
||||
line,
|
||||
$create('td', {attributes: {role: 'sep'}}, ':'),
|
||||
col,
|
||||
message
|
||||
]);
|
||||
return {
|
||||
element: trElement,
|
||||
update,
|
||||
getAnnotation: () => anno
|
||||
};
|
||||
|
||||
function update(_anno) {
|
||||
anno = _anno;
|
||||
trElement.className = anno.severity;
|
||||
severity.dataset.rule = anno.rule;
|
||||
severityIcon.className = `CodeMirror-lint-marker-${anno.severity}`;
|
||||
severityIcon.textContent = anno.severity;
|
||||
line.textContent = anno.from.line + 1;
|
||||
col.textContent = anno.from.ch + 1;
|
||||
message.title = clipString(anno.message, 1000) + `\n(${anno.rule})`;
|
||||
message.textContent = clipString(anno.message, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gotoLintIssue(cm, anno) {
|
||||
makeSectionVisible(cm);
|
||||
cm.focus();
|
||||
cm.setSelection(anno.from);
|
||||
}
|
||||
})());
|
65
edit/linter.js
Normal file
65
edit/linter.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
'use strict';
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
var linter = (() => {
|
||||
const lintingUpdatedListeners = [];
|
||||
const unhookListeners = [];
|
||||
const linters = [];
|
||||
const cms = new Set();
|
||||
|
||||
return {
|
||||
register,
|
||||
run,
|
||||
enableForEditor,
|
||||
disableForEditor,
|
||||
onLintingUpdated,
|
||||
onUnhook
|
||||
};
|
||||
|
||||
function onUnhook(cb) {
|
||||
unhookListeners.push(cb);
|
||||
}
|
||||
|
||||
function onLintingUpdated(cb) {
|
||||
lintingUpdatedListeners.push(cb);
|
||||
}
|
||||
|
||||
function onUpdateLinting(...args) {
|
||||
for (const cb of lintingUpdatedListeners) {
|
||||
cb(...args);
|
||||
}
|
||||
}
|
||||
|
||||
function enableForEditor(cm) {
|
||||
cm.setOption('lint', {onUpdateLinting, getAnnotations});
|
||||
cms.add(cm);
|
||||
}
|
||||
|
||||
function disableForEditor(cm) {
|
||||
cm.setOption('lint', false);
|
||||
cms.delete(cm);
|
||||
for (const cb of unhookListeners) {
|
||||
cb(cm);
|
||||
}
|
||||
}
|
||||
|
||||
function register(linterFn) {
|
||||
linters.push(linterFn);
|
||||
}
|
||||
|
||||
function run() {
|
||||
for (const cm of cms) {
|
||||
cm.performLint();
|
||||
}
|
||||
}
|
||||
|
||||
function getAnnotations(...args) {
|
||||
return Promise.all(linters.map(fn => fn(...args)))
|
||||
.then(results => [].concat(...results.filter(Boolean)));
|
||||
}
|
||||
})();
|
||||
|
||||
// FIXME: this should be put inside edit.js
|
||||
prefs.subscribe(['editor.linter'], () => {
|
||||
linter.run();
|
||||
});
|
|
@ -1,10 +1,11 @@
|
|||
/*
|
||||
global CodeMirror
|
||||
global editors propertyToCss CssToProperty
|
||||
global onChange indicateCodeChange initHooks setCleanGlobal
|
||||
global onChange initHooks setCleanGlobal
|
||||
global fromMozillaFormat maximizeCodeHeight toggleContextMenuDelete
|
||||
global setCleanItem updateTitle updateLintReportIfEnabled renderLintReport
|
||||
global setCleanItem updateTitle
|
||||
global showAppliesToHelp beautify regExpTester setGlobalProgress setCleanSection
|
||||
global clipString linter
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
|
@ -14,7 +15,7 @@ function initWithSectionStyle(style, codeIsUpdated) {
|
|||
$('#url').href = style.url || '';
|
||||
if (codeIsUpdated !== false) {
|
||||
editors.length = 0;
|
||||
getSections().forEach(div => div.remove());
|
||||
$('#sections').textContent = '';
|
||||
addSections(style.sections.length ? style.sections : [{code: ''}]);
|
||||
initHooks();
|
||||
}
|
||||
|
@ -76,9 +77,12 @@ function addSections(sections, onAdded = () => {}) {
|
|||
|
||||
function addSection(event, section) {
|
||||
const div = template.section.cloneNode(true);
|
||||
$('.applies-to-help', div).addEventListener('click', showAppliesToHelp, false);
|
||||
$('.remove-section', div).addEventListener('click', removeSection, false);
|
||||
$('.add-section', div).addEventListener('click', addSection, false);
|
||||
$('.applies-to-help', div).addEventListener('click', showAppliesToHelp);
|
||||
$('.remove-section', div).addEventListener('click', removeSection);
|
||||
$('.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);
|
||||
|
||||
const code = (section || {}).code || '';
|
||||
|
@ -97,7 +101,7 @@ function addSection(event, section) {
|
|||
}
|
||||
}
|
||||
if (!appliesToAdded) {
|
||||
addAppliesTo(appliesTo);
|
||||
addAppliesTo(appliesTo, event && 'url-prefix', '');
|
||||
}
|
||||
|
||||
appliesTo.addEventListener('change', onChange);
|
||||
|
@ -134,17 +138,21 @@ function addSection(event, section) {
|
|||
const sections = $('#sections');
|
||||
let cm;
|
||||
if (event) {
|
||||
const clickedSection = getSectionForChild(event.target);
|
||||
sections.insertBefore(div, clickedSection.nextElementSibling);
|
||||
let clickedSection = event && getSectionForChild(event.target, {includeDeleted: true});
|
||||
clickedSection.insertAdjacentElement('afterend', div);
|
||||
while (clickedSection && !clickedSection.matches('.section')) {
|
||||
clickedSection = clickedSection.previousElementSibling;
|
||||
}
|
||||
const newIndex = getSections().indexOf(clickedSection) + 1;
|
||||
cm = setupCodeMirror(div, code, newIndex);
|
||||
makeSectionVisible(cm);
|
||||
renderLintReport();
|
||||
cm.focus();
|
||||
} else {
|
||||
sections.appendChild(div);
|
||||
cm = setupCodeMirror(div, code);
|
||||
}
|
||||
linter.enableForEditor(cm);
|
||||
linter.refreshReport();
|
||||
div.CodeMirror = cm;
|
||||
setCleanSection(div);
|
||||
return div;
|
||||
|
@ -192,7 +200,31 @@ function addAppliesTo(list, type, value) {
|
|||
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 => {
|
||||
$('.code-label', sectionDiv).insertAdjacentElement('afterend', wrapper);
|
||||
}, {
|
||||
|
@ -269,7 +301,7 @@ function setupCodeMirror(sectionDiv, code, index) {
|
|||
});
|
||||
};
|
||||
|
||||
editors.splice(index || editors.length, 0, cm);
|
||||
editors.splice(index, 0, cm);
|
||||
return cm;
|
||||
}
|
||||
|
||||
|
@ -277,7 +309,6 @@ function indicateCodeChange(cm) {
|
|||
const section = cm.getSection();
|
||||
setCleanItem(section, cm.isClean(section.savedValue));
|
||||
updateTitle();
|
||||
updateLintReportIfEnabled(cm);
|
||||
}
|
||||
|
||||
function setupAutocomplete(cm, enable = true) {
|
||||
|
@ -385,17 +416,17 @@ function toggleSectionHeight(cm) {
|
|||
}
|
||||
}
|
||||
|
||||
function getSectionForChild(e) {
|
||||
return e.closest('#sections > div');
|
||||
function getSectionForChild(el, {includeDeleted} = {}) {
|
||||
return el.closest(`#sections > ${includeDeleted ? '*' : '.section'}`);
|
||||
}
|
||||
|
||||
function getSections() {
|
||||
return $$('#sections > div');
|
||||
return $$('#sections > .section');
|
||||
}
|
||||
|
||||
function getSectionsHashes() {
|
||||
function getSectionsHashes(elements = getSections()) {
|
||||
const sections = [];
|
||||
for (const div of getSections()) {
|
||||
for (const div of elements) {
|
||||
const meta = {urls: [], urlPrefixes: [], domains: [], regexps: []};
|
||||
for (const li of $('.applies-to-list', div).childNodes) {
|
||||
if (li.className === template.appliesToEverything.className) {
|
||||
|
@ -430,10 +461,36 @@ function removeAppliesTo(event) {
|
|||
function removeSection(event) {
|
||||
const section = getSectionForChild(event.target);
|
||||
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();
|
||||
linter.enableForEditor(cm);
|
||||
linter.refreshReport();
|
||||
};
|
||||
section.insertAdjacentElement('afterend', stub);
|
||||
}
|
||||
setCleanItem($('#sections'), false);
|
||||
removeAreaAndSetDirty(section);
|
||||
editors.splice(editors.indexOf(cm), 1);
|
||||
renderLintReport();
|
||||
linter.disableForEditor(cm);
|
||||
linter.refreshReport();
|
||||
}
|
||||
|
||||
function removeAreaAndSetDirty(area) {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/*
|
||||
global editors styleId: true
|
||||
global CodeMirror dirtyReporter
|
||||
global updateLintReportIfEnabled initLint linterConfig updateLinter
|
||||
global createAppliesToLineWidget messageBox
|
||||
global sectionsToMozFormat
|
||||
global exclusions
|
||||
global beforeUnload
|
||||
global createMetaCompiler linter
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
|
@ -13,14 +14,16 @@ function createSourceEditor(style) {
|
|||
$('#save-button').disabled = true;
|
||||
$('#mozilla-format-container').remove();
|
||||
$('#save-button').onclick = save;
|
||||
$('#header').addEventListener('wheel', headerOnScroll, {passive: true});
|
||||
$('#header').addEventListener('wheel', headerOnScroll);
|
||||
$('#sections').textContent = '';
|
||||
$('#sections').appendChild($create('.single-editor'));
|
||||
|
||||
const dirty = dirtyReporter();
|
||||
dirty.onChange(() => {
|
||||
document.body.classList.toggle('dirty', dirty.isDirty());
|
||||
$('#save-button').disabled = !dirty.isDirty();
|
||||
const isDirty = dirty.isDirty();
|
||||
window.onbeforeunload = isDirty ? beforeUnload : null;
|
||||
document.body.classList.toggle('dirty', isDirty);
|
||||
$('#save-button').disabled = !isDirty;
|
||||
updateTitle();
|
||||
});
|
||||
|
||||
|
@ -42,7 +45,6 @@ function createSourceEditor(style) {
|
|||
|
||||
cm.on('changes', () => {
|
||||
dirty.modify('sourceGeneration', savedGeneration, cm.changeGeneration());
|
||||
updateLintReportIfEnabled(cm);
|
||||
});
|
||||
|
||||
CodeMirror.commands.prevEditor = cm => nextPrevMozDocument(cm, -1);
|
||||
|
@ -53,9 +55,17 @@ function createSourceEditor(style) {
|
|||
|
||||
cm.operation(initAppliesToLineWidget);
|
||||
|
||||
updateMeta().then(() => {
|
||||
const metaCompiler = createMetaCompiler(cm);
|
||||
metaCompiler.onUpdated(meta => {
|
||||
style.usercssData = meta;
|
||||
style.name = meta.name;
|
||||
style.url = meta.homepageURL;
|
||||
updateMeta();
|
||||
});
|
||||
|
||||
initLint();
|
||||
linter.enableForEditor(cm);
|
||||
|
||||
updateMeta().then(() => {
|
||||
|
||||
let prevMode = NaN;
|
||||
cm.on('optionChange', (cm, option) => {
|
||||
|
@ -63,7 +73,7 @@ function createSourceEditor(style) {
|
|||
const mode = getModeName();
|
||||
if (mode === prevMode) return;
|
||||
prevMode = mode;
|
||||
updateLinter();
|
||||
linter.run();
|
||||
updateLinterSwitch();
|
||||
});
|
||||
|
||||
|
@ -86,7 +96,7 @@ function createSourceEditor(style) {
|
|||
|
||||
function updateLinterSwitch() {
|
||||
const el = $('#editor.linter');
|
||||
el.value = linterConfig.getName();
|
||||
el.value = getCurrentLinter();
|
||||
const cssLintOption = $('[value="csslint"]', el);
|
||||
const mode = getModeName();
|
||||
if (mode !== 'css') {
|
||||
|
@ -98,6 +108,14 @@ function createSourceEditor(style) {
|
|||
}
|
||||
}
|
||||
|
||||
function getCurrentLinter() {
|
||||
const name = prefs.get('editor.linter');
|
||||
if (cm.getOption('mode') !== 'css' && name === 'csslint') {
|
||||
return 'stylelint';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
function setupNewStyle(style) {
|
||||
style.sections[0].code = ' '.repeat(prefs.get('editor.tabSize')) +
|
||||
`/* ${t('usercssReplaceTemplateSectionBody')} */`;
|
||||
|
@ -108,12 +126,9 @@ function createSourceEditor(style) {
|
|||
}
|
||||
const DEFAULT_CODE = `
|
||||
/* ==UserStyle==
|
||||
@name ${
|
||||
style.name ||
|
||||
t('usercssReplaceTemplateName') + ' - ' + new Date().toLocaleString()
|
||||
}
|
||||
@name ${''/* a trick to preserve the trailing spaces */}
|
||||
@namespace github.com/openstyles/stylus
|
||||
@version 0.1.0
|
||||
@version 1.0.0
|
||||
@description A new userstyle
|
||||
@author Me
|
||||
==/UserStyle== */
|
||||
|
@ -123,9 +138,13 @@ function createSourceEditor(style) {
|
|||
style.sourceCode = '';
|
||||
|
||||
chromeSync.getLZValue('usercssTemplate').then(code => {
|
||||
const name = style.name || t('usercssReplaceTemplateName');
|
||||
const date = new Date().toLocaleString();
|
||||
code = code || DEFAULT_CODE;
|
||||
code = code.replace(/@name(\s*)(?=[\r\n])/, (str, space) =>
|
||||
`${str}${space ? '' : ' '}${name} - ${date}`);
|
||||
// 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.setValue(style.sourceCode);
|
||||
cm.clearHistory();
|
||||
|
@ -146,7 +165,7 @@ function createSourceEditor(style) {
|
|||
|
||||
function updateTitle() {
|
||||
const newTitle = (dirty.isDirty() ? '* ' : '') +
|
||||
(style.id ? t('editStyleTitle', [style.name]) : t('addStyleTitle'));
|
||||
(style.id ? style.name : t('addStyleTitle'));
|
||||
if (document.title !== newTitle) {
|
||||
document.title = newTitle;
|
||||
}
|
||||
|
@ -204,8 +223,8 @@ function createSourceEditor(style) {
|
|||
id: style.id,
|
||||
exclusionList
|
||||
});
|
||||
return (
|
||||
API.saveUsercssUnsafe({
|
||||
return ensureUniqueStyle(code)
|
||||
.then(() => API.saveUsercssUnsafe({
|
||||
id: style.id,
|
||||
reason: 'editSave',
|
||||
enabled: style.enabled,
|
||||
|
@ -217,6 +236,7 @@ function createSourceEditor(style) {
|
|||
if (errors) return Promise.reject(errors);
|
||||
})
|
||||
.catch(err => {
|
||||
if (err.handled) return;
|
||||
if (err.message === t('styleMissingMeta', 'name')) {
|
||||
messageBox.confirm(t('usercssReplaceTemplateConfirmation')).then(ok => ok &&
|
||||
chromeSync.setLZValue('usercssTemplate', code)
|
||||
|
@ -236,6 +256,20 @@ function createSourceEditor(style) {
|
|||
});
|
||||
}
|
||||
|
||||
function ensureUniqueStyle(code) {
|
||||
return style.id ? Promise.resolve() :
|
||||
API.buildUsercss({
|
||||
sourceCode: code,
|
||||
checkDup: true,
|
||||
metaOnly: true,
|
||||
}).then(({dup}) => {
|
||||
if (dup) {
|
||||
messageBox.alert(t('usercssAvoidOverwriting'), 'danger', t('genericError'));
|
||||
return Promise.reject({handled: true});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function drawLinePointer(pos) {
|
||||
const SIZE = 60;
|
||||
const line = cm.getLine(pos.line);
|
||||
|
@ -328,7 +362,7 @@ function createSourceEditor(style) {
|
|||
}
|
||||
cm.display.scroller.scrollTop +=
|
||||
// WheelEvent.DOM_DELTA_LINE
|
||||
deltaMode === 1 ? deltaY * cm.display.cachedTextHeight :
|
||||
deltaMode === 1 ? deltaY * cm.defaultTextHeight() :
|
||||
// WheelEvent.DOM_DELTA_PAGE
|
||||
deltaMode === 2 || shiftKey ? Math.sign(deltaY) * cm.display.scroller.clientHeight :
|
||||
// WheelEvent.DOM_DELTA_PIXEL
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
/* global require importScripts */
|
||||
'use strict';
|
||||
|
||||
importScripts('/vendor/stylelint-bundle/stylelint-bundle.min.js');
|
||||
|
||||
const stylelint = require('stylelint');
|
||||
|
||||
self.onmessage = ({data: {action = 'run', code, config}}) => {
|
||||
switch (action) {
|
||||
case 'getAllRuleIds':
|
||||
// the functions are non-tranferable
|
||||
self.postMessage(Object.keys(stylelint.rules));
|
||||
return;
|
||||
case 'getAllRuleOptions':
|
||||
self.postMessage(getAllRuleOptions());
|
||||
return;
|
||||
case 'run':
|
||||
stylelint.lint({code, config}).then(results =>
|
||||
self.postMessage(results));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
function getAllRuleOptions() {
|
||||
const options = {};
|
||||
const rxPossible = /\bpossible:("(?:[^"]*?)"|\[(?:[^\]]*?)\]|\{(?:[^}]*?)\})/g;
|
||||
const rxString = /"([-\w\s]{3,}?)"/g;
|
||||
for (const id of Object.keys(stylelint.rules)) {
|
||||
const ruleCode = String(stylelint.rules[id]);
|
||||
const sets = [];
|
||||
let m, mStr;
|
||||
while ((m = rxPossible.exec(ruleCode))) {
|
||||
const possible = m[1];
|
||||
const set = [];
|
||||
while ((mStr = rxString.exec(possible))) {
|
||||
const s = mStr[1];
|
||||
if (s.includes(' ')) {
|
||||
set.push(...s.split(/\s+/));
|
||||
} else {
|
||||
set.push(s);
|
||||
}
|
||||
}
|
||||
if (possible.includes('ignoreAtRules')) {
|
||||
set.push('ignoreAtRules');
|
||||
}
|
||||
if (possible.includes('ignoreShorthands')) {
|
||||
set.push('ignoreShorthands');
|
||||
}
|
||||
if (set.length) {
|
||||
sets.push(set);
|
||||
}
|
||||
}
|
||||
if (sets.length) {
|
||||
options[id] = sets;
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
18
edit/util.js
18
edit/util.js
|
@ -116,3 +116,21 @@ function sectionsToMozFormat(style) {
|
|||
section.code;
|
||||
}).join('\n\n');
|
||||
}
|
||||
|
||||
|
||||
function clipString(str, limit = 100) {
|
||||
return str.length <= limit ? str : str.substr(0, limit) + '...';
|
||||
}
|
||||
|
||||
// this is a decorator. Cache the first call
|
||||
function memoize(fn) {
|
||||
let cached = false;
|
||||
let result;
|
||||
return (...args) => {
|
||||
if (!cached) {
|
||||
result = fn(...args);
|
||||
cached = true;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
|
47
global.css
47
global.css
|
@ -1,3 +1,20 @@
|
|||
body {
|
||||
font: normal 12px Arial, system-ui, sans-serif;
|
||||
}
|
||||
|
||||
body:lang(ja) {
|
||||
font-family: Arial, 'Meiryo UI', 'MS Gothic', system-ui, sans-serif;
|
||||
}
|
||||
|
||||
body:lang(zh-CN) {
|
||||
font-family: Arial, 'Microsoft YaHei UI', 'Microsoft YaHei', system-ui, sans-serif;
|
||||
}
|
||||
|
||||
body:lang(zh-TW),
|
||||
body:lang(zh-HK) {
|
||||
font-family: Arial, 'Microsoft JhengHei UI', 'Microsoft JhengHei', system-ui, sans-serif;
|
||||
}
|
||||
|
||||
button {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
|
@ -8,7 +25,8 @@ button {
|
|||
text-overflow: ellipsis;
|
||||
padding: 2px 7px;
|
||||
border: 1px solid hsl(0, 0%, 62%);
|
||||
font: 400 13.3333px Arial;
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
color: #000;
|
||||
background-color: hsl(0, 0%, 100%);
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAYAAADtlXTHAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QwGBBwIHvKt6QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAL0lEQVQI12NoaGgQZ2JgYGBkYmBgYGZiYGBggrMY4VxsYsyoskQQCB2MWAxAMhkADVECDhlW9CoAAAAASUVORK5CYII=');
|
||||
|
@ -36,6 +54,10 @@ button:active {
|
|||
border-color: hsl(0, 0%, 50%);
|
||||
}
|
||||
|
||||
input {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
input:not([type]) {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
|
@ -43,7 +65,7 @@ input:not([type]) {
|
|||
min-height: 22px!important;
|
||||
line-height: 22px;
|
||||
padding: 0 3px;
|
||||
font: 400 13.3333px Arial;
|
||||
font: inherit;
|
||||
border: 1px solid hsl(0, 0%, 66%);
|
||||
}
|
||||
|
||||
|
@ -110,7 +132,7 @@ select {
|
|||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
height: 22px;
|
||||
font: 400 13.3333px Arial;
|
||||
font: inherit;
|
||||
color: #000;
|
||||
background-color: transparent;
|
||||
border: 1px solid hsl(0, 0%, 66%);
|
||||
|
@ -186,19 +208,6 @@ select[disabled] > option {
|
|||
outline: none;
|
||||
}
|
||||
|
||||
/* use a readable font for Japanese/Chinese */
|
||||
|
||||
.actions:lang(ja) *,
|
||||
#header:lang(ja) * {
|
||||
font-family: 'Meiryo UI', system-ui, 'MS Gothic', Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.actions:lang(zh) *,
|
||||
#header:lang(zh) * {
|
||||
font-family: 'MingLiU', system-ui, Arial, sans-serif;
|
||||
}
|
||||
|
||||
@supports (-moz-appearance: none) {
|
||||
.moz-appearance-bug .svg-icon.checked,
|
||||
.moz-appearance-bug .onoffswitch input,
|
||||
|
@ -215,7 +224,6 @@ select[disabled] > option {
|
|||
}
|
||||
|
||||
.firefox select {
|
||||
font-size: 13px;
|
||||
padding: 0 20px 0 2px;
|
||||
line-height: 22px!important;
|
||||
}
|
||||
|
@ -243,13 +251,8 @@ select[disabled] > option {
|
|||
padding: 4px;
|
||||
}
|
||||
|
||||
.firefox.non-windows .style-name {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
/* Firefox cannot handle fractions in font-size */
|
||||
.firefox button:not(.install) {
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
padding: 3px 7px;
|
||||
}
|
||||
|
|
|
@ -306,7 +306,7 @@ li {
|
|||
user-select: auto;
|
||||
}
|
||||
|
||||
label {
|
||||
label:not(.unavailable) {
|
||||
padding-left: 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
'use strict';
|
||||
|
||||
(() => {
|
||||
const DUMMY_URL = 'foo:';
|
||||
|
||||
// TODO: remove .replace(/^\?/, '') when minimum_chrome_version >= 52 (https://crbug.com/601425)
|
||||
const params = new URLSearchParams(location.search.replace(/^\?/, ''));
|
||||
let liveReload = false;
|
||||
|
@ -14,7 +16,8 @@
|
|||
let port;
|
||||
|
||||
if (params.has('direct')) {
|
||||
$('.live-reload').remove();
|
||||
$('.live-reload').textContent = t('liveReloadUnavailable');
|
||||
$('.live-reload').classList.add('unavailable');
|
||||
getCodeDirectly();
|
||||
} else {
|
||||
port = chrome.tabs.connect(tabId);
|
||||
|
@ -308,15 +311,17 @@
|
|||
const checker = $('.set-update-url input[type=checkbox]');
|
||||
// prefer the installation URL unless drag'n'dropped on the manage page
|
||||
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');
|
||||
if (dup && dup.updateUrl === updateUrl.href) {
|
||||
checker.checked = true;
|
||||
// there is no way to "unset" updateUrl, you can only overwrite it.
|
||||
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
|
||||
checker.disabled = true;
|
||||
$('.set-update-url').textContent = t('installUpdateUnavailable');
|
||||
$('.set-update-url').classList.add('unavailable');
|
||||
return;
|
||||
} else if (updateUrl.protocol !== 'file:') {
|
||||
checker.checked = true;
|
||||
style.updateUrl = updateUrl.href;
|
||||
|
|
53
js/dom.js
53
js/dom.js
|
@ -313,20 +313,31 @@ function initCollapsibles({bindClickOn = 'h2'} = {}) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Makes the focus outline appear on keyboard tabbing, but not on mouse clicks.
|
||||
function focusAccessibility() {
|
||||
// Makes the focus outline appear on keyboard tabbing, but not on mouse clicks.
|
||||
// Since we don't want full layout recalc, we modify only the closest focusable element,
|
||||
// which we try to find in DOM for this many parentElement jumps:
|
||||
const focusables = focusAccessibility.ELEMENTS =
|
||||
['a', 'button', 'input', 'textarea', 'label', 'select', 'summary'];
|
||||
// last event's focusedViaClick
|
||||
focusAccessibility.lastFocusedViaClick = false;
|
||||
// tags of focusable elements;
|
||||
// to avoid a full layout recalc we modify the closest one
|
||||
focusAccessibility.ELEMENTS = [
|
||||
'a',
|
||||
'button',
|
||||
'input',
|
||||
'textarea',
|
||||
'label',
|
||||
'select',
|
||||
'summary',
|
||||
];
|
||||
// try to find a focusable parent for this many parentElement jumps:
|
||||
const GIVE_UP_DEPTH = 4;
|
||||
|
||||
addEventListener('mousedown', suppressOutlineOnClick, {passive: true});
|
||||
addEventListener('keydown', keepOutlineOnTab, {passive: true});
|
||||
|
||||
function suppressOutlineOnClick({target}) {
|
||||
for (let el = target, i = 0; el && i++ < GIVE_UP_DEPTH; el = el.parentElement) {
|
||||
if (focusables.includes(el.localName)) {
|
||||
if (focusAccessibility.ELEMENTS.includes(el.localName)) {
|
||||
focusAccessibility.lastFocusedViaClick = true;
|
||||
if (el.dataset.focusedViaClick === undefined) {
|
||||
el.dataset.focusedViaClick = '';
|
||||
}
|
||||
|
@ -337,13 +348,14 @@ function focusAccessibility() {
|
|||
|
||||
function keepOutlineOnTab(event) {
|
||||
if (event.which === 9) {
|
||||
focusAccessibility.lastFocusedViaClick = false;
|
||||
setTimeout(keepOutlineOnTab, 0, true);
|
||||
return;
|
||||
} else if (event !== true) {
|
||||
return;
|
||||
}
|
||||
let el = document.activeElement;
|
||||
if (!el || !focusables.includes(el.localName)) {
|
||||
if (!el || !focusAccessibility.ELEMENTS.includes(el.localName)) {
|
||||
return;
|
||||
}
|
||||
if (el.dataset.focusedViaClick !== undefined) {
|
||||
|
@ -355,3 +367,28 @@ function focusAccessibility() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches to the next/previous keyboard-focusable element
|
||||
* @param {HTMLElement} rootElement
|
||||
* @param {Number} step - for exmaple 1 or -1
|
||||
* @returns {HTMLElement|false|undefined} -
|
||||
* HTMLElement: focus changed,
|
||||
* false: focus unchanged,
|
||||
* undefined: nothing to focus
|
||||
*/
|
||||
function moveFocus(rootElement, step) {
|
||||
const elements = [...rootElement.getElementsByTagName('*')];
|
||||
const activeIndex = Math.max(0, elements.indexOf(document.activeElement));
|
||||
const num = elements.length;
|
||||
const {activeElement} = document;
|
||||
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 activeElement !== el && el;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ var prefs = new function Prefs() {
|
|||
newline_between_properties: true,
|
||||
newline_before_close_brace: true,
|
||||
newline_between_rules: false,
|
||||
preserve_newlines: true,
|
||||
end_with_newline: false,
|
||||
indent_conditional: true,
|
||||
},
|
||||
|
|
|
@ -1,7 +1,24 @@
|
|||
'use strict';
|
||||
|
||||
// ignoreCode=true is used by invalidateCache to determine if cached filters should be cleared
|
||||
function styleSectionsEqual({sections: a}, {sections: b}, {ignoreCode = false} = {}) {
|
||||
/**
|
||||
* @param {Style} a - first style object
|
||||
* @param {Style} b - second style object
|
||||
* @param {Object} options
|
||||
* @param {Boolean=} options.ignoreCode -
|
||||
* true used by invalidateCache to determine if cached filters should be cleared
|
||||
* @param {Boolean=} options.checkSource -
|
||||
* true used by update check to compare the server response
|
||||
* instead of sections that depend on @preprocessor
|
||||
* @returns {Boolean|undefined}
|
||||
*/
|
||||
function styleSectionsEqual(a, b, {ignoreCode, checkSource} = {}) {
|
||||
if (checkSource &&
|
||||
typeof a.sourceCode === 'string' &&
|
||||
typeof b.sourceCode === 'string') {
|
||||
return a.sourceCode === b.sourceCode;
|
||||
}
|
||||
a = a.sections;
|
||||
b = b.sections;
|
||||
if (!a || !b) {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ var usercss = (() => {
|
|||
['version', 0],
|
||||
]);
|
||||
const MANDATORY_META = ['name', 'namespace', 'version'];
|
||||
const META_VARS = ['text', 'color', 'checkbox', 'select', 'dropdown', 'image'];
|
||||
const META_VARS = ['text', 'color', 'checkbox', 'select', 'dropdown', 'image', 'number', 'range'];
|
||||
const META_URLS = [...KNOWN_META.keys()].filter(k => k.endsWith('URL'));
|
||||
|
||||
const BUILDER = {
|
||||
|
@ -194,12 +194,40 @@ var usercss = (() => {
|
|||
state.errorPrefix = 'Invalid JSON: ';
|
||||
parseJSONValue(state);
|
||||
state.errorPrefix = '';
|
||||
const extractDefaultOption = (key, value) => {
|
||||
if (key.endsWith('*')) {
|
||||
const option = createOption(key.slice(0, -1), value);
|
||||
result.default = option.name;
|
||||
return option;
|
||||
}
|
||||
return createOption(key, value);
|
||||
};
|
||||
if (Array.isArray(state.value)) {
|
||||
result.options = state.value.map(text => createOption(text));
|
||||
result.options = state.value.map(k => extractDefaultOption(k));
|
||||
} else {
|
||||
result.options = Object.keys(state.value).map(k => createOption(k, state.value[k]));
|
||||
result.options = Object.keys(state.value).map(k => extractDefaultOption(k, state.value[k]));
|
||||
}
|
||||
if (result.default === null) {
|
||||
result.default = (result.options[0] || {}).name || '';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'number':
|
||||
case 'range': {
|
||||
state.errorPrefix = 'Invalid JSON: ';
|
||||
parseJSONValue(state);
|
||||
state.errorPrefix = '';
|
||||
// [default, start, end, step, units] (start, end, step & units are optional)
|
||||
if (Array.isArray(state.value) && state.value.length) {
|
||||
// label may be placed anywhere
|
||||
result.units = (state.value.find(i => typeof i === 'string') || '').replace(/[\d.+-]/g, '');
|
||||
const range = state.value.filter(i => typeof i === 'number' || i === null);
|
||||
result.default = range[0];
|
||||
result.min = range[1];
|
||||
result.max = range[2];
|
||||
result.step = range[3] === 0 ? 1 : range[3];
|
||||
}
|
||||
result.default = (result.options[0] || {}).name || '';
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -541,6 +569,9 @@ var usercss = (() => {
|
|||
// TODO: handle customized image
|
||||
return va.options.find(o => o.name === va[prop]).value;
|
||||
}
|
||||
if ((va.type === 'number' || va.type === 'range') && va.units) {
|
||||
return va[prop] + va.units;
|
||||
}
|
||||
return va[prop];
|
||||
}
|
||||
|
||||
|
@ -578,6 +609,8 @@ var usercss = (() => {
|
|||
throw new Error(chrome.i18n.getMessage('styleMetaErrorCheckbox'));
|
||||
} else if (va.type === 'color') {
|
||||
va[value] = colorConverter.format(colorConverter.parse(va[value]), 'rgb');
|
||||
} else if ((va.type === 'number' || va.type === 'range') && typeof va[value] !== 'number') {
|
||||
throw new Error(chrome.i18n.getMessage('styleMetaErrorRangeOrNumber', va.type));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -599,7 +632,7 @@ var usercss = (() => {
|
|||
|
||||
function invokeWorker(message) {
|
||||
if (!worker.queue) {
|
||||
worker.instance = new Worker('/edit/csslint-loader.js');
|
||||
worker.instance = new Worker('/background/parserlib-loader.js');
|
||||
worker.queue = [];
|
||||
worker.instance.onmessage = ({data}) => {
|
||||
worker.queue.shift().resolve(data.__ERROR__ ? Promise.reject(data.__ERROR__) : data);
|
||||
|
|
|
@ -254,7 +254,9 @@
|
|||
<label id="only-updates" class="hidden">
|
||||
<input type="checkbox"
|
||||
data-filter=".can-update, .update-problem, .update-done"
|
||||
data-filter-hide=":not(.updatable):not(.update-done), .no-update:not(.update-problem)">
|
||||
data-filter-hide=":not(.updatable):not(.update-done),
|
||||
.no-update:not(.update-problem),
|
||||
.updatable:not(.can-update):not(.update-problem):not(.update-done)">
|
||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||
<span i18n-text="manageOnlyUpdates"></span>
|
||||
</label>
|
||||
|
@ -378,6 +380,7 @@
|
|||
<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://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>
|
||||
|
|
|
@ -98,6 +98,15 @@
|
|||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.current-value {
|
||||
padding: 2px 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.config-number span, .config-range span {
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.config-body label:not(.nondefault) .config-reset-icon {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
|
|
@ -258,16 +258,44 @@ function configDialog(style) {
|
|||
];
|
||||
break;
|
||||
|
||||
case 'range':
|
||||
case 'number': {
|
||||
const options = {
|
||||
va,
|
||||
type: va.type,
|
||||
onfocus: va.type === 'number' ? selectAllOnFocus : null,
|
||||
onblur: va.type === 'number' ? updateVarOnBlur : null,
|
||||
onchange: updateVarOnChange,
|
||||
oninput: updateVarOnInput,
|
||||
required: true
|
||||
};
|
||||
if (typeof va.min === 'number') {
|
||||
options.min = va.min;
|
||||
}
|
||||
if (typeof va.max === 'number') {
|
||||
options.max = va.max;
|
||||
}
|
||||
if (typeof va.step === 'number' && isFinite(va.step)) {
|
||||
options.step = va.step;
|
||||
}
|
||||
children = [
|
||||
va.type === 'range' && $create('span.current-value'),
|
||||
va.input = $create('input.config-value', options)
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
children = [
|
||||
va.input = $create('input.config-value', {
|
||||
va,
|
||||
type: 'text',
|
||||
type: va.type,
|
||||
onchange: updateVarOnChange,
|
||||
oninput: updateVarOnInput,
|
||||
onfocus: selectAllOnFocus,
|
||||
}),
|
||||
];
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
resetter = resetter.cloneNode(true);
|
||||
|
@ -285,8 +313,28 @@ function configDialog(style) {
|
|||
}
|
||||
}
|
||||
|
||||
function updateVarOnBlur() {
|
||||
this.value = isDefault(this.va) ? this.va.default : this.va.value;
|
||||
}
|
||||
|
||||
function updateVarOnChange() {
|
||||
this.va.value = this.type !== 'checkbox' ? this.value : this.checked ? '1' : '0';
|
||||
if (this.type === 'range') {
|
||||
this.va.value = Number(this.value);
|
||||
updateRangeCurrentValue(this.va, this.va.value);
|
||||
} else if (this.type === 'number') {
|
||||
if (this.reportValidity()) {
|
||||
this.va.value = Number(this.value);
|
||||
}
|
||||
} else {
|
||||
this.va.value = this.type !== 'checkbox' ? this.value : this.checked ? '1' : '0';
|
||||
}
|
||||
}
|
||||
|
||||
function updateRangeCurrentValue(va, value) {
|
||||
const span = $('.current-value', va.input.closest('.config-range'));
|
||||
if (span) {
|
||||
span.textContent = value + (va.units || '');
|
||||
}
|
||||
}
|
||||
|
||||
function updateVarOnInput(event, debounced = false) {
|
||||
|
@ -297,8 +345,15 @@ function configDialog(style) {
|
|||
}
|
||||
}
|
||||
|
||||
function selectAllOnFocus(event) {
|
||||
event.target.select();
|
||||
}
|
||||
|
||||
function renderValues(varsToRender = vars) {
|
||||
for (const va of varsToRender) {
|
||||
if (va.input === document.activeElement) {
|
||||
continue;
|
||||
}
|
||||
const value = isDefault(va) ? va.default : va.value;
|
||||
if (va.type === 'color') {
|
||||
va.input.style.backgroundColor = value;
|
||||
|
@ -307,6 +362,9 @@ function configDialog(style) {
|
|||
}
|
||||
} else if (va.type === 'checkbox') {
|
||||
va.input.checked = Number(value);
|
||||
} else if (va.type === 'range') {
|
||||
va.input.value = value;
|
||||
updateRangeCurrentValue(va, va.input.value);
|
||||
} else {
|
||||
va.input.value = value;
|
||||
}
|
||||
|
|
|
@ -203,7 +203,7 @@ function importFromString(jsonString, oldStyles) {
|
|||
messageBox({
|
||||
title: t('importReportTitle'),
|
||||
contents: report.length ? report : t('importReportUnchanged'),
|
||||
buttons: [t('confirmOK'), numChanged && t('undo')],
|
||||
buttons: [t('confirmClose'), numChanged && t('undo')],
|
||||
onshow: bindClick,
|
||||
}).then(({button}) => {
|
||||
if (button === 1) {
|
||||
|
@ -241,7 +241,7 @@ function importFromString(jsonString, oldStyles) {
|
|||
.then(() => messageBox({
|
||||
title: t('importReportUndoneTitle'),
|
||||
contents: newIds.length + ' ' + t('importReportUndone'),
|
||||
buttons: [t('confirmOK')],
|
||||
buttons: [t('confirmClose')],
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -275,39 +275,37 @@ function importFromString(jsonString, oldStyles) {
|
|||
|
||||
$('#file-all-styles').onclick = () => {
|
||||
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
|
||||
if (!FIREFOX && !(CHROME > 3310 && CHROME < Infinity)) {
|
||||
link.dispatchEvent(new MouseEvent('click'));
|
||||
return doTimeout()
|
||||
.then(() => URL.revokeObjectURL(url));
|
||||
}
|
||||
const iframe = document.body.appendChild($create('iframe', {
|
||||
style: 'width: 0; height: 0; position: fixed; opacity: 0;'.replace(/;/g, '!important;'),
|
||||
}));
|
||||
return doTimeout()
|
||||
.then(() => {
|
||||
link = iframe.contentDocument.importNode(link, true);
|
||||
iframe.contentDocument.body.appendChild(link);
|
||||
document.documentElement.appendChild(
|
||||
$create('iframe', {
|
||||
onload() {
|
||||
const text = JSON.stringify(styles, null, '\t');
|
||||
const type = 'application/json';
|
||||
this.onload = null;
|
||||
this.contentDocument.body.appendChild(
|
||||
$create('a', {
|
||||
href: URL.createObjectURL(new Blob([text], {type})),
|
||||
download: generateFileName(),
|
||||
type,
|
||||
})
|
||||
).dispatchEvent(new MouseEvent('click'));
|
||||
},
|
||||
// we can't use display:none as some browsers are ignoring such iframes
|
||||
style: `
|
||||
all: unset;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
border: none;
|
||||
`.replace(/;/g, '!important;'),
|
||||
})
|
||||
.then(() => doTimeout())
|
||||
.then(() => link.dispatchEvent(new MouseEvent('click')))
|
||||
.then(() => doTimeout(1000))
|
||||
.then(() => URL.revokeObjectURL(url))
|
||||
.then(() => iframe.remove());
|
||||
);
|
||||
// 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() {
|
||||
const today = new Date();
|
||||
const dd = ('0' + today.getDate()).substr(-2);
|
||||
|
|
|
@ -9,12 +9,15 @@
|
|||
|
||||
body {
|
||||
margin: 0;
|
||||
font: 12px arial, sans-serif;
|
||||
/* Firefox: fill the entire page for drag'n'drop to work */
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#header:lang(ja) h1 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body.all-styles-hidden-by-filters:before,
|
||||
body.all-styles-hidden-by-filters:after {
|
||||
position: absolute;
|
||||
|
@ -45,10 +48,6 @@ a:hover {
|
|||
color: #666;
|
||||
}
|
||||
|
||||
select {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#header {
|
||||
width: var(--header-width);
|
||||
height: 100vh;
|
||||
|
@ -72,6 +71,11 @@ select {
|
|||
max-width: calc(100% - 30px);
|
||||
}
|
||||
|
||||
#check-all-updates-force {
|
||||
white-space: normal;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#header h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: .3em;
|
||||
|
@ -241,6 +245,8 @@ select {
|
|||
border-radius: 4px;
|
||||
margin-left: 1ex;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.entry.usercss .style-name-link::after {
|
||||
|
@ -446,6 +452,7 @@ select {
|
|||
|
||||
#manage-text {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
padding-top: .35rem;
|
||||
}
|
||||
|
@ -466,7 +473,6 @@ select {
|
|||
|
||||
.newUI .style-name {
|
||||
font-size: 14px;
|
||||
font-family: sans-serif;
|
||||
text-indent: calc(var(--checkbox-width) - var(--name-padding-left) - 4px);
|
||||
padding-left: var(--name-padding-left);
|
||||
padding-right: var(--name-padding-right);
|
||||
|
@ -474,7 +480,7 @@ select {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.newUI .entry .style-name::before {
|
||||
.newUI .entry .style-name:hover::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -483,13 +489,6 @@ select {
|
|||
bottom: 0;
|
||||
background: linear-gradient(to right, hsla(180, 50%, 30%, 0.2), hsla(180, 20%, 10%, 0.05) 50%, transparent);
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity .1s;
|
||||
will-change: opacity;
|
||||
}
|
||||
|
||||
.newUI .entry .style-name:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.newUI .entry.enabled .style-name:hover .style-name-link {
|
||||
|
@ -825,6 +824,15 @@ input[id^="manage.newUI"] {
|
|||
margin-top: 1ex;
|
||||
}
|
||||
|
||||
#update-all-no-updates[data-skipped-edited="true"] {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#update-all-no-updates[data-skipped-edited="true"]::after {
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* highlight updated/added styles */
|
||||
.highlight {
|
||||
animation: highlight 10s cubic-bezier(0,.82,.47,.98);
|
||||
|
@ -941,7 +949,6 @@ input[id^="manage.newUI"] {
|
|||
height: 20px;
|
||||
box-sizing: border-box;
|
||||
padding: 3px 3px 3px 4px;
|
||||
font: 400 12px Arial;
|
||||
color: #000;
|
||||
border: 1px solid hsl(0, 0%, 66%);
|
||||
}
|
||||
|
|
119
manage/manage.js
119
manage/manage.js
|
@ -73,8 +73,7 @@ function initGlobalEvents() {
|
|||
installed.addEventListener('mouseover', handleEvent.lazyAddEntryTitle);
|
||||
installed.addEventListener('mouseout', handleEvent.lazyAddEntryTitle);
|
||||
|
||||
// remember scroll position on normal history navigation
|
||||
window.onbeforeunload = rememberScrollPosition;
|
||||
document.addEventListener('visibilitychange', onVisibilityChange);
|
||||
|
||||
$$('[data-toggle-on-click]').forEach(el => {
|
||||
// dataset on SVG doesn't work in Chrome 49-??, works in 57+
|
||||
|
@ -107,16 +106,15 @@ function initGlobalEvents() {
|
|||
.disabled h2::after {
|
||||
content: "${t('genericDisabledLabel')}";
|
||||
}
|
||||
#update-all-no-updates[data-skipped-edited="true"]:after {
|
||||
#update-all-no-updates[data-skipped-edited="true"]::after {
|
||||
content: " ${t('updateAllCheckSucceededSomeEdited')}";
|
||||
}
|
||||
body.all-styles-hidden-by-filters:after {
|
||||
body.all-styles-hidden-by-filters::after {
|
||||
content: "${t('filteredStylesAllHidden')}";
|
||||
}
|
||||
`));
|
||||
}
|
||||
|
||||
|
||||
function showStyles(styles = [], matchUrlIds) {
|
||||
const sorted = sorter.sort({
|
||||
styles: styles.map(style => ({
|
||||
|
@ -155,23 +153,15 @@ function showStyles(styles = [], matchUrlIds) {
|
|||
filterAndAppend({container: renderBin}).then(sorter.updateStripes);
|
||||
if (index < sorted.length) {
|
||||
requestAnimationFrame(renderStyles);
|
||||
if (firstRun) setTimeout(recreateStyleTargets, 0, {styles, iconsOnly: true});
|
||||
if (firstRun) setTimeout(getFaviconImgSrc);
|
||||
firstRun = false;
|
||||
return;
|
||||
}
|
||||
if (newUI.enabled && newUI.favicons) {
|
||||
setTimeout(recreateStyleTargets, 0, {iconsOnly: true});
|
||||
}
|
||||
if ('scrollY' in (history.state || {}) && !sessionStorage.justEditedStyleId) {
|
||||
setTimeout(window.scrollTo, 0, 0, history.state.scrollY);
|
||||
}
|
||||
setTimeout(getFaviconImgSrc);
|
||||
if (sessionStorage.justEditedStyleId) {
|
||||
const entry = $(ENTRY_ID_PREFIX + sessionStorage.justEditedStyleId);
|
||||
delete sessionStorage.justEditedStyleId;
|
||||
if (entry) {
|
||||
animateElement(entry);
|
||||
requestAnimationFrame(() => scrollElementIntoView(entry));
|
||||
}
|
||||
highlightEditedStyle();
|
||||
} else if ('scrollY' in (history.state || {})) {
|
||||
setTimeout(window.scrollTo, 0, 0, history.state.scrollY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -247,10 +237,10 @@ function createStyleElement({style, name}) {
|
|||
}
|
||||
|
||||
|
||||
function createStyleTargetsElement({entry, style, iconsOnly}) {
|
||||
function createStyleTargetsElement({entry, style}) {
|
||||
const parts = createStyleElement.parts;
|
||||
const entryTargets = $('.targets', entry);
|
||||
const targets = iconsOnly ? entryTargets : parts.targets.cloneNode(true);
|
||||
const targets = parts.targets.cloneNode(true);
|
||||
let container = targets;
|
||||
let numTargets = 0;
|
||||
const displayed = new Set();
|
||||
|
@ -269,23 +259,21 @@ function createStyleTargetsElement({entry, style, iconsOnly}) {
|
|||
continue;
|
||||
}
|
||||
displayed.add(targetValue);
|
||||
const element = iconsOnly ? targets.children[numTargets] : template.appliesToTarget.cloneNode(true);
|
||||
const element = template.appliesToTarget.cloneNode(true);
|
||||
if (!newUI.enabled) {
|
||||
if (numTargets === 10) {
|
||||
container = container.appendChild(template.extraAppliesTo.cloneNode(true));
|
||||
} else if (numTargets > 1) {
|
||||
} else if (numTargets > 0) {
|
||||
container.appendChild(template.appliesToSeparator.cloneNode(true));
|
||||
}
|
||||
}
|
||||
if (!iconsOnly) {
|
||||
element.dataset.type = type;
|
||||
element.appendChild(
|
||||
document.createTextNode(
|
||||
(parts.decorations[type + 'Before'] || '') +
|
||||
targetValue +
|
||||
(parts.decorations[type + 'After'] || '')));
|
||||
container.appendChild(element);
|
||||
}
|
||||
element.dataset.type = type;
|
||||
element.appendChild(
|
||||
document.createTextNode(
|
||||
(parts.decorations[type + 'Before'] || '') +
|
||||
targetValue +
|
||||
(parts.decorations[type + 'After'] || '')));
|
||||
container.appendChild(element);
|
||||
numTargets++;
|
||||
}
|
||||
}
|
||||
|
@ -296,9 +284,7 @@ function createStyleTargetsElement({entry, style, iconsOnly}) {
|
|||
}
|
||||
}
|
||||
if (numTargets) {
|
||||
if (!iconsOnly) {
|
||||
entryTargets.parentElement.replaceChild(targets, entryTargets);
|
||||
}
|
||||
entryTargets.parentElement.replaceChild(targets, entryTargets);
|
||||
} else if (!entry.classList.contains('global') ||
|
||||
!entryTargets.firstElementChild) {
|
||||
if (entryTargets.firstElementChild) {
|
||||
|
@ -310,35 +296,17 @@ function createStyleTargetsElement({entry, style, iconsOnly}) {
|
|||
}
|
||||
|
||||
|
||||
function recreateStyleTargets({styles, iconsOnly = false} = {}) {
|
||||
Promise.resolve(styles || API.getStyles()).then(styles => {
|
||||
for (const style of styles) {
|
||||
const entry = $(ENTRY_ID_PREFIX + style.id);
|
||||
if (entry) {
|
||||
createStyleTargetsElement({
|
||||
entry,
|
||||
style,
|
||||
iconsOnly,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (newUI.enabled && newUI.favicons) {
|
||||
debounce(getFaviconImgSrc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getFaviconImgSrc(container = installed) {
|
||||
const targets = $$('.target', container);
|
||||
if (!newUI.enabled || !newUI.favicons) return;
|
||||
const regexpRemoveNegativeLookAhead = /(\?!([^)]+\))|\(\?![\w(]+[^)]+[\w|)]+)/g;
|
||||
// replace extra characters & all but the first group entry "(abc|def|ghi)xyz" => abcxyz
|
||||
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 = new RegExp(`[\\w-]+[\\.(]+(${domainExt.join('|')})\\b`, 'g');
|
||||
const regexpMatchRegExp = /[\w-]+[.(]+(com|org|co|net|im|io|edu|gov|biz|info|de|cn|uk|nl|eu|ru)\b/g;
|
||||
const regexpMatchDomain = /^.*?:\/\/([^/]+)/;
|
||||
for (const target of targets) {
|
||||
for (const target of $$('.target', container)) {
|
||||
const type = target.dataset.type;
|
||||
const targetValue = target.textContent;
|
||||
if (!targetValue) continue;
|
||||
let favicon = '';
|
||||
if (type === 'domains') {
|
||||
favicon = GET_FAVICON_URL + targetValue;
|
||||
|
@ -426,7 +394,7 @@ Object.assign(handleEvent, {
|
|||
});
|
||||
}
|
||||
} else {
|
||||
rememberScrollPosition();
|
||||
onVisibilityChange();
|
||||
getActiveTab().then(tab => {
|
||||
sessionStorageHash('manageStylesHistory').set(tab.id, url);
|
||||
location.href = url;
|
||||
|
@ -575,9 +543,7 @@ function handleUpdate(style, {reason, method} = {}) {
|
|||
animateElement(entry);
|
||||
requestAnimationFrame(() => scrollElementIntoView(entry));
|
||||
}
|
||||
if (newUI.enabled && newUI.favicons) {
|
||||
getFaviconImgSrc(entry);
|
||||
}
|
||||
getFaviconImgSrc(entry);
|
||||
|
||||
function handleToggledOrCodeOnly() {
|
||||
const newStyleMeta = getStyleWithNoCode(style);
|
||||
|
@ -694,14 +660,41 @@ function switchUI({styleOnly} = {}) {
|
|||
return;
|
||||
}
|
||||
if (missingFavicons) {
|
||||
recreateStyleTargets();
|
||||
debounce(getFaviconImgSrc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function rememberScrollPosition() {
|
||||
history.replaceState({scrollY: window.scrollY}, document.title);
|
||||
function onVisibilityChange() {
|
||||
switch (document.visibilityState) {
|
||||
// page restored without reloading via history navigation (currently only in FF)
|
||||
// the catch here is that DOM may be outdated so we'll at least refresh the just edited style
|
||||
// assuming other changes aren't important enough to justify making a complicated DOM sync
|
||||
case 'visible':
|
||||
if (sessionStorage.justEditedStyleId) {
|
||||
API.getStyles({id: sessionStorage.justEditedStyleId}).then(([style]) => {
|
||||
handleUpdate(style, {method: 'styleUpdated'});
|
||||
});
|
||||
delete sessionStorage.justEditedStyleId;
|
||||
}
|
||||
break;
|
||||
// going away
|
||||
case 'hidden':
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ function checkUpdateAll() {
|
|||
if (info.updated) {
|
||||
if (++updated === 1) {
|
||||
btnApply.disabled = true;
|
||||
btnApply.classList.remove('hidden');
|
||||
}
|
||||
btnApply.dataset.value = updated;
|
||||
}
|
||||
|
@ -156,6 +155,16 @@ function reportUpdateState({updated, style, error, STATES}) {
|
|||
$('.update-note', entry).textContent = message;
|
||||
$('.check-update', entry).title = newUI.enabled ? message : '';
|
||||
$('.update', entry).title = t(edited ? 'updateCheckManualUpdateForce' : 'installUpdate');
|
||||
// digest may change silently when forcing an update of a locally edited style
|
||||
// so we need to update it in entry's styleMeta in all open manager tabs
|
||||
if (error === STATES.SAME_CODE) {
|
||||
for (const view of chrome.extension.getViews({type: 'tab'})) {
|
||||
if (view.location.pathname === location.pathname) {
|
||||
const entry = view.$(ENTRY_ID_PREFIX + style.id);
|
||||
if (entry) entry.styleMeta.originalDigest = style.originalDigest;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isCheckAll) {
|
||||
renderUpdatesOnlyFilter({show: $('.can-update, .update-problem')});
|
||||
}
|
||||
|
@ -179,6 +188,8 @@ function reportUpdateState({updated, style, error, STATES}) {
|
|||
|
||||
if (filtersSelector.hide && isCheckAll) {
|
||||
filterAndAppend({entry}).then(sorter.updateStripes);
|
||||
} else if (updated && !isCheckAll) {
|
||||
renderUpdatesOnlyFilter();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,13 +206,8 @@ function renderUpdatesOnlyFilter({show, check} = {}) {
|
|||
checkbox.dispatchEvent(new Event('change'));
|
||||
|
||||
const btnApply = $('#apply-all-updates');
|
||||
if (!btnApply.matches('.hidden')) {
|
||||
if (numUpdatable > 0) {
|
||||
btnApply.dataset.value = numUpdatable;
|
||||
} else {
|
||||
btnApply.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
btnApply.classList.toggle('hidden', !numUpdatable);
|
||||
btnApply.dataset.value = numUpdatable;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Stylus",
|
||||
"version": "1.4.16",
|
||||
"version": "1.4.22",
|
||||
"minimum_chrome_version": "49",
|
||||
"description": "__MSG_description__",
|
||||
"homepage_url": "https://add0n.com/stylus.html",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* global focusAccessibility */
|
||||
/* global moveFocus */
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
|
@ -33,12 +34,22 @@ function messageBox({
|
|||
document.body.appendChild(messageBox.element);
|
||||
|
||||
messageBox.originalFocus = document.activeElement;
|
||||
moveFocus(1);
|
||||
// skip external links like feedback
|
||||
while ((moveFocus(messageBox.element, 1) || {}).target === '_blank') {/*NOP*/}
|
||||
// suppress focus outline when invoked via click
|
||||
if (focusAccessibility.lastFocusedViaClick && document.activeElement) {
|
||||
document.activeElement.dataset.focusedViaClick = '';
|
||||
}
|
||||
|
||||
if (typeof onshow === 'function') {
|
||||
onshow(messageBox.element);
|
||||
}
|
||||
|
||||
if (!$('#message-box-title').textContent) {
|
||||
$('#message-box-title').hidden = true;
|
||||
$('#message-box-close-icon').hidden = true;
|
||||
}
|
||||
|
||||
return new Promise(_resolve => {
|
||||
messageBox.resolve = _resolve;
|
||||
});
|
||||
|
@ -67,7 +78,7 @@ function messageBox({
|
|||
event.stopPropagation();
|
||||
break;
|
||||
case 9:
|
||||
moveFocus(shiftKey ? -1 : 1);
|
||||
moveFocus(messageBox.element, shiftKey ? -1 : 1);
|
||||
event.preventDefault();
|
||||
return;
|
||||
default:
|
||||
|
@ -139,30 +150,17 @@ function messageBox({
|
|||
messageBox.element = 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String|Node|Array<String|Node>} contents
|
||||
* @param {String} [className] like 'pre' for monospace font
|
||||
* @param {String} [title]
|
||||
* @returns {Promise<Boolean>} same as messageBox
|
||||
*/
|
||||
messageBox.alert = (contents, className) =>
|
||||
messageBox.alert = (contents, className, title) =>
|
||||
messageBox({
|
||||
title,
|
||||
contents,
|
||||
className: `center ${className || ''}`,
|
||||
buttons: [t('confirmClose')]
|
||||
|
|
25
package.json
25
package.json
|
@ -1,28 +1,31 @@
|
|||
{
|
||||
"name": "Stylus",
|
||||
"version": "1.4.16",
|
||||
"version": "1.4.22",
|
||||
"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",
|
||||
"archiver": "^3.0.0",
|
||||
"codemirror": "^5.40.0",
|
||||
"eslint": "^5.4.0",
|
||||
"fs-extra": "^7.0.0",
|
||||
"jsonlint": "^1.6.3",
|
||||
"less": "^3.7.1",
|
||||
"lz-string-unsafe": "^1.4.4-beta",
|
||||
"semver-bundle": "^0.1.0",
|
||||
"less": "^3.8.1",
|
||||
"lz-string-unsafe": "^1.4.4-fork-1",
|
||||
"rimraf": "^2.6.2",
|
||||
"semver-bundle": "^0.1.1",
|
||||
"stylelint-bundle": "^8.0.0",
|
||||
"stylus-lang-bundle": "^0.54.5",
|
||||
"updates": "^4.0.1"
|
||||
"updates": "^4.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint **/*.js || true",
|
||||
"update": "npm run update-node && npm run update-versions && npm run update-codemirror",
|
||||
"lint": "eslint **/*.js --cache || exit 0",
|
||||
"update": "npm run update-node && npm run update-main",
|
||||
"update-quick": "updates -u && npm update && npm run update-main",
|
||||
"update-main": "npm run update-versions && npm run update-codemirror",
|
||||
"update-node": "updates -u && node tools/remove-modules.js && npm install",
|
||||
"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"
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ function initPopup() {
|
|||
$('label', info).textContent = t('unreachableAMO');
|
||||
const note = (FIREFOX < 59 ? t('unreachableAMOHintOldFF') : t('unreachableAMOHint')) +
|
||||
(FIREFOX < 60 ? '' : '\n' + t('unreachableAMOHintNewFF'));
|
||||
const renderToken = s => s[0] === '<' ? $create('b', s.slice(1, -1)) : s;
|
||||
const renderToken = s => s[0] === '<' ? $create('b', tWordBreak(s.slice(1, -1))) : s;
|
||||
const renderLine = line => $create('p', line.split(/(<.*?>)/).map(renderToken));
|
||||
const noteNode = $create('fragment', note.split('\n').map(renderLine));
|
||||
const target = $('p', info);
|
||||
|
@ -314,7 +314,14 @@ function createStyleElement({
|
|||
if (check) detectSloppyRegexps([style]);
|
||||
|
||||
const oldElement = $(ENTRY_ID_PREFIX + style.id);
|
||||
if (oldElement) {
|
||||
if (oldElement && oldElement.contains(document.activeElement)) {
|
||||
// preserve the focused element inside
|
||||
const {className} = document.activeElement;
|
||||
oldElement.parentNode.replaceChild(entry, oldElement);
|
||||
// we're not using $() since className may contain multiple tokens
|
||||
const el = entry.getElementsByClassName(className)[0];
|
||||
if (el) el.focus();
|
||||
} else if (oldElement) {
|
||||
oldElement.parentNode.replaceChild(entry, oldElement);
|
||||
} else {
|
||||
container.appendChild(entry);
|
||||
|
@ -338,6 +345,7 @@ Object.assign(handleEvent, {
|
|||
},
|
||||
|
||||
toggle(event) {
|
||||
// when fired on checkbox, prevent the parent label from seeing the event, see #501
|
||||
event.stopPropagation();
|
||||
API.saveStyle({
|
||||
id: handleEvent.getClickedStyleId(event),
|
||||
|
|
8
tools/remove-modules.js
Normal file
8
tools/remove-modules.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const rimraf = require('rimraf');
|
||||
|
||||
// See https://github.com/isaacs/rimraf/issues/102#issuecomment-412310309
|
||||
rimraf('node_modules/!(rimraf|.bin)', fs, () => {});
|
|
@ -43,6 +43,12 @@ function isFolder(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/`;
|
||||
|
@ -54,8 +60,8 @@ function updateExisting(lib) {
|
|||
const folderRoot = `${vendorRoot}${folder}`;
|
||||
const entries = fs.readdirSync(folderRoot);
|
||||
entries.forEach(entry => {
|
||||
// Ignore README.md & LICENSE files
|
||||
if (entry !== 'README.md' && entry !== 'LICENSE') {
|
||||
// Ignore README.md & LICENSE files
|
||||
const entryPath = `${folderRoot}/${entry}`;
|
||||
try {
|
||||
if (fs.existsSync(entryPath)) {
|
||||
|
@ -63,6 +69,10 @@ function updateExisting(lib) {
|
|||
folders.push(`${folder}/${entry}`);
|
||||
} else {
|
||||
fs.copySync(`${libRoot}${folder}/${entry}`, entryPath);
|
||||
// Remove $1 from "CodeMirror$1" in codemirror.js
|
||||
if (entry === 'codemirror.js') {
|
||||
renameCodeMirrorVariable(entryPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
11
tools/zip.js
11
tools/zip.js
|
@ -8,9 +8,12 @@ function createZip() {
|
|||
const fileName = 'stylus.zip';
|
||||
const exclude = [
|
||||
'.*', // dot files/folders (glob, not regexp)
|
||||
'node_modules',
|
||||
'tools',
|
||||
'vendor/codemirror/lib/**', // get unmodified copy from node_modules
|
||||
'node_modules/**',
|
||||
'tools/**',
|
||||
'package.json',
|
||||
'package-lock.json',
|
||||
'yarn.lock',
|
||||
'*.zip'
|
||||
];
|
||||
|
||||
|
@ -34,7 +37,9 @@ function createZip() {
|
|||
});
|
||||
|
||||
archive.pipe(file);
|
||||
archive.glob(`!(${exclude.join('|')})`);
|
||||
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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -508,15 +508,11 @@
|
|||
// sass/less parent reference 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"
|
||||
if (lookBack(" ") && output[output.length - 1] !== " ") {
|
||||
if (lookBack(" ") && outputPosCol && !/\s$/.test(output[output.length - 1])) {
|
||||
output.push(" ");
|
||||
outputPosCol++;
|
||||
}
|
||||
*/
|
||||
|
||||
if (peek() === ":") {
|
||||
// pseudo-element
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.colorview-swatch::before,
|
||||
.colorview-swatch::after {
|
||||
.colorview-swatch::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
|
@ -18,21 +17,14 @@
|
|||
width: 10px;
|
||||
height: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.colorview-swatch::before {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQYV2NctWrVfwYkEBYWxojMZ6SDAmT7QGx0K1EcRBsFAADeG/3M/HteAAAAAElFTkSuQmCC");
|
||||
background: linear-gradient(var(--colorview-swatch), var(--colorview-swatch)), url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQYV2NctWrVfwYkEBYWxojMZ6SDAmT7QGx0K1EcRBsFAADeG/3M/HteAAAAAElFTkSuQmCC");
|
||||
background-repeat: repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.colorview-swatch::after {
|
||||
border: 1px solid #8e8e8e;
|
||||
cursor: pointer;
|
||||
background-color: var(--colorview-swatch);
|
||||
}
|
||||
|
||||
.colorview-swatch:hover::after {
|
||||
.colorview-swatch:hover::before {
|
||||
border-color: #494949;
|
||||
}
|
||||
|
||||
|
|
|
@ -222,11 +222,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
function hide({notify = true} = {}) {
|
||||
function hide() {
|
||||
if (shown) {
|
||||
if (notify) {
|
||||
colorpickerCallback('');
|
||||
}
|
||||
colorpickerCallback('');
|
||||
unregisterEvents();
|
||||
focusNoScroll(prevFocusedElement);
|
||||
$root.remove();
|
||||
|
@ -623,7 +621,7 @@
|
|||
case 27:
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
hide({notify: false});
|
||||
hide();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -643,17 +641,20 @@
|
|||
//region Event utilities
|
||||
|
||||
function colorpickerCallback(colorString = currentColorToString()) {
|
||||
// Esc pressed?
|
||||
if (!colorString) {
|
||||
const isCallable = typeof options.callback === 'function';
|
||||
// hiding
|
||||
if (!colorString && isCallable) {
|
||||
options.callback('');
|
||||
return;
|
||||
}
|
||||
if (
|
||||
userActivity &&
|
||||
$inputs[currentFormat].every(el => el.checkValidity()) &&
|
||||
typeof options.callback === 'function'
|
||||
$inputs[currentFormat].every(el => el.checkValidity())
|
||||
) {
|
||||
lastOutputColor = colorString.replace(/\b0\./g, '.');
|
||||
options.callback(lastOutputColor);
|
||||
if (isCallable) {
|
||||
options.callback(lastOutputColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -788,8 +789,8 @@
|
|||
const maxTopUnobscured = options.top <= maxTop ? maxTop : options.top - height - 20;
|
||||
const maxRight = window.innerWidth - width;
|
||||
const maxRightUnobscured = options.left <= maxRight ? maxRight : options.left - width;
|
||||
const left = constrain(0, maxRightUnobscured, options.left);
|
||||
const top = constrain(0, maxTopUnobscured, options.top);
|
||||
const left = constrain(0, Math.max(0, maxRightUnobscured), options.left);
|
||||
const top = constrain(0, Math.max(0, maxTopUnobscured), options.top);
|
||||
$root.style.setProperty('left', left + 'px', 'important');
|
||||
$root.style.setProperty('top', top + 'px', 'important');
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
!CSS.supports('color', 'hsl(1turn, 2%, 3%)') && /deg|g?rad|turn/,
|
||||
].filter(Boolean).map(rx => rx.source).join('|') || '^$', 'i'),
|
||||
};
|
||||
if (RX_COLOR.unsupported.source === '^$') {
|
||||
RX_COLOR.unsupported = null;
|
||||
}
|
||||
const RX_DETECT = new RegExp('(^|[\\s(){}[\\]:,/"=])' +
|
||||
'(' +
|
||||
RX_COLOR.hex.source + '|' +
|
||||
|
@ -100,7 +103,7 @@
|
|||
if (!this.popup) {
|
||||
delete CM_EVENTS.mousedown;
|
||||
document.head.appendChild(document.createElement('style')).textContent = `
|
||||
.colorview-swatch::after {
|
||||
.colorview-swatch::before {
|
||||
cursor: auto;
|
||||
}
|
||||
`;
|
||||
|
@ -418,7 +421,7 @@
|
|||
|
||||
function getSafeColorValue() {
|
||||
if (isHex && color.length !== 5 && color.length !== 9) return color;
|
||||
if (!isFunc || !RX_COLOR.unsupported.test(color)) return color;
|
||||
if (!RX_COLOR.unsupported || !RX_COLOR.unsupported.test(color)) return color;
|
||||
const value = colorConverter.parse(color);
|
||||
return colorConverter.format(value, 'rgb');
|
||||
}
|
||||
|
@ -691,7 +694,7 @@
|
|||
if (button) return;
|
||||
const swatch = target.closest('.' + COLORVIEW_CLASS);
|
||||
if (!swatch) return;
|
||||
const {left, width, height} = getComputedStyle(swatch, '::after');
|
||||
const {left, width, height} = getComputedStyle(swatch, '::before');
|
||||
const bounds = swatch.getBoundingClientRect();
|
||||
const swatchClicked =
|
||||
offsetX >= parseFloat(left) - 1 &&
|
||||
|
|
|
@ -425,7 +425,7 @@ CSSLint.addRule({
|
|||
}
|
||||
};
|
||||
|
||||
CSSLint.util.registerBlockEvents(parser, startRule, endRule, property);
|
||||
CSSLint.Util.registerBlockEvents(parser, startRule, endRule, property);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ self.parserlib = (() => {
|
|||
vmax: 'length',
|
||||
vmin: 'length',
|
||||
fr: 'length',
|
||||
q: 'length',
|
||||
|
||||
deg: 'angle',
|
||||
rad: 'angle',
|
||||
|
@ -591,8 +592,8 @@ self.parserlib = (() => {
|
|||
'text-align-all': 'start | end | left | right | center | justify | match-parent',
|
||||
'text-align-last': 'auto | start | end | left | right | center | justify',
|
||||
'text-anchor': 'start | middle | end',
|
||||
'text-decoration': '<text-decoration-line> || <text-decoration-style> || <text-decoration-color>',
|
||||
'text-decoration-color': '<text-decoration-color>',
|
||||
'text-decoration': '<text-decoration-line> || <text-decoration-style> || <color>',
|
||||
'text-decoration-color': '<color>',
|
||||
'text-decoration-line': '<text-decoration-line>',
|
||||
'text-decoration-skip': 'none | [ objects || [ spaces | [ leading-spaces || trailing-spaces ] ] || ' +
|
||||
'edges || box-decoration ]',
|
||||
|
@ -756,7 +757,7 @@ self.parserlib = (() => {
|
|||
|
||||
'<gradient>': part =>
|
||||
part.type === 'function' &&
|
||||
/^(?:-(?:ms|moz|o|webkit)-)?(?:repeating-)?(?:radial-|linear-)?gradient/i.test(part),
|
||||
/^(?:-(?:ms|moz|o|webkit)-)?(?:repeating-)?(?:radial-|linear-|conic-)?gradient/i.test(part),
|
||||
|
||||
//eslint-disable-next-line no-use-before-define
|
||||
'<hex-color>': part => part.tokenType === Tokens.HASH,
|
||||
|
@ -859,8 +860,6 @@ self.parserlib = (() => {
|
|||
|
||||
'<string>': part => part.type === 'string',
|
||||
|
||||
'<text-decoration-color>': '<color>',
|
||||
|
||||
'<text-decoration-style>': 'solid | double | dotted | dashed | wavy',
|
||||
|
||||
'<time>': part => part.type === 'time',
|
||||
|
|
13
vendor/README.md
vendored
13
vendor/README.md
vendored
|
@ -24,3 +24,16 @@ The following changes are made:
|
|||
* `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`.
|
||||
|
||||
## Creating the ZIP
|
||||
|
||||
Use `npm run zip`.
|
||||
|
||||
This command creates a zip file that includes all the files from the repository **except**:
|
||||
|
||||
* All dot files (e.g. `.eslintrc` & `.gitignore`).
|
||||
* `node_modules` folder.
|
||||
* `tools` folder.
|
||||
* `package.json` file.
|
||||
* `package-lock.json` and/or `yarn.lock` file(s).
|
||||
* `vendor/codemirror/lib` files. This path is excluded because it contains a file modified for development purposes only. Instead, the CodeMirror files are copied directly from `node_modules/codemirror/lib`.
|
||||
|
|
2
vendor/codemirror/README.md
vendored
2
vendor/codemirror/README.md
vendored
|
@ -1,3 +1,3 @@
|
|||
## CodeMirror v5.39.2
|
||||
## CodeMirror v5.40.0
|
||||
|
||||
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.
|
||||
|
|
2
vendor/codemirror/addon/comment/comment.js
vendored
2
vendor/codemirror/addon/comment/comment.js
vendored
|
@ -1,5 +1,5 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
|
|
2
vendor/codemirror/addon/dialog/dialog.js
vendored
2
vendor/codemirror/addon/dialog/dialog.js
vendored
|
@ -1,5 +1,5 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
// Open simple dialogs on top of an editor. Relies on dialog.css.
|
||||
|
||||
|
|
11
vendor/codemirror/addon/edit/closebrackets.js
vendored
11
vendor/codemirror/addon/edit/closebrackets.js
vendored
|
@ -1,5 +1,5 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
|
@ -136,9 +136,7 @@
|
|||
var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur)
|
||||
if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both";
|
||||
else return CodeMirror.Pass;
|
||||
} else if (opening && (cm.getLine(cur.line).length == cur.ch ||
|
||||
isClosingBracket(next, pairs) ||
|
||||
/\s/.test(next))) {
|
||||
} else if (opening) {
|
||||
curType = "both";
|
||||
} else {
|
||||
return CodeMirror.Pass;
|
||||
|
@ -175,11 +173,6 @@
|
|||
});
|
||||
}
|
||||
|
||||
function isClosingBracket(ch, pairs) {
|
||||
var pos = pairs.lastIndexOf(ch);
|
||||
return pos > -1 && pos % 2 == 1;
|
||||
}
|
||||
|
||||
function charsAround(cm, pos) {
|
||||
var str = cm.getRange(Pos(pos.line, pos.ch - 1),
|
||||
Pos(pos.line, pos.ch + 1));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
|
|
2
vendor/codemirror/addon/fold/brace-fold.js
vendored
2
vendor/codemirror/addon/fold/brace-fold.js
vendored
|
@ -1,5 +1,5 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
|
|
2
vendor/codemirror/addon/fold/comment-fold.js
vendored
2
vendor/codemirror/addon/fold/comment-fold.js
vendored
|
@ -1,5 +1,5 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
|
|
2
vendor/codemirror/addon/fold/foldcode.js
vendored
2
vendor/codemirror/addon/fold/foldcode.js
vendored
|
@ -1,5 +1,5 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
|
|
2
vendor/codemirror/addon/fold/foldgutter.js
vendored
2
vendor/codemirror/addon/fold/foldgutter.js
vendored
|
@ -1,5 +1,5 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
|
|
2
vendor/codemirror/addon/fold/indent-fold.js
vendored
2
vendor/codemirror/addon/fold/indent-fold.js
vendored
|
@ -1,5 +1,5 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user